]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/builtins.c
PR testsuite/52011
[thirdparty/gcc.git] / gcc / builtins.c
CommitLineData
53800dbe 1/* Expand builtin functions.
61f1dccc 2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
750d7b16 3 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
f96bd2bf 4 Free Software Foundation, Inc.
53800dbe 5
f12b58b3 6This file is part of GCC.
53800dbe 7
f12b58b3 8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
8c4c00c1 10Software Foundation; either version 3, or (at your option) any later
f12b58b3 11version.
53800dbe 12
f12b58b3 13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
53800dbe 17
18You should have received a copy of the GNU General Public License
8c4c00c1 19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
53800dbe 21
22#include "config.h"
23#include "system.h"
805e22b2 24#include "coretypes.h"
25#include "tm.h"
53800dbe 26#include "machmode.h"
27#include "rtl.h"
28#include "tree.h"
dae0b5cb 29#include "realmpfr.h"
75a70cf9 30#include "gimple.h"
53800dbe 31#include "flags.h"
32#include "regs.h"
33#include "hard-reg-set.h"
34#include "except.h"
35#include "function.h"
53800dbe 36#include "insn-config.h"
37#include "expr.h"
d8fc4d0b 38#include "optabs.h"
39#include "libfuncs.h"
53800dbe 40#include "recog.h"
41#include "output.h"
42#include "typeclass.h"
689df48e 43#include "predict.h"
1dd6c958 44#include "tm_p.h"
fc2a2dcb 45#include "target.h"
63c62881 46#include "langhooks.h"
0ec80471 47#include "basic-block.h"
fd62c19a 48#include "tree-mudflap.h"
5a84fdd6 49#include "tree-flow.h"
162719b3 50#include "value-prof.h"
852f689e 51#include "diagnostic-core.h"
3b9c3a16 52#include "builtins.h"
53800dbe 53
5383fb56 54
726e2588 55#ifndef PAD_VARARGS_DOWN
56#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
57#endif
239d491a 58static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_rnd_t));
726e2588 59
3b9c3a16 60struct target_builtins default_target_builtins;
61#if SWITCHABLE_TARGET
62struct target_builtins *this_target_builtins = &default_target_builtins;
63#endif
64
ab7943b9 65/* Define the names of the builtin function types and codes. */
8934cb0c 66const char *const built_in_class_names[4]
ab7943b9 67 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
68
9cfddb70 69#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
0dfc45b5 70const char * built_in_names[(int) END_BUILTINS] =
4e9d90c7 71{
72#include "builtins.def"
73};
74#undef DEF_BUILTIN
ab7943b9 75
df94cd3b 76/* Setup an array of _DECL trees, make sure each element is
77 initialized to NULL_TREE. */
b9a16870 78builtin_info_type builtin_info;
df94cd3b 79
aecda0d6 80static const char *c_getstr (tree);
81static rtx c_readstr (const char *, enum machine_mode);
82static int target_char_cast (tree, char *);
d8ae1baa 83static rtx get_memory_rtx (tree, tree);
aecda0d6 84static int apply_args_size (void);
85static int apply_result_size (void);
d8c9779c 86#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
aecda0d6 87static rtx result_vector (int, rtx);
d8c9779c 88#endif
843d08a9 89static void expand_builtin_update_setjmp_buf (rtx);
aecda0d6 90static void expand_builtin_prefetch (tree);
91static rtx expand_builtin_apply_args (void);
92static rtx expand_builtin_apply_args_1 (void);
93static rtx expand_builtin_apply (rtx, rtx, rtx);
94static void expand_builtin_return (rtx);
95static enum type_class type_to_class (tree);
96static rtx expand_builtin_classify_type (tree);
97static void expand_errno_check (tree, rtx);
98static rtx expand_builtin_mathfn (tree, rtx, rtx);
99static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
6b43bae4 100static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
7e0713b1 101static rtx expand_builtin_mathfn_ternary (tree, rtx, rtx);
f97eea22 102static rtx expand_builtin_interclass_mathfn (tree, rtx);
c3147c1a 103static rtx expand_builtin_sincos (tree);
f97eea22 104static rtx expand_builtin_cexpi (tree, rtx);
ff1b14e4 105static rtx expand_builtin_int_roundingfn (tree, rtx);
106static rtx expand_builtin_int_roundingfn_2 (tree, rtx);
79012a9d 107static rtx expand_builtin_next_arg (void);
aecda0d6 108static rtx expand_builtin_va_start (tree);
109static rtx expand_builtin_va_end (tree);
110static rtx expand_builtin_va_copy (tree);
c2f47e15 111static rtx expand_builtin_memcmp (tree, rtx, enum machine_mode);
a65c4d64 112static rtx expand_builtin_strcmp (tree, rtx);
aecda0d6 113static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
114static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
a65c4d64 115static rtx expand_builtin_memcpy (tree, rtx);
c2f47e15 116static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode);
48e1416a 117static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx,
c2f47e15 118 enum machine_mode, int);
a65c4d64 119static rtx expand_builtin_strcpy (tree, rtx);
120static rtx expand_builtin_strcpy_args (tree, tree, rtx);
aecda0d6 121static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
a65c4d64 122static rtx expand_builtin_strncpy (tree, rtx);
aecda0d6 123static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
c2f47e15 124static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
125static rtx expand_builtin_memset_args (tree, tree, tree, rtx, enum machine_mode, tree);
aecda0d6 126static rtx expand_builtin_bzero (tree);
127static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
5be42b39 128static rtx expand_builtin_alloca (tree, bool);
aecda0d6 129static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
130static rtx expand_builtin_frame_address (tree, tree);
389dd41b 131static tree stabilize_va_list_loc (location_t, tree, int);
aecda0d6 132static rtx expand_builtin_expect (tree, rtx);
133static tree fold_builtin_constant_p (tree);
389dd41b 134static tree fold_builtin_expect (location_t, tree, tree);
aecda0d6 135static tree fold_builtin_classify_type (tree);
c7cbde74 136static tree fold_builtin_strlen (location_t, tree, tree);
389dd41b 137static tree fold_builtin_inf (location_t, tree, int);
aecda0d6 138static tree fold_builtin_nan (tree, tree, int);
389dd41b 139static tree rewrite_call_expr (location_t, tree, int, tree, int, ...);
b7bf20db 140static bool validate_arg (const_tree, enum tree_code code);
277f8dd2 141static bool integer_valued_real_p (tree);
389dd41b 142static tree fold_trunc_transparent_mathfn (location_t, tree, tree);
aecda0d6 143static bool readonly_data_expr (tree);
144static rtx expand_builtin_fabs (tree, rtx, rtx);
27f261ef 145static rtx expand_builtin_signbit (tree, rtx);
389dd41b 146static tree fold_builtin_sqrt (location_t, tree, tree);
147static tree fold_builtin_cbrt (location_t, tree, tree);
148static tree fold_builtin_pow (location_t, tree, tree, tree, tree);
149static tree fold_builtin_powi (location_t, tree, tree, tree, tree);
150static tree fold_builtin_cos (location_t, tree, tree, tree);
151static tree fold_builtin_cosh (location_t, tree, tree, tree);
bffb7645 152static tree fold_builtin_tan (tree, tree);
389dd41b 153static tree fold_builtin_trunc (location_t, tree, tree);
154static tree fold_builtin_floor (location_t, tree, tree);
155static tree fold_builtin_ceil (location_t, tree, tree);
156static tree fold_builtin_round (location_t, tree, tree);
157static tree fold_builtin_int_roundingfn (location_t, tree, tree);
10b9666f 158static tree fold_builtin_bitop (tree, tree);
389dd41b 159static tree fold_builtin_memory_op (location_t, tree, tree, tree, tree, bool, int);
160static tree fold_builtin_strchr (location_t, tree, tree, tree);
161static tree fold_builtin_memchr (location_t, tree, tree, tree, tree);
162static tree fold_builtin_memcmp (location_t, tree, tree, tree);
163static tree fold_builtin_strcmp (location_t, tree, tree);
164static tree fold_builtin_strncmp (location_t, tree, tree, tree);
165static tree fold_builtin_signbit (location_t, tree, tree);
166static tree fold_builtin_copysign (location_t, tree, tree, tree, tree);
167static tree fold_builtin_isascii (location_t, tree);
168static tree fold_builtin_toascii (location_t, tree);
169static tree fold_builtin_isdigit (location_t, tree);
170static tree fold_builtin_fabs (location_t, tree, tree);
171static tree fold_builtin_abs (location_t, tree, tree);
172static tree fold_builtin_unordered_cmp (location_t, tree, tree, tree, enum tree_code,
d5019fe8 173 enum tree_code);
389dd41b 174static tree fold_builtin_n (location_t, tree, tree *, int, bool);
175static tree fold_builtin_0 (location_t, tree, bool);
176static tree fold_builtin_1 (location_t, tree, tree, bool);
177static tree fold_builtin_2 (location_t, tree, tree, tree, bool);
178static tree fold_builtin_3 (location_t, tree, tree, tree, tree, bool);
179static tree fold_builtin_4 (location_t, tree, tree, tree, tree, tree, bool);
180static tree fold_builtin_varargs (location_t, tree, tree, bool);
181
182static tree fold_builtin_strpbrk (location_t, tree, tree, tree);
183static tree fold_builtin_strstr (location_t, tree, tree, tree);
184static tree fold_builtin_strrchr (location_t, tree, tree, tree);
185static tree fold_builtin_strcat (location_t, tree, tree);
186static tree fold_builtin_strncat (location_t, tree, tree, tree);
187static tree fold_builtin_strspn (location_t, tree, tree);
188static tree fold_builtin_strcspn (location_t, tree, tree);
189static tree fold_builtin_sprintf (location_t, tree, tree, tree, int);
750d7b16 190static tree fold_builtin_snprintf (location_t, tree, tree, tree, tree, int);
4ee9c684 191
0a39fd54 192static rtx expand_builtin_object_size (tree);
193static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
194 enum built_in_function);
195static void maybe_emit_chk_warning (tree, enum built_in_function);
196static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
2c281b15 197static void maybe_emit_free_warning (tree);
c2f47e15 198static tree fold_builtin_object_size (tree, tree);
389dd41b 199static tree fold_builtin_strcat_chk (location_t, tree, tree, tree, tree);
200static tree fold_builtin_strncat_chk (location_t, tree, tree, tree, tree, tree);
201static tree fold_builtin_sprintf_chk (location_t, tree, enum built_in_function);
202static tree fold_builtin_printf (location_t, tree, tree, tree, bool, enum built_in_function);
203static tree fold_builtin_fprintf (location_t, tree, tree, tree, tree, bool,
c2f47e15 204 enum built_in_function);
99eabcc1 205static bool init_target_chars (void);
206
207static unsigned HOST_WIDE_INT target_newline;
208static unsigned HOST_WIDE_INT target_percent;
209static unsigned HOST_WIDE_INT target_c;
210static unsigned HOST_WIDE_INT target_s;
211static char target_percent_c[3];
212static char target_percent_s[3];
213static char target_percent_s_newline[4];
728bac60 214static tree do_mpfr_arg1 (tree, tree, int (*)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
215 const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, bool);
f0c477f2 216static tree do_mpfr_arg2 (tree, tree, tree,
217 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
9917422b 218static tree do_mpfr_arg3 (tree, tree, tree, tree,
219 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
d92f994c 220static tree do_mpfr_sincos (tree, tree, tree);
65dd1378 221static tree do_mpfr_bessel_n (tree, tree, tree,
222 int (*)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
223 const REAL_VALUE_TYPE *, bool);
e5407ca6 224static tree do_mpfr_remquo (tree, tree, tree);
e84da7c1 225static tree do_mpfr_lgamma_r (tree, tree, tree);
1cd6e20d 226static void expand_builtin_sync_synchronize (void);
0a39fd54 227
7bfefa9d 228/* Return true if NAME starts with __builtin_ or __sync_. */
229
b29139ad 230static bool
1c47b3e8 231is_builtin_name (const char *name)
b6a5fc45 232{
b6a5fc45 233 if (strncmp (name, "__builtin_", 10) == 0)
234 return true;
235 if (strncmp (name, "__sync_", 7) == 0)
236 return true;
1cd6e20d 237 if (strncmp (name, "__atomic_", 9) == 0)
238 return true;
b6a5fc45 239 return false;
240}
4ee9c684 241
7bfefa9d 242
243/* Return true if DECL is a function symbol representing a built-in. */
244
245bool
246is_builtin_fn (tree decl)
247{
248 return TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl);
249}
250
251
1c47b3e8 252/* Return true if NODE should be considered for inline expansion regardless
253 of the optimization level. This means whenever a function is invoked with
254 its "internal" name, which normally contains the prefix "__builtin". */
255
256static bool
257called_as_built_in (tree node)
258{
259 /* Note that we must use DECL_NAME, not DECL_ASSEMBLER_NAME_SET_P since
260 we want the name used to call the function, not the name it
261 will have. */
262 const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
263 return is_builtin_name (name);
264}
265
0d8f7716 266/* Compute values M and N such that M divides (address of EXP - N) and
267 such that N < M. Store N in *BITPOSP and return M.
268
269 Note that the address (and thus the alignment) computed here is based
270 on the address to which a symbol resolves, whereas DECL_ALIGN is based
271 on the address at which an object is actually located. These two
272 addresses are not always the same. For example, on ARM targets,
273 the address &foo of a Thumb function foo() has the lowest bit set,
274 whereas foo() itself starts on an even address. */
698537d1 275
98ab9e8f 276unsigned int
0c883ef3 277get_object_alignment_1 (tree exp, unsigned HOST_WIDE_INT *bitposp)
698537d1 278{
98ab9e8f 279 HOST_WIDE_INT bitsize, bitpos;
280 tree offset;
281 enum machine_mode mode;
282 int unsignedp, volatilep;
283 unsigned int align, inner;
698537d1 284
98ab9e8f 285 /* Get the innermost object and the constant (bitpos) and possibly
286 variable (offset) offset of the access. */
287 exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
288 &mode, &unsignedp, &volatilep, true);
289
290 /* Extract alignment information from the innermost object and
291 possibly adjust bitpos and offset. */
0ea95334 292 if (TREE_CODE (exp) == CONST_DECL)
293 exp = DECL_INITIAL (exp);
e064ace6 294 if (DECL_P (exp)
295 && TREE_CODE (exp) != LABEL_DECL)
0d8f7716 296 {
297 if (TREE_CODE (exp) == FUNCTION_DECL)
298 {
299 /* Function addresses can encode extra information besides their
300 alignment. However, if TARGET_PTRMEMFUNC_VBIT_LOCATION
301 allows the low bit to be used as a virtual bit, we know
302 that the address itself must be 2-byte aligned. */
303 if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn)
304 align = 2 * BITS_PER_UNIT;
305 else
306 align = BITS_PER_UNIT;
307 }
308 else
309 align = DECL_ALIGN (exp);
310 }
698537d1 311 else if (CONSTANT_CLASS_P (exp))
98ab9e8f 312 {
313 align = TYPE_ALIGN (TREE_TYPE (exp));
314#ifdef CONSTANT_ALIGNMENT
315 align = (unsigned)CONSTANT_ALIGNMENT (exp, align);
698537d1 316#endif
98ab9e8f 317 }
318 else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR)
319 align = TYPE_ALIGN (TREE_TYPE (exp));
320 else if (TREE_CODE (exp) == INDIRECT_REF)
321 align = TYPE_ALIGN (TREE_TYPE (exp));
98ab9e8f 322 else if (TREE_CODE (exp) == MEM_REF)
323 {
324 tree addr = TREE_OPERAND (exp, 0);
153c3b50 325 struct ptr_info_def *pi;
98ab9e8f 326 if (TREE_CODE (addr) == BIT_AND_EXPR
327 && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
328 {
329 align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))
330 & -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)));
331 align *= BITS_PER_UNIT;
332 addr = TREE_OPERAND (addr, 0);
333 }
334 else
335 align = BITS_PER_UNIT;
153c3b50 336 if (TREE_CODE (addr) == SSA_NAME
337 && (pi = SSA_NAME_PTR_INFO (addr)))
338 {
339 bitpos += (pi->misalign * BITS_PER_UNIT) & ~(align - 1);
340 align = MAX (pi->align * BITS_PER_UNIT, align);
341 }
342 else if (TREE_CODE (addr) == ADDR_EXPR)
957d0361 343 align = MAX (align, get_object_alignment (TREE_OPERAND (addr, 0)));
98ab9e8f 344 bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT;
345 }
28daba6f 346 else if (TREE_CODE (exp) == TARGET_MEM_REF)
153c3b50 347 {
348 struct ptr_info_def *pi;
349 tree addr = TMR_BASE (exp);
350 if (TREE_CODE (addr) == BIT_AND_EXPR
351 && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
352 {
353 align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))
354 & -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)));
355 align *= BITS_PER_UNIT;
356 addr = TREE_OPERAND (addr, 0);
357 }
358 else
359 align = BITS_PER_UNIT;
360 if (TREE_CODE (addr) == SSA_NAME
361 && (pi = SSA_NAME_PTR_INFO (addr)))
362 {
363 bitpos += (pi->misalign * BITS_PER_UNIT) & ~(align - 1);
364 align = MAX (pi->align * BITS_PER_UNIT, align);
365 }
366 else if (TREE_CODE (addr) == ADDR_EXPR)
957d0361 367 align = MAX (align, get_object_alignment (TREE_OPERAND (addr, 0)));
153c3b50 368 if (TMR_OFFSET (exp))
369 bitpos += TREE_INT_CST_LOW (TMR_OFFSET (exp)) * BITS_PER_UNIT;
370 if (TMR_INDEX (exp) && TMR_STEP (exp))
371 {
372 unsigned HOST_WIDE_INT step = TREE_INT_CST_LOW (TMR_STEP (exp));
373 align = MIN (align, (step & -step) * BITS_PER_UNIT);
374 }
375 else if (TMR_INDEX (exp))
376 align = BITS_PER_UNIT;
28daba6f 377 if (TMR_INDEX2 (exp))
e077c79b 378 align = BITS_PER_UNIT;
98ab9e8f 379 }
698537d1 380 else
98ab9e8f 381 align = BITS_PER_UNIT;
382
383 /* If there is a non-constant offset part extract the maximum
384 alignment that can prevail. */
0c883ef3 385 inner = ~0U;
98ab9e8f 386 while (offset)
387 {
388 tree next_offset;
389
390 if (TREE_CODE (offset) == PLUS_EXPR)
391 {
392 next_offset = TREE_OPERAND (offset, 0);
393 offset = TREE_OPERAND (offset, 1);
394 }
395 else
396 next_offset = NULL;
397 if (host_integerp (offset, 1))
398 {
399 /* Any overflow in calculating offset_bits won't change
400 the alignment. */
401 unsigned offset_bits
402 = ((unsigned) tree_low_cst (offset, 1) * BITS_PER_UNIT);
403
404 if (offset_bits)
405 inner = MIN (inner, (offset_bits & -offset_bits));
406 }
407 else if (TREE_CODE (offset) == MULT_EXPR
408 && host_integerp (TREE_OPERAND (offset, 1), 1))
409 {
410 /* Any overflow in calculating offset_factor won't change
411 the alignment. */
412 unsigned offset_factor
413 = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
414 * BITS_PER_UNIT);
415
416 if (offset_factor)
417 inner = MIN (inner, (offset_factor & -offset_factor));
418 }
419 else
420 {
421 inner = MIN (inner, BITS_PER_UNIT);
422 break;
423 }
424 offset = next_offset;
425 }
426
427 /* Alignment is innermost object alignment adjusted by the constant
428 and non-constant offset parts. */
429 align = MIN (align, inner);
430 bitpos = bitpos & (align - 1);
431
0c883ef3 432 *bitposp = bitpos;
433 return align;
434}
435
957d0361 436/* Return the alignment in bits of EXP, an object. */
0c883ef3 437
438unsigned int
957d0361 439get_object_alignment (tree exp)
0c883ef3 440{
441 unsigned HOST_WIDE_INT bitpos = 0;
442 unsigned int align;
443
444 align = get_object_alignment_1 (exp, &bitpos);
445
98ab9e8f 446 /* align and bitpos now specify known low bits of the pointer.
447 ptr & (align - 1) == bitpos. */
448
449 if (bitpos != 0)
450 align = (bitpos & -bitpos);
451
957d0361 452 return align;
698537d1 453}
454
e3694d1d 455/* Return the alignment of object EXP, also considering its type when we do
456 not know of explicit misalignment. Only handle MEM_REF and TARGET_MEM_REF.
457
458 ??? Note that, in the general case, the type of an expression is not kept
459 consistent with misalignment information by the front-end, for example when
460 taking the address of a member of a packed structure. However, in most of
461 the cases, expressions have the alignment of their type so we optimistically
462 fall back to this alignment when we cannot compute a misalignment. */
463
464unsigned int
465get_object_or_type_alignment (tree exp)
466{
467 unsigned HOST_WIDE_INT misalign;
468 unsigned int align = get_object_alignment_1 (exp, &misalign);
469
470 gcc_assert (TREE_CODE (exp) == MEM_REF || TREE_CODE (exp) == TARGET_MEM_REF);
471
472 if (misalign != 0)
473 align = (misalign & -misalign);
474 else
475 align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), align);
476
477 return align;
478}
479
69fbc3aa 480/* For a pointer valued expression EXP compute values M and N such that
481 M divides (EXP - N) and such that N < M. Store N in *BITPOSP and return M.
53800dbe 482
69fbc3aa 483 If EXP is not a pointer, 0 is returned. */
53800dbe 484
153c3b50 485unsigned int
69fbc3aa 486get_pointer_alignment_1 (tree exp, unsigned HOST_WIDE_INT *bitposp)
53800dbe 487{
153c3b50 488 STRIP_NOPS (exp);
535e2026 489
153c3b50 490 if (TREE_CODE (exp) == ADDR_EXPR)
69fbc3aa 491 return get_object_alignment_1 (TREE_OPERAND (exp, 0), bitposp);
153c3b50 492 else if (TREE_CODE (exp) == SSA_NAME
493 && POINTER_TYPE_P (TREE_TYPE (exp)))
53800dbe 494 {
153c3b50 495 struct ptr_info_def *pi = SSA_NAME_PTR_INFO (exp);
153c3b50 496 if (!pi)
69fbc3aa 497 {
498 *bitposp = 0;
499 return BITS_PER_UNIT;
500 }
501 *bitposp = pi->misalign * BITS_PER_UNIT;
502 return pi->align * BITS_PER_UNIT;
53800dbe 503 }
153c3b50 504
69fbc3aa 505 *bitposp = 0;
153c3b50 506 return POINTER_TYPE_P (TREE_TYPE (exp)) ? BITS_PER_UNIT : 0;
53800dbe 507}
508
69fbc3aa 509/* Return the alignment in bits of EXP, a pointer valued expression.
510 The alignment returned is, by default, the alignment of the thing that
511 EXP points to. If it is not a POINTER_TYPE, 0 is returned.
512
513 Otherwise, look at the expression to see if we can do better, i.e., if the
514 expression is actually pointing at an object whose alignment is tighter. */
515
516unsigned int
517get_pointer_alignment (tree exp)
518{
519 unsigned HOST_WIDE_INT bitpos = 0;
520 unsigned int align;
521
522 align = get_pointer_alignment_1 (exp, &bitpos);
523
524 /* align and bitpos now specify known low bits of the pointer.
525 ptr & (align - 1) == bitpos. */
526
527 if (bitpos != 0)
528 align = (bitpos & -bitpos);
529
530 return align;
531}
532
53800dbe 533/* Compute the length of a C string. TREE_STRING_LENGTH is not the right
534 way, because it could contain a zero byte in the middle.
535 TREE_STRING_LENGTH is the size of the character array, not the string.
536
4172d65e 537 ONLY_VALUE should be nonzero if the result is not going to be emitted
c09841f6 538 into the instruction stream and zero if it is going to be expanded.
4172d65e 539 E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
681fab1e 540 is returned, otherwise NULL, since
541 len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
542 evaluate the side-effects.
543
902de8ed 544 The value returned is of type `ssizetype'.
545
53800dbe 546 Unfortunately, string_constant can't access the values of const char
547 arrays with initializers, so neither can we do so here. */
548
4ee9c684 549tree
681fab1e 550c_strlen (tree src, int only_value)
53800dbe 551{
552 tree offset_node;
27d0c333 553 HOST_WIDE_INT offset;
554 int max;
44acf429 555 const char *ptr;
da136652 556 location_t loc;
53800dbe 557
681fab1e 558 STRIP_NOPS (src);
559 if (TREE_CODE (src) == COND_EXPR
560 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
561 {
562 tree len1, len2;
563
564 len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
565 len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
0862b7e9 566 if (tree_int_cst_equal (len1, len2))
681fab1e 567 return len1;
568 }
569
570 if (TREE_CODE (src) == COMPOUND_EXPR
571 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
572 return c_strlen (TREE_OPERAND (src, 1), only_value);
573
8637f1db 574 loc = EXPR_LOC_OR_HERE (src);
da136652 575
53800dbe 576 src = string_constant (src, &offset_node);
577 if (src == 0)
c2f47e15 578 return NULL_TREE;
902de8ed 579
83d79705 580 max = TREE_STRING_LENGTH (src) - 1;
53800dbe 581 ptr = TREE_STRING_POINTER (src);
902de8ed 582
53800dbe 583 if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
584 {
585 /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
586 compute the offset to the following null if we don't know where to
587 start searching for it. */
588 int i;
902de8ed 589
53800dbe 590 for (i = 0; i < max; i++)
591 if (ptr[i] == 0)
c2f47e15 592 return NULL_TREE;
902de8ed 593
53800dbe 594 /* We don't know the starting offset, but we do know that the string
595 has no internal zero bytes. We can assume that the offset falls
596 within the bounds of the string; otherwise, the programmer deserves
597 what he gets. Subtract the offset from the length of the string,
902de8ed 598 and return that. This would perhaps not be valid if we were dealing
599 with named arrays in addition to literal string constants. */
600
da136652 601 return size_diffop_loc (loc, size_int (max), offset_node);
53800dbe 602 }
603
604 /* We have a known offset into the string. Start searching there for
27d0c333 605 a null character if we can represent it as a single HOST_WIDE_INT. */
dabc4084 606 if (offset_node == 0)
53800dbe 607 offset = 0;
dabc4084 608 else if (! host_integerp (offset_node, 0))
609 offset = -1;
53800dbe 610 else
27d0c333 611 offset = tree_low_cst (offset_node, 0);
902de8ed 612
1f63a7d6 613 /* If the offset is known to be out of bounds, warn, and call strlen at
614 runtime. */
53800dbe 615 if (offset < 0 || offset > max)
616 {
1f63a7d6 617 /* Suppress multiple warnings for propagated constant strings. */
618 if (! TREE_NO_WARNING (src))
619 {
da136652 620 warning_at (loc, 0, "offset outside bounds of constant string");
1f63a7d6 621 TREE_NO_WARNING (src) = 1;
622 }
c2f47e15 623 return NULL_TREE;
53800dbe 624 }
902de8ed 625
53800dbe 626 /* Use strlen to search for the first zero byte. Since any strings
627 constructed with build_string will have nulls appended, we win even
628 if we get handed something like (char[4])"abcd".
629
630 Since OFFSET is our starting index into the string, no further
631 calculation is needed. */
902de8ed 632 return ssize_int (strlen (ptr + offset));
53800dbe 633}
634
83d79705 635/* Return a char pointer for a C string if it is a string constant
636 or sum of string constant and integer constant. */
637
638static const char *
aecda0d6 639c_getstr (tree src)
83d79705 640{
641 tree offset_node;
83d79705 642
643 src = string_constant (src, &offset_node);
644 if (src == 0)
645 return 0;
646
8c85fcb7 647 if (offset_node == 0)
648 return TREE_STRING_POINTER (src);
649 else if (!host_integerp (offset_node, 1)
650 || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
83d79705 651 return 0;
83d79705 652
8c85fcb7 653 return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
83d79705 654}
655
8c85fcb7 656/* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
657 GET_MODE_BITSIZE (MODE) bits from string constant STR. */
ecc318ff 658
6840589f 659static rtx
aecda0d6 660c_readstr (const char *str, enum machine_mode mode)
6840589f 661{
662 HOST_WIDE_INT c[2];
663 HOST_WIDE_INT ch;
664 unsigned int i, j;
665
64db345d 666 gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
7d3f6cc7 667
6840589f 668 c[0] = 0;
669 c[1] = 0;
670 ch = 1;
671 for (i = 0; i < GET_MODE_SIZE (mode); i++)
672 {
673 j = i;
674 if (WORDS_BIG_ENDIAN)
675 j = GET_MODE_SIZE (mode) - i - 1;
676 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
ad8f8e52 677 && GET_MODE_SIZE (mode) >= UNITS_PER_WORD)
6840589f 678 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
679 j *= BITS_PER_UNIT;
e212f99a 680 gcc_assert (j < 2 * HOST_BITS_PER_WIDE_INT);
7d3f6cc7 681
6840589f 682 if (ch)
683 ch = (unsigned char) str[i];
684 c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
685 }
686 return immed_double_const (c[0], c[1], mode);
687}
688
ecc318ff 689/* Cast a target constant CST to target CHAR and if that value fits into
5206b159 690 host char type, return zero and put that value into variable pointed to by
ecc318ff 691 P. */
692
693static int
aecda0d6 694target_char_cast (tree cst, char *p)
ecc318ff 695{
696 unsigned HOST_WIDE_INT val, hostval;
697
c19686c5 698 if (TREE_CODE (cst) != INTEGER_CST
ecc318ff 699 || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
700 return 1;
701
c19686c5 702 val = TREE_INT_CST_LOW (cst);
ecc318ff 703 if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
704 val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
705
706 hostval = val;
707 if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
708 hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
709
710 if (val != hostval)
711 return 1;
712
713 *p = hostval;
714 return 0;
715}
716
4ee9c684 717/* Similar to save_expr, but assumes that arbitrary code is not executed
718 in between the multiple evaluations. In particular, we assume that a
719 non-addressable local variable will not be modified. */
720
721static tree
722builtin_save_expr (tree exp)
723{
f6c35aa4 724 if (TREE_CODE (exp) == SSA_NAME
725 || (TREE_ADDRESSABLE (exp) == 0
726 && (TREE_CODE (exp) == PARM_DECL
727 || (TREE_CODE (exp) == VAR_DECL && !TREE_STATIC (exp)))))
4ee9c684 728 return exp;
729
730 return save_expr (exp);
731}
732
53800dbe 733/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
734 times to get the address of either a higher stack frame, or a return
735 address located within it (depending on FNDECL_CODE). */
902de8ed 736
c626df3d 737static rtx
869d0ef0 738expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
53800dbe 739{
740 int i;
741
869d0ef0 742#ifdef INITIAL_FRAME_ADDRESS_RTX
743 rtx tem = INITIAL_FRAME_ADDRESS_RTX;
744#else
e3e15c50 745 rtx tem;
746
1b74fde7 747 /* For a zero count with __builtin_return_address, we don't care what
748 frame address we return, because target-specific definitions will
749 override us. Therefore frame pointer elimination is OK, and using
750 the soft frame pointer is OK.
751
fa7637bd 752 For a nonzero count, or a zero count with __builtin_frame_address,
1b74fde7 753 we require a stable offset from the current frame pointer to the
754 previous one, so we must use the hard frame pointer, and
e3e15c50 755 we must disable frame pointer elimination. */
1b74fde7 756 if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
e3e15c50 757 tem = frame_pointer_rtx;
a0c938f0 758 else
e3e15c50 759 {
760 tem = hard_frame_pointer_rtx;
761
762 /* Tell reload not to eliminate the frame pointer. */
18d50ae6 763 crtl->accesses_prior_frames = 1;
e3e15c50 764 }
869d0ef0 765#endif
766
53800dbe 767 /* Some machines need special handling before we can access
3a69c60c 768 arbitrary frames. For example, on the SPARC, we must first flush
53800dbe 769 all register windows to the stack. */
770#ifdef SETUP_FRAME_ADDRESSES
771 if (count > 0)
772 SETUP_FRAME_ADDRESSES ();
773#endif
774
3a69c60c 775 /* On the SPARC, the return address is not in the frame, it is in a
53800dbe 776 register. There is no way to access it off of the current frame
777 pointer, but it can be accessed off the previous frame pointer by
778 reading the value from the register window save area. */
779#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
780 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
781 count--;
782#endif
783
784 /* Scan back COUNT frames to the specified frame. */
785 for (i = 0; i < count; i++)
786 {
787 /* Assume the dynamic chain pointer is in the word that the
788 frame address points to, unless otherwise specified. */
789#ifdef DYNAMIC_CHAIN_ADDRESS
790 tem = DYNAMIC_CHAIN_ADDRESS (tem);
791#endif
792 tem = memory_address (Pmode, tem);
00060fc2 793 tem = gen_frame_mem (Pmode, tem);
83fc1478 794 tem = copy_to_reg (tem);
53800dbe 795 }
796
3a69c60c 797 /* For __builtin_frame_address, return what we've got. But, on
798 the SPARC for example, we may have to add a bias. */
53800dbe 799 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
3a69c60c 800#ifdef FRAME_ADDR_RTX
801 return FRAME_ADDR_RTX (tem);
802#else
53800dbe 803 return tem;
3a69c60c 804#endif
53800dbe 805
3a69c60c 806 /* For __builtin_return_address, get the return address from that frame. */
53800dbe 807#ifdef RETURN_ADDR_RTX
808 tem = RETURN_ADDR_RTX (count, tem);
809#else
810 tem = memory_address (Pmode,
811 plus_constant (tem, GET_MODE_SIZE (Pmode)));
00060fc2 812 tem = gen_frame_mem (Pmode, tem);
53800dbe 813#endif
814 return tem;
815}
816
f7c44134 817/* Alias set used for setjmp buffer. */
32c2fdea 818static alias_set_type setjmp_alias_set = -1;
f7c44134 819
6b7f6858 820/* Construct the leading half of a __builtin_setjmp call. Control will
2c8a1497 821 return to RECEIVER_LABEL. This is also called directly by the SJLJ
822 exception handling code. */
53800dbe 823
6b7f6858 824void
aecda0d6 825expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
53800dbe 826{
53800dbe 827 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
53800dbe 828 rtx stack_save;
f7c44134 829 rtx mem;
53800dbe 830
f7c44134 831 if (setjmp_alias_set == -1)
832 setjmp_alias_set = new_alias_set ();
833
85d654dd 834 buf_addr = convert_memory_address (Pmode, buf_addr);
53800dbe 835
37ae8504 836 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
53800dbe 837
6b7f6858 838 /* We store the frame pointer and the address of receiver_label in
839 the buffer and use the rest of it for the stack save area, which
840 is machine-dependent. */
53800dbe 841
f7c44134 842 mem = gen_rtx_MEM (Pmode, buf_addr);
ab6ab77e 843 set_mem_alias_set (mem, setjmp_alias_set);
e3e026e8 844 emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
f7c44134 845
846 mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
ab6ab77e 847 set_mem_alias_set (mem, setjmp_alias_set);
f7c44134 848
849 emit_move_insn (validize_mem (mem),
6b7f6858 850 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
53800dbe 851
852 stack_save = gen_rtx_MEM (sa_mode,
853 plus_constant (buf_addr,
854 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 855 set_mem_alias_set (stack_save, setjmp_alias_set);
e9c97615 856 emit_stack_save (SAVE_NONLOCAL, &stack_save);
53800dbe 857
858 /* If there is further processing to do, do it. */
859#ifdef HAVE_builtin_setjmp_setup
860 if (HAVE_builtin_setjmp_setup)
861 emit_insn (gen_builtin_setjmp_setup (buf_addr));
862#endif
863
29f09705 864 /* We have a nonlocal label. */
18d50ae6 865 cfun->has_nonlocal_label = 1;
6b7f6858 866}
53800dbe 867
2c8a1497 868/* Construct the trailing part of a __builtin_setjmp call. This is
869 also called directly by the SJLJ exception handling code. */
6b7f6858 870
871void
aecda0d6 872expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
6b7f6858 873{
82c7907c 874 rtx chain;
875
53800dbe 876 /* Clobber the FP when we get here, so we have to make sure it's
877 marked as used by this function. */
18b42941 878 emit_use (hard_frame_pointer_rtx);
53800dbe 879
880 /* Mark the static chain as clobbered here so life information
881 doesn't get messed up for it. */
82c7907c 882 chain = targetm.calls.static_chain (current_function_decl, true);
883 if (chain && REG_P (chain))
884 emit_clobber (chain);
53800dbe 885
886 /* Now put in the code to restore the frame pointer, and argument
491e04ef 887 pointer, if needed. */
53800dbe 888#ifdef HAVE_nonlocal_goto
889 if (! HAVE_nonlocal_goto)
890#endif
5a1c3f40 891 {
892 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
893 /* This might change the hard frame pointer in ways that aren't
894 apparent to early optimization passes, so force a clobber. */
18b42941 895 emit_clobber (hard_frame_pointer_rtx);
5a1c3f40 896 }
53800dbe 897
5ae82d58 898#if !HARD_FRAME_POINTER_IS_ARG_POINTER
53800dbe 899 if (fixed_regs[ARG_POINTER_REGNUM])
900 {
901#ifdef ELIMINABLE_REGS
902 size_t i;
e99c3a1d 903 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
53800dbe 904
3098b2d3 905 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
53800dbe 906 if (elim_regs[i].from == ARG_POINTER_REGNUM
907 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
908 break;
909
3098b2d3 910 if (i == ARRAY_SIZE (elim_regs))
53800dbe 911#endif
912 {
913 /* Now restore our arg pointer from the address at which it
05927e40 914 was saved in our stack frame. */
27a7a23a 915 emit_move_insn (crtl->args.internal_arg_pointer,
b079a207 916 copy_to_reg (get_arg_pointer_save_area ()));
53800dbe 917 }
918 }
919#endif
920
921#ifdef HAVE_builtin_setjmp_receiver
922 if (HAVE_builtin_setjmp_receiver)
6b7f6858 923 emit_insn (gen_builtin_setjmp_receiver (receiver_label));
53800dbe 924 else
925#endif
926#ifdef HAVE_nonlocal_goto_receiver
927 if (HAVE_nonlocal_goto_receiver)
928 emit_insn (gen_nonlocal_goto_receiver ());
929 else
930#endif
6b7f6858 931 { /* Nothing */ }
57f6bb94 932
3072d30e 933 /* We must not allow the code we just generated to be reordered by
934 scheduling. Specifically, the update of the frame pointer must
935 happen immediately, not later. */
936 emit_insn (gen_blockage ());
6b7f6858 937}
53800dbe 938
53800dbe 939/* __builtin_longjmp is passed a pointer to an array of five words (not
940 all will be used on all machines). It operates similarly to the C
941 library function of the same name, but is more efficient. Much of
2c8a1497 942 the code below is copied from the handling of non-local gotos. */
53800dbe 943
c626df3d 944static void
aecda0d6 945expand_builtin_longjmp (rtx buf_addr, rtx value)
53800dbe 946{
4712c7d6 947 rtx fp, lab, stack, insn, last;
53800dbe 948 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
949
48e1416a 950 /* DRAP is needed for stack realign if longjmp is expanded to current
27a7a23a 951 function */
952 if (SUPPORTS_STACK_ALIGNMENT)
953 crtl->need_drap = true;
954
f7c44134 955 if (setjmp_alias_set == -1)
956 setjmp_alias_set = new_alias_set ();
957
85d654dd 958 buf_addr = convert_memory_address (Pmode, buf_addr);
479e4d5e 959
53800dbe 960 buf_addr = force_reg (Pmode, buf_addr);
961
82c7907c 962 /* We require that the user must pass a second argument of 1, because
963 that is what builtin_setjmp will return. */
64db345d 964 gcc_assert (value == const1_rtx);
53800dbe 965
4712c7d6 966 last = get_last_insn ();
53800dbe 967#ifdef HAVE_builtin_longjmp
968 if (HAVE_builtin_longjmp)
969 emit_insn (gen_builtin_longjmp (buf_addr));
970 else
971#endif
972 {
973 fp = gen_rtx_MEM (Pmode, buf_addr);
974 lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
975 GET_MODE_SIZE (Pmode)));
976
977 stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
978 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 979 set_mem_alias_set (fp, setjmp_alias_set);
980 set_mem_alias_set (lab, setjmp_alias_set);
981 set_mem_alias_set (stack, setjmp_alias_set);
53800dbe 982
983 /* Pick up FP, label, and SP from the block and jump. This code is
984 from expand_goto in stmt.c; see there for detailed comments. */
03fd9d2c 985#ifdef HAVE_nonlocal_goto
53800dbe 986 if (HAVE_nonlocal_goto)
987 /* We have to pass a value to the nonlocal_goto pattern that will
988 get copied into the static_chain pointer, but it does not matter
989 what that value is, because builtin_setjmp does not use it. */
28d202a8 990 emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
53800dbe 991 else
992#endif
993 {
994 lab = copy_to_reg (lab);
995
18b42941 996 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
997 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
2a871ad1 998
53800dbe 999 emit_move_insn (hard_frame_pointer_rtx, fp);
e9c97615 1000 emit_stack_restore (SAVE_NONLOCAL, stack);
53800dbe 1001
18b42941 1002 emit_use (hard_frame_pointer_rtx);
1003 emit_use (stack_pointer_rtx);
53800dbe 1004 emit_indirect_jump (lab);
1005 }
1006 }
615166bb 1007
1008 /* Search backwards and mark the jump insn as a non-local goto.
1009 Note that this precludes the use of __builtin_longjmp to a
1010 __builtin_setjmp target in the same function. However, we've
1011 already cautioned the user that these functions are for
1012 internal exception handling use only. */
449c0509 1013 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
1014 {
64db345d 1015 gcc_assert (insn != last);
7d3f6cc7 1016
6d7dc5b9 1017 if (JUMP_P (insn))
449c0509 1018 {
a1ddb869 1019 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
449c0509 1020 break;
1021 }
6d7dc5b9 1022 else if (CALL_P (insn))
9342ee68 1023 break;
449c0509 1024 }
53800dbe 1025}
1026
4ee9c684 1027/* Expand a call to __builtin_nonlocal_goto. We're passed the target label
1028 and the address of the save area. */
1029
1030static rtx
c2f47e15 1031expand_builtin_nonlocal_goto (tree exp)
4ee9c684 1032{
1033 tree t_label, t_save_area;
1034 rtx r_label, r_save_area, r_fp, r_sp, insn;
1035
c2f47e15 1036 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4ee9c684 1037 return NULL_RTX;
1038
c2f47e15 1039 t_label = CALL_EXPR_ARG (exp, 0);
1040 t_save_area = CALL_EXPR_ARG (exp, 1);
4ee9c684 1041
8ec3c5c2 1042 r_label = expand_normal (t_label);
3dce56cc 1043 r_label = convert_memory_address (Pmode, r_label);
8ec3c5c2 1044 r_save_area = expand_normal (t_save_area);
3dce56cc 1045 r_save_area = convert_memory_address (Pmode, r_save_area);
d1ff492e 1046 /* Copy the address of the save location to a register just in case it was
1047 based on the frame pointer. */
51adbc8a 1048 r_save_area = copy_to_reg (r_save_area);
4ee9c684 1049 r_fp = gen_rtx_MEM (Pmode, r_save_area);
1050 r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
1051 plus_constant (r_save_area, GET_MODE_SIZE (Pmode)));
1052
18d50ae6 1053 crtl->has_nonlocal_goto = 1;
4ee9c684 1054
03fd9d2c 1055#ifdef HAVE_nonlocal_goto
4ee9c684 1056 /* ??? We no longer need to pass the static chain value, afaik. */
1057 if (HAVE_nonlocal_goto)
1058 emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
1059 else
1060#endif
1061 {
1062 r_label = copy_to_reg (r_label);
1063
18b42941 1064 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
1065 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
491e04ef 1066
d1ff492e 1067 /* Restore frame pointer for containing function. */
4ee9c684 1068 emit_move_insn (hard_frame_pointer_rtx, r_fp);
e9c97615 1069 emit_stack_restore (SAVE_NONLOCAL, r_sp);
491e04ef 1070
4ee9c684 1071 /* USE of hard_frame_pointer_rtx added for consistency;
1072 not clear if really needed. */
18b42941 1073 emit_use (hard_frame_pointer_rtx);
1074 emit_use (stack_pointer_rtx);
ad0d0af8 1075
1076 /* If the architecture is using a GP register, we must
1077 conservatively assume that the target function makes use of it.
1078 The prologue of functions with nonlocal gotos must therefore
1079 initialize the GP register to the appropriate value, and we
1080 must then make sure that this value is live at the point
1081 of the jump. (Note that this doesn't necessarily apply
1082 to targets with a nonlocal_goto pattern; they are free
1083 to implement it in their own way. Note also that this is
1084 a no-op if the GP register is a global invariant.) */
1085 if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
1086 && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
18b42941 1087 emit_use (pic_offset_table_rtx);
ad0d0af8 1088
4ee9c684 1089 emit_indirect_jump (r_label);
1090 }
491e04ef 1091
4ee9c684 1092 /* Search backwards to the jump insn and mark it as a
1093 non-local goto. */
1094 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
1095 {
6d7dc5b9 1096 if (JUMP_P (insn))
4ee9c684 1097 {
a1ddb869 1098 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
4ee9c684 1099 break;
1100 }
6d7dc5b9 1101 else if (CALL_P (insn))
4ee9c684 1102 break;
1103 }
1104
1105 return const0_rtx;
1106}
1107
843d08a9 1108/* __builtin_update_setjmp_buf is passed a pointer to an array of five words
1109 (not all will be used on all machines) that was passed to __builtin_setjmp.
1110 It updates the stack pointer in that block to correspond to the current
1111 stack pointer. */
1112
1113static void
1114expand_builtin_update_setjmp_buf (rtx buf_addr)
1115{
d1ff492e 1116 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
1117 rtx stack_save
843d08a9 1118 = gen_rtx_MEM (sa_mode,
1119 memory_address
1120 (sa_mode,
1121 plus_constant (buf_addr, 2 * GET_MODE_SIZE (Pmode))));
1122
e9c97615 1123 emit_stack_save (SAVE_NONLOCAL, &stack_save);
843d08a9 1124}
1125
5e3608d8 1126/* Expand a call to __builtin_prefetch. For a target that does not support
1127 data prefetch, evaluate the memory address argument in case it has side
1128 effects. */
1129
1130static void
c2f47e15 1131expand_builtin_prefetch (tree exp)
5e3608d8 1132{
1133 tree arg0, arg1, arg2;
c2f47e15 1134 int nargs;
5e3608d8 1135 rtx op0, op1, op2;
1136
c2f47e15 1137 if (!validate_arglist (exp, POINTER_TYPE, 0))
26a5cadb 1138 return;
1139
c2f47e15 1140 arg0 = CALL_EXPR_ARG (exp, 0);
1141
26a5cadb 1142 /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
1143 zero (read) and argument 2 (locality) defaults to 3 (high degree of
1144 locality). */
c2f47e15 1145 nargs = call_expr_nargs (exp);
1146 if (nargs > 1)
1147 arg1 = CALL_EXPR_ARG (exp, 1);
26a5cadb 1148 else
c2f47e15 1149 arg1 = integer_zero_node;
1150 if (nargs > 2)
1151 arg2 = CALL_EXPR_ARG (exp, 2);
1152 else
2512209b 1153 arg2 = integer_three_node;
5e3608d8 1154
1155 /* Argument 0 is an address. */
1156 op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
1157
1158 /* Argument 1 (read/write flag) must be a compile-time constant int. */
1159 if (TREE_CODE (arg1) != INTEGER_CST)
1160 {
07e3a3d2 1161 error ("second argument to %<__builtin_prefetch%> must be a constant");
9342ee68 1162 arg1 = integer_zero_node;
5e3608d8 1163 }
8ec3c5c2 1164 op1 = expand_normal (arg1);
5e3608d8 1165 /* Argument 1 must be either zero or one. */
1166 if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
1167 {
c3ceba8e 1168 warning (0, "invalid second argument to %<__builtin_prefetch%>;"
07e3a3d2 1169 " using zero");
5e3608d8 1170 op1 = const0_rtx;
1171 }
1172
1173 /* Argument 2 (locality) must be a compile-time constant int. */
1174 if (TREE_CODE (arg2) != INTEGER_CST)
1175 {
07e3a3d2 1176 error ("third argument to %<__builtin_prefetch%> must be a constant");
5e3608d8 1177 arg2 = integer_zero_node;
1178 }
8ec3c5c2 1179 op2 = expand_normal (arg2);
5e3608d8 1180 /* Argument 2 must be 0, 1, 2, or 3. */
1181 if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
1182 {
c3ceba8e 1183 warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
5e3608d8 1184 op2 = const0_rtx;
1185 }
1186
1187#ifdef HAVE_prefetch
1188 if (HAVE_prefetch)
1189 {
8786db1e 1190 struct expand_operand ops[3];
1191
1192 create_address_operand (&ops[0], op0);
1193 create_integer_operand (&ops[1], INTVAL (op1));
1194 create_integer_operand (&ops[2], INTVAL (op2));
1195 if (maybe_expand_insn (CODE_FOR_prefetch, 3, ops))
1196 return;
5e3608d8 1197 }
5e3608d8 1198#endif
0a534ba7 1199
f0ce3b1f 1200 /* Don't do anything with direct references to volatile memory, but
1201 generate code to handle other side effects. */
e16ceb8e 1202 if (!MEM_P (op0) && side_effects_p (op0))
f0ce3b1f 1203 emit_insn (op0);
5e3608d8 1204}
1205
f7c44134 1206/* Get a MEM rtx for expression EXP which is the address of an operand
d8ae1baa 1207 to be used in a string instruction (cmpstrsi, movmemsi, ..). LEN is
1208 the maximum length of the block of memory that might be accessed or
1209 NULL if unknown. */
f7c44134 1210
53800dbe 1211static rtx
d8ae1baa 1212get_memory_rtx (tree exp, tree len)
53800dbe 1213{
ad0a178f 1214 tree orig_exp = exp;
1215 rtx addr, mem;
1216 HOST_WIDE_INT off;
1217
1218 /* When EXP is not resolved SAVE_EXPR, MEM_ATTRS can be still derived
1219 from its expression, for expr->a.b only <variable>.a.b is recorded. */
1220 if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp))
1221 exp = TREE_OPERAND (exp, 0);
1222
1223 addr = expand_expr (orig_exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
1224 mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
2a631e19 1225
f7c44134 1226 /* Get an expression we can use to find the attributes to assign to MEM.
1227 If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
1228 we can. First remove any nops. */
72dd6141 1229 while (CONVERT_EXPR_P (exp)
f7c44134 1230 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
1231 exp = TREE_OPERAND (exp, 0);
1232
ad0a178f 1233 off = 0;
1234 if (TREE_CODE (exp) == POINTER_PLUS_EXPR
1235 && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
1236 && host_integerp (TREE_OPERAND (exp, 1), 0)
1237 && (off = tree_low_cst (TREE_OPERAND (exp, 1), 0)) > 0)
1238 exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
1239 else if (TREE_CODE (exp) == ADDR_EXPR)
a1a25d19 1240 exp = TREE_OPERAND (exp, 0);
f7c44134 1241 else if (POINTER_TYPE_P (TREE_TYPE (exp)))
a1a25d19 1242 exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
1243 else
1244 exp = NULL;
1245
1246 /* Honor attributes derived from exp, except for the alias set
1247 (as builtin stringops may alias with anything) and the size
1248 (as stringops may access multiple array elements). */
1249 if (exp)
eec8e941 1250 {
a1a25d19 1251 set_mem_attributes (mem, exp, 0);
d8ae1baa 1252
ad0a178f 1253 if (off)
1254 mem = adjust_automodify_address_nv (mem, BLKmode, NULL, off);
1255
d8ae1baa 1256 /* Allow the string and memory builtins to overflow from one
1257 field into another, see http://gcc.gnu.org/PR23561.
1258 Thus avoid COMPONENT_REFs in MEM_EXPR unless we know the whole
1259 memory accessed by the string or memory builtin will fit
1260 within the field. */
1261 if (MEM_EXPR (mem) && TREE_CODE (MEM_EXPR (mem)) == COMPONENT_REF)
1262 {
1263 tree mem_expr = MEM_EXPR (mem);
1264 HOST_WIDE_INT offset = -1, length = -1;
1265 tree inner = exp;
1266
1267 while (TREE_CODE (inner) == ARRAY_REF
72dd6141 1268 || CONVERT_EXPR_P (inner)
d8ae1baa 1269 || TREE_CODE (inner) == VIEW_CONVERT_EXPR
1270 || TREE_CODE (inner) == SAVE_EXPR)
1271 inner = TREE_OPERAND (inner, 0);
1272
1273 gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
1274
da443c27 1275 if (MEM_OFFSET_KNOWN_P (mem))
1276 offset = MEM_OFFSET (mem);
d8ae1baa 1277
1278 if (offset >= 0 && len && host_integerp (len, 0))
1279 length = tree_low_cst (len, 0);
1280
1281 while (TREE_CODE (inner) == COMPONENT_REF)
1282 {
1283 tree field = TREE_OPERAND (inner, 1);
d8ae1baa 1284 gcc_assert (TREE_CODE (mem_expr) == COMPONENT_REF);
1285 gcc_assert (field == TREE_OPERAND (mem_expr, 1));
1286
6933ebec 1287 /* Bitfields are generally not byte-addressable. */
1288 gcc_assert (!DECL_BIT_FIELD (field)
1289 || ((tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
1290 % BITS_PER_UNIT) == 0
1291 && host_integerp (DECL_SIZE (field), 0)
1292 && (TREE_INT_CST_LOW (DECL_SIZE (field))
1293 % BITS_PER_UNIT) == 0));
1294
b2f0b2a3 1295 /* If we can prove that the memory starting at XEXP (mem, 0) and
1296 ending at XEXP (mem, 0) + LENGTH will fit into this field, we
1297 can keep the COMPONENT_REF in MEM_EXPR. But be careful with
1298 fields without DECL_SIZE_UNIT like flexible array members. */
d8ae1baa 1299 if (length >= 0
b2f0b2a3 1300 && DECL_SIZE_UNIT (field)
6933ebec 1301 && host_integerp (DECL_SIZE_UNIT (field), 0))
d8ae1baa 1302 {
1303 HOST_WIDE_INT size
6933ebec 1304 = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
d8ae1baa 1305 if (offset <= size
1306 && length <= size
1307 && offset + length <= size)
1308 break;
1309 }
1310
1311 if (offset >= 0
1312 && host_integerp (DECL_FIELD_OFFSET (field), 0))
6933ebec 1313 offset += TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
d8ae1baa 1314 + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
1315 / BITS_PER_UNIT;
1316 else
1317 {
1318 offset = -1;
1319 length = -1;
1320 }
1321
1322 mem_expr = TREE_OPERAND (mem_expr, 0);
1323 inner = TREE_OPERAND (inner, 0);
d8ae1baa 1324 }
1325
1326 if (mem_expr == NULL)
1327 offset = -1;
1328 if (mem_expr != MEM_EXPR (mem))
1329 {
1330 set_mem_expr (mem, mem_expr);
da443c27 1331 if (offset >= 0)
1332 set_mem_offset (mem, offset);
1333 else
1334 clear_mem_offset (mem);
d8ae1baa 1335 }
1336 }
eec8e941 1337 set_mem_alias_set (mem, 0);
5b2a69fa 1338 clear_mem_size (mem);
eec8e941 1339 }
53800dbe 1340
53800dbe 1341 return mem;
1342}
1343\f
1344/* Built-in functions to perform an untyped call and return. */
1345
3b9c3a16 1346#define apply_args_mode \
1347 (this_target_builtins->x_apply_args_mode)
1348#define apply_result_mode \
1349 (this_target_builtins->x_apply_result_mode)
53800dbe 1350
53800dbe 1351/* Return the size required for the block returned by __builtin_apply_args,
1352 and initialize apply_args_mode. */
1353
1354static int
aecda0d6 1355apply_args_size (void)
53800dbe 1356{
1357 static int size = -1;
58e9ce8f 1358 int align;
1359 unsigned int regno;
53800dbe 1360 enum machine_mode mode;
1361
1362 /* The values computed by this function never change. */
1363 if (size < 0)
1364 {
1365 /* The first value is the incoming arg-pointer. */
1366 size = GET_MODE_SIZE (Pmode);
1367
1368 /* The second value is the structure value address unless this is
1369 passed as an "invisible" first argument. */
6812c89e 1370 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1371 size += GET_MODE_SIZE (Pmode);
1372
1373 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1374 if (FUNCTION_ARG_REGNO_P (regno))
1375 {
4bac51c9 1376 mode = targetm.calls.get_raw_arg_mode (regno);
0862b7e9 1377
64db345d 1378 gcc_assert (mode != VOIDmode);
53800dbe 1379
1380 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1381 if (size % align != 0)
1382 size = CEIL (size, align) * align;
53800dbe 1383 size += GET_MODE_SIZE (mode);
1384 apply_args_mode[regno] = mode;
1385 }
1386 else
1387 {
1388 apply_args_mode[regno] = VOIDmode;
53800dbe 1389 }
1390 }
1391 return size;
1392}
1393
1394/* Return the size required for the block returned by __builtin_apply,
1395 and initialize apply_result_mode. */
1396
1397static int
aecda0d6 1398apply_result_size (void)
53800dbe 1399{
1400 static int size = -1;
1401 int align, regno;
1402 enum machine_mode mode;
1403
1404 /* The values computed by this function never change. */
1405 if (size < 0)
1406 {
1407 size = 0;
1408
1409 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
e1ce1485 1410 if (targetm.calls.function_value_regno_p (regno))
53800dbe 1411 {
4bac51c9 1412 mode = targetm.calls.get_raw_result_mode (regno);
0862b7e9 1413
64db345d 1414 gcc_assert (mode != VOIDmode);
53800dbe 1415
1416 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1417 if (size % align != 0)
1418 size = CEIL (size, align) * align;
1419 size += GET_MODE_SIZE (mode);
1420 apply_result_mode[regno] = mode;
1421 }
1422 else
1423 apply_result_mode[regno] = VOIDmode;
1424
1425 /* Allow targets that use untyped_call and untyped_return to override
1426 the size so that machine-specific information can be stored here. */
1427#ifdef APPLY_RESULT_SIZE
1428 size = APPLY_RESULT_SIZE;
1429#endif
1430 }
1431 return size;
1432}
1433
1434#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1435/* Create a vector describing the result block RESULT. If SAVEP is true,
1436 the result block is used to save the values; otherwise it is used to
1437 restore the values. */
1438
1439static rtx
aecda0d6 1440result_vector (int savep, rtx result)
53800dbe 1441{
1442 int regno, size, align, nelts;
1443 enum machine_mode mode;
1444 rtx reg, mem;
364c0c59 1445 rtx *savevec = XALLOCAVEC (rtx, FIRST_PSEUDO_REGISTER);
bf8e3599 1446
53800dbe 1447 size = nelts = 0;
1448 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1449 if ((mode = apply_result_mode[regno]) != VOIDmode)
1450 {
1451 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1452 if (size % align != 0)
1453 size = CEIL (size, align) * align;
1454 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
e513d163 1455 mem = adjust_address (result, mode, size);
53800dbe 1456 savevec[nelts++] = (savep
1457 ? gen_rtx_SET (VOIDmode, mem, reg)
1458 : gen_rtx_SET (VOIDmode, reg, mem));
1459 size += GET_MODE_SIZE (mode);
1460 }
1461 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1462}
1463#endif /* HAVE_untyped_call or HAVE_untyped_return */
1464
1465/* Save the state required to perform an untyped call with the same
1466 arguments as were passed to the current function. */
1467
1468static rtx
aecda0d6 1469expand_builtin_apply_args_1 (void)
53800dbe 1470{
1c7e61a7 1471 rtx registers, tem;
53800dbe 1472 int size, align, regno;
1473 enum machine_mode mode;
6812c89e 1474 rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
53800dbe 1475
1476 /* Create a block where the arg-pointer, structure value address,
1477 and argument registers can be saved. */
1478 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1479
1480 /* Walk past the arg-pointer and structure value address. */
1481 size = GET_MODE_SIZE (Pmode);
6812c89e 1482 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1483 size += GET_MODE_SIZE (Pmode);
1484
1485 /* Save each register used in calling a function to the block. */
1486 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1487 if ((mode = apply_args_mode[regno]) != VOIDmode)
1488 {
53800dbe 1489 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1490 if (size % align != 0)
1491 size = CEIL (size, align) * align;
1492
1493 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1494
e513d163 1495 emit_move_insn (adjust_address (registers, mode, size), tem);
53800dbe 1496 size += GET_MODE_SIZE (mode);
1497 }
1498
1499 /* Save the arg pointer to the block. */
27a7a23a 1500 tem = copy_to_reg (crtl->args.internal_arg_pointer);
f083a92b 1501#ifdef STACK_GROWS_DOWNWARD
1c7e61a7 1502 /* We need the pointer as the caller actually passed them to us, not
9d4b544c 1503 as we might have pretended they were passed. Make sure it's a valid
1504 operand, as emit_move_insn isn't expected to handle a PLUS. */
1505 tem
abe32cce 1506 = force_operand (plus_constant (tem, crtl->args.pretend_args_size),
9d4b544c 1507 NULL_RTX);
1c7e61a7 1508#endif
1509 emit_move_insn (adjust_address (registers, Pmode, 0), tem);
0862b7e9 1510
53800dbe 1511 size = GET_MODE_SIZE (Pmode);
1512
1513 /* Save the structure value address unless this is passed as an
1514 "invisible" first argument. */
45550790 1515 if (struct_incoming_value)
53800dbe 1516 {
e513d163 1517 emit_move_insn (adjust_address (registers, Pmode, size),
45550790 1518 copy_to_reg (struct_incoming_value));
53800dbe 1519 size += GET_MODE_SIZE (Pmode);
1520 }
1521
1522 /* Return the address of the block. */
1523 return copy_addr_to_reg (XEXP (registers, 0));
1524}
1525
1526/* __builtin_apply_args returns block of memory allocated on
1527 the stack into which is stored the arg pointer, structure
1528 value address, static chain, and all the registers that might
1529 possibly be used in performing a function call. The code is
1530 moved to the start of the function so the incoming values are
1531 saved. */
27d0c333 1532
53800dbe 1533static rtx
aecda0d6 1534expand_builtin_apply_args (void)
53800dbe 1535{
1536 /* Don't do __builtin_apply_args more than once in a function.
1537 Save the result of the first call and reuse it. */
1538 if (apply_args_value != 0)
1539 return apply_args_value;
1540 {
1541 /* When this function is called, it means that registers must be
1542 saved on entry to this function. So we migrate the
1543 call to the first insn of this function. */
1544 rtx temp;
1545 rtx seq;
1546
1547 start_sequence ();
1548 temp = expand_builtin_apply_args_1 ();
1549 seq = get_insns ();
1550 end_sequence ();
1551
1552 apply_args_value = temp;
1553
31d3e01c 1554 /* Put the insns after the NOTE that starts the function.
1555 If this is inside a start_sequence, make the outer-level insn
53800dbe 1556 chain current, so the code is placed at the start of the
0ef1a651 1557 function. If internal_arg_pointer is a non-virtual pseudo,
1558 it needs to be placed after the function that initializes
1559 that pseudo. */
53800dbe 1560 push_topmost_sequence ();
0ef1a651 1561 if (REG_P (crtl->args.internal_arg_pointer)
1562 && REGNO (crtl->args.internal_arg_pointer) > LAST_VIRTUAL_REGISTER)
1563 emit_insn_before (seq, parm_birth_insn);
1564 else
1565 emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
53800dbe 1566 pop_topmost_sequence ();
1567 return temp;
1568 }
1569}
1570
1571/* Perform an untyped call and save the state required to perform an
1572 untyped return of whatever value was returned by the given function. */
1573
1574static rtx
aecda0d6 1575expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
53800dbe 1576{
1577 int size, align, regno;
1578 enum machine_mode mode;
2a631e19 1579 rtx incoming_args, result, reg, dest, src, call_insn;
53800dbe 1580 rtx old_stack_level = 0;
1581 rtx call_fusage = 0;
6812c89e 1582 rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
53800dbe 1583
85d654dd 1584 arguments = convert_memory_address (Pmode, arguments);
726ec87c 1585
53800dbe 1586 /* Create a block where the return registers can be saved. */
1587 result = assign_stack_local (BLKmode, apply_result_size (), -1);
1588
53800dbe 1589 /* Fetch the arg pointer from the ARGUMENTS block. */
1590 incoming_args = gen_reg_rtx (Pmode);
726ec87c 1591 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
53800dbe 1592#ifndef STACK_GROWS_DOWNWARD
ad99e708 1593 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1594 incoming_args, 0, OPTAB_LIB_WIDEN);
53800dbe 1595#endif
1596
04a46d40 1597 /* Push a new argument block and copy the arguments. Do not allow
1598 the (potential) memcpy call below to interfere with our stack
1599 manipulations. */
53800dbe 1600 do_pending_stack_adjust ();
04a46d40 1601 NO_DEFER_POP;
53800dbe 1602
2358393e 1603 /* Save the stack with nonlocal if available. */
53800dbe 1604#ifdef HAVE_save_stack_nonlocal
1605 if (HAVE_save_stack_nonlocal)
e9c97615 1606 emit_stack_save (SAVE_NONLOCAL, &old_stack_level);
53800dbe 1607 else
1608#endif
e9c97615 1609 emit_stack_save (SAVE_BLOCK, &old_stack_level);
53800dbe 1610
59647703 1611 /* Allocate a block of memory onto the stack and copy the memory
990495a7 1612 arguments to the outgoing arguments address. We can pass TRUE
1613 as the 4th argument because we just saved the stack pointer
1614 and will restore it right after the call. */
5be42b39 1615 allocate_dynamic_stack_space (argsize, 0, BIGGEST_ALIGNMENT, true);
27a7a23a 1616
1617 /* Set DRAP flag to true, even though allocate_dynamic_stack_space
1618 may have already set current_function_calls_alloca to true.
1619 current_function_calls_alloca won't be set if argsize is zero,
1620 so we have to guarantee need_drap is true here. */
1621 if (SUPPORTS_STACK_ALIGNMENT)
1622 crtl->need_drap = true;
1623
59647703 1624 dest = virtual_outgoing_args_rtx;
1625#ifndef STACK_GROWS_DOWNWARD
971ba038 1626 if (CONST_INT_P (argsize))
59647703 1627 dest = plus_constant (dest, -INTVAL (argsize));
1628 else
1629 dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1630#endif
2a631e19 1631 dest = gen_rtx_MEM (BLKmode, dest);
1632 set_mem_align (dest, PARM_BOUNDARY);
1633 src = gen_rtx_MEM (BLKmode, incoming_args);
1634 set_mem_align (src, PARM_BOUNDARY);
0378dbdc 1635 emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
53800dbe 1636
1637 /* Refer to the argument block. */
1638 apply_args_size ();
1639 arguments = gen_rtx_MEM (BLKmode, arguments);
2a631e19 1640 set_mem_align (arguments, PARM_BOUNDARY);
53800dbe 1641
1642 /* Walk past the arg-pointer and structure value address. */
1643 size = GET_MODE_SIZE (Pmode);
45550790 1644 if (struct_value)
53800dbe 1645 size += GET_MODE_SIZE (Pmode);
1646
1647 /* Restore each of the registers previously saved. Make USE insns
1648 for each of these registers for use in making the call. */
1649 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1650 if ((mode = apply_args_mode[regno]) != VOIDmode)
1651 {
1652 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1653 if (size % align != 0)
1654 size = CEIL (size, align) * align;
1655 reg = gen_rtx_REG (mode, regno);
e513d163 1656 emit_move_insn (reg, adjust_address (arguments, mode, size));
53800dbe 1657 use_reg (&call_fusage, reg);
1658 size += GET_MODE_SIZE (mode);
1659 }
1660
1661 /* Restore the structure value address unless this is passed as an
1662 "invisible" first argument. */
1663 size = GET_MODE_SIZE (Pmode);
45550790 1664 if (struct_value)
53800dbe 1665 {
1666 rtx value = gen_reg_rtx (Pmode);
e513d163 1667 emit_move_insn (value, adjust_address (arguments, Pmode, size));
45550790 1668 emit_move_insn (struct_value, value);
8ad4c111 1669 if (REG_P (struct_value))
45550790 1670 use_reg (&call_fusage, struct_value);
53800dbe 1671 size += GET_MODE_SIZE (Pmode);
1672 }
1673
1674 /* All arguments and registers used for the call are set up by now! */
82c7907c 1675 function = prepare_call_address (NULL, function, NULL, &call_fusage, 0, 0);
53800dbe 1676
1677 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1678 and we don't want to load it into a register as an optimization,
1679 because prepare_call_address already did it if it should be done. */
1680 if (GET_CODE (function) != SYMBOL_REF)
1681 function = memory_address (FUNCTION_MODE, function);
1682
1683 /* Generate the actual call instruction and save the return value. */
1684#ifdef HAVE_untyped_call
1685 if (HAVE_untyped_call)
1686 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1687 result, result_vector (1, result)));
1688 else
1689#endif
1690#ifdef HAVE_call_value
1691 if (HAVE_call_value)
1692 {
1693 rtx valreg = 0;
1694
1695 /* Locate the unique return register. It is not possible to
1696 express a call that sets more than one return register using
1697 call_value; use untyped_call for that. In fact, untyped_call
1698 only needs to save the return registers in the given block. */
1699 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1700 if ((mode = apply_result_mode[regno]) != VOIDmode)
1701 {
64db345d 1702 gcc_assert (!valreg); /* HAVE_untyped_call required. */
7d3f6cc7 1703
53800dbe 1704 valreg = gen_rtx_REG (mode, regno);
1705 }
1706
2ed6c343 1707 emit_call_insn (GEN_CALL_VALUE (valreg,
53800dbe 1708 gen_rtx_MEM (FUNCTION_MODE, function),
1709 const0_rtx, NULL_RTX, const0_rtx));
1710
e513d163 1711 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
53800dbe 1712 }
1713 else
1714#endif
64db345d 1715 gcc_unreachable ();
53800dbe 1716
d5f9786f 1717 /* Find the CALL insn we just emitted, and attach the register usage
1718 information. */
1719 call_insn = last_call_insn ();
1720 add_function_usage_to (call_insn, call_fusage);
53800dbe 1721
1722 /* Restore the stack. */
1723#ifdef HAVE_save_stack_nonlocal
1724 if (HAVE_save_stack_nonlocal)
e9c97615 1725 emit_stack_restore (SAVE_NONLOCAL, old_stack_level);
53800dbe 1726 else
1727#endif
e9c97615 1728 emit_stack_restore (SAVE_BLOCK, old_stack_level);
4bb7c660 1729 fixup_args_size_notes (call_insn, get_last_insn(), 0);
53800dbe 1730
04a46d40 1731 OK_DEFER_POP;
1732
53800dbe 1733 /* Return the address of the result block. */
85d654dd 1734 result = copy_addr_to_reg (XEXP (result, 0));
1735 return convert_memory_address (ptr_mode, result);
53800dbe 1736}
1737
1738/* Perform an untyped return. */
1739
1740static void
aecda0d6 1741expand_builtin_return (rtx result)
53800dbe 1742{
1743 int size, align, regno;
1744 enum machine_mode mode;
1745 rtx reg;
1746 rtx call_fusage = 0;
1747
85d654dd 1748 result = convert_memory_address (Pmode, result);
726ec87c 1749
53800dbe 1750 apply_result_size ();
1751 result = gen_rtx_MEM (BLKmode, result);
1752
1753#ifdef HAVE_untyped_return
1754 if (HAVE_untyped_return)
1755 {
1756 emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1757 emit_barrier ();
1758 return;
1759 }
1760#endif
1761
1762 /* Restore the return value and note that each value is used. */
1763 size = 0;
1764 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1765 if ((mode = apply_result_mode[regno]) != VOIDmode)
1766 {
1767 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1768 if (size % align != 0)
1769 size = CEIL (size, align) * align;
1770 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
e513d163 1771 emit_move_insn (reg, adjust_address (result, mode, size));
53800dbe 1772
1773 push_to_sequence (call_fusage);
18b42941 1774 emit_use (reg);
53800dbe 1775 call_fusage = get_insns ();
1776 end_sequence ();
1777 size += GET_MODE_SIZE (mode);
1778 }
1779
1780 /* Put the USE insns before the return. */
31d3e01c 1781 emit_insn (call_fusage);
53800dbe 1782
1783 /* Return whatever values was restored by jumping directly to the end
1784 of the function. */
62380d2d 1785 expand_naked_return ();
53800dbe 1786}
1787
539a3a92 1788/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
27d0c333 1789
539a3a92 1790static enum type_class
aecda0d6 1791type_to_class (tree type)
539a3a92 1792{
1793 switch (TREE_CODE (type))
1794 {
1795 case VOID_TYPE: return void_type_class;
1796 case INTEGER_TYPE: return integer_type_class;
539a3a92 1797 case ENUMERAL_TYPE: return enumeral_type_class;
1798 case BOOLEAN_TYPE: return boolean_type_class;
1799 case POINTER_TYPE: return pointer_type_class;
1800 case REFERENCE_TYPE: return reference_type_class;
1801 case OFFSET_TYPE: return offset_type_class;
1802 case REAL_TYPE: return real_type_class;
1803 case COMPLEX_TYPE: return complex_type_class;
1804 case FUNCTION_TYPE: return function_type_class;
1805 case METHOD_TYPE: return method_type_class;
1806 case RECORD_TYPE: return record_type_class;
1807 case UNION_TYPE:
1808 case QUAL_UNION_TYPE: return union_type_class;
1809 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1810 ? string_type_class : array_type_class);
539a3a92 1811 case LANG_TYPE: return lang_type_class;
1812 default: return no_type_class;
1813 }
1814}
bf8e3599 1815
c2f47e15 1816/* Expand a call EXP to __builtin_classify_type. */
27d0c333 1817
53800dbe 1818static rtx
c2f47e15 1819expand_builtin_classify_type (tree exp)
53800dbe 1820{
c2f47e15 1821 if (call_expr_nargs (exp))
1822 return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0))));
53800dbe 1823 return GEN_INT (no_type_class);
1824}
1825
07976da7 1826/* This helper macro, meant to be used in mathfn_built_in below,
1827 determines which among a set of three builtin math functions is
1828 appropriate for a given type mode. The `F' and `L' cases are
1829 automatically generated from the `double' case. */
1830#define CASE_MATHFN(BUILT_IN_MATHFN) \
1831 case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1832 fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1833 fcodel = BUILT_IN_MATHFN##L ; break;
cd2656b0 1834/* Similar to above, but appends _R after any F/L suffix. */
1835#define CASE_MATHFN_REENT(BUILT_IN_MATHFN) \
1836 case BUILT_IN_MATHFN##_R: case BUILT_IN_MATHFN##F_R: case BUILT_IN_MATHFN##L_R: \
1837 fcode = BUILT_IN_MATHFN##_R; fcodef = BUILT_IN_MATHFN##F_R ; \
1838 fcodel = BUILT_IN_MATHFN##L_R ; break;
07976da7 1839
b9a16870 1840/* Return mathematic function equivalent to FN but operating directly on TYPE,
1841 if available. If IMPLICIT is true use the implicit builtin declaration,
1842 otherwise use the explicit declaration. If we can't do the conversion,
1843 return zero. */
c319d56a 1844
1845static tree
b9a16870 1846mathfn_built_in_1 (tree type, enum built_in_function fn, bool implicit_p)
0a68165a 1847{
b9a16870 1848 enum built_in_function fcode, fcodef, fcodel, fcode2;
07976da7 1849
1850 switch (fn)
1851 {
746114e8 1852 CASE_MATHFN (BUILT_IN_ACOS)
1853 CASE_MATHFN (BUILT_IN_ACOSH)
1854 CASE_MATHFN (BUILT_IN_ASIN)
1855 CASE_MATHFN (BUILT_IN_ASINH)
07976da7 1856 CASE_MATHFN (BUILT_IN_ATAN)
746114e8 1857 CASE_MATHFN (BUILT_IN_ATAN2)
1858 CASE_MATHFN (BUILT_IN_ATANH)
1859 CASE_MATHFN (BUILT_IN_CBRT)
07976da7 1860 CASE_MATHFN (BUILT_IN_CEIL)
d735c391 1861 CASE_MATHFN (BUILT_IN_CEXPI)
746114e8 1862 CASE_MATHFN (BUILT_IN_COPYSIGN)
07976da7 1863 CASE_MATHFN (BUILT_IN_COS)
746114e8 1864 CASE_MATHFN (BUILT_IN_COSH)
1865 CASE_MATHFN (BUILT_IN_DREM)
1866 CASE_MATHFN (BUILT_IN_ERF)
1867 CASE_MATHFN (BUILT_IN_ERFC)
07976da7 1868 CASE_MATHFN (BUILT_IN_EXP)
746114e8 1869 CASE_MATHFN (BUILT_IN_EXP10)
1870 CASE_MATHFN (BUILT_IN_EXP2)
1871 CASE_MATHFN (BUILT_IN_EXPM1)
1872 CASE_MATHFN (BUILT_IN_FABS)
1873 CASE_MATHFN (BUILT_IN_FDIM)
07976da7 1874 CASE_MATHFN (BUILT_IN_FLOOR)
746114e8 1875 CASE_MATHFN (BUILT_IN_FMA)
1876 CASE_MATHFN (BUILT_IN_FMAX)
1877 CASE_MATHFN (BUILT_IN_FMIN)
1878 CASE_MATHFN (BUILT_IN_FMOD)
1879 CASE_MATHFN (BUILT_IN_FREXP)
1880 CASE_MATHFN (BUILT_IN_GAMMA)
cd2656b0 1881 CASE_MATHFN_REENT (BUILT_IN_GAMMA) /* GAMMA_R */
746114e8 1882 CASE_MATHFN (BUILT_IN_HUGE_VAL)
1883 CASE_MATHFN (BUILT_IN_HYPOT)
1884 CASE_MATHFN (BUILT_IN_ILOGB)
80ff6494 1885 CASE_MATHFN (BUILT_IN_ICEIL)
1886 CASE_MATHFN (BUILT_IN_IFLOOR)
746114e8 1887 CASE_MATHFN (BUILT_IN_INF)
80ff6494 1888 CASE_MATHFN (BUILT_IN_IRINT)
1889 CASE_MATHFN (BUILT_IN_IROUND)
69b779ea 1890 CASE_MATHFN (BUILT_IN_ISINF)
746114e8 1891 CASE_MATHFN (BUILT_IN_J0)
1892 CASE_MATHFN (BUILT_IN_J1)
1893 CASE_MATHFN (BUILT_IN_JN)
ac148751 1894 CASE_MATHFN (BUILT_IN_LCEIL)
746114e8 1895 CASE_MATHFN (BUILT_IN_LDEXP)
ad52b9b7 1896 CASE_MATHFN (BUILT_IN_LFLOOR)
746114e8 1897 CASE_MATHFN (BUILT_IN_LGAMMA)
cd2656b0 1898 CASE_MATHFN_REENT (BUILT_IN_LGAMMA) /* LGAMMA_R */
ac148751 1899 CASE_MATHFN (BUILT_IN_LLCEIL)
ad52b9b7 1900 CASE_MATHFN (BUILT_IN_LLFLOOR)
746114e8 1901 CASE_MATHFN (BUILT_IN_LLRINT)
1902 CASE_MATHFN (BUILT_IN_LLROUND)
07976da7 1903 CASE_MATHFN (BUILT_IN_LOG)
746114e8 1904 CASE_MATHFN (BUILT_IN_LOG10)
1905 CASE_MATHFN (BUILT_IN_LOG1P)
1906 CASE_MATHFN (BUILT_IN_LOG2)
1907 CASE_MATHFN (BUILT_IN_LOGB)
1908 CASE_MATHFN (BUILT_IN_LRINT)
1909 CASE_MATHFN (BUILT_IN_LROUND)
1910 CASE_MATHFN (BUILT_IN_MODF)
1911 CASE_MATHFN (BUILT_IN_NAN)
1912 CASE_MATHFN (BUILT_IN_NANS)
07976da7 1913 CASE_MATHFN (BUILT_IN_NEARBYINT)
746114e8 1914 CASE_MATHFN (BUILT_IN_NEXTAFTER)
1915 CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1916 CASE_MATHFN (BUILT_IN_POW)
757c219d 1917 CASE_MATHFN (BUILT_IN_POWI)
746114e8 1918 CASE_MATHFN (BUILT_IN_POW10)
1919 CASE_MATHFN (BUILT_IN_REMAINDER)
1920 CASE_MATHFN (BUILT_IN_REMQUO)
1921 CASE_MATHFN (BUILT_IN_RINT)
07976da7 1922 CASE_MATHFN (BUILT_IN_ROUND)
746114e8 1923 CASE_MATHFN (BUILT_IN_SCALB)
1924 CASE_MATHFN (BUILT_IN_SCALBLN)
1925 CASE_MATHFN (BUILT_IN_SCALBN)
c319d56a 1926 CASE_MATHFN (BUILT_IN_SIGNBIT)
746114e8 1927 CASE_MATHFN (BUILT_IN_SIGNIFICAND)
07976da7 1928 CASE_MATHFN (BUILT_IN_SIN)
746114e8 1929 CASE_MATHFN (BUILT_IN_SINCOS)
1930 CASE_MATHFN (BUILT_IN_SINH)
07976da7 1931 CASE_MATHFN (BUILT_IN_SQRT)
1932 CASE_MATHFN (BUILT_IN_TAN)
746114e8 1933 CASE_MATHFN (BUILT_IN_TANH)
1934 CASE_MATHFN (BUILT_IN_TGAMMA)
07976da7 1935 CASE_MATHFN (BUILT_IN_TRUNC)
746114e8 1936 CASE_MATHFN (BUILT_IN_Y0)
1937 CASE_MATHFN (BUILT_IN_Y1)
1938 CASE_MATHFN (BUILT_IN_YN)
07976da7 1939
0a68165a 1940 default:
c2f47e15 1941 return NULL_TREE;
0a68165a 1942 }
07976da7 1943
96b9f485 1944 if (TYPE_MAIN_VARIANT (type) == double_type_node)
b9a16870 1945 fcode2 = fcode;
96b9f485 1946 else if (TYPE_MAIN_VARIANT (type) == float_type_node)
b9a16870 1947 fcode2 = fcodef;
96b9f485 1948 else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
b9a16870 1949 fcode2 = fcodel;
07976da7 1950 else
c2f47e15 1951 return NULL_TREE;
b9a16870 1952
1953 if (implicit_p && !builtin_decl_implicit_p (fcode2))
1954 return NULL_TREE;
1955
1956 return builtin_decl_explicit (fcode2);
0a68165a 1957}
1958
c319d56a 1959/* Like mathfn_built_in_1(), but always use the implicit array. */
1960
1961tree
1962mathfn_built_in (tree type, enum built_in_function fn)
1963{
1964 return mathfn_built_in_1 (type, fn, /*implicit=*/ 1);
1965}
1966
0fd605a5 1967/* If errno must be maintained, expand the RTL to check if the result,
1968 TARGET, of a built-in function call, EXP, is NaN, and if so set
1969 errno to EDOM. */
1970
1971static void
aecda0d6 1972expand_errno_check (tree exp, rtx target)
0fd605a5 1973{
7f05340e 1974 rtx lab = gen_label_rtx ();
0fd605a5 1975
7f05340e 1976 /* Test the result; if it is NaN, set errno=EDOM because
1977 the argument was not in the domain. */
3fcf767f 1978 do_compare_rtx_and_jump (target, target, EQ, 0, GET_MODE (target),
79ab74cc 1979 NULL_RTX, NULL_RTX, lab,
1980 /* The jump is very likely. */
1981 REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1));
0fd605a5 1982
1983#ifdef TARGET_EDOM
7f05340e 1984 /* If this built-in doesn't throw an exception, set errno directly. */
c2f47e15 1985 if (TREE_NOTHROW (TREE_OPERAND (CALL_EXPR_FN (exp), 0)))
7f05340e 1986 {
0fd605a5 1987#ifdef GEN_ERRNO_RTX
7f05340e 1988 rtx errno_rtx = GEN_ERRNO_RTX;
0fd605a5 1989#else
7f05340e 1990 rtx errno_rtx
0fd605a5 1991 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1992#endif
7f05340e 1993 emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
0fd605a5 1994 emit_label (lab);
7f05340e 1995 return;
0fd605a5 1996 }
7f05340e 1997#endif
1998
08491912 1999 /* Make sure the library call isn't expanded as a tail call. */
2000 CALL_EXPR_TAILCALL (exp) = 0;
2001
7f05340e 2002 /* We can't set errno=EDOM directly; let the library call do it.
2003 Pop the arguments right away in case the call gets deleted. */
2004 NO_DEFER_POP;
2005 expand_call (exp, target, 0);
2006 OK_DEFER_POP;
2007 emit_label (lab);
0fd605a5 2008}
2009
6b43bae4 2010/* Expand a call to one of the builtin math functions (sqrt, exp, or log).
c2f47e15 2011 Return NULL_RTX if a normal call should be emitted rather than expanding
2012 the function in-line. EXP is the expression that is a call to the builtin
53800dbe 2013 function; if convenient, the result should be placed in TARGET.
2014 SUBTARGET may be used as the target for computing one of EXP's operands. */
27d0c333 2015
53800dbe 2016static rtx
aecda0d6 2017expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
53800dbe 2018{
bf8e3599 2019 optab builtin_optab;
1e4adcfc 2020 rtx op0, insns;
c6e6ecb1 2021 tree fndecl = get_callee_fndecl (exp);
7f05340e 2022 enum machine_mode mode;
528ee710 2023 bool errno_set = false;
abfea505 2024 tree arg;
53800dbe 2025
c2f47e15 2026 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2027 return NULL_RTX;
53800dbe 2028
c2f47e15 2029 arg = CALL_EXPR_ARG (exp, 0);
53800dbe 2030
2031 switch (DECL_FUNCTION_CODE (fndecl))
2032 {
4f35b1fc 2033 CASE_FLT_FN (BUILT_IN_SQRT):
7f05340e 2034 errno_set = ! tree_expr_nonnegative_p (arg);
2035 builtin_optab = sqrt_optab;
2036 break;
4f35b1fc 2037 CASE_FLT_FN (BUILT_IN_EXP):
528ee710 2038 errno_set = true; builtin_optab = exp_optab; break;
4f35b1fc 2039 CASE_FLT_FN (BUILT_IN_EXP10):
2040 CASE_FLT_FN (BUILT_IN_POW10):
750ef9f5 2041 errno_set = true; builtin_optab = exp10_optab; break;
4f35b1fc 2042 CASE_FLT_FN (BUILT_IN_EXP2):
750ef9f5 2043 errno_set = true; builtin_optab = exp2_optab; break;
4f35b1fc 2044 CASE_FLT_FN (BUILT_IN_EXPM1):
a6b4eed2 2045 errno_set = true; builtin_optab = expm1_optab; break;
4f35b1fc 2046 CASE_FLT_FN (BUILT_IN_LOGB):
4efbc641 2047 errno_set = true; builtin_optab = logb_optab; break;
4f35b1fc 2048 CASE_FLT_FN (BUILT_IN_LOG):
528ee710 2049 errno_set = true; builtin_optab = log_optab; break;
4f35b1fc 2050 CASE_FLT_FN (BUILT_IN_LOG10):
d3cd9bde 2051 errno_set = true; builtin_optab = log10_optab; break;
4f35b1fc 2052 CASE_FLT_FN (BUILT_IN_LOG2):
d3cd9bde 2053 errno_set = true; builtin_optab = log2_optab; break;
4f35b1fc 2054 CASE_FLT_FN (BUILT_IN_LOG1P):
f474cd93 2055 errno_set = true; builtin_optab = log1p_optab; break;
4f35b1fc 2056 CASE_FLT_FN (BUILT_IN_ASIN):
8de2f465 2057 builtin_optab = asin_optab; break;
4f35b1fc 2058 CASE_FLT_FN (BUILT_IN_ACOS):
8de2f465 2059 builtin_optab = acos_optab; break;
4f35b1fc 2060 CASE_FLT_FN (BUILT_IN_TAN):
528ee710 2061 builtin_optab = tan_optab; break;
4f35b1fc 2062 CASE_FLT_FN (BUILT_IN_ATAN):
528ee710 2063 builtin_optab = atan_optab; break;
4f35b1fc 2064 CASE_FLT_FN (BUILT_IN_FLOOR):
528ee710 2065 builtin_optab = floor_optab; break;
4f35b1fc 2066 CASE_FLT_FN (BUILT_IN_CEIL):
528ee710 2067 builtin_optab = ceil_optab; break;
4f35b1fc 2068 CASE_FLT_FN (BUILT_IN_TRUNC):
a7cc195f 2069 builtin_optab = btrunc_optab; break;
4f35b1fc 2070 CASE_FLT_FN (BUILT_IN_ROUND):
528ee710 2071 builtin_optab = round_optab; break;
4f35b1fc 2072 CASE_FLT_FN (BUILT_IN_NEARBYINT):
0ddf4ad9 2073 builtin_optab = nearbyint_optab;
2074 if (flag_trapping_math)
2075 break;
2076 /* Else fallthrough and expand as rint. */
4f35b1fc 2077 CASE_FLT_FN (BUILT_IN_RINT):
aef94a0f 2078 builtin_optab = rint_optab; break;
b3154a1f 2079 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
2080 builtin_optab = significand_optab; break;
42721db0 2081 default:
64db345d 2082 gcc_unreachable ();
53800dbe 2083 }
2084
7f05340e 2085 /* Make a suitable register to place result in. */
2086 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2087
7f05340e 2088 if (! flag_errno_math || ! HONOR_NANS (mode))
2089 errno_set = false;
2090
bd421108 2091 /* Before working hard, check whether the instruction is available. */
f2aca212 2092 if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing
2093 && (!errno_set || !optimize_insn_for_size_p ()))
68e6cb9d 2094 {
bd421108 2095 target = gen_reg_rtx (mode);
7f05340e 2096
bd421108 2097 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2098 need to expand the argument again. This way, we will not perform
2099 side-effects more the once. */
abfea505 2100 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7f05340e 2101
1db6d067 2102 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
7f05340e 2103
bd421108 2104 start_sequence ();
53800dbe 2105
bd421108 2106 /* Compute into TARGET.
2107 Set TARGET to wherever the result comes back. */
2108 target = expand_unop (mode, builtin_optab, op0, target, 0);
2109
2110 if (target != 0)
2111 {
2112 if (errno_set)
2113 expand_errno_check (exp, target);
2114
2115 /* Output the entire sequence. */
2116 insns = get_insns ();
2117 end_sequence ();
2118 emit_insn (insns);
2119 return target;
2120 }
2121
2122 /* If we were unable to expand via the builtin, stop the sequence
2123 (without outputting the insns) and call to the library function
2124 with the stabilized argument list. */
53800dbe 2125 end_sequence ();
53800dbe 2126 }
2127
1e5b92fa 2128 return expand_call (exp, target, target == const0_rtx);
0fd605a5 2129}
2130
2131/* Expand a call to the builtin binary math functions (pow and atan2).
c2f47e15 2132 Return NULL_RTX if a normal call should be emitted rather than expanding the
0fd605a5 2133 function in-line. EXP is the expression that is a call to the builtin
2134 function; if convenient, the result should be placed in TARGET.
2135 SUBTARGET may be used as the target for computing one of EXP's
2136 operands. */
2137
2138static rtx
aecda0d6 2139expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
0fd605a5 2140{
2141 optab builtin_optab;
2142 rtx op0, op1, insns;
4737caf2 2143 int op1_type = REAL_TYPE;
c6e6ecb1 2144 tree fndecl = get_callee_fndecl (exp);
abfea505 2145 tree arg0, arg1;
7f05340e 2146 enum machine_mode mode;
0fd605a5 2147 bool errno_set = true;
0fd605a5 2148
73a954a1 2149 switch (DECL_FUNCTION_CODE (fndecl))
2150 {
2151 CASE_FLT_FN (BUILT_IN_SCALBN):
2152 CASE_FLT_FN (BUILT_IN_SCALBLN):
2153 CASE_FLT_FN (BUILT_IN_LDEXP):
2154 op1_type = INTEGER_TYPE;
2155 default:
2156 break;
2157 }
4737caf2 2158
c2f47e15 2159 if (!validate_arglist (exp, REAL_TYPE, op1_type, VOID_TYPE))
2160 return NULL_RTX;
0fd605a5 2161
c2f47e15 2162 arg0 = CALL_EXPR_ARG (exp, 0);
2163 arg1 = CALL_EXPR_ARG (exp, 1);
0fd605a5 2164
0fd605a5 2165 switch (DECL_FUNCTION_CODE (fndecl))
2166 {
4f35b1fc 2167 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 2168 builtin_optab = pow_optab; break;
4f35b1fc 2169 CASE_FLT_FN (BUILT_IN_ATAN2):
0fd605a5 2170 builtin_optab = atan2_optab; break;
73a954a1 2171 CASE_FLT_FN (BUILT_IN_SCALB):
2172 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2173 return 0;
2174 builtin_optab = scalb_optab; break;
2175 CASE_FLT_FN (BUILT_IN_SCALBN):
2176 CASE_FLT_FN (BUILT_IN_SCALBLN):
2177 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2178 return 0;
2179 /* Fall through... */
4f35b1fc 2180 CASE_FLT_FN (BUILT_IN_LDEXP):
4737caf2 2181 builtin_optab = ldexp_optab; break;
4f35b1fc 2182 CASE_FLT_FN (BUILT_IN_FMOD):
80ed5c06 2183 builtin_optab = fmod_optab; break;
ef722005 2184 CASE_FLT_FN (BUILT_IN_REMAINDER):
4f35b1fc 2185 CASE_FLT_FN (BUILT_IN_DREM):
ef722005 2186 builtin_optab = remainder_optab; break;
0fd605a5 2187 default:
64db345d 2188 gcc_unreachable ();
0fd605a5 2189 }
2190
7f05340e 2191 /* Make a suitable register to place result in. */
2192 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2193
2194 /* Before working hard, check whether the instruction is available. */
d6bf3b14 2195 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
c2f47e15 2196 return NULL_RTX;
fc4eef90 2197
7f05340e 2198 target = gen_reg_rtx (mode);
2199
2200 if (! flag_errno_math || ! HONOR_NANS (mode))
2201 errno_set = false;
2202
f2aca212 2203 if (errno_set && optimize_insn_for_size_p ())
2204 return 0;
2205
4ee9c684 2206 /* Always stabilize the argument list. */
abfea505 2207 CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
2208 CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
7f05340e 2209
8ec3c5c2 2210 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2211 op1 = expand_normal (arg1);
7f05340e 2212
7f05340e 2213 start_sequence ();
2214
0fd605a5 2215 /* Compute into TARGET.
2216 Set TARGET to wherever the result comes back. */
7f05340e 2217 target = expand_binop (mode, builtin_optab, op0, op1,
0fd605a5 2218 target, 0, OPTAB_DIRECT);
53800dbe 2219
68e6cb9d 2220 /* If we were unable to expand via the builtin, stop the sequence
2221 (without outputting the insns) and call to the library function
2222 with the stabilized argument list. */
0fd605a5 2223 if (target == 0)
2224 {
2225 end_sequence ();
68e6cb9d 2226 return expand_call (exp, target, target == const0_rtx);
53800dbe 2227 }
2228
a4356fb9 2229 if (errno_set)
2230 expand_errno_check (exp, target);
0fd605a5 2231
53800dbe 2232 /* Output the entire sequence. */
2233 insns = get_insns ();
2234 end_sequence ();
31d3e01c 2235 emit_insn (insns);
bf8e3599 2236
53800dbe 2237 return target;
2238}
2239
7e0713b1 2240/* Expand a call to the builtin trinary math functions (fma).
2241 Return NULL_RTX if a normal call should be emitted rather than expanding the
2242 function in-line. EXP is the expression that is a call to the builtin
2243 function; if convenient, the result should be placed in TARGET.
2244 SUBTARGET may be used as the target for computing one of EXP's
2245 operands. */
2246
2247static rtx
2248expand_builtin_mathfn_ternary (tree exp, rtx target, rtx subtarget)
2249{
2250 optab builtin_optab;
2251 rtx op0, op1, op2, insns;
2252 tree fndecl = get_callee_fndecl (exp);
2253 tree arg0, arg1, arg2;
2254 enum machine_mode mode;
2255
2256 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2257 return NULL_RTX;
2258
2259 arg0 = CALL_EXPR_ARG (exp, 0);
2260 arg1 = CALL_EXPR_ARG (exp, 1);
2261 arg2 = CALL_EXPR_ARG (exp, 2);
2262
2263 switch (DECL_FUNCTION_CODE (fndecl))
2264 {
2265 CASE_FLT_FN (BUILT_IN_FMA):
2266 builtin_optab = fma_optab; break;
2267 default:
2268 gcc_unreachable ();
2269 }
2270
2271 /* Make a suitable register to place result in. */
2272 mode = TYPE_MODE (TREE_TYPE (exp));
2273
2274 /* Before working hard, check whether the instruction is available. */
2275 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
2276 return NULL_RTX;
2277
2278 target = gen_reg_rtx (mode);
2279
2280 /* Always stabilize the argument list. */
2281 CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
2282 CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
2283 CALL_EXPR_ARG (exp, 2) = arg2 = builtin_save_expr (arg2);
2284
2285 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2286 op1 = expand_normal (arg1);
2287 op2 = expand_normal (arg2);
2288
2289 start_sequence ();
2290
2291 /* Compute into TARGET.
2292 Set TARGET to wherever the result comes back. */
2293 target = expand_ternary_op (mode, builtin_optab, op0, op1, op2,
2294 target, 0);
2295
2296 /* If we were unable to expand via the builtin, stop the sequence
2297 (without outputting the insns) and call to the library function
2298 with the stabilized argument list. */
2299 if (target == 0)
2300 {
2301 end_sequence ();
2302 return expand_call (exp, target, target == const0_rtx);
2303 }
2304
2305 /* Output the entire sequence. */
2306 insns = get_insns ();
2307 end_sequence ();
2308 emit_insn (insns);
2309
2310 return target;
2311}
2312
6b43bae4 2313/* Expand a call to the builtin sin and cos math functions.
c2f47e15 2314 Return NULL_RTX if a normal call should be emitted rather than expanding the
6b43bae4 2315 function in-line. EXP is the expression that is a call to the builtin
2316 function; if convenient, the result should be placed in TARGET.
2317 SUBTARGET may be used as the target for computing one of EXP's
2318 operands. */
2319
2320static rtx
2321expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
2322{
2323 optab builtin_optab;
7511b819 2324 rtx op0, insns;
6b43bae4 2325 tree fndecl = get_callee_fndecl (exp);
6b43bae4 2326 enum machine_mode mode;
abfea505 2327 tree arg;
6b43bae4 2328
c2f47e15 2329 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2330 return NULL_RTX;
6b43bae4 2331
c2f47e15 2332 arg = CALL_EXPR_ARG (exp, 0);
6b43bae4 2333
2334 switch (DECL_FUNCTION_CODE (fndecl))
2335 {
4f35b1fc 2336 CASE_FLT_FN (BUILT_IN_SIN):
2337 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2338 builtin_optab = sincos_optab; break;
2339 default:
64db345d 2340 gcc_unreachable ();
6b43bae4 2341 }
2342
2343 /* Make a suitable register to place result in. */
2344 mode = TYPE_MODE (TREE_TYPE (exp));
2345
6b43bae4 2346 /* Check if sincos insn is available, otherwise fallback
0bed3869 2347 to sin or cos insn. */
d6bf3b14 2348 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
6b43bae4 2349 switch (DECL_FUNCTION_CODE (fndecl))
2350 {
4f35b1fc 2351 CASE_FLT_FN (BUILT_IN_SIN):
6b43bae4 2352 builtin_optab = sin_optab; break;
4f35b1fc 2353 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2354 builtin_optab = cos_optab; break;
2355 default:
64db345d 2356 gcc_unreachable ();
6b43bae4 2357 }
6b43bae4 2358
2359 /* Before working hard, check whether the instruction is available. */
d6bf3b14 2360 if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing)
6b43bae4 2361 {
2362 target = gen_reg_rtx (mode);
2363
2364 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2365 need to expand the argument again. This way, we will not perform
2366 side-effects more the once. */
abfea505 2367 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
6b43bae4 2368
1db6d067 2369 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
6b43bae4 2370
6b43bae4 2371 start_sequence ();
2372
2373 /* Compute into TARGET.
2374 Set TARGET to wherever the result comes back. */
2375 if (builtin_optab == sincos_optab)
2376 {
64db345d 2377 int result;
7d3f6cc7 2378
6b43bae4 2379 switch (DECL_FUNCTION_CODE (fndecl))
2380 {
4f35b1fc 2381 CASE_FLT_FN (BUILT_IN_SIN):
64db345d 2382 result = expand_twoval_unop (builtin_optab, op0, 0, target, 0);
6b43bae4 2383 break;
4f35b1fc 2384 CASE_FLT_FN (BUILT_IN_COS):
64db345d 2385 result = expand_twoval_unop (builtin_optab, op0, target, 0, 0);
6b43bae4 2386 break;
2387 default:
64db345d 2388 gcc_unreachable ();
6b43bae4 2389 }
64db345d 2390 gcc_assert (result);
6b43bae4 2391 }
2392 else
2393 {
2394 target = expand_unop (mode, builtin_optab, op0, target, 0);
2395 }
2396
2397 if (target != 0)
2398 {
6b43bae4 2399 /* Output the entire sequence. */
2400 insns = get_insns ();
2401 end_sequence ();
2402 emit_insn (insns);
2403 return target;
2404 }
2405
2406 /* If we were unable to expand via the builtin, stop the sequence
2407 (without outputting the insns) and call to the library function
2408 with the stabilized argument list. */
2409 end_sequence ();
2410 }
2411
6b43bae4 2412 target = expand_call (exp, target, target == const0_rtx);
2413
2414 return target;
2415}
2416
a65c4d64 2417/* Given an interclass math builtin decl FNDECL and it's argument ARG
2418 return an RTL instruction code that implements the functionality.
2419 If that isn't possible or available return CODE_FOR_nothing. */
a67a90e5 2420
a65c4d64 2421static enum insn_code
2422interclass_mathfn_icode (tree arg, tree fndecl)
a67a90e5 2423{
a65c4d64 2424 bool errno_set = false;
cde061c1 2425 optab builtin_optab = 0;
a67a90e5 2426 enum machine_mode mode;
a67a90e5 2427
2428 switch (DECL_FUNCTION_CODE (fndecl))
2429 {
2430 CASE_FLT_FN (BUILT_IN_ILOGB):
2431 errno_set = true; builtin_optab = ilogb_optab; break;
69b779ea 2432 CASE_FLT_FN (BUILT_IN_ISINF):
2433 builtin_optab = isinf_optab; break;
8a1a9cb7 2434 case BUILT_IN_ISNORMAL:
cde061c1 2435 case BUILT_IN_ISFINITE:
2436 CASE_FLT_FN (BUILT_IN_FINITE):
a65c4d64 2437 case BUILT_IN_FINITED32:
2438 case BUILT_IN_FINITED64:
2439 case BUILT_IN_FINITED128:
2440 case BUILT_IN_ISINFD32:
2441 case BUILT_IN_ISINFD64:
2442 case BUILT_IN_ISINFD128:
cde061c1 2443 /* These builtins have no optabs (yet). */
2444 break;
a67a90e5 2445 default:
2446 gcc_unreachable ();
2447 }
2448
2449 /* There's no easy way to detect the case we need to set EDOM. */
2450 if (flag_errno_math && errno_set)
a65c4d64 2451 return CODE_FOR_nothing;
a67a90e5 2452
2453 /* Optab mode depends on the mode of the input argument. */
2454 mode = TYPE_MODE (TREE_TYPE (arg));
2455
cde061c1 2456 if (builtin_optab)
d6bf3b14 2457 return optab_handler (builtin_optab, mode);
a65c4d64 2458 return CODE_FOR_nothing;
2459}
2460
2461/* Expand a call to one of the builtin math functions that operate on
2462 floating point argument and output an integer result (ilogb, isinf,
2463 isnan, etc).
2464 Return 0 if a normal call should be emitted rather than expanding the
2465 function in-line. EXP is the expression that is a call to the builtin
f97eea22 2466 function; if convenient, the result should be placed in TARGET. */
a65c4d64 2467
2468static rtx
f97eea22 2469expand_builtin_interclass_mathfn (tree exp, rtx target)
a65c4d64 2470{
2471 enum insn_code icode = CODE_FOR_nothing;
2472 rtx op0;
2473 tree fndecl = get_callee_fndecl (exp);
2474 enum machine_mode mode;
2475 tree arg;
2476
2477 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2478 return NULL_RTX;
2479
2480 arg = CALL_EXPR_ARG (exp, 0);
2481 icode = interclass_mathfn_icode (arg, fndecl);
2482 mode = TYPE_MODE (TREE_TYPE (arg));
2483
a67a90e5 2484 if (icode != CODE_FOR_nothing)
2485 {
8786db1e 2486 struct expand_operand ops[1];
4e2a2fb4 2487 rtx last = get_last_insn ();
2488 tree orig_arg = arg;
a67a90e5 2489
2490 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2491 need to expand the argument again. This way, we will not perform
2492 side-effects more the once. */
abfea505 2493 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
a67a90e5 2494
f97eea22 2495 op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
a67a90e5 2496
2497 if (mode != GET_MODE (op0))
2498 op0 = convert_to_mode (mode, op0, 0);
2499
8786db1e 2500 create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
2501 if (maybe_legitimize_operands (icode, 0, 1, ops)
2502 && maybe_emit_unop_insn (icode, ops[0].value, op0, UNKNOWN))
2503 return ops[0].value;
2504
4e2a2fb4 2505 delete_insns_since (last);
2506 CALL_EXPR_ARG (exp, 0) = orig_arg;
a67a90e5 2507 }
2508
a65c4d64 2509 return NULL_RTX;
a67a90e5 2510}
2511
c3147c1a 2512/* Expand a call to the builtin sincos math function.
c2f47e15 2513 Return NULL_RTX if a normal call should be emitted rather than expanding the
c3147c1a 2514 function in-line. EXP is the expression that is a call to the builtin
2515 function. */
2516
2517static rtx
2518expand_builtin_sincos (tree exp)
2519{
2520 rtx op0, op1, op2, target1, target2;
c3147c1a 2521 enum machine_mode mode;
2522 tree arg, sinp, cosp;
2523 int result;
389dd41b 2524 location_t loc = EXPR_LOCATION (exp);
be5575b2 2525 tree alias_type, alias_off;
c3147c1a 2526
c2f47e15 2527 if (!validate_arglist (exp, REAL_TYPE,
2528 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2529 return NULL_RTX;
c3147c1a 2530
c2f47e15 2531 arg = CALL_EXPR_ARG (exp, 0);
2532 sinp = CALL_EXPR_ARG (exp, 1);
2533 cosp = CALL_EXPR_ARG (exp, 2);
c3147c1a 2534
2535 /* Make a suitable register to place result in. */
2536 mode = TYPE_MODE (TREE_TYPE (arg));
2537
2538 /* Check if sincos insn is available, otherwise emit the call. */
d6bf3b14 2539 if (optab_handler (sincos_optab, mode) == CODE_FOR_nothing)
c3147c1a 2540 return NULL_RTX;
2541
2542 target1 = gen_reg_rtx (mode);
2543 target2 = gen_reg_rtx (mode);
2544
8ec3c5c2 2545 op0 = expand_normal (arg);
be5575b2 2546 alias_type = build_pointer_type_for_mode (TREE_TYPE (arg), ptr_mode, true);
2547 alias_off = build_int_cst (alias_type, 0);
2548 op1 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
2549 sinp, alias_off));
2550 op2 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
2551 cosp, alias_off));
c3147c1a 2552
2553 /* Compute into target1 and target2.
2554 Set TARGET to wherever the result comes back. */
2555 result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
2556 gcc_assert (result);
2557
2558 /* Move target1 and target2 to the memory locations indicated
2559 by op1 and op2. */
2560 emit_move_insn (op1, target1);
2561 emit_move_insn (op2, target2);
2562
2563 return const0_rtx;
2564}
2565
d735c391 2566/* Expand a call to the internal cexpi builtin to the sincos math function.
2567 EXP is the expression that is a call to the builtin function; if convenient,
f97eea22 2568 the result should be placed in TARGET. */
d735c391 2569
2570static rtx
f97eea22 2571expand_builtin_cexpi (tree exp, rtx target)
d735c391 2572{
2573 tree fndecl = get_callee_fndecl (exp);
d735c391 2574 tree arg, type;
c2f47e15 2575 enum machine_mode mode;
d735c391 2576 rtx op0, op1, op2;
389dd41b 2577 location_t loc = EXPR_LOCATION (exp);
d735c391 2578
c2f47e15 2579 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2580 return NULL_RTX;
d735c391 2581
c2f47e15 2582 arg = CALL_EXPR_ARG (exp, 0);
d735c391 2583 type = TREE_TYPE (arg);
2584 mode = TYPE_MODE (TREE_TYPE (arg));
2585
2586 /* Try expanding via a sincos optab, fall back to emitting a libcall
18b8d8ae 2587 to sincos or cexp. We are sure we have sincos or cexp because cexpi
2588 is only generated from sincos, cexp or if we have either of them. */
d6bf3b14 2589 if (optab_handler (sincos_optab, mode) != CODE_FOR_nothing)
d735c391 2590 {
2591 op1 = gen_reg_rtx (mode);
2592 op2 = gen_reg_rtx (mode);
2593
f97eea22 2594 op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
d735c391 2595
2596 /* Compute into op1 and op2. */
2597 expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
2598 }
18b8d8ae 2599 else if (TARGET_HAS_SINCOS)
d735c391 2600 {
c2f47e15 2601 tree call, fn = NULL_TREE;
d735c391 2602 tree top1, top2;
2603 rtx op1a, op2a;
2604
2605 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
b9a16870 2606 fn = builtin_decl_explicit (BUILT_IN_SINCOSF);
d735c391 2607 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
b9a16870 2608 fn = builtin_decl_explicit (BUILT_IN_SINCOS);
d735c391 2609 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
b9a16870 2610 fn = builtin_decl_explicit (BUILT_IN_SINCOSL);
c2f47e15 2611 else
2612 gcc_unreachable ();
48e1416a 2613
d735c391 2614 op1 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
2615 op2 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
2616 op1a = copy_to_mode_reg (Pmode, XEXP (op1, 0));
2617 op2a = copy_to_mode_reg (Pmode, XEXP (op2, 0));
2618 top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
2619 top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
2620
d735c391 2621 /* Make sure not to fold the sincos call again. */
2622 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
c2f47e15 2623 expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
2624 call, 3, arg, top1, top2));
d735c391 2625 }
18b8d8ae 2626 else
2627 {
0ecbc158 2628 tree call, fn = NULL_TREE, narg;
18b8d8ae 2629 tree ctype = build_complex_type (type);
2630
0ecbc158 2631 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
b9a16870 2632 fn = builtin_decl_explicit (BUILT_IN_CEXPF);
0ecbc158 2633 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
b9a16870 2634 fn = builtin_decl_explicit (BUILT_IN_CEXP);
0ecbc158 2635 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
b9a16870 2636 fn = builtin_decl_explicit (BUILT_IN_CEXPL);
c2f47e15 2637 else
2638 gcc_unreachable ();
fc0dfa6e 2639
2640 /* If we don't have a decl for cexp create one. This is the
2641 friendliest fallback if the user calls __builtin_cexpi
2642 without full target C99 function support. */
2643 if (fn == NULL_TREE)
2644 {
2645 tree fntype;
2646 const char *name = NULL;
2647
2648 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2649 name = "cexpf";
2650 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2651 name = "cexp";
2652 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2653 name = "cexpl";
2654
2655 fntype = build_function_type_list (ctype, ctype, NULL_TREE);
2656 fn = build_fn_decl (name, fntype);
2657 }
2658
389dd41b 2659 narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype,
18b8d8ae 2660 build_real (type, dconst0), arg);
2661
2662 /* Make sure not to fold the cexp call again. */
2663 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
48e1416a 2664 return expand_expr (build_call_nary (ctype, call, 1, narg),
1db6d067 2665 target, VOIDmode, EXPAND_NORMAL);
18b8d8ae 2666 }
d735c391 2667
2668 /* Now build the proper return type. */
2669 return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
2670 make_tree (TREE_TYPE (arg), op2),
2671 make_tree (TREE_TYPE (arg), op1)),
1db6d067 2672 target, VOIDmode, EXPAND_NORMAL);
d735c391 2673}
2674
a65c4d64 2675/* Conveniently construct a function call expression. FNDECL names the
2676 function to be called, N is the number of arguments, and the "..."
2677 parameters are the argument expressions. Unlike build_call_exr
2678 this doesn't fold the call, hence it will always return a CALL_EXPR. */
2679
2680static tree
2681build_call_nofold_loc (location_t loc, tree fndecl, int n, ...)
2682{
2683 va_list ap;
2684 tree fntype = TREE_TYPE (fndecl);
2685 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
2686
2687 va_start (ap, n);
2688 fn = build_call_valist (TREE_TYPE (fntype), fn, n, ap);
2689 va_end (ap);
2690 SET_EXPR_LOCATION (fn, loc);
2691 return fn;
2692}
a65c4d64 2693
7d3afc77 2694/* Expand a call to one of the builtin rounding functions gcc defines
2695 as an extension (lfloor and lceil). As these are gcc extensions we
2696 do not need to worry about setting errno to EDOM.
ad52b9b7 2697 If expanding via optab fails, lower expression to (int)(floor(x)).
2698 EXP is the expression that is a call to the builtin function;
ff1b14e4 2699 if convenient, the result should be placed in TARGET. */
ad52b9b7 2700
2701static rtx
ff1b14e4 2702expand_builtin_int_roundingfn (tree exp, rtx target)
ad52b9b7 2703{
9c42dd28 2704 convert_optab builtin_optab;
ad52b9b7 2705 rtx op0, insns, tmp;
2706 tree fndecl = get_callee_fndecl (exp);
ad52b9b7 2707 enum built_in_function fallback_fn;
2708 tree fallback_fndecl;
2709 enum machine_mode mode;
4de0924f 2710 tree arg;
ad52b9b7 2711
c2f47e15 2712 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
ad52b9b7 2713 gcc_unreachable ();
2714
c2f47e15 2715 arg = CALL_EXPR_ARG (exp, 0);
ad52b9b7 2716
2717 switch (DECL_FUNCTION_CODE (fndecl))
2718 {
80ff6494 2719 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 2720 CASE_FLT_FN (BUILT_IN_LCEIL):
2721 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 2722 builtin_optab = lceil_optab;
2723 fallback_fn = BUILT_IN_CEIL;
2724 break;
2725
80ff6494 2726 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 2727 CASE_FLT_FN (BUILT_IN_LFLOOR):
2728 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 2729 builtin_optab = lfloor_optab;
2730 fallback_fn = BUILT_IN_FLOOR;
2731 break;
2732
2733 default:
2734 gcc_unreachable ();
2735 }
2736
2737 /* Make a suitable register to place result in. */
2738 mode = TYPE_MODE (TREE_TYPE (exp));
2739
9c42dd28 2740 target = gen_reg_rtx (mode);
ad52b9b7 2741
9c42dd28 2742 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2743 need to expand the argument again. This way, we will not perform
2744 side-effects more the once. */
abfea505 2745 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
ad52b9b7 2746
ff1b14e4 2747 op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
ad52b9b7 2748
9c42dd28 2749 start_sequence ();
ad52b9b7 2750
9c42dd28 2751 /* Compute into TARGET. */
2752 if (expand_sfix_optab (target, op0, builtin_optab))
2753 {
2754 /* Output the entire sequence. */
2755 insns = get_insns ();
ad52b9b7 2756 end_sequence ();
9c42dd28 2757 emit_insn (insns);
2758 return target;
ad52b9b7 2759 }
2760
9c42dd28 2761 /* If we were unable to expand via the builtin, stop the sequence
2762 (without outputting the insns). */
2763 end_sequence ();
2764
ad52b9b7 2765 /* Fall back to floating point rounding optab. */
2766 fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
fc0dfa6e 2767
2768 /* For non-C99 targets we may end up without a fallback fndecl here
2769 if the user called __builtin_lfloor directly. In this case emit
2770 a call to the floor/ceil variants nevertheless. This should result
2771 in the best user experience for not full C99 targets. */
2772 if (fallback_fndecl == NULL_TREE)
2773 {
2774 tree fntype;
2775 const char *name = NULL;
2776
2777 switch (DECL_FUNCTION_CODE (fndecl))
2778 {
80ff6494 2779 case BUILT_IN_ICEIL:
fc0dfa6e 2780 case BUILT_IN_LCEIL:
2781 case BUILT_IN_LLCEIL:
2782 name = "ceil";
2783 break;
80ff6494 2784 case BUILT_IN_ICEILF:
fc0dfa6e 2785 case BUILT_IN_LCEILF:
2786 case BUILT_IN_LLCEILF:
2787 name = "ceilf";
2788 break;
80ff6494 2789 case BUILT_IN_ICEILL:
fc0dfa6e 2790 case BUILT_IN_LCEILL:
2791 case BUILT_IN_LLCEILL:
2792 name = "ceill";
2793 break;
80ff6494 2794 case BUILT_IN_IFLOOR:
fc0dfa6e 2795 case BUILT_IN_LFLOOR:
2796 case BUILT_IN_LLFLOOR:
2797 name = "floor";
2798 break;
80ff6494 2799 case BUILT_IN_IFLOORF:
fc0dfa6e 2800 case BUILT_IN_LFLOORF:
2801 case BUILT_IN_LLFLOORF:
2802 name = "floorf";
2803 break;
80ff6494 2804 case BUILT_IN_IFLOORL:
fc0dfa6e 2805 case BUILT_IN_LFLOORL:
2806 case BUILT_IN_LLFLOORL:
2807 name = "floorl";
2808 break;
2809 default:
2810 gcc_unreachable ();
2811 }
2812
2813 fntype = build_function_type_list (TREE_TYPE (arg),
2814 TREE_TYPE (arg), NULL_TREE);
2815 fallback_fndecl = build_fn_decl (name, fntype);
2816 }
2817
0568e9c1 2818 exp = build_call_nofold_loc (EXPR_LOCATION (exp), fallback_fndecl, 1, arg);
ad52b9b7 2819
d4c690af 2820 tmp = expand_normal (exp);
ad52b9b7 2821
2822 /* Truncate the result of floating point optab to integer
2823 via expand_fix (). */
2824 target = gen_reg_rtx (mode);
2825 expand_fix (target, tmp, 0);
2826
2827 return target;
2828}
2829
7d3afc77 2830/* Expand a call to one of the builtin math functions doing integer
2831 conversion (lrint).
2832 Return 0 if a normal call should be emitted rather than expanding the
2833 function in-line. EXP is the expression that is a call to the builtin
ff1b14e4 2834 function; if convenient, the result should be placed in TARGET. */
7d3afc77 2835
2836static rtx
ff1b14e4 2837expand_builtin_int_roundingfn_2 (tree exp, rtx target)
7d3afc77 2838{
5f51ee59 2839 convert_optab builtin_optab;
7d3afc77 2840 rtx op0, insns;
2841 tree fndecl = get_callee_fndecl (exp);
4de0924f 2842 tree arg;
c2f47e15 2843 enum machine_mode mode;
7d3afc77 2844
2845 /* There's no easy way to detect the case we need to set EDOM. */
2846 if (flag_errno_math)
2847 return NULL_RTX;
2848
c2f47e15 2849 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2850 gcc_unreachable ();
48e1416a 2851
c2f47e15 2852 arg = CALL_EXPR_ARG (exp, 0);
7d3afc77 2853
2854 switch (DECL_FUNCTION_CODE (fndecl))
2855 {
80ff6494 2856 CASE_FLT_FN (BUILT_IN_IRINT):
7d3afc77 2857 CASE_FLT_FN (BUILT_IN_LRINT):
2858 CASE_FLT_FN (BUILT_IN_LLRINT):
2859 builtin_optab = lrint_optab; break;
80ff6494 2860
2861 CASE_FLT_FN (BUILT_IN_IROUND):
ef2f1a10 2862 CASE_FLT_FN (BUILT_IN_LROUND):
2863 CASE_FLT_FN (BUILT_IN_LLROUND):
2864 builtin_optab = lround_optab; break;
80ff6494 2865
7d3afc77 2866 default:
2867 gcc_unreachable ();
2868 }
2869
2870 /* Make a suitable register to place result in. */
2871 mode = TYPE_MODE (TREE_TYPE (exp));
2872
5f51ee59 2873 target = gen_reg_rtx (mode);
7d3afc77 2874
5f51ee59 2875 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2876 need to expand the argument again. This way, we will not perform
2877 side-effects more the once. */
abfea505 2878 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7d3afc77 2879
ff1b14e4 2880 op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
7d3afc77 2881
5f51ee59 2882 start_sequence ();
7d3afc77 2883
5f51ee59 2884 if (expand_sfix_optab (target, op0, builtin_optab))
2885 {
2886 /* Output the entire sequence. */
2887 insns = get_insns ();
7d3afc77 2888 end_sequence ();
5f51ee59 2889 emit_insn (insns);
2890 return target;
7d3afc77 2891 }
2892
5f51ee59 2893 /* If we were unable to expand via the builtin, stop the sequence
2894 (without outputting the insns) and call to the library function
2895 with the stabilized argument list. */
2896 end_sequence ();
2897
7d3afc77 2898 target = expand_call (exp, target, target == const0_rtx);
2899
2900 return target;
2901}
2902
c2f47e15 2903/* Expand a call to the powi built-in mathematical function. Return NULL_RTX if
757c219d 2904 a normal call should be emitted rather than expanding the function
2905 in-line. EXP is the expression that is a call to the builtin
2906 function; if convenient, the result should be placed in TARGET. */
2907
2908static rtx
f97eea22 2909expand_builtin_powi (tree exp, rtx target)
757c219d 2910{
757c219d 2911 tree arg0, arg1;
2912 rtx op0, op1;
2913 enum machine_mode mode;
d0405f40 2914 enum machine_mode mode2;
757c219d 2915
c2f47e15 2916 if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
2917 return NULL_RTX;
757c219d 2918
c2f47e15 2919 arg0 = CALL_EXPR_ARG (exp, 0);
2920 arg1 = CALL_EXPR_ARG (exp, 1);
757c219d 2921 mode = TYPE_MODE (TREE_TYPE (exp));
2922
757c219d 2923 /* Emit a libcall to libgcc. */
2924
c2f47e15 2925 /* Mode of the 2nd argument must match that of an int. */
d0405f40 2926 mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
2927
757c219d 2928 if (target == NULL_RTX)
2929 target = gen_reg_rtx (mode);
2930
f97eea22 2931 op0 = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
757c219d 2932 if (GET_MODE (op0) != mode)
2933 op0 = convert_to_mode (mode, op0, 0);
1db6d067 2934 op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
d0405f40 2935 if (GET_MODE (op1) != mode2)
2936 op1 = convert_to_mode (mode2, op1, 0);
757c219d 2937
f36b9f69 2938 target = emit_library_call_value (optab_libfunc (powi_optab, mode),
2dd6f9ed 2939 target, LCT_CONST, mode, 2,
d0405f40 2940 op0, mode, op1, mode2);
757c219d 2941
2942 return target;
2943}
2944
48e1416a 2945/* Expand expression EXP which is a call to the strlen builtin. Return
c2f47e15 2946 NULL_RTX if we failed the caller should emit a normal call, otherwise
aed0bd19 2947 try to get the result in TARGET, if convenient. */
f7c44134 2948
53800dbe 2949static rtx
c2f47e15 2950expand_builtin_strlen (tree exp, rtx target,
aecda0d6 2951 enum machine_mode target_mode)
53800dbe 2952{
c2f47e15 2953 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2954 return NULL_RTX;
53800dbe 2955 else
2956 {
8786db1e 2957 struct expand_operand ops[4];
911c0150 2958 rtx pat;
c2f47e15 2959 tree len;
2960 tree src = CALL_EXPR_ARG (exp, 0);
8786db1e 2961 rtx src_reg, before_strlen;
2962 enum machine_mode insn_mode = target_mode;
ef2c4a29 2963 enum insn_code icode = CODE_FOR_nothing;
153c3b50 2964 unsigned int align;
6248e345 2965
2966 /* If the length can be computed at compile-time, return it. */
681fab1e 2967 len = c_strlen (src, 0);
6248e345 2968 if (len)
80cd7a5e 2969 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
6248e345 2970
681fab1e 2971 /* If the length can be computed at compile-time and is constant
2972 integer, but there are side-effects in src, evaluate
2973 src for side-effects, then return len.
2974 E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
2975 can be optimized into: i++; x = 3; */
2976 len = c_strlen (src, 1);
2977 if (len && TREE_CODE (len) == INTEGER_CST)
2978 {
2979 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2980 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
2981 }
2982
957d0361 2983 align = get_pointer_alignment (src) / BITS_PER_UNIT;
53800dbe 2984
53800dbe 2985 /* If SRC is not a pointer type, don't do this operation inline. */
2986 if (align == 0)
c2f47e15 2987 return NULL_RTX;
53800dbe 2988
911c0150 2989 /* Bail out if we can't compute strlen in the right mode. */
53800dbe 2990 while (insn_mode != VOIDmode)
2991 {
d6bf3b14 2992 icode = optab_handler (strlen_optab, insn_mode);
53800dbe 2993 if (icode != CODE_FOR_nothing)
c28ae87f 2994 break;
53800dbe 2995
2996 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
2997 }
2998 if (insn_mode == VOIDmode)
c2f47e15 2999 return NULL_RTX;
53800dbe 3000
911c0150 3001 /* Make a place to hold the source address. We will not expand
3002 the actual source until we are sure that the expansion will
3003 not fail -- there are trees that cannot be expanded twice. */
3004 src_reg = gen_reg_rtx (Pmode);
53800dbe 3005
911c0150 3006 /* Mark the beginning of the strlen sequence so we can emit the
3007 source operand later. */
f0ce3b1f 3008 before_strlen = get_last_insn ();
53800dbe 3009
8786db1e 3010 create_output_operand (&ops[0], target, insn_mode);
3011 create_fixed_operand (&ops[1], gen_rtx_MEM (BLKmode, src_reg));
3012 create_integer_operand (&ops[2], 0);
3013 create_integer_operand (&ops[3], align);
3014 if (!maybe_expand_insn (icode, 4, ops))
c2f47e15 3015 return NULL_RTX;
911c0150 3016
3017 /* Now that we are assured of success, expand the source. */
3018 start_sequence ();
499eee58 3019 pat = expand_expr (src, src_reg, Pmode, EXPAND_NORMAL);
911c0150 3020 if (pat != src_reg)
499eee58 3021 {
3022#ifdef POINTERS_EXTEND_UNSIGNED
3023 if (GET_MODE (pat) != Pmode)
3024 pat = convert_to_mode (Pmode, pat,
3025 POINTERS_EXTEND_UNSIGNED);
3026#endif
3027 emit_move_insn (src_reg, pat);
3028 }
31d3e01c 3029 pat = get_insns ();
911c0150 3030 end_sequence ();
bceb0d1f 3031
3032 if (before_strlen)
3033 emit_insn_after (pat, before_strlen);
3034 else
3035 emit_insn_before (pat, get_insns ());
53800dbe 3036
3037 /* Return the value in the proper mode for this function. */
8786db1e 3038 if (GET_MODE (ops[0].value) == target_mode)
3039 target = ops[0].value;
53800dbe 3040 else if (target != 0)
8786db1e 3041 convert_move (target, ops[0].value, 0);
53800dbe 3042 else
8786db1e 3043 target = convert_to_mode (target_mode, ops[0].value, 0);
911c0150 3044
3045 return target;
53800dbe 3046 }
3047}
3048
6840589f 3049/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3050 bytes from constant string DATA + OFFSET and return it as target
3051 constant. */
3052
3053static rtx
aecda0d6 3054builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
3055 enum machine_mode mode)
6840589f 3056{
3057 const char *str = (const char *) data;
3058
64db345d 3059 gcc_assert (offset >= 0
3060 && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
3061 <= strlen (str) + 1));
6840589f 3062
3063 return c_readstr (str + offset, mode);
3064}
3065
c2f47e15 3066/* Expand a call EXP to the memcpy builtin.
3067 Return NULL_RTX if we failed, the caller should emit a normal call,
3b824fa6 3068 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3069 mode MODE if that's convenient). */
c2f47e15 3070
53800dbe 3071static rtx
a65c4d64 3072expand_builtin_memcpy (tree exp, rtx target)
53800dbe 3073{
c2f47e15 3074 if (!validate_arglist (exp,
3075 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3076 return NULL_RTX;
53800dbe 3077 else
3078 {
c2f47e15 3079 tree dest = CALL_EXPR_ARG (exp, 0);
3080 tree src = CALL_EXPR_ARG (exp, 1);
3081 tree len = CALL_EXPR_ARG (exp, 2);
6840589f 3082 const char *src_str;
957d0361 3083 unsigned int src_align = get_pointer_alignment (src);
3084 unsigned int dest_align = get_pointer_alignment (dest);
53800dbe 3085 rtx dest_mem, src_mem, dest_addr, len_rtx;
162719b3 3086 HOST_WIDE_INT expected_size = -1;
3087 unsigned int expected_align = 0;
5a0de151 3088
6f428e8b 3089 /* If DEST is not a pointer type, call the normal function. */
3090 if (dest_align == 0)
c2f47e15 3091 return NULL_RTX;
6f428e8b 3092
6f428e8b 3093 /* If either SRC is not a pointer type, don't do this
a0c938f0 3094 operation in-line. */
6f428e8b 3095 if (src_align == 0)
c2f47e15 3096 return NULL_RTX;
48e1416a 3097
8cee8dc0 3098 if (currently_expanding_gimple_stmt)
3099 stringop_block_profile (currently_expanding_gimple_stmt,
3100 &expected_align, &expected_size);
75a70cf9 3101
162719b3 3102 if (expected_align < dest_align)
3103 expected_align = dest_align;
d8ae1baa 3104 dest_mem = get_memory_rtx (dest, len);
2a631e19 3105 set_mem_align (dest_mem, dest_align);
8ec3c5c2 3106 len_rtx = expand_normal (len);
6840589f 3107 src_str = c_getstr (src);
3108
3109 /* If SRC is a string constant and block move would be done
3110 by pieces, we can avoid loading the string from memory
3111 and only stored the computed constants. */
3112 if (src_str
971ba038 3113 && CONST_INT_P (len_rtx)
6840589f 3114 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3115 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3116 CONST_CAST (char *, src_str),
3117 dest_align, false))
6840589f 3118 {
9fe0e1b8 3119 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3120 builtin_memcpy_read_str,
364c0c59 3121 CONST_CAST (char *, src_str),
3122 dest_align, false, 0);
a65c4d64 3123 dest_mem = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3124 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3125 return dest_mem;
6840589f 3126 }
3127
d8ae1baa 3128 src_mem = get_memory_rtx (src, len);
2a631e19 3129 set_mem_align (src_mem, src_align);
53800dbe 3130
53800dbe 3131 /* Copy word part most expediently. */
162719b3 3132 dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
3133 CALL_EXPR_TAILCALL (exp)
3134 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3135 expected_align, expected_size);
53800dbe 3136
3137 if (dest_addr == 0)
e5716f7e 3138 {
a65c4d64 3139 dest_addr = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3140 dest_addr = convert_memory_address (ptr_mode, dest_addr);
e5716f7e 3141 }
9fe0e1b8 3142 return dest_addr;
53800dbe 3143 }
3144}
3145
c2f47e15 3146/* Expand a call EXP to the mempcpy builtin.
3147 Return NULL_RTX if we failed; the caller should emit a normal call,
647661c6 3148 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3149 mode MODE if that's convenient). If ENDP is 0 return the
3150 destination pointer, if ENDP is 1 return the end pointer ala
3151 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3152 stpcpy. */
647661c6 3153
3154static rtx
c8b17b2e 3155expand_builtin_mempcpy (tree exp, rtx target, enum machine_mode mode)
647661c6 3156{
c2f47e15 3157 if (!validate_arglist (exp,
3158 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3159 return NULL_RTX;
3160 else
3161 {
3162 tree dest = CALL_EXPR_ARG (exp, 0);
3163 tree src = CALL_EXPR_ARG (exp, 1);
3164 tree len = CALL_EXPR_ARG (exp, 2);
3165 return expand_builtin_mempcpy_args (dest, src, len,
c2f47e15 3166 target, mode, /*endp=*/ 1);
3167 }
3168}
3169
3170/* Helper function to do the actual work for expand_builtin_mempcpy. The
3171 arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out
3172 so that this can also be called without constructing an actual CALL_EXPR.
a65c4d64 3173 The other arguments and return value are the same as for
3174 expand_builtin_mempcpy. */
c2f47e15 3175
3176static rtx
a65c4d64 3177expand_builtin_mempcpy_args (tree dest, tree src, tree len,
c2f47e15 3178 rtx target, enum machine_mode mode, int endp)
3179{
3180 /* If return value is ignored, transform mempcpy into memcpy. */
b9a16870 3181 if (target == const0_rtx && builtin_decl_implicit_p (BUILT_IN_MEMCPY))
9fe0e1b8 3182 {
b9a16870 3183 tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
0568e9c1 3184 tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3,
3185 dest, src, len);
c8b17b2e 3186 return expand_expr (result, target, mode, EXPAND_NORMAL);
9fe0e1b8 3187 }
647661c6 3188 else
3189 {
9fe0e1b8 3190 const char *src_str;
957d0361 3191 unsigned int src_align = get_pointer_alignment (src);
3192 unsigned int dest_align = get_pointer_alignment (dest);
9fe0e1b8 3193 rtx dest_mem, src_mem, len_rtx;
a0c938f0 3194
7da1412b 3195 /* If either SRC or DEST is not a pointer type, don't do this
a0c938f0 3196 operation in-line. */
7da1412b 3197 if (dest_align == 0 || src_align == 0)
c2f47e15 3198 return NULL_RTX;
9fe0e1b8 3199
6217c238 3200 /* If LEN is not constant, call the normal function. */
3201 if (! host_integerp (len, 1))
c2f47e15 3202 return NULL_RTX;
0862b7e9 3203
8ec3c5c2 3204 len_rtx = expand_normal (len);
9fe0e1b8 3205 src_str = c_getstr (src);
647661c6 3206
9fe0e1b8 3207 /* If SRC is a string constant and block move would be done
3208 by pieces, we can avoid loading the string from memory
3209 and only stored the computed constants. */
3210 if (src_str
971ba038 3211 && CONST_INT_P (len_rtx)
9fe0e1b8 3212 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3213 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3214 CONST_CAST (char *, src_str),
3215 dest_align, false))
9fe0e1b8 3216 {
d8ae1baa 3217 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3218 set_mem_align (dest_mem, dest_align);
3219 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3220 builtin_memcpy_read_str,
364c0c59 3221 CONST_CAST (char *, src_str),
3222 dest_align, false, endp);
9fe0e1b8 3223 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3224 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3225 return dest_mem;
647661c6 3226 }
3227
971ba038 3228 if (CONST_INT_P (len_rtx)
9fe0e1b8 3229 && can_move_by_pieces (INTVAL (len_rtx),
3230 MIN (dest_align, src_align)))
3231 {
d8ae1baa 3232 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3233 set_mem_align (dest_mem, dest_align);
d8ae1baa 3234 src_mem = get_memory_rtx (src, len);
9fe0e1b8 3235 set_mem_align (src_mem, src_align);
3236 dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
3237 MIN (dest_align, src_align), endp);
3238 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3239 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3240 return dest_mem;
3241 }
3242
c2f47e15 3243 return NULL_RTX;
647661c6 3244 }
3245}
3246
727c62dd 3247#ifndef HAVE_movstr
3248# define HAVE_movstr 0
3249# define CODE_FOR_movstr CODE_FOR_nothing
3250#endif
3251
c2f47e15 3252/* Expand into a movstr instruction, if one is available. Return NULL_RTX if
727c62dd 3253 we failed, the caller should emit a normal call, otherwise try to
3254 get the result in TARGET, if convenient. If ENDP is 0 return the
3255 destination pointer, if ENDP is 1 return the end pointer ala
3256 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3257 stpcpy. */
3258
3259static rtx
3260expand_movstr (tree dest, tree src, rtx target, int endp)
3261{
8786db1e 3262 struct expand_operand ops[3];
727c62dd 3263 rtx dest_mem;
3264 rtx src_mem;
727c62dd 3265
3266 if (!HAVE_movstr)
c2f47e15 3267 return NULL_RTX;
727c62dd 3268
d8ae1baa 3269 dest_mem = get_memory_rtx (dest, NULL);
3270 src_mem = get_memory_rtx (src, NULL);
727c62dd 3271 if (!endp)
3272 {
3273 target = force_reg (Pmode, XEXP (dest_mem, 0));
3274 dest_mem = replace_equiv_address (dest_mem, target);
727c62dd 3275 }
3276
8786db1e 3277 create_output_operand (&ops[0], endp ? target : NULL_RTX, Pmode);
3278 create_fixed_operand (&ops[1], dest_mem);
3279 create_fixed_operand (&ops[2], src_mem);
3280 expand_insn (CODE_FOR_movstr, 3, ops);
727c62dd 3281
8786db1e 3282 if (endp && target != const0_rtx)
c5aba89c 3283 {
8786db1e 3284 target = ops[0].value;
3285 /* movstr is supposed to set end to the address of the NUL
3286 terminator. If the caller requested a mempcpy-like return value,
3287 adjust it. */
3288 if (endp == 1)
3289 {
45c0b118 3290 rtx tem = plus_constant (gen_lowpart (GET_MODE (target), target), 1);
8786db1e 3291 emit_move_insn (target, force_operand (tem, NULL_RTX));
3292 }
c5aba89c 3293 }
727c62dd 3294 return target;
3295}
3296
48e1416a 3297/* Expand expression EXP, which is a call to the strcpy builtin. Return
3298 NULL_RTX if we failed the caller should emit a normal call, otherwise
c2f47e15 3299 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3300 convenient). */
902de8ed 3301
53800dbe 3302static rtx
a65c4d64 3303expand_builtin_strcpy (tree exp, rtx target)
53800dbe 3304{
c2f47e15 3305 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3306 {
3307 tree dest = CALL_EXPR_ARG (exp, 0);
3308 tree src = CALL_EXPR_ARG (exp, 1);
a65c4d64 3309 return expand_builtin_strcpy_args (dest, src, target);
c2f47e15 3310 }
3311 return NULL_RTX;
3312}
3313
3314/* Helper function to do the actual work for expand_builtin_strcpy. The
3315 arguments to the builtin_strcpy call DEST and SRC are broken out
3316 so that this can also be called without constructing an actual CALL_EXPR.
3317 The other arguments and return value are the same as for
3318 expand_builtin_strcpy. */
3319
3320static rtx
a65c4d64 3321expand_builtin_strcpy_args (tree dest, tree src, rtx target)
c2f47e15 3322{
c2f47e15 3323 return expand_movstr (dest, src, target, /*endp=*/0);
53800dbe 3324}
3325
c2f47e15 3326/* Expand a call EXP to the stpcpy builtin.
3327 Return NULL_RTX if we failed the caller should emit a normal call,
3b824fa6 3328 otherwise try to get the result in TARGET, if convenient (and in
3329 mode MODE if that's convenient). */
3330
3331static rtx
dc369150 3332expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
3b824fa6 3333{
c2f47e15 3334 tree dst, src;
389dd41b 3335 location_t loc = EXPR_LOCATION (exp);
c2f47e15 3336
3337 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3338 return NULL_RTX;
3339
3340 dst = CALL_EXPR_ARG (exp, 0);
3341 src = CALL_EXPR_ARG (exp, 1);
3342
727c62dd 3343 /* If return value is ignored, transform stpcpy into strcpy. */
b9a16870 3344 if (target == const0_rtx && builtin_decl_implicit (BUILT_IN_STRCPY))
978836e5 3345 {
b9a16870 3346 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
0568e9c1 3347 tree result = build_call_nofold_loc (loc, fn, 2, dst, src);
c8b17b2e 3348 return expand_expr (result, target, mode, EXPAND_NORMAL);
978836e5 3349 }
3b824fa6 3350 else
3351 {
c2f47e15 3352 tree len, lenp1;
727c62dd 3353 rtx ret;
647661c6 3354
9fe0e1b8 3355 /* Ensure we get an actual string whose length can be evaluated at
a0c938f0 3356 compile-time, not an expression containing a string. This is
3357 because the latter will potentially produce pessimized code
3358 when used to produce the return value. */
681fab1e 3359 if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
c2f47e15 3360 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3361
389dd41b 3362 lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
a65c4d64 3363 ret = expand_builtin_mempcpy_args (dst, src, lenp1,
c2f47e15 3364 target, mode, /*endp=*/2);
727c62dd 3365
3366 if (ret)
3367 return ret;
3368
3369 if (TREE_CODE (len) == INTEGER_CST)
3370 {
8ec3c5c2 3371 rtx len_rtx = expand_normal (len);
727c62dd 3372
971ba038 3373 if (CONST_INT_P (len_rtx))
727c62dd 3374 {
a65c4d64 3375 ret = expand_builtin_strcpy_args (dst, src, target);
727c62dd 3376
3377 if (ret)
3378 {
3379 if (! target)
7ac87324 3380 {
3381 if (mode != VOIDmode)
3382 target = gen_reg_rtx (mode);
3383 else
3384 target = gen_reg_rtx (GET_MODE (ret));
3385 }
727c62dd 3386 if (GET_MODE (target) != GET_MODE (ret))
3387 ret = gen_lowpart (GET_MODE (target), ret);
3388
c5aba89c 3389 ret = plus_constant (ret, INTVAL (len_rtx));
3390 ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
64db345d 3391 gcc_assert (ret);
727c62dd 3392
3393 return target;
3394 }
3395 }
3396 }
3397
c2f47e15 3398 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3399 }
3400}
3401
6840589f 3402/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3403 bytes from constant string DATA + OFFSET and return it as target
3404 constant. */
3405
09879952 3406rtx
aecda0d6 3407builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
3408 enum machine_mode mode)
6840589f 3409{
3410 const char *str = (const char *) data;
3411
3412 if ((unsigned HOST_WIDE_INT) offset > strlen (str))
3413 return const0_rtx;
3414
3415 return c_readstr (str + offset, mode);
3416}
3417
48e1416a 3418/* Expand expression EXP, which is a call to the strncpy builtin. Return
c2f47e15 3419 NULL_RTX if we failed the caller should emit a normal call. */
ed09096d 3420
3421static rtx
a65c4d64 3422expand_builtin_strncpy (tree exp, rtx target)
ed09096d 3423{
389dd41b 3424 location_t loc = EXPR_LOCATION (exp);
c2f47e15 3425
3426 if (validate_arglist (exp,
3427 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
ed09096d 3428 {
c2f47e15 3429 tree dest = CALL_EXPR_ARG (exp, 0);
3430 tree src = CALL_EXPR_ARG (exp, 1);
3431 tree len = CALL_EXPR_ARG (exp, 2);
3432 tree slen = c_strlen (src, 1);
6840589f 3433
8ff6a5cd 3434 /* We must be passed a constant len and src parameter. */
3435 if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
c2f47e15 3436 return NULL_RTX;
ed09096d 3437
389dd41b 3438 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
ed09096d 3439
3440 /* We're required to pad with trailing zeros if the requested
a0c938f0 3441 len is greater than strlen(s2)+1. In that case try to
6840589f 3442 use store_by_pieces, if it fails, punt. */
ed09096d 3443 if (tree_int_cst_lt (slen, len))
6840589f 3444 {
957d0361 3445 unsigned int dest_align = get_pointer_alignment (dest);
c2f47e15 3446 const char *p = c_getstr (src);
6840589f 3447 rtx dest_mem;
3448
27d0c333 3449 if (!p || dest_align == 0 || !host_integerp (len, 1)
3450 || !can_store_by_pieces (tree_low_cst (len, 1),
6840589f 3451 builtin_strncpy_read_str,
364c0c59 3452 CONST_CAST (char *, p),
3453 dest_align, false))
c2f47e15 3454 return NULL_RTX;
6840589f 3455
d8ae1baa 3456 dest_mem = get_memory_rtx (dest, len);
27d0c333 3457 store_by_pieces (dest_mem, tree_low_cst (len, 1),
6840589f 3458 builtin_strncpy_read_str,
364c0c59 3459 CONST_CAST (char *, p), dest_align, false, 0);
a65c4d64 3460 dest_mem = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3461 dest_mem = convert_memory_address (ptr_mode, dest_mem);
e5716f7e 3462 return dest_mem;
6840589f 3463 }
ed09096d 3464 }
c2f47e15 3465 return NULL_RTX;
ed09096d 3466}
3467
ecc318ff 3468/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3469 bytes from constant string DATA + OFFSET and return it as target
3470 constant. */
3471
f656b751 3472rtx
aecda0d6 3473builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3474 enum machine_mode mode)
ecc318ff 3475{
3476 const char *c = (const char *) data;
364c0c59 3477 char *p = XALLOCAVEC (char, GET_MODE_SIZE (mode));
ecc318ff 3478
3479 memset (p, *c, GET_MODE_SIZE (mode));
3480
3481 return c_readstr (p, mode);
3482}
3483
a7ec6974 3484/* Callback routine for store_by_pieces. Return the RTL of a register
3485 containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
3486 char value given in the RTL register data. For example, if mode is
3487 4 bytes wide, return the RTL for 0x01010101*data. */
3488
3489static rtx
aecda0d6 3490builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3491 enum machine_mode mode)
a7ec6974 3492{
3493 rtx target, coeff;
3494 size_t size;
3495 char *p;
3496
3497 size = GET_MODE_SIZE (mode);
f0ce3b1f 3498 if (size == 1)
3499 return (rtx) data;
a7ec6974 3500
364c0c59 3501 p = XALLOCAVEC (char, size);
a7ec6974 3502 memset (p, 1, size);
3503 coeff = c_readstr (p, mode);
3504
f0ce3b1f 3505 target = convert_to_mode (mode, (rtx) data, 1);
a7ec6974 3506 target = expand_mult (mode, target, coeff, NULL_RTX, 1);
3507 return force_reg (mode, target);
3508}
3509
48e1416a 3510/* Expand expression EXP, which is a call to the memset builtin. Return
3511 NULL_RTX if we failed the caller should emit a normal call, otherwise
c2f47e15 3512 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3513 convenient). */
902de8ed 3514
53800dbe 3515static rtx
c2f47e15 3516expand_builtin_memset (tree exp, rtx target, enum machine_mode mode)
53800dbe 3517{
c2f47e15 3518 if (!validate_arglist (exp,
3519 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
3520 return NULL_RTX;
53800dbe 3521 else
3522 {
c2f47e15 3523 tree dest = CALL_EXPR_ARG (exp, 0);
3524 tree val = CALL_EXPR_ARG (exp, 1);
3525 tree len = CALL_EXPR_ARG (exp, 2);
3526 return expand_builtin_memset_args (dest, val, len, target, mode, exp);
3527 }
3528}
53800dbe 3529
c2f47e15 3530/* Helper function to do the actual work for expand_builtin_memset. The
3531 arguments to the builtin_memset call DEST, VAL, and LEN are broken out
3532 so that this can also be called without constructing an actual CALL_EXPR.
3533 The other arguments and return value are the same as for
3534 expand_builtin_memset. */
6b961939 3535
c2f47e15 3536static rtx
3537expand_builtin_memset_args (tree dest, tree val, tree len,
3538 rtx target, enum machine_mode mode, tree orig_exp)
3539{
3540 tree fndecl, fn;
3541 enum built_in_function fcode;
03a5dda9 3542 enum machine_mode val_mode;
c2f47e15 3543 char c;
3544 unsigned int dest_align;
3545 rtx dest_mem, dest_addr, len_rtx;
3546 HOST_WIDE_INT expected_size = -1;
3547 unsigned int expected_align = 0;
53800dbe 3548
957d0361 3549 dest_align = get_pointer_alignment (dest);
162719b3 3550
c2f47e15 3551 /* If DEST is not a pointer type, don't do this operation in-line. */
3552 if (dest_align == 0)
3553 return NULL_RTX;
6f428e8b 3554
8cee8dc0 3555 if (currently_expanding_gimple_stmt)
3556 stringop_block_profile (currently_expanding_gimple_stmt,
3557 &expected_align, &expected_size);
75a70cf9 3558
c2f47e15 3559 if (expected_align < dest_align)
3560 expected_align = dest_align;
6b961939 3561
c2f47e15 3562 /* If the LEN parameter is zero, return DEST. */
3563 if (integer_zerop (len))
3564 {
3565 /* Evaluate and ignore VAL in case it has side-effects. */
3566 expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
3567 return expand_expr (dest, target, mode, EXPAND_NORMAL);
3568 }
7a3e5564 3569
c2f47e15 3570 /* Stabilize the arguments in case we fail. */
3571 dest = builtin_save_expr (dest);
3572 val = builtin_save_expr (val);
3573 len = builtin_save_expr (len);
a7ec6974 3574
c2f47e15 3575 len_rtx = expand_normal (len);
3576 dest_mem = get_memory_rtx (dest, len);
03a5dda9 3577 val_mode = TYPE_MODE (unsigned_char_type_node);
a7ec6974 3578
c2f47e15 3579 if (TREE_CODE (val) != INTEGER_CST)
3580 {
3581 rtx val_rtx;
a7ec6974 3582
c2f47e15 3583 val_rtx = expand_normal (val);
03a5dda9 3584 val_rtx = convert_to_mode (val_mode, val_rtx, 0);
53800dbe 3585
c2f47e15 3586 /* Assume that we can memset by pieces if we can store
3587 * the coefficients by pieces (in the required modes).
3588 * We can't pass builtin_memset_gen_str as that emits RTL. */
3589 c = 1;
3590 if (host_integerp (len, 1)
c2f47e15 3591 && can_store_by_pieces (tree_low_cst (len, 1),
4b297e2e 3592 builtin_memset_read_str, &c, dest_align,
3593 true))
c2f47e15 3594 {
03a5dda9 3595 val_rtx = force_reg (val_mode, val_rtx);
c2f47e15 3596 store_by_pieces (dest_mem, tree_low_cst (len, 1),
4b297e2e 3597 builtin_memset_gen_str, val_rtx, dest_align,
3598 true, 0);
c2f47e15 3599 }
3600 else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
3601 dest_align, expected_align,
3602 expected_size))
6b961939 3603 goto do_libcall;
48e1416a 3604
c2f47e15 3605 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3606 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3607 return dest_mem;
3608 }
53800dbe 3609
c2f47e15 3610 if (target_char_cast (val, &c))
3611 goto do_libcall;
ecc318ff 3612
c2f47e15 3613 if (c)
3614 {
3615 if (host_integerp (len, 1)
c2f47e15 3616 && can_store_by_pieces (tree_low_cst (len, 1),
4b297e2e 3617 builtin_memset_read_str, &c, dest_align,
3618 true))
c2f47e15 3619 store_by_pieces (dest_mem, tree_low_cst (len, 1),
4b297e2e 3620 builtin_memset_read_str, &c, dest_align, true, 0);
03a5dda9 3621 else if (!set_storage_via_setmem (dest_mem, len_rtx,
3622 gen_int_mode (c, val_mode),
c2f47e15 3623 dest_align, expected_align,
3624 expected_size))
3625 goto do_libcall;
48e1416a 3626
c2f47e15 3627 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3628 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3629 return dest_mem;
3630 }
ecc318ff 3631
c2f47e15 3632 set_mem_align (dest_mem, dest_align);
3633 dest_addr = clear_storage_hints (dest_mem, len_rtx,
3634 CALL_EXPR_TAILCALL (orig_exp)
3635 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3636 expected_align, expected_size);
53800dbe 3637
c2f47e15 3638 if (dest_addr == 0)
3639 {
3640 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3641 dest_addr = convert_memory_address (ptr_mode, dest_addr);
3642 }
53800dbe 3643
c2f47e15 3644 return dest_addr;
6b961939 3645
c2f47e15 3646 do_libcall:
3647 fndecl = get_callee_fndecl (orig_exp);
3648 fcode = DECL_FUNCTION_CODE (fndecl);
3649 if (fcode == BUILT_IN_MEMSET)
0568e9c1 3650 fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 3,
3651 dest, val, len);
c2f47e15 3652 else if (fcode == BUILT_IN_BZERO)
0568e9c1 3653 fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 2,
3654 dest, len);
c2f47e15 3655 else
3656 gcc_unreachable ();
a65c4d64 3657 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
3658 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
c2f47e15 3659 return expand_call (fn, target, target == const0_rtx);
53800dbe 3660}
3661
48e1416a 3662/* Expand expression EXP, which is a call to the bzero builtin. Return
c2f47e15 3663 NULL_RTX if we failed the caller should emit a normal call. */
27d0c333 3664
ffc83088 3665static rtx
0b25db21 3666expand_builtin_bzero (tree exp)
ffc83088 3667{
c2f47e15 3668 tree dest, size;
389dd41b 3669 location_t loc = EXPR_LOCATION (exp);
ffc83088 3670
c2f47e15 3671 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
7369e7ba 3672 return NULL_RTX;
ffc83088 3673
c2f47e15 3674 dest = CALL_EXPR_ARG (exp, 0);
3675 size = CALL_EXPR_ARG (exp, 1);
bf8e3599 3676
7369e7ba 3677 /* New argument list transforming bzero(ptr x, int y) to
6f428e8b 3678 memset(ptr x, int 0, size_t y). This is done this way
3679 so that if it isn't expanded inline, we fallback to
3680 calling bzero instead of memset. */
bf8e3599 3681
c2f47e15 3682 return expand_builtin_memset_args (dest, integer_zero_node,
a0553bff 3683 fold_convert_loc (loc,
3684 size_type_node, size),
c2f47e15 3685 const0_rtx, VOIDmode, exp);
ffc83088 3686}
3687
7a3f89b5 3688/* Expand expression EXP, which is a call to the memcmp built-in function.
bd021c1c 3689 Return NULL_RTX if we failed and the caller should emit a normal call,
3690 otherwise try to get the result in TARGET, if convenient (and in mode
3691 MODE, if that's convenient). */
27d0c333 3692
53800dbe 3693static rtx
a65c4d64 3694expand_builtin_memcmp (tree exp, ATTRIBUTE_UNUSED rtx target,
3695 ATTRIBUTE_UNUSED enum machine_mode mode)
53800dbe 3696{
a65c4d64 3697 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
389dd41b 3698
c2f47e15 3699 if (!validate_arglist (exp,
3700 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3701 return NULL_RTX;
6f428e8b 3702
bd021c1c 3703 /* Note: The cmpstrnsi pattern, if it exists, is not suitable for
3704 implementing memcmp because it will stop if it encounters two
3705 zero bytes. */
3706#if defined HAVE_cmpmemsi
53800dbe 3707 {
0cd832f0 3708 rtx arg1_rtx, arg2_rtx, arg3_rtx;
53800dbe 3709 rtx result;
0cd832f0 3710 rtx insn;
c2f47e15 3711 tree arg1 = CALL_EXPR_ARG (exp, 0);
3712 tree arg2 = CALL_EXPR_ARG (exp, 1);
3713 tree len = CALL_EXPR_ARG (exp, 2);
53800dbe 3714
957d0361 3715 unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
3716 unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
b428c0a5 3717 enum machine_mode insn_mode;
3718
b428c0a5 3719 if (HAVE_cmpmemsi)
3720 insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
3721 else
c2f47e15 3722 return NULL_RTX;
53800dbe 3723
3724 /* If we don't have POINTER_TYPE, call the function. */
3725 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 3726 return NULL_RTX;
53800dbe 3727
3728 /* Make a place to write the result of the instruction. */
3729 result = target;
3730 if (! (result != 0
8ad4c111 3731 && REG_P (result) && GET_MODE (result) == insn_mode
53800dbe 3732 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3733 result = gen_reg_rtx (insn_mode);
3734
d8ae1baa 3735 arg1_rtx = get_memory_rtx (arg1, len);
3736 arg2_rtx = get_memory_rtx (arg2, len);
389dd41b 3737 arg3_rtx = expand_normal (fold_convert_loc (loc, sizetype, len));
83f88f8e 3738
3739 /* Set MEM_SIZE as appropriate. */
971ba038 3740 if (CONST_INT_P (arg3_rtx))
83f88f8e 3741 {
5b2a69fa 3742 set_mem_size (arg1_rtx, INTVAL (arg3_rtx));
3743 set_mem_size (arg2_rtx, INTVAL (arg3_rtx));
83f88f8e 3744 }
3745
b428c0a5 3746 if (HAVE_cmpmemsi)
3747 insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3748 GEN_INT (MIN (arg1_align, arg2_align)));
0cd832f0 3749 else
64db345d 3750 gcc_unreachable ();
0cd832f0 3751
3752 if (insn)
3753 emit_insn (insn);
3754 else
2dd6f9ed 3755 emit_library_call_value (memcmp_libfunc, result, LCT_PURE,
0cd832f0 3756 TYPE_MODE (integer_type_node), 3,
3757 XEXP (arg1_rtx, 0), Pmode,
3758 XEXP (arg2_rtx, 0), Pmode,
3759 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
78a8ed03 3760 TYPE_UNSIGNED (sizetype)),
0cd832f0 3761 TYPE_MODE (sizetype));
53800dbe 3762
3763 /* Return the value in the proper mode for this function. */
3764 mode = TYPE_MODE (TREE_TYPE (exp));
3765 if (GET_MODE (result) == mode)
3766 return result;
3767 else if (target != 0)
3768 {
3769 convert_move (target, result, 0);
3770 return target;
3771 }
3772 else
3773 return convert_to_mode (mode, result, 0);
3774 }
bd021c1c 3775#endif /* HAVE_cmpmemsi. */
53800dbe 3776
c2f47e15 3777 return NULL_RTX;
6f428e8b 3778}
3779
c2f47e15 3780/* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX
53800dbe 3781 if we failed the caller should emit a normal call, otherwise try to get
3782 the result in TARGET, if convenient. */
902de8ed 3783
53800dbe 3784static rtx
a65c4d64 3785expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
53800dbe 3786{
c2f47e15 3787 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3788 return NULL_RTX;
bf8e3599 3789
6ac5504b 3790#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
6b531606 3791 if (direct_optab_handler (cmpstr_optab, SImode) != CODE_FOR_nothing
3792 || direct_optab_handler (cmpstrn_optab, SImode) != CODE_FOR_nothing)
6ac5504b 3793 {
3794 rtx arg1_rtx, arg2_rtx;
3795 rtx result, insn = NULL_RTX;
3796 tree fndecl, fn;
c2f47e15 3797 tree arg1 = CALL_EXPR_ARG (exp, 0);
3798 tree arg2 = CALL_EXPR_ARG (exp, 1);
a0c938f0 3799
957d0361 3800 unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
3801 unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
6ac5504b 3802
3803 /* If we don't have POINTER_TYPE, call the function. */
3804 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 3805 return NULL_RTX;
7a3f89b5 3806
6ac5504b 3807 /* Stabilize the arguments in case gen_cmpstr(n)si fail. */
3808 arg1 = builtin_save_expr (arg1);
3809 arg2 = builtin_save_expr (arg2);
7a3f89b5 3810
d8ae1baa 3811 arg1_rtx = get_memory_rtx (arg1, NULL);
3812 arg2_rtx = get_memory_rtx (arg2, NULL);
53800dbe 3813
6ac5504b 3814#ifdef HAVE_cmpstrsi
3815 /* Try to call cmpstrsi. */
3816 if (HAVE_cmpstrsi)
3817 {
a0c938f0 3818 enum machine_mode insn_mode
6ac5504b 3819 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3820
3821 /* Make a place to write the result of the instruction. */
3822 result = target;
3823 if (! (result != 0
3824 && REG_P (result) && GET_MODE (result) == insn_mode
3825 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3826 result = gen_reg_rtx (insn_mode);
3827
3828 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
3829 GEN_INT (MIN (arg1_align, arg2_align)));
3830 }
3831#endif
03fd9d2c 3832#ifdef HAVE_cmpstrnsi
6ac5504b 3833 /* Try to determine at least one length and call cmpstrnsi. */
a0c938f0 3834 if (!insn && HAVE_cmpstrnsi)
6ac5504b 3835 {
3836 tree len;
3837 rtx arg3_rtx;
3838
a0c938f0 3839 enum machine_mode insn_mode
6ac5504b 3840 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
3841 tree len1 = c_strlen (arg1, 1);
3842 tree len2 = c_strlen (arg2, 1);
3843
3844 if (len1)
3845 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3846 if (len2)
3847 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3848
3849 /* If we don't have a constant length for the first, use the length
3850 of the second, if we know it. We don't require a constant for
3851 this case; some cost analysis could be done if both are available
3852 but neither is constant. For now, assume they're equally cheap,
3853 unless one has side effects. If both strings have constant lengths,
3854 use the smaller. */
3855
3856 if (!len1)
3857 len = len2;
3858 else if (!len2)
3859 len = len1;
3860 else if (TREE_SIDE_EFFECTS (len1))
3861 len = len2;
3862 else if (TREE_SIDE_EFFECTS (len2))
3863 len = len1;
3864 else if (TREE_CODE (len1) != INTEGER_CST)
3865 len = len2;
3866 else if (TREE_CODE (len2) != INTEGER_CST)
3867 len = len1;
3868 else if (tree_int_cst_lt (len1, len2))
3869 len = len1;
3870 else
3871 len = len2;
3872
3873 /* If both arguments have side effects, we cannot optimize. */
3874 if (!len || TREE_SIDE_EFFECTS (len))
6b961939 3875 goto do_libcall;
53800dbe 3876
8ec3c5c2 3877 arg3_rtx = expand_normal (len);
902de8ed 3878
6ac5504b 3879 /* Make a place to write the result of the instruction. */
3880 result = target;
3881 if (! (result != 0
3882 && REG_P (result) && GET_MODE (result) == insn_mode
3883 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3884 result = gen_reg_rtx (insn_mode);
53800dbe 3885
6ac5504b 3886 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3887 GEN_INT (MIN (arg1_align, arg2_align)));
3888 }
3889#endif
3f8aefe2 3890
6ac5504b 3891 if (insn)
3892 {
a65c4d64 3893 enum machine_mode mode;
6ac5504b 3894 emit_insn (insn);
3f8aefe2 3895
6ac5504b 3896 /* Return the value in the proper mode for this function. */
3897 mode = TYPE_MODE (TREE_TYPE (exp));
3898 if (GET_MODE (result) == mode)
3899 return result;
3900 if (target == 0)
3901 return convert_to_mode (mode, result, 0);
3902 convert_move (target, result, 0);
3903 return target;
3904 }
902de8ed 3905
6ac5504b 3906 /* Expand the library call ourselves using a stabilized argument
3907 list to avoid re-evaluating the function's arguments twice. */
2694880e 3908#ifdef HAVE_cmpstrnsi
6b961939 3909 do_libcall:
2694880e 3910#endif
6ac5504b 3911 fndecl = get_callee_fndecl (exp);
0568e9c1 3912 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2);
a65c4d64 3913 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
3914 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
6ac5504b 3915 return expand_call (fn, target, target == const0_rtx);
3916 }
7a3f89b5 3917#endif
c2f47e15 3918 return NULL_RTX;
83d79705 3919}
53800dbe 3920
48e1416a 3921/* Expand expression EXP, which is a call to the strncmp builtin. Return
c2f47e15 3922 NULL_RTX if we failed the caller should emit a normal call, otherwise try to get
ed09096d 3923 the result in TARGET, if convenient. */
27d0c333 3924
ed09096d 3925static rtx
a65c4d64 3926expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
3927 ATTRIBUTE_UNUSED enum machine_mode mode)
ed09096d 3928{
a65c4d64 3929 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
389dd41b 3930
c2f47e15 3931 if (!validate_arglist (exp,
3932 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3933 return NULL_RTX;
ed09096d 3934
6e34e617 3935 /* If c_strlen can determine an expression for one of the string
6ac5504b 3936 lengths, and it doesn't have side effects, then emit cmpstrnsi
7a3f89b5 3937 using length MIN(strlen(string)+1, arg3). */
6ac5504b 3938#ifdef HAVE_cmpstrnsi
3939 if (HAVE_cmpstrnsi)
7a3f89b5 3940 {
3941 tree len, len1, len2;
3942 rtx arg1_rtx, arg2_rtx, arg3_rtx;
3943 rtx result, insn;
0b25db21 3944 tree fndecl, fn;
c2f47e15 3945 tree arg1 = CALL_EXPR_ARG (exp, 0);
3946 tree arg2 = CALL_EXPR_ARG (exp, 1);
3947 tree arg3 = CALL_EXPR_ARG (exp, 2);
6f428e8b 3948
957d0361 3949 unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
3950 unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
7a3f89b5 3951 enum machine_mode insn_mode
6ac5504b 3952 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
bf8e3599 3953
681fab1e 3954 len1 = c_strlen (arg1, 1);
3955 len2 = c_strlen (arg2, 1);
7a3f89b5 3956
3957 if (len1)
389dd41b 3958 len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1);
7a3f89b5 3959 if (len2)
389dd41b 3960 len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2);
7a3f89b5 3961
3962 /* If we don't have a constant length for the first, use the length
3963 of the second, if we know it. We don't require a constant for
3964 this case; some cost analysis could be done if both are available
3965 but neither is constant. For now, assume they're equally cheap,
3966 unless one has side effects. If both strings have constant lengths,
3967 use the smaller. */
3968
3969 if (!len1)
3970 len = len2;
3971 else if (!len2)
3972 len = len1;
3973 else if (TREE_SIDE_EFFECTS (len1))
3974 len = len2;
3975 else if (TREE_SIDE_EFFECTS (len2))
3976 len = len1;
3977 else if (TREE_CODE (len1) != INTEGER_CST)
3978 len = len2;
3979 else if (TREE_CODE (len2) != INTEGER_CST)
3980 len = len1;
3981 else if (tree_int_cst_lt (len1, len2))
3982 len = len1;
3983 else
3984 len = len2;
6e34e617 3985
7a3f89b5 3986 /* If both arguments have side effects, we cannot optimize. */
3987 if (!len || TREE_SIDE_EFFECTS (len))
c2f47e15 3988 return NULL_RTX;
bf8e3599 3989
7a3f89b5 3990 /* The actual new length parameter is MIN(len,arg3). */
389dd41b 3991 len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len,
3992 fold_convert_loc (loc, TREE_TYPE (len), arg3));
7a3f89b5 3993
3994 /* If we don't have POINTER_TYPE, call the function. */
3995 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 3996 return NULL_RTX;
7a3f89b5 3997
3998 /* Make a place to write the result of the instruction. */
3999 result = target;
4000 if (! (result != 0
8ad4c111 4001 && REG_P (result) && GET_MODE (result) == insn_mode
7a3f89b5 4002 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4003 result = gen_reg_rtx (insn_mode);
4004
a65c4d64 4005 /* Stabilize the arguments in case gen_cmpstrnsi fails. */
4006 arg1 = builtin_save_expr (arg1);
4007 arg2 = builtin_save_expr (arg2);
4008 len = builtin_save_expr (len);
27d0c333 4009
a65c4d64 4010 arg1_rtx = get_memory_rtx (arg1, len);
4011 arg2_rtx = get_memory_rtx (arg2, len);
4012 arg3_rtx = expand_normal (len);
4013 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4014 GEN_INT (MIN (arg1_align, arg2_align)));
4015 if (insn)
4016 {
4017 emit_insn (insn);
49f0327b 4018
a65c4d64 4019 /* Return the value in the proper mode for this function. */
4020 mode = TYPE_MODE (TREE_TYPE (exp));
4021 if (GET_MODE (result) == mode)
4022 return result;
4023 if (target == 0)
4024 return convert_to_mode (mode, result, 0);
4025 convert_move (target, result, 0);
4026 return target;
4027 }
27d0c333 4028
a65c4d64 4029 /* Expand the library call ourselves using a stabilized argument
4030 list to avoid re-evaluating the function's arguments twice. */
4031 fndecl = get_callee_fndecl (exp);
0568e9c1 4032 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 3,
4033 arg1, arg2, len);
a65c4d64 4034 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
4035 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4036 return expand_call (fn, target, target == const0_rtx);
4037 }
4038#endif
c2f47e15 4039 return NULL_RTX;
49f0327b 4040}
4041
a66c9326 4042/* Expand a call to __builtin_saveregs, generating the result in TARGET,
4043 if that's convenient. */
902de8ed 4044
a66c9326 4045rtx
aecda0d6 4046expand_builtin_saveregs (void)
53800dbe 4047{
a66c9326 4048 rtx val, seq;
53800dbe 4049
4050 /* Don't do __builtin_saveregs more than once in a function.
4051 Save the result of the first call and reuse it. */
4052 if (saveregs_value != 0)
4053 return saveregs_value;
53800dbe 4054
a66c9326 4055 /* When this function is called, it means that registers must be
4056 saved on entry to this function. So we migrate the call to the
4057 first insn of this function. */
4058
4059 start_sequence ();
53800dbe 4060
a66c9326 4061 /* Do whatever the machine needs done in this case. */
45550790 4062 val = targetm.calls.expand_builtin_saveregs ();
53800dbe 4063
a66c9326 4064 seq = get_insns ();
4065 end_sequence ();
53800dbe 4066
a66c9326 4067 saveregs_value = val;
53800dbe 4068
31d3e01c 4069 /* Put the insns after the NOTE that starts the function. If this
4070 is inside a start_sequence, make the outer-level insn chain current, so
a66c9326 4071 the code is placed at the start of the function. */
4072 push_topmost_sequence ();
0ec80471 4073 emit_insn_after (seq, entry_of_function ());
a66c9326 4074 pop_topmost_sequence ();
4075
4076 return val;
53800dbe 4077}
4078
79012a9d 4079/* Expand a call to __builtin_next_arg. */
27d0c333 4080
53800dbe 4081static rtx
79012a9d 4082expand_builtin_next_arg (void)
53800dbe 4083{
79012a9d 4084 /* Checking arguments is already done in fold_builtin_next_arg
4085 that must be called before this function. */
940ddc5c 4086 return expand_binop (ptr_mode, add_optab,
abe32cce 4087 crtl->args.internal_arg_pointer,
4088 crtl->args.arg_offset_rtx,
53800dbe 4089 NULL_RTX, 0, OPTAB_LIB_WIDEN);
4090}
4091
a66c9326 4092/* Make it easier for the backends by protecting the valist argument
4093 from multiple evaluations. */
4094
4095static tree
389dd41b 4096stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
a66c9326 4097{
5f57a8b1 4098 tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
4099
182cf5a9 4100 /* The current way of determining the type of valist is completely
4101 bogus. We should have the information on the va builtin instead. */
4102 if (!vatype)
4103 vatype = targetm.fn_abi_va_list (cfun->decl);
5f57a8b1 4104
4105 if (TREE_CODE (vatype) == ARRAY_TYPE)
a66c9326 4106 {
2d47cc32 4107 if (TREE_SIDE_EFFECTS (valist))
4108 valist = save_expr (valist);
11a61dea 4109
2d47cc32 4110 /* For this case, the backends will be expecting a pointer to
5f57a8b1 4111 vatype, but it's possible we've actually been given an array
4112 (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)).
2d47cc32 4113 So fix it. */
4114 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
8a15c04a 4115 {
5f57a8b1 4116 tree p1 = build_pointer_type (TREE_TYPE (vatype));
389dd41b 4117 valist = build_fold_addr_expr_with_type_loc (loc, valist, p1);
8a15c04a 4118 }
a66c9326 4119 }
11a61dea 4120 else
a66c9326 4121 {
182cf5a9 4122 tree pt = build_pointer_type (vatype);
11a61dea 4123
2d47cc32 4124 if (! needs_lvalue)
4125 {
11a61dea 4126 if (! TREE_SIDE_EFFECTS (valist))
4127 return valist;
bf8e3599 4128
389dd41b 4129 valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist);
a66c9326 4130 TREE_SIDE_EFFECTS (valist) = 1;
a66c9326 4131 }
2d47cc32 4132
11a61dea 4133 if (TREE_SIDE_EFFECTS (valist))
2d47cc32 4134 valist = save_expr (valist);
182cf5a9 4135 valist = fold_build2_loc (loc, MEM_REF,
4136 vatype, valist, build_int_cst (pt, 0));
a66c9326 4137 }
4138
4139 return valist;
4140}
4141
2e15d750 4142/* The "standard" definition of va_list is void*. */
4143
4144tree
4145std_build_builtin_va_list (void)
4146{
4147 return ptr_type_node;
4148}
4149
5f57a8b1 4150/* The "standard" abi va_list is va_list_type_node. */
4151
4152tree
4153std_fn_abi_va_list (tree fndecl ATTRIBUTE_UNUSED)
4154{
4155 return va_list_type_node;
4156}
4157
4158/* The "standard" type of va_list is va_list_type_node. */
4159
4160tree
4161std_canonical_va_list_type (tree type)
4162{
4163 tree wtype, htype;
4164
4165 if (INDIRECT_REF_P (type))
4166 type = TREE_TYPE (type);
4167 else if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE(type)))
4168 type = TREE_TYPE (type);
5f57a8b1 4169 wtype = va_list_type_node;
4170 htype = type;
7b36f9ab 4171 /* Treat structure va_list types. */
4172 if (TREE_CODE (wtype) == RECORD_TYPE && POINTER_TYPE_P (htype))
4173 htype = TREE_TYPE (htype);
4174 else if (TREE_CODE (wtype) == ARRAY_TYPE)
5f57a8b1 4175 {
4176 /* If va_list is an array type, the argument may have decayed
4177 to a pointer type, e.g. by being passed to another function.
4178 In that case, unwrap both types so that we can compare the
4179 underlying records. */
4180 if (TREE_CODE (htype) == ARRAY_TYPE
4181 || POINTER_TYPE_P (htype))
4182 {
4183 wtype = TREE_TYPE (wtype);
4184 htype = TREE_TYPE (htype);
4185 }
4186 }
4187 if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype))
4188 return va_list_type_node;
4189
4190 return NULL_TREE;
4191}
4192
a66c9326 4193/* The "standard" implementation of va_start: just assign `nextarg' to
4194 the variable. */
27d0c333 4195
a66c9326 4196void
aecda0d6 4197std_expand_builtin_va_start (tree valist, rtx nextarg)
a66c9326 4198{
f03c17bc 4199 rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
4200 convert_move (va_r, nextarg, 0);
a66c9326 4201}
4202
c2f47e15 4203/* Expand EXP, a call to __builtin_va_start. */
27d0c333 4204
a66c9326 4205static rtx
c2f47e15 4206expand_builtin_va_start (tree exp)
a66c9326 4207{
4208 rtx nextarg;
c2f47e15 4209 tree valist;
389dd41b 4210 location_t loc = EXPR_LOCATION (exp);
a66c9326 4211
c2f47e15 4212 if (call_expr_nargs (exp) < 2)
cb166087 4213 {
389dd41b 4214 error_at (loc, "too few arguments to function %<va_start%>");
cb166087 4215 return const0_rtx;
4216 }
a66c9326 4217
c2f47e15 4218 if (fold_builtin_next_arg (exp, true))
79012a9d 4219 return const0_rtx;
7c2f0500 4220
79012a9d 4221 nextarg = expand_builtin_next_arg ();
389dd41b 4222 valist = stabilize_va_list_loc (loc, CALL_EXPR_ARG (exp, 0), 1);
a66c9326 4223
8a58ed0a 4224 if (targetm.expand_builtin_va_start)
4225 targetm.expand_builtin_va_start (valist, nextarg);
4226 else
4227 std_expand_builtin_va_start (valist, nextarg);
a66c9326 4228
4229 return const0_rtx;
4230}
4231
a66c9326 4232/* The "standard" implementation of va_arg: read the value from the
4233 current (padded) address and increment by the (padded) size. */
f7c44134 4234
e0eca1fa 4235tree
75a70cf9 4236std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
4237 gimple_seq *post_p)
fcdd3ab3 4238{
52cc2eeb 4239 tree addr, t, type_size, rounded_size, valist_tmp;
b8e8e485 4240 unsigned HOST_WIDE_INT align, boundary;
bef380a4 4241 bool indirect;
52cc2eeb 4242
4243#ifdef ARGS_GROW_DOWNWARD
4244 /* All of the alignment and movement below is for args-grow-up machines.
4245 As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
4246 implement their own specialized gimplify_va_arg_expr routines. */
64db345d 4247 gcc_unreachable ();
52cc2eeb 4248#endif
fcdd3ab3 4249
bef380a4 4250 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
4251 if (indirect)
4252 type = build_pointer_type (type);
4253
52cc2eeb 4254 align = PARM_BOUNDARY / BITS_PER_UNIT;
bd99ba64 4255 boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
c8b779eb 4256
4257 /* When we align parameter on stack for caller, if the parameter
befa808c 4258 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
4259 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
c8b779eb 4260 here with caller. */
befa808c 4261 if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
4262 boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
c8b779eb 4263
4264 boundary /= BITS_PER_UNIT;
fcdd3ab3 4265
52cc2eeb 4266 /* Hoist the valist value into a temporary for the moment. */
ecdeeb37 4267 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
4268
fcdd3ab3 4269 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
4270 requires greater alignment, we must perform dynamic alignment. */
85c1f587 4271 if (boundary > align
4272 && !integer_zerop (TYPE_SIZE (type)))
fcdd3ab3 4273 {
41076ef6 4274 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
2cc66f2a 4275 fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
52cc2eeb 4276 gimplify_and_add (t, pre_p);
4277
41076ef6 4278 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
a0553bff 4279 fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
4280 valist_tmp,
4281 build_int_cst (TREE_TYPE (valist), -boundary)));
ecdeeb37 4282 gimplify_and_add (t, pre_p);
fcdd3ab3 4283 }
c5dc0c32 4284 else
4285 boundary = align;
4286
4287 /* If the actual alignment is less than the alignment of the type,
4288 adjust the type accordingly so that we don't assume strict alignment
f0b5f617 4289 when dereferencing the pointer. */
c5dc0c32 4290 boundary *= BITS_PER_UNIT;
4291 if (boundary < TYPE_ALIGN (type))
4292 {
4293 type = build_variant_type_copy (type);
4294 TYPE_ALIGN (type) = boundary;
4295 }
fcdd3ab3 4296
bcff3604 4297 /* Compute the rounded size of the type. */
52cc2eeb 4298 type_size = size_in_bytes (type);
4299 rounded_size = round_up (type_size, align);
4300
fcdd3ab3 4301 /* Reduce rounded_size so it's sharable with the postqueue. */
4302 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
4303
4304 /* Get AP. */
ecdeeb37 4305 addr = valist_tmp;
52cc2eeb 4306 if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
fcdd3ab3 4307 {
4308 /* Small args are padded downward. */
389dd41b 4309 t = fold_build2_loc (input_location, GT_EXPR, sizetype,
4310 rounded_size, size_int (align));
49d00087 4311 t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
4312 size_binop (MINUS_EXPR, rounded_size, type_size));
2cc66f2a 4313 addr = fold_build_pointer_plus (addr, t);
fcdd3ab3 4314 }
4315
fcdd3ab3 4316 /* Compute new value for AP. */
2cc66f2a 4317 t = fold_build_pointer_plus (valist_tmp, rounded_size);
41076ef6 4318 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
ecdeeb37 4319 gimplify_and_add (t, pre_p);
e0eca1fa 4320
4321 addr = fold_convert (build_pointer_type (type), addr);
fcdd3ab3 4322
bef380a4 4323 if (indirect)
f2462d6c 4324 addr = build_va_arg_indirect_ref (addr);
4325
4326 return build_va_arg_indirect_ref (addr);
4327}
a0930a69 4328
f2462d6c 4329/* Build an indirect-ref expression over the given TREE, which represents a
4330 piece of a va_arg() expansion. */
4331tree
4332build_va_arg_indirect_ref (tree addr)
4333{
5c9d7b33 4334 addr = build_simple_mem_ref_loc (EXPR_LOCATION (addr), addr);
f2462d6c 4335
a0930a69 4336 if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */
4337 mf_mark (addr);
bef380a4 4338
a0930a69 4339 return addr;
433006a9 4340}
4341
fcdd3ab3 4342/* Return a dummy expression of type TYPE in order to keep going after an
4343 error. */
4344
4345static tree
4346dummy_object (tree type)
4347{
535664e3 4348 tree t = build_int_cst (build_pointer_type (type), 0);
377bc54c 4349 return build2 (MEM_REF, type, t, t);
fcdd3ab3 4350}
4351
2799a2b7 4352/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
4353 builtin function, but a very special sort of operator. */
fcdd3ab3 4354
4355enum gimplify_status
75a70cf9 4356gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
fcdd3ab3 4357{
5f57a8b1 4358 tree promoted_type, have_va_type;
fcdd3ab3 4359 tree valist = TREE_OPERAND (*expr_p, 0);
4360 tree type = TREE_TYPE (*expr_p);
4361 tree t;
389dd41b 4362 location_t loc = EXPR_LOCATION (*expr_p);
fcdd3ab3 4363
4364 /* Verify that valist is of the proper type. */
fcdd3ab3 4365 have_va_type = TREE_TYPE (valist);
f43dda35 4366 if (have_va_type == error_mark_node)
4367 return GS_ERROR;
5f57a8b1 4368 have_va_type = targetm.canonical_va_list_type (have_va_type);
f43dda35 4369
5f57a8b1 4370 if (have_va_type == NULL_TREE)
fcdd3ab3 4371 {
e60a6f7b 4372 error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>");
e0eca1fa 4373 return GS_ERROR;
fcdd3ab3 4374 }
4375
4376 /* Generate a diagnostic for requesting data of a type that cannot
4377 be passed through `...' due to type promotion at the call site. */
5f57a8b1 4378 if ((promoted_type = lang_hooks.types.type_promotes_to (type))
fcdd3ab3 4379 != type)
4380 {
4381 static bool gave_help;
a52d5726 4382 bool warned;
fcdd3ab3 4383
4384 /* Unfortunately, this is merely undefined, rather than a constraint
4385 violation, so we cannot make this an error. If this call is never
4386 executed, the program is still strictly conforming. */
e60a6f7b 4387 warned = warning_at (loc, 0,
4388 "%qT is promoted to %qT when passed through %<...%>",
4389 type, promoted_type);
a52d5726 4390 if (!gave_help && warned)
fcdd3ab3 4391 {
4392 gave_help = true;
e60a6f7b 4393 inform (loc, "(so you should pass %qT not %qT to %<va_arg%>)",
4394 promoted_type, type);
fcdd3ab3 4395 }
4396
4397 /* We can, however, treat "undefined" any way we please.
4398 Call abort to encourage the user to fix the program. */
a52d5726 4399 if (warned)
e60a6f7b 4400 inform (loc, "if this code is reached, the program will abort");
ad0e7a06 4401 /* Before the abort, allow the evaluation of the va_list
4402 expression to exit or longjmp. */
4403 gimplify_and_add (valist, pre_p);
389dd41b 4404 t = build_call_expr_loc (loc,
b9a16870 4405 builtin_decl_implicit (BUILT_IN_TRAP), 0);
75a70cf9 4406 gimplify_and_add (t, pre_p);
fcdd3ab3 4407
4408 /* This is dead code, but go ahead and finish so that the
4409 mode of the result comes out right. */
4410 *expr_p = dummy_object (type);
4411 return GS_ALL_DONE;
4412 }
4413 else
4414 {
4415 /* Make it easier for the backends by protecting the valist argument
a0c938f0 4416 from multiple evaluations. */
5f57a8b1 4417 if (TREE_CODE (have_va_type) == ARRAY_TYPE)
e0eca1fa 4418 {
4419 /* For this case, the backends will be expecting a pointer to
5f57a8b1 4420 TREE_TYPE (abi), but it's possible we've
4421 actually been given an array (an actual TARGET_FN_ABI_VA_LIST).
e0eca1fa 4422 So fix it. */
4423 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
4424 {
5f57a8b1 4425 tree p1 = build_pointer_type (TREE_TYPE (have_va_type));
389dd41b 4426 valist = fold_convert_loc (loc, p1,
4427 build_fold_addr_expr_loc (loc, valist));
e0eca1fa 4428 }
75a70cf9 4429
e0eca1fa 4430 gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
4431 }
4432 else
4433 gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
fcdd3ab3 4434
17a6380d 4435 if (!targetm.gimplify_va_arg_expr)
75a70cf9 4436 /* FIXME: Once most targets are converted we should merely
89f18f73 4437 assert this is non-null. */
fcdd3ab3 4438 return GS_ALL_DONE;
4439
17a6380d 4440 *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
fcdd3ab3 4441 return GS_OK;
4442 }
4443}
4444
c2f47e15 4445/* Expand EXP, a call to __builtin_va_end. */
f7c44134 4446
a66c9326 4447static rtx
c2f47e15 4448expand_builtin_va_end (tree exp)
a66c9326 4449{
c2f47e15 4450 tree valist = CALL_EXPR_ARG (exp, 0);
8a15c04a 4451
8a15c04a 4452 /* Evaluate for side effects, if needed. I hate macros that don't
4453 do that. */
4454 if (TREE_SIDE_EFFECTS (valist))
4455 expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
a66c9326 4456
4457 return const0_rtx;
4458}
4459
c2f47e15 4460/* Expand EXP, a call to __builtin_va_copy. We do this as a
a66c9326 4461 builtin rather than just as an assignment in stdarg.h because of the
4462 nastiness of array-type va_list types. */
f7c44134 4463
a66c9326 4464static rtx
c2f47e15 4465expand_builtin_va_copy (tree exp)
a66c9326 4466{
4467 tree dst, src, t;
389dd41b 4468 location_t loc = EXPR_LOCATION (exp);
a66c9326 4469
c2f47e15 4470 dst = CALL_EXPR_ARG (exp, 0);
4471 src = CALL_EXPR_ARG (exp, 1);
a66c9326 4472
389dd41b 4473 dst = stabilize_va_list_loc (loc, dst, 1);
4474 src = stabilize_va_list_loc (loc, src, 0);
a66c9326 4475
5f57a8b1 4476 gcc_assert (cfun != NULL && cfun->decl != NULL_TREE);
4477
4478 if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE)
a66c9326 4479 {
5f57a8b1 4480 t = build2 (MODIFY_EXPR, targetm.fn_abi_va_list (cfun->decl), dst, src);
a66c9326 4481 TREE_SIDE_EFFECTS (t) = 1;
4482 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4483 }
4484 else
4485 {
11a61dea 4486 rtx dstb, srcb, size;
4487
4488 /* Evaluate to pointers. */
4489 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
4490 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
5f57a8b1 4491 size = expand_expr (TYPE_SIZE_UNIT (targetm.fn_abi_va_list (cfun->decl)),
4492 NULL_RTX, VOIDmode, EXPAND_NORMAL);
11a61dea 4493
85d654dd 4494 dstb = convert_memory_address (Pmode, dstb);
4495 srcb = convert_memory_address (Pmode, srcb);
726ec87c 4496
11a61dea 4497 /* "Dereference" to BLKmode memories. */
4498 dstb = gen_rtx_MEM (BLKmode, dstb);
ab6ab77e 4499 set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
5f57a8b1 4500 set_mem_align (dstb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 4501 srcb = gen_rtx_MEM (BLKmode, srcb);
ab6ab77e 4502 set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
5f57a8b1 4503 set_mem_align (srcb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 4504
4505 /* Copy. */
0378dbdc 4506 emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
a66c9326 4507 }
4508
4509 return const0_rtx;
4510}
4511
53800dbe 4512/* Expand a call to one of the builtin functions __builtin_frame_address or
4513 __builtin_return_address. */
27d0c333 4514
53800dbe 4515static rtx
c2f47e15 4516expand_builtin_frame_address (tree fndecl, tree exp)
53800dbe 4517{
53800dbe 4518 /* The argument must be a nonnegative integer constant.
4519 It counts the number of frames to scan up the stack.
4520 The value is the return address saved in that frame. */
c2f47e15 4521 if (call_expr_nargs (exp) == 0)
53800dbe 4522 /* Warning about missing arg was already issued. */
4523 return const0_rtx;
c2f47e15 4524 else if (! host_integerp (CALL_EXPR_ARG (exp, 0), 1))
53800dbe 4525 {
4526 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
07e3a3d2 4527 error ("invalid argument to %<__builtin_frame_address%>");
53800dbe 4528 else
07e3a3d2 4529 error ("invalid argument to %<__builtin_return_address%>");
53800dbe 4530 return const0_rtx;
4531 }
4532 else
4533 {
27d0c333 4534 rtx tem
4535 = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
c2f47e15 4536 tree_low_cst (CALL_EXPR_ARG (exp, 0), 1));
53800dbe 4537
4538 /* Some ports cannot access arbitrary stack frames. */
4539 if (tem == NULL)
4540 {
4541 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
c3ceba8e 4542 warning (0, "unsupported argument to %<__builtin_frame_address%>");
53800dbe 4543 else
c3ceba8e 4544 warning (0, "unsupported argument to %<__builtin_return_address%>");
53800dbe 4545 return const0_rtx;
4546 }
4547
4548 /* For __builtin_frame_address, return what we've got. */
4549 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4550 return tem;
4551
8ad4c111 4552 if (!REG_P (tem)
53800dbe 4553 && ! CONSTANT_P (tem))
4554 tem = copy_to_mode_reg (Pmode, tem);
4555 return tem;
4556 }
4557}
4558
990495a7 4559/* Expand EXP, a call to the alloca builtin. Return NULL_RTX if we
5be42b39 4560 failed and the caller should emit a normal call. CANNOT_ACCUMULATE
4561 is the same as for allocate_dynamic_stack_space. */
15c6cf6b 4562
53800dbe 4563static rtx
5be42b39 4564expand_builtin_alloca (tree exp, bool cannot_accumulate)
53800dbe 4565{
4566 rtx op0;
15c6cf6b 4567 rtx result;
581bf1c2 4568 bool valid_arglist;
4569 unsigned int align;
4570 bool alloca_with_align = (DECL_FUNCTION_CODE (get_callee_fndecl (exp))
4571 == BUILT_IN_ALLOCA_WITH_ALIGN);
53800dbe 4572
f883da84 4573 /* Emit normal call if we use mudflap. */
4574 if (flag_mudflap)
c2f47e15 4575 return NULL_RTX;
4ee9c684 4576
581bf1c2 4577 valid_arglist
4578 = (alloca_with_align
4579 ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
4580 : validate_arglist (exp, INTEGER_TYPE, VOID_TYPE));
4581
4582 if (!valid_arglist)
c2f47e15 4583 return NULL_RTX;
53800dbe 4584
4585 /* Compute the argument. */
c2f47e15 4586 op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
53800dbe 4587
581bf1c2 4588 /* Compute the alignment. */
4589 align = (alloca_with_align
4590 ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1))
4591 : BIGGEST_ALIGNMENT);
4592
53800dbe 4593 /* Allocate the desired space. */
581bf1c2 4594 result = allocate_dynamic_stack_space (op0, 0, align, cannot_accumulate);
85d654dd 4595 result = convert_memory_address (ptr_mode, result);
15c6cf6b 4596
4597 return result;
53800dbe 4598}
4599
c2f47e15 4600/* Expand a call to a bswap builtin with argument ARG0. MODE
42791117 4601 is the mode to expand with. */
4602
4603static rtx
c2f47e15 4604expand_builtin_bswap (tree exp, rtx target, rtx subtarget)
42791117 4605{
4606 enum machine_mode mode;
4607 tree arg;
4608 rtx op0;
4609
c2f47e15 4610 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4611 return NULL_RTX;
42791117 4612
c2f47e15 4613 arg = CALL_EXPR_ARG (exp, 0);
42791117 4614 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 4615 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
42791117 4616
4617 target = expand_unop (mode, bswap_optab, op0, target, 1);
4618
4619 gcc_assert (target);
4620
4621 return convert_to_mode (mode, target, 0);
4622}
4623
c2f47e15 4624/* Expand a call to a unary builtin in EXP.
4625 Return NULL_RTX if a normal call should be emitted rather than expanding the
53800dbe 4626 function in-line. If convenient, the result should be placed in TARGET.
4627 SUBTARGET may be used as the target for computing one of EXP's operands. */
15c6cf6b 4628
53800dbe 4629static rtx
c2f47e15 4630expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target,
aecda0d6 4631 rtx subtarget, optab op_optab)
53800dbe 4632{
4633 rtx op0;
c2f47e15 4634
4635 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4636 return NULL_RTX;
53800dbe 4637
4638 /* Compute the argument. */
f97eea22 4639 op0 = expand_expr (CALL_EXPR_ARG (exp, 0),
4640 (subtarget
4641 && (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0)))
4642 == GET_MODE (subtarget))) ? subtarget : NULL_RTX,
1db6d067 4643 VOIDmode, EXPAND_NORMAL);
6a08d0ab 4644 /* Compute op, into TARGET if possible.
53800dbe 4645 Set TARGET to wherever the result comes back. */
c2f47e15 4646 target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
6aaa1f9e 4647 op_optab, op0, target, op_optab != clrsb_optab);
64db345d 4648 gcc_assert (target);
7d3f6cc7 4649
efb070c8 4650 return convert_to_mode (target_mode, target, 0);
53800dbe 4651}
89cfe6e5 4652
48e1416a 4653/* Expand a call to __builtin_expect. We just return our argument
5a74f77e 4654 as the builtin_expect semantic should've been already executed by
4655 tree branch prediction pass. */
89cfe6e5 4656
4657static rtx
c2f47e15 4658expand_builtin_expect (tree exp, rtx target)
89cfe6e5 4659{
1e4adcfc 4660 tree arg;
89cfe6e5 4661
c2f47e15 4662 if (call_expr_nargs (exp) < 2)
89cfe6e5 4663 return const0_rtx;
c2f47e15 4664 arg = CALL_EXPR_ARG (exp, 0);
89cfe6e5 4665
c2f47e15 4666 target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5a74f77e 4667 /* When guessing was done, the hints should be already stripped away. */
07311427 4668 gcc_assert (!flag_guess_branch_prob
852f689e 4669 || optimize == 0 || seen_error ());
89cfe6e5 4670 return target;
4671}
689df48e 4672
fca0886c 4673/* Expand a call to __builtin_assume_aligned. We just return our first
4674 argument as the builtin_assume_aligned semantic should've been already
4675 executed by CCP. */
4676
4677static rtx
4678expand_builtin_assume_aligned (tree exp, rtx target)
4679{
4680 if (call_expr_nargs (exp) < 2)
4681 return const0_rtx;
4682 target = expand_expr (CALL_EXPR_ARG (exp, 0), target, VOIDmode,
4683 EXPAND_NORMAL);
4684 gcc_assert (!TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 1))
4685 && (call_expr_nargs (exp) < 3
4686 || !TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 2))));
4687 return target;
4688}
4689
c22de3f0 4690void
aecda0d6 4691expand_builtin_trap (void)
a0ef1725 4692{
4693#ifdef HAVE_trap
4694 if (HAVE_trap)
4695 emit_insn (gen_trap ());
4696 else
4697#endif
4698 emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
4699 emit_barrier ();
4700}
78a74442 4701
d2b48f0c 4702/* Expand a call to __builtin_unreachable. We do nothing except emit
4703 a barrier saying that control flow will not pass here.
4704
4705 It is the responsibility of the program being compiled to ensure
4706 that control flow does never reach __builtin_unreachable. */
4707static void
4708expand_builtin_unreachable (void)
4709{
4710 emit_barrier ();
4711}
4712
c2f47e15 4713/* Expand EXP, a call to fabs, fabsf or fabsl.
4714 Return NULL_RTX if a normal call should be emitted rather than expanding
78a74442 4715 the function inline. If convenient, the result should be placed
4716 in TARGET. SUBTARGET may be used as the target for computing
4717 the operand. */
4718
4719static rtx
c2f47e15 4720expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
78a74442 4721{
4722 enum machine_mode mode;
4723 tree arg;
4724 rtx op0;
4725
c2f47e15 4726 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
4727 return NULL_RTX;
78a74442 4728
c2f47e15 4729 arg = CALL_EXPR_ARG (exp, 0);
c7f617c2 4730 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
78a74442 4731 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 4732 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
78a74442 4733 return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
4734}
4735
c2f47e15 4736/* Expand EXP, a call to copysign, copysignf, or copysignl.
270436f3 4737 Return NULL is a normal call should be emitted rather than expanding the
4738 function inline. If convenient, the result should be placed in TARGET.
4739 SUBTARGET may be used as the target for computing the operand. */
4740
4741static rtx
c2f47e15 4742expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
270436f3 4743{
4744 rtx op0, op1;
4745 tree arg;
4746
c2f47e15 4747 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
4748 return NULL_RTX;
270436f3 4749
c2f47e15 4750 arg = CALL_EXPR_ARG (exp, 0);
8ec3c5c2 4751 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
270436f3 4752
c2f47e15 4753 arg = CALL_EXPR_ARG (exp, 1);
8ec3c5c2 4754 op1 = expand_normal (arg);
270436f3 4755
4756 return expand_copysign (op0, op1, target);
4757}
4758
19bf118a 4759/* Create a new constant string literal and return a char* pointer to it.
4760 The STRING_CST value is the LEN characters at STR. */
1e8e9920 4761tree
19bf118a 4762build_string_literal (int len, const char *str)
4763{
4764 tree t, elem, index, type;
4765
4766 t = build_string (len, str);
4767 elem = build_type_variant (char_type_node, 1, 0);
40238f64 4768 index = build_index_type (size_int (len - 1));
19bf118a 4769 type = build_array_type (elem, index);
4770 TREE_TYPE (t) = type;
4771 TREE_CONSTANT (t) = 1;
4772 TREE_READONLY (t) = 1;
4773 TREE_STATIC (t) = 1;
4774
19bf118a 4775 type = build_pointer_type (elem);
40238f64 4776 t = build1 (ADDR_EXPR, type,
4777 build4 (ARRAY_REF, elem,
4778 t, integer_zero_node, NULL_TREE, NULL_TREE));
19bf118a 4779 return t;
4780}
4781
ac8fb6db 4782/* Expand a call to __builtin___clear_cache. */
4783
4784static rtx
4785expand_builtin___clear_cache (tree exp ATTRIBUTE_UNUSED)
4786{
4787#ifndef HAVE_clear_cache
4788#ifdef CLEAR_INSN_CACHE
4789 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
4790 does something. Just do the default expansion to a call to
4791 __clear_cache(). */
4792 return NULL_RTX;
4793#else
4794 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
4795 does nothing. There is no need to call it. Do nothing. */
4796 return const0_rtx;
4797#endif /* CLEAR_INSN_CACHE */
4798#else
4799 /* We have a "clear_cache" insn, and it will handle everything. */
4800 tree begin, end;
4801 rtx begin_rtx, end_rtx;
ac8fb6db 4802
4803 /* We must not expand to a library call. If we did, any
4804 fallback library function in libgcc that might contain a call to
4805 __builtin___clear_cache() would recurse infinitely. */
4806 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4807 {
4808 error ("both arguments to %<__builtin___clear_cache%> must be pointers");
4809 return const0_rtx;
4810 }
4811
4812 if (HAVE_clear_cache)
4813 {
8786db1e 4814 struct expand_operand ops[2];
ac8fb6db 4815
4816 begin = CALL_EXPR_ARG (exp, 0);
4817 begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
ac8fb6db 4818
4819 end = CALL_EXPR_ARG (exp, 1);
4820 end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
ac8fb6db 4821
8786db1e 4822 create_address_operand (&ops[0], begin_rtx);
4823 create_address_operand (&ops[1], end_rtx);
4824 if (maybe_expand_insn (CODE_FOR_clear_cache, 2, ops))
4825 return const0_rtx;
ac8fb6db 4826 }
4827 return const0_rtx;
4828#endif /* HAVE_clear_cache */
4829}
4830
4ee9c684 4831/* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
4832
4833static rtx
4834round_trampoline_addr (rtx tramp)
4835{
4836 rtx temp, addend, mask;
4837
4838 /* If we don't need too much alignment, we'll have been guaranteed
4839 proper alignment by get_trampoline_type. */
4840 if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
4841 return tramp;
4842
4843 /* Round address up to desired boundary. */
4844 temp = gen_reg_rtx (Pmode);
4845 addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
4846 mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
4847
4848 temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
4849 temp, 0, OPTAB_LIB_WIDEN);
4850 tramp = expand_simple_binop (Pmode, AND, temp, mask,
4851 temp, 0, OPTAB_LIB_WIDEN);
4852
4853 return tramp;
4854}
4855
4856static rtx
c2f47e15 4857expand_builtin_init_trampoline (tree exp)
4ee9c684 4858{
4859 tree t_tramp, t_func, t_chain;
82c7907c 4860 rtx m_tramp, r_tramp, r_chain, tmp;
4ee9c684 4861
c2f47e15 4862 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
4ee9c684 4863 POINTER_TYPE, VOID_TYPE))
4864 return NULL_RTX;
4865
c2f47e15 4866 t_tramp = CALL_EXPR_ARG (exp, 0);
4867 t_func = CALL_EXPR_ARG (exp, 1);
4868 t_chain = CALL_EXPR_ARG (exp, 2);
4ee9c684 4869
8ec3c5c2 4870 r_tramp = expand_normal (t_tramp);
82c7907c 4871 m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
4872 MEM_NOTRAP_P (m_tramp) = 1;
4873
4874 /* The TRAMP argument should be the address of a field within the
4875 local function's FRAME decl. Let's see if we can fill in the
4876 to fill in the MEM_ATTRs for this memory. */
4877 if (TREE_CODE (t_tramp) == ADDR_EXPR)
4878 set_mem_attributes_minus_bitpos (m_tramp, TREE_OPERAND (t_tramp, 0),
4879 true, 0);
4880
4881 tmp = round_trampoline_addr (r_tramp);
4882 if (tmp != r_tramp)
4883 {
4884 m_tramp = change_address (m_tramp, BLKmode, tmp);
4885 set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
5b2a69fa 4886 set_mem_size (m_tramp, TRAMPOLINE_SIZE);
82c7907c 4887 }
4888
4889 /* The FUNC argument should be the address of the nested function.
4890 Extract the actual function decl to pass to the hook. */
4891 gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
4892 t_func = TREE_OPERAND (t_func, 0);
4893 gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
4894
8ec3c5c2 4895 r_chain = expand_normal (t_chain);
4ee9c684 4896
4897 /* Generate insns to initialize the trampoline. */
82c7907c 4898 targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
4ee9c684 4899
82c7907c 4900 trampolines_created = 1;
8bc8a8f4 4901
4902 warning_at (DECL_SOURCE_LOCATION (t_func), OPT_Wtrampolines,
4903 "trampoline generated for nested function %qD", t_func);
4904
4ee9c684 4905 return const0_rtx;
4906}
4907
4908static rtx
c2f47e15 4909expand_builtin_adjust_trampoline (tree exp)
4ee9c684 4910{
4911 rtx tramp;
4912
c2f47e15 4913 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
4ee9c684 4914 return NULL_RTX;
4915
c2f47e15 4916 tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
4ee9c684 4917 tramp = round_trampoline_addr (tramp);
82c7907c 4918 if (targetm.calls.trampoline_adjust_address)
4919 tramp = targetm.calls.trampoline_adjust_address (tramp);
4ee9c684 4920
4921 return tramp;
4922}
4923
93f564d6 4924/* Expand the call EXP to the built-in signbit, signbitf or signbitl
4925 function. The function first checks whether the back end provides
4926 an insn to implement signbit for the respective mode. If not, it
4927 checks whether the floating point format of the value is such that
4928 the sign bit can be extracted. If that is not the case, the
4929 function returns NULL_RTX to indicate that a normal call should be
4930 emitted rather than expanding the function in-line. EXP is the
4931 expression that is a call to the builtin function; if convenient,
4932 the result should be placed in TARGET. */
27f261ef 4933static rtx
4934expand_builtin_signbit (tree exp, rtx target)
4935{
4936 const struct real_format *fmt;
4937 enum machine_mode fmode, imode, rmode;
c2f47e15 4938 tree arg;
ca4f1f5b 4939 int word, bitpos;
27eda240 4940 enum insn_code icode;
27f261ef 4941 rtx temp;
389dd41b 4942 location_t loc = EXPR_LOCATION (exp);
27f261ef 4943
c2f47e15 4944 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
4945 return NULL_RTX;
27f261ef 4946
c2f47e15 4947 arg = CALL_EXPR_ARG (exp, 0);
27f261ef 4948 fmode = TYPE_MODE (TREE_TYPE (arg));
4949 rmode = TYPE_MODE (TREE_TYPE (exp));
4950 fmt = REAL_MODE_FORMAT (fmode);
4951
93f564d6 4952 arg = builtin_save_expr (arg);
4953
4954 /* Expand the argument yielding a RTX expression. */
4955 temp = expand_normal (arg);
4956
4957 /* Check if the back end provides an insn that handles signbit for the
4958 argument's mode. */
d6bf3b14 4959 icode = optab_handler (signbit_optab, fmode);
27eda240 4960 if (icode != CODE_FOR_nothing)
93f564d6 4961 {
4e2a2fb4 4962 rtx last = get_last_insn ();
93f564d6 4963 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
4e2a2fb4 4964 if (maybe_emit_unop_insn (icode, target, temp, UNKNOWN))
4965 return target;
4966 delete_insns_since (last);
93f564d6 4967 }
4968
27f261ef 4969 /* For floating point formats without a sign bit, implement signbit
4970 as "ARG < 0.0". */
8d564692 4971 bitpos = fmt->signbit_ro;
ca4f1f5b 4972 if (bitpos < 0)
27f261ef 4973 {
4974 /* But we can't do this if the format supports signed zero. */
4975 if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
c2f47e15 4976 return NULL_RTX;
27f261ef 4977
389dd41b 4978 arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
49d00087 4979 build_real (TREE_TYPE (arg), dconst0));
27f261ef 4980 return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
4981 }
4982
ca4f1f5b 4983 if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
27f261ef 4984 {
ca4f1f5b 4985 imode = int_mode_for_mode (fmode);
4986 if (imode == BLKmode)
c2f47e15 4987 return NULL_RTX;
ca4f1f5b 4988 temp = gen_lowpart (imode, temp);
24fd4260 4989 }
4990 else
4991 {
ca4f1f5b 4992 imode = word_mode;
4993 /* Handle targets with different FP word orders. */
4994 if (FLOAT_WORDS_BIG_ENDIAN)
a0c938f0 4995 word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
ca4f1f5b 4996 else
a0c938f0 4997 word = bitpos / BITS_PER_WORD;
ca4f1f5b 4998 temp = operand_subword_force (temp, word, fmode);
4999 bitpos = bitpos % BITS_PER_WORD;
5000 }
5001
44b0f1d0 5002 /* Force the intermediate word_mode (or narrower) result into a
5003 register. This avoids attempting to create paradoxical SUBREGs
5004 of floating point modes below. */
5005 temp = force_reg (imode, temp);
5006
ca4f1f5b 5007 /* If the bitpos is within the "result mode" lowpart, the operation
5008 can be implement with a single bitwise AND. Otherwise, we need
5009 a right shift and an AND. */
5010
5011 if (bitpos < GET_MODE_BITSIZE (rmode))
5012 {
3e052aec 5013 double_int mask = double_int_setbit (double_int_zero, bitpos);
27f261ef 5014
4a46f016 5015 if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
ca4f1f5b 5016 temp = gen_lowpart (rmode, temp);
24fd4260 5017 temp = expand_binop (rmode, and_optab, temp,
3e052aec 5018 immed_double_int_const (mask, rmode),
ca4f1f5b 5019 NULL_RTX, 1, OPTAB_LIB_WIDEN);
27f261ef 5020 }
ca4f1f5b 5021 else
5022 {
5023 /* Perform a logical right shift to place the signbit in the least
a0c938f0 5024 significant bit, then truncate the result to the desired mode
ca4f1f5b 5025 and mask just this bit. */
f5ff0b21 5026 temp = expand_shift (RSHIFT_EXPR, imode, temp, bitpos, NULL_RTX, 1);
ca4f1f5b 5027 temp = gen_lowpart (rmode, temp);
5028 temp = expand_binop (rmode, and_optab, temp, const1_rtx,
5029 NULL_RTX, 1, OPTAB_LIB_WIDEN);
5030 }
5031
27f261ef 5032 return temp;
5033}
73673831 5034
5035/* Expand fork or exec calls. TARGET is the desired target of the
c2f47e15 5036 call. EXP is the call. FN is the
73673831 5037 identificator of the actual function. IGNORE is nonzero if the
5038 value is to be ignored. */
5039
5040static rtx
c2f47e15 5041expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
73673831 5042{
5043 tree id, decl;
5044 tree call;
5045
5046 /* If we are not profiling, just call the function. */
5047 if (!profile_arc_flag)
5048 return NULL_RTX;
5049
5050 /* Otherwise call the wrapper. This should be equivalent for the rest of
5051 compiler, so the code does not diverge, and the wrapper may run the
9c9bad97 5052 code necessary for keeping the profiling sane. */
73673831 5053
5054 switch (DECL_FUNCTION_CODE (fn))
5055 {
5056 case BUILT_IN_FORK:
5057 id = get_identifier ("__gcov_fork");
5058 break;
5059
5060 case BUILT_IN_EXECL:
5061 id = get_identifier ("__gcov_execl");
5062 break;
5063
5064 case BUILT_IN_EXECV:
5065 id = get_identifier ("__gcov_execv");
5066 break;
5067
5068 case BUILT_IN_EXECLP:
5069 id = get_identifier ("__gcov_execlp");
5070 break;
5071
5072 case BUILT_IN_EXECLE:
5073 id = get_identifier ("__gcov_execle");
5074 break;
5075
5076 case BUILT_IN_EXECVP:
5077 id = get_identifier ("__gcov_execvp");
5078 break;
5079
5080 case BUILT_IN_EXECVE:
5081 id = get_identifier ("__gcov_execve");
5082 break;
5083
5084 default:
64db345d 5085 gcc_unreachable ();
73673831 5086 }
5087
e60a6f7b 5088 decl = build_decl (DECL_SOURCE_LOCATION (fn),
5089 FUNCTION_DECL, id, TREE_TYPE (fn));
73673831 5090 DECL_EXTERNAL (decl) = 1;
5091 TREE_PUBLIC (decl) = 1;
5092 DECL_ARTIFICIAL (decl) = 1;
5093 TREE_NOTHROW (decl) = 1;
e82d310b 5094 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
5095 DECL_VISIBILITY_SPECIFIED (decl) = 1;
389dd41b 5096 call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0);
73673831 5097 return expand_call (call, target, ignore);
c2f47e15 5098 }
48e1416a 5099
b6a5fc45 5100
5101\f
3e272de8 5102/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
5103 the pointer in these functions is void*, the tree optimizers may remove
5104 casts. The mode computed in expand_builtin isn't reliable either, due
5105 to __sync_bool_compare_and_swap.
5106
5107 FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
5108 group of builtins. This gives us log2 of the mode size. */
5109
5110static inline enum machine_mode
5111get_builtin_sync_mode (int fcode_diff)
5112{
ad3a13b5 5113 /* The size is not negotiable, so ask not to get BLKmode in return
5114 if the target indicates that a smaller size would be better. */
5115 return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
3e272de8 5116}
5117
041e0215 5118/* Expand the memory expression LOC and return the appropriate memory operand
5119 for the builtin_sync operations. */
5120
5121static rtx
5122get_builtin_sync_mem (tree loc, enum machine_mode mode)
5123{
5124 rtx addr, mem;
5125
7f4d56ad 5126 addr = expand_expr (loc, NULL_RTX, ptr_mode, EXPAND_SUM);
5127 addr = convert_memory_address (Pmode, addr);
041e0215 5128
5129 /* Note that we explicitly do not want any alias information for this
5130 memory, so that we kill all other live memories. Otherwise we don't
5131 satisfy the full barrier semantics of the intrinsic. */
5132 mem = validize_mem (gen_rtx_MEM (mode, addr));
5133
153c3b50 5134 /* The alignment needs to be at least according to that of the mode. */
5135 set_mem_align (mem, MAX (GET_MODE_ALIGNMENT (mode),
957d0361 5136 get_pointer_alignment (loc)));
c94cfd1c 5137 set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
041e0215 5138 MEM_VOLATILE_P (mem) = 1;
5139
5140 return mem;
5141}
5142
1cd6e20d 5143/* Make sure an argument is in the right mode.
5144 EXP is the tree argument.
5145 MODE is the mode it should be in. */
5146
5147static rtx
5148expand_expr_force_mode (tree exp, enum machine_mode mode)
5149{
5150 rtx val;
5151 enum machine_mode old_mode;
5152
5153 val = expand_expr (exp, NULL_RTX, mode, EXPAND_NORMAL);
5154 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5155 of CONST_INTs, where we know the old_mode only from the call argument. */
5156
5157 old_mode = GET_MODE (val);
5158 if (old_mode == VOIDmode)
5159 old_mode = TYPE_MODE (TREE_TYPE (exp));
5160 val = convert_modes (mode, old_mode, val, 1);
5161 return val;
5162}
5163
5164
b6a5fc45 5165/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
c2f47e15 5166 EXP is the CALL_EXPR. CODE is the rtx code
b6a5fc45 5167 that corresponds to the arithmetic or logical operation from the name;
5168 an exception here is that NOT actually means NAND. TARGET is an optional
5169 place for us to store the results; AFTER is true if this is the
1cd6e20d 5170 fetch_and_xxx form. */
b6a5fc45 5171
5172static rtx
c2f47e15 5173expand_builtin_sync_operation (enum machine_mode mode, tree exp,
3e272de8 5174 enum rtx_code code, bool after,
1cd6e20d 5175 rtx target)
b6a5fc45 5176{
041e0215 5177 rtx val, mem;
e60a6f7b 5178 location_t loc = EXPR_LOCATION (exp);
b6a5fc45 5179
cf73e559 5180 if (code == NOT && warn_sync_nand)
5181 {
5182 tree fndecl = get_callee_fndecl (exp);
5183 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
5184
5185 static bool warned_f_a_n, warned_n_a_f;
5186
5187 switch (fcode)
5188 {
2797f13a 5189 case BUILT_IN_SYNC_FETCH_AND_NAND_1:
5190 case BUILT_IN_SYNC_FETCH_AND_NAND_2:
5191 case BUILT_IN_SYNC_FETCH_AND_NAND_4:
5192 case BUILT_IN_SYNC_FETCH_AND_NAND_8:
5193 case BUILT_IN_SYNC_FETCH_AND_NAND_16:
cf73e559 5194 if (warned_f_a_n)
5195 break;
5196
b9a16870 5197 fndecl = builtin_decl_implicit (BUILT_IN_SYNC_FETCH_AND_NAND_N);
e60a6f7b 5198 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
cf73e559 5199 warned_f_a_n = true;
5200 break;
5201
2797f13a 5202 case BUILT_IN_SYNC_NAND_AND_FETCH_1:
5203 case BUILT_IN_SYNC_NAND_AND_FETCH_2:
5204 case BUILT_IN_SYNC_NAND_AND_FETCH_4:
5205 case BUILT_IN_SYNC_NAND_AND_FETCH_8:
5206 case BUILT_IN_SYNC_NAND_AND_FETCH_16:
cf73e559 5207 if (warned_n_a_f)
5208 break;
5209
b9a16870 5210 fndecl = builtin_decl_implicit (BUILT_IN_SYNC_NAND_AND_FETCH_N);
e60a6f7b 5211 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
cf73e559 5212 warned_n_a_f = true;
5213 break;
5214
5215 default:
5216 gcc_unreachable ();
5217 }
5218 }
5219
b6a5fc45 5220 /* Expand the operands. */
c2f47e15 5221 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1cd6e20d 5222 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
b6a5fc45 5223
1cd6e20d 5224 return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SEQ_CST,
5225 after);
b6a5fc45 5226}
5227
5228/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
c2f47e15 5229 intrinsics. EXP is the CALL_EXPR. IS_BOOL is
b6a5fc45 5230 true if this is the boolean form. TARGET is a place for us to store the
5231 results; this is NOT optional if IS_BOOL is true. */
5232
5233static rtx
c2f47e15 5234expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
3e272de8 5235 bool is_bool, rtx target)
b6a5fc45 5236{
041e0215 5237 rtx old_val, new_val, mem;
ba885f6a 5238 rtx *pbool, *poval;
b6a5fc45 5239
5240 /* Expand the operands. */
c2f47e15 5241 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1cd6e20d 5242 old_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5243 new_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
b6a5fc45 5244
ba885f6a 5245 pbool = poval = NULL;
5246 if (target != const0_rtx)
5247 {
5248 if (is_bool)
5249 pbool = &target;
5250 else
5251 poval = &target;
5252 }
5253 if (!expand_atomic_compare_and_swap (pbool, poval, mem, old_val, new_val,
5254 false, MEMMODEL_SEQ_CST,
5255 MEMMODEL_SEQ_CST))
1cd6e20d 5256 return NULL_RTX;
c2f47e15 5257
1cd6e20d 5258 return target;
b6a5fc45 5259}
5260
5261/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
5262 general form is actually an atomic exchange, and some targets only
5263 support a reduced form with the second argument being a constant 1.
48e1416a 5264 EXP is the CALL_EXPR; TARGET is an optional place for us to store
c2f47e15 5265 the results. */
b6a5fc45 5266
5267static rtx
2797f13a 5268expand_builtin_sync_lock_test_and_set (enum machine_mode mode, tree exp,
1cd6e20d 5269 rtx target)
b6a5fc45 5270{
041e0215 5271 rtx val, mem;
b6a5fc45 5272
5273 /* Expand the operands. */
c2f47e15 5274 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1cd6e20d 5275 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5276
7821cde1 5277 return expand_sync_lock_test_and_set (target, mem, val);
1cd6e20d 5278}
5279
5280/* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */
5281
5282static void
5283expand_builtin_sync_lock_release (enum machine_mode mode, tree exp)
5284{
5285 rtx mem;
5286
5287 /* Expand the operands. */
5288 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5289
8808bf16 5290 expand_atomic_store (mem, const0_rtx, MEMMODEL_RELEASE, true);
1cd6e20d 5291}
5292
5293/* Given an integer representing an ``enum memmodel'', verify its
5294 correctness and return the memory model enum. */
5295
5296static enum memmodel
5297get_memmodel (tree exp)
5298{
5299 rtx op;
5300
5301 /* If the parameter is not a constant, it's a run time value so we'll just
5302 convert it to MEMMODEL_SEQ_CST to avoid annoying runtime checking. */
5303 if (TREE_CODE (exp) != INTEGER_CST)
5304 return MEMMODEL_SEQ_CST;
5305
5306 op = expand_normal (exp);
5307 if (INTVAL (op) < 0 || INTVAL (op) >= MEMMODEL_LAST)
5308 {
5309 warning (OPT_Winvalid_memory_model,
5310 "invalid memory model argument to builtin");
5311 return MEMMODEL_SEQ_CST;
5312 }
5313 return (enum memmodel) INTVAL (op);
5314}
5315
5316/* Expand the __atomic_exchange intrinsic:
5317 TYPE __atomic_exchange (TYPE *object, TYPE desired, enum memmodel)
5318 EXP is the CALL_EXPR.
5319 TARGET is an optional place for us to store the results. */
5320
5321static rtx
5322expand_builtin_atomic_exchange (enum machine_mode mode, tree exp, rtx target)
5323{
5324 rtx val, mem;
5325 enum memmodel model;
5326
5327 model = get_memmodel (CALL_EXPR_ARG (exp, 2));
5328 if (model == MEMMODEL_CONSUME)
5329 {
5330 error ("invalid memory model for %<__atomic_exchange%>");
5331 return NULL_RTX;
5332 }
5333
5334 if (!flag_inline_atomics)
5335 return NULL_RTX;
5336
5337 /* Expand the operands. */
5338 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5339 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5340
7821cde1 5341 return expand_atomic_exchange (target, mem, val, model);
1cd6e20d 5342}
5343
5344/* Expand the __atomic_compare_exchange intrinsic:
5345 bool __atomic_compare_exchange (TYPE *object, TYPE *expect,
5346 TYPE desired, BOOL weak,
5347 enum memmodel success,
5348 enum memmodel failure)
5349 EXP is the CALL_EXPR.
5350 TARGET is an optional place for us to store the results. */
5351
5352static rtx
5353expand_builtin_atomic_compare_exchange (enum machine_mode mode, tree exp,
5354 rtx target)
5355{
5356 rtx expect, desired, mem, oldval;
5357 enum memmodel success, failure;
5358 tree weak;
5359 bool is_weak;
5360
5361 success = get_memmodel (CALL_EXPR_ARG (exp, 4));
5362 failure = get_memmodel (CALL_EXPR_ARG (exp, 5));
5363
5364 if (failure == MEMMODEL_RELEASE || failure == MEMMODEL_ACQ_REL)
5365 {
5366 error ("invalid failure memory model for %<__atomic_compare_exchange%>");
5367 return NULL_RTX;
5368 }
5369
5370 if (failure > success)
5371 {
5372 error ("failure memory model cannot be stronger than success "
5373 "memory model for %<__atomic_compare_exchange%>");
5374 return NULL_RTX;
5375 }
5376
5377 if (!flag_inline_atomics)
5378 return NULL_RTX;
5379
5380 /* Expand the operands. */
5381 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5382
5383 expect = expand_normal (CALL_EXPR_ARG (exp, 1));
5384 expect = convert_memory_address (Pmode, expect);
5385 desired = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
5386
5387 weak = CALL_EXPR_ARG (exp, 3);
5388 is_weak = false;
5389 if (host_integerp (weak, 0) && tree_low_cst (weak, 0) != 0)
5390 is_weak = true;
5391
5392 oldval = copy_to_reg (gen_rtx_MEM (mode, expect));
5393
ba885f6a 5394 if (!expand_atomic_compare_and_swap ((target == const0_rtx ? NULL : &target),
5395 &oldval, mem, oldval, desired,
5396 is_weak, success, failure))
1cd6e20d 5397 return NULL_RTX;
5398
5399 emit_move_insn (gen_rtx_MEM (mode, expect), oldval);
5400 return target;
5401}
5402
5403/* Expand the __atomic_load intrinsic:
5404 TYPE __atomic_load (TYPE *object, enum memmodel)
5405 EXP is the CALL_EXPR.
5406 TARGET is an optional place for us to store the results. */
5407
5408static rtx
5409expand_builtin_atomic_load (enum machine_mode mode, tree exp, rtx target)
5410{
5411 rtx mem;
5412 enum memmodel model;
5413
5414 model = get_memmodel (CALL_EXPR_ARG (exp, 1));
5415 if (model == MEMMODEL_RELEASE
5416 || model == MEMMODEL_ACQ_REL)
5417 {
5418 error ("invalid memory model for %<__atomic_load%>");
5419 return NULL_RTX;
5420 }
5421
5422 if (!flag_inline_atomics)
5423 return NULL_RTX;
5424
5425 /* Expand the operand. */
5426 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5427
5428 return expand_atomic_load (target, mem, model);
5429}
5430
5431
5432/* Expand the __atomic_store intrinsic:
5433 void __atomic_store (TYPE *object, TYPE desired, enum memmodel)
5434 EXP is the CALL_EXPR.
5435 TARGET is an optional place for us to store the results. */
5436
5437static rtx
5438expand_builtin_atomic_store (enum machine_mode mode, tree exp)
5439{
5440 rtx mem, val;
5441 enum memmodel model;
5442
5443 model = get_memmodel (CALL_EXPR_ARG (exp, 2));
5444 if (model != MEMMODEL_RELAXED
5445 && model != MEMMODEL_SEQ_CST
5446 && model != MEMMODEL_RELEASE)
5447 {
5448 error ("invalid memory model for %<__atomic_store%>");
5449 return NULL_RTX;
5450 }
5451
5452 if (!flag_inline_atomics)
5453 return NULL_RTX;
5454
5455 /* Expand the operands. */
5456 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5457 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5458
8808bf16 5459 return expand_atomic_store (mem, val, model, false);
1cd6e20d 5460}
5461
5462/* Expand the __atomic_fetch_XXX intrinsic:
5463 TYPE __atomic_fetch_XXX (TYPE *object, TYPE val, enum memmodel)
5464 EXP is the CALL_EXPR.
5465 TARGET is an optional place for us to store the results.
5466 CODE is the operation, PLUS, MINUS, ADD, XOR, or IOR.
5467 FETCH_AFTER is true if returning the result of the operation.
5468 FETCH_AFTER is false if returning the value before the operation.
5469 IGNORE is true if the result is not used.
5470 EXT_CALL is the correct builtin for an external call if this cannot be
5471 resolved to an instruction sequence. */
5472
5473static rtx
5474expand_builtin_atomic_fetch_op (enum machine_mode mode, tree exp, rtx target,
5475 enum rtx_code code, bool fetch_after,
5476 bool ignore, enum built_in_function ext_call)
5477{
5478 rtx val, mem, ret;
5479 enum memmodel model;
5480 tree fndecl;
5481 tree addr;
5482
5483 model = get_memmodel (CALL_EXPR_ARG (exp, 2));
5484
5485 /* Expand the operands. */
5486 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5487 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5488
5489 /* Only try generating instructions if inlining is turned on. */
5490 if (flag_inline_atomics)
5491 {
5492 ret = expand_atomic_fetch_op (target, mem, val, code, model, fetch_after);
5493 if (ret)
5494 return ret;
5495 }
5496
5497 /* Return if a different routine isn't needed for the library call. */
5498 if (ext_call == BUILT_IN_NONE)
5499 return NULL_RTX;
5500
5501 /* Change the call to the specified function. */
5502 fndecl = get_callee_fndecl (exp);
5503 addr = CALL_EXPR_FN (exp);
5504 STRIP_NOPS (addr);
5505
5506 gcc_assert (TREE_OPERAND (addr, 0) == fndecl);
5507 TREE_OPERAND (addr, 0) = builtin_decl_explicit(ext_call);
5508
5509 /* Expand the call here so we can emit trailing code. */
5510 ret = expand_call (exp, target, ignore);
5511
5512 /* Replace the original function just in case it matters. */
5513 TREE_OPERAND (addr, 0) = fndecl;
5514
5515 /* Then issue the arithmetic correction to return the right result. */
5516 if (!ignore)
c449f851 5517 {
5518 if (code == NOT)
5519 {
5520 ret = expand_simple_binop (mode, AND, ret, val, NULL_RTX, true,
5521 OPTAB_LIB_WIDEN);
5522 ret = expand_simple_unop (mode, NOT, ret, target, true);
5523 }
5524 else
5525 ret = expand_simple_binop (mode, code, ret, val, target, true,
5526 OPTAB_LIB_WIDEN);
5527 }
1cd6e20d 5528 return ret;
5529}
5530
10b744a3 5531
7821cde1 5532#ifndef HAVE_atomic_clear
5533# define HAVE_atomic_clear 0
5534# define gen_atomic_clear(x,y) (gcc_unreachable (), NULL_RTX)
5535#endif
5536
10b744a3 5537/* Expand an atomic clear operation.
5538 void _atomic_clear (BOOL *obj, enum memmodel)
5539 EXP is the call expression. */
5540
5541static rtx
5542expand_builtin_atomic_clear (tree exp)
5543{
5544 enum machine_mode mode;
5545 rtx mem, ret;
5546 enum memmodel model;
5547
5548 mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0);
5549 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5550 model = get_memmodel (CALL_EXPR_ARG (exp, 1));
5551
5552 if (model == MEMMODEL_ACQUIRE || model == MEMMODEL_ACQ_REL)
5553 {
5554 error ("invalid memory model for %<__atomic_store%>");
5555 return const0_rtx;
5556 }
5557
7821cde1 5558 if (HAVE_atomic_clear)
5559 {
5560 emit_insn (gen_atomic_clear (mem, model));
5561 return const0_rtx;
5562 }
5563
10b744a3 5564 /* Try issuing an __atomic_store, and allow fallback to __sync_lock_release.
5565 Failing that, a store is issued by __atomic_store. The only way this can
5566 fail is if the bool type is larger than a word size. Unlikely, but
5567 handle it anyway for completeness. Assume a single threaded model since
5568 there is no atomic support in this case, and no barriers are required. */
5569 ret = expand_atomic_store (mem, const0_rtx, model, true);
5570 if (!ret)
5571 emit_move_insn (mem, const0_rtx);
5572 return const0_rtx;
5573}
5574
5575/* Expand an atomic test_and_set operation.
5576 bool _atomic_test_and_set (BOOL *obj, enum memmodel)
5577 EXP is the call expression. */
5578
5579static rtx
7821cde1 5580expand_builtin_atomic_test_and_set (tree exp, rtx target)
10b744a3 5581{
7821cde1 5582 rtx mem;
10b744a3 5583 enum memmodel model;
5584 enum machine_mode mode;
5585
5586 mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0);
5587 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5588 model = get_memmodel (CALL_EXPR_ARG (exp, 1));
5589
7821cde1 5590 return expand_atomic_test_and_set (target, mem, model);
10b744a3 5591}
5592
5593
1cd6e20d 5594/* Return true if (optional) argument ARG1 of size ARG0 is always lock free on
5595 this architecture. If ARG1 is NULL, use typical alignment for size ARG0. */
5596
5597static tree
5598fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
5599{
5600 int size;
5601 enum machine_mode mode;
5602 unsigned int mode_align, type_align;
5603
5604 if (TREE_CODE (arg0) != INTEGER_CST)
5605 return NULL_TREE;
b6a5fc45 5606
1cd6e20d 5607 size = INTVAL (expand_normal (arg0)) * BITS_PER_UNIT;
5608 mode = mode_for_size (size, MODE_INT, 0);
5609 mode_align = GET_MODE_ALIGNMENT (mode);
5610
5611 if (TREE_CODE (arg1) == INTEGER_CST && INTVAL (expand_normal (arg1)) == 0)
5612 type_align = mode_align;
5613 else
5614 {
5615 tree ttype = TREE_TYPE (arg1);
5616
5617 /* This function is usually invoked and folded immediately by the front
5618 end before anything else has a chance to look at it. The pointer
5619 parameter at this point is usually cast to a void *, so check for that
5620 and look past the cast. */
5621 if (TREE_CODE (arg1) == NOP_EXPR && POINTER_TYPE_P (ttype)
5622 && VOID_TYPE_P (TREE_TYPE (ttype)))
5623 arg1 = TREE_OPERAND (arg1, 0);
5624
5625 ttype = TREE_TYPE (arg1);
5626 gcc_assert (POINTER_TYPE_P (ttype));
5627
5628 /* Get the underlying type of the object. */
5629 ttype = TREE_TYPE (ttype);
5630 type_align = TYPE_ALIGN (ttype);
5631 }
5632
5633 /* If the object has smaller alignment, the the lock free routines cannot
5634 be used. */
5635 if (type_align < mode_align)
5636 return integer_zero_node;
5637
5638 /* Check if a compare_and_swap pattern exists for the mode which represents
5639 the required size. The pattern is not allowed to fail, so the existence
5640 of the pattern indicates support is present. */
29139cdc 5641 if (can_compare_and_swap_p (mode, true))
1cd6e20d 5642 return integer_one_node;
5643 else
5644 return integer_zero_node;
5645}
5646
5647/* Return true if the parameters to call EXP represent an object which will
5648 always generate lock free instructions. The first argument represents the
5649 size of the object, and the second parameter is a pointer to the object
5650 itself. If NULL is passed for the object, then the result is based on
5651 typical alignment for an object of the specified size. Otherwise return
5652 false. */
5653
5654static rtx
5655expand_builtin_atomic_always_lock_free (tree exp)
5656{
5657 tree size;
5658 tree arg0 = CALL_EXPR_ARG (exp, 0);
5659 tree arg1 = CALL_EXPR_ARG (exp, 1);
5660
5661 if (TREE_CODE (arg0) != INTEGER_CST)
5662 {
5663 error ("non-constant argument 1 to __atomic_always_lock_free");
5664 return const0_rtx;
5665 }
5666
5667 size = fold_builtin_atomic_always_lock_free (arg0, arg1);
5668 if (size == integer_one_node)
5669 return const1_rtx;
5670 return const0_rtx;
5671}
5672
5673/* Return a one or zero if it can be determined that object ARG1 of size ARG
5674 is lock free on this architecture. */
5675
5676static tree
5677fold_builtin_atomic_is_lock_free (tree arg0, tree arg1)
5678{
5679 if (!flag_inline_atomics)
5680 return NULL_TREE;
5681
5682 /* If it isn't always lock free, don't generate a result. */
5683 if (fold_builtin_atomic_always_lock_free (arg0, arg1) == integer_one_node)
5684 return integer_one_node;
5685
5686 return NULL_TREE;
5687}
5688
5689/* Return true if the parameters to call EXP represent an object which will
5690 always generate lock free instructions. The first argument represents the
5691 size of the object, and the second parameter is a pointer to the object
5692 itself. If NULL is passed for the object, then the result is based on
5693 typical alignment for an object of the specified size. Otherwise return
5694 NULL*/
5695
5696static rtx
5697expand_builtin_atomic_is_lock_free (tree exp)
5698{
5699 tree size;
5700 tree arg0 = CALL_EXPR_ARG (exp, 0);
5701 tree arg1 = CALL_EXPR_ARG (exp, 1);
5702
5703 if (!INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
5704 {
5705 error ("non-integer argument 1 to __atomic_is_lock_free");
5706 return NULL_RTX;
5707 }
5708
5709 if (!flag_inline_atomics)
5710 return NULL_RTX;
5711
5712 /* If the value is known at compile time, return the RTX for it. */
5713 size = fold_builtin_atomic_is_lock_free (arg0, arg1);
5714 if (size == integer_one_node)
5715 return const1_rtx;
5716
5717 return NULL_RTX;
5718}
5719
1cd6e20d 5720/* Expand the __atomic_thread_fence intrinsic:
5721 void __atomic_thread_fence (enum memmodel)
5722 EXP is the CALL_EXPR. */
5723
5724static void
5725expand_builtin_atomic_thread_fence (tree exp)
5726{
fe54c06b 5727 enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
5728 expand_mem_thread_fence (model);
1cd6e20d 5729}
5730
5731/* Expand the __atomic_signal_fence intrinsic:
5732 void __atomic_signal_fence (enum memmodel)
5733 EXP is the CALL_EXPR. */
5734
5735static void
5736expand_builtin_atomic_signal_fence (tree exp)
5737{
fe54c06b 5738 enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
5739 expand_mem_signal_fence (model);
b6a5fc45 5740}
5741
5742/* Expand the __sync_synchronize intrinsic. */
5743
5744static void
2797f13a 5745expand_builtin_sync_synchronize (void)
b6a5fc45 5746{
fe54c06b 5747 expand_mem_thread_fence (MEMMODEL_SEQ_CST);
b6a5fc45 5748}
5749
53800dbe 5750\f
5751/* Expand an expression EXP that calls a built-in function,
5752 with result going to TARGET if that's convenient
5753 (and in mode MODE if that's convenient).
5754 SUBTARGET may be used as the target for computing one of EXP's operands.
5755 IGNORE is nonzero if the value is to be ignored. */
5756
5757rtx
aecda0d6 5758expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
5759 int ignore)
53800dbe 5760{
c6e6ecb1 5761 tree fndecl = get_callee_fndecl (exp);
53800dbe 5762 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
efb070c8 5763 enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
67fa4078 5764 int flags;
53800dbe 5765
8305149e 5766 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
883b2e73 5767 return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
bf8e3599 5768
53800dbe 5769 /* When not optimizing, generate calls to library functions for a certain
5770 set of builtins. */
cd9ff771 5771 if (!optimize
b6a5fc45 5772 && !called_as_built_in (fndecl)
cd9ff771 5773 && DECL_ASSEMBLER_NAME_SET_P (fndecl)
2c281b15 5774 && fcode != BUILT_IN_ALLOCA
581bf1c2 5775 && fcode != BUILT_IN_ALLOCA_WITH_ALIGN
2c281b15 5776 && fcode != BUILT_IN_FREE)
cd9ff771 5777 return expand_call (exp, target, ignore);
53800dbe 5778
8d6d7930 5779 /* The built-in function expanders test for target == const0_rtx
5780 to determine whether the function's result will be ignored. */
5781 if (ignore)
5782 target = const0_rtx;
5783
5784 /* If the result of a pure or const built-in function is ignored, and
5785 none of its arguments are volatile, we can avoid expanding the
5786 built-in call and just evaluate the arguments for side-effects. */
5787 if (target == const0_rtx
67fa4078 5788 && ((flags = flags_from_decl_or_type (fndecl)) & (ECF_CONST | ECF_PURE))
5789 && !(flags & ECF_LOOPING_CONST_OR_PURE))
8d6d7930 5790 {
5791 bool volatilep = false;
5792 tree arg;
c2f47e15 5793 call_expr_arg_iterator iter;
8d6d7930 5794
c2f47e15 5795 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5796 if (TREE_THIS_VOLATILE (arg))
8d6d7930 5797 {
5798 volatilep = true;
5799 break;
5800 }
5801
5802 if (! volatilep)
5803 {
c2f47e15 5804 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5805 expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
8d6d7930 5806 return const0_rtx;
5807 }
5808 }
5809
53800dbe 5810 switch (fcode)
5811 {
4f35b1fc 5812 CASE_FLT_FN (BUILT_IN_FABS):
c2f47e15 5813 target = expand_builtin_fabs (exp, target, subtarget);
78a74442 5814 if (target)
a0c938f0 5815 return target;
78a74442 5816 break;
5817
4f35b1fc 5818 CASE_FLT_FN (BUILT_IN_COPYSIGN):
c2f47e15 5819 target = expand_builtin_copysign (exp, target, subtarget);
270436f3 5820 if (target)
5821 return target;
5822 break;
5823
7d3f6cc7 5824 /* Just do a normal library call if we were unable to fold
5825 the values. */
4f35b1fc 5826 CASE_FLT_FN (BUILT_IN_CABS):
78a74442 5827 break;
53800dbe 5828
4f35b1fc 5829 CASE_FLT_FN (BUILT_IN_EXP):
5830 CASE_FLT_FN (BUILT_IN_EXP10):
5831 CASE_FLT_FN (BUILT_IN_POW10):
5832 CASE_FLT_FN (BUILT_IN_EXP2):
5833 CASE_FLT_FN (BUILT_IN_EXPM1):
5834 CASE_FLT_FN (BUILT_IN_LOGB):
4f35b1fc 5835 CASE_FLT_FN (BUILT_IN_LOG):
5836 CASE_FLT_FN (BUILT_IN_LOG10):
5837 CASE_FLT_FN (BUILT_IN_LOG2):
5838 CASE_FLT_FN (BUILT_IN_LOG1P):
5839 CASE_FLT_FN (BUILT_IN_TAN):
5840 CASE_FLT_FN (BUILT_IN_ASIN):
5841 CASE_FLT_FN (BUILT_IN_ACOS):
5842 CASE_FLT_FN (BUILT_IN_ATAN):
b3154a1f 5843 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
7f3be425 5844 /* Treat these like sqrt only if unsafe math optimizations are allowed,
5845 because of possible accuracy problems. */
5846 if (! flag_unsafe_math_optimizations)
53800dbe 5847 break;
4f35b1fc 5848 CASE_FLT_FN (BUILT_IN_SQRT):
5849 CASE_FLT_FN (BUILT_IN_FLOOR):
5850 CASE_FLT_FN (BUILT_IN_CEIL):
5851 CASE_FLT_FN (BUILT_IN_TRUNC):
5852 CASE_FLT_FN (BUILT_IN_ROUND):
5853 CASE_FLT_FN (BUILT_IN_NEARBYINT):
5854 CASE_FLT_FN (BUILT_IN_RINT):
53800dbe 5855 target = expand_builtin_mathfn (exp, target, subtarget);
5856 if (target)
5857 return target;
5858 break;
5859
7e0713b1 5860 CASE_FLT_FN (BUILT_IN_FMA):
5861 target = expand_builtin_mathfn_ternary (exp, target, subtarget);
5862 if (target)
5863 return target;
5864 break;
5865
a67a90e5 5866 CASE_FLT_FN (BUILT_IN_ILOGB):
5867 if (! flag_unsafe_math_optimizations)
5868 break;
69b779ea 5869 CASE_FLT_FN (BUILT_IN_ISINF):
cde061c1 5870 CASE_FLT_FN (BUILT_IN_FINITE):
5871 case BUILT_IN_ISFINITE:
8a1a9cb7 5872 case BUILT_IN_ISNORMAL:
f97eea22 5873 target = expand_builtin_interclass_mathfn (exp, target);
a67a90e5 5874 if (target)
5875 return target;
5876 break;
5877
80ff6494 5878 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 5879 CASE_FLT_FN (BUILT_IN_LCEIL):
5880 CASE_FLT_FN (BUILT_IN_LLCEIL):
5881 CASE_FLT_FN (BUILT_IN_LFLOOR):
80ff6494 5882 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 5883 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ff1b14e4 5884 target = expand_builtin_int_roundingfn (exp, target);
ad52b9b7 5885 if (target)
5886 return target;
5887 break;
5888
80ff6494 5889 CASE_FLT_FN (BUILT_IN_IRINT):
7d3afc77 5890 CASE_FLT_FN (BUILT_IN_LRINT):
5891 CASE_FLT_FN (BUILT_IN_LLRINT):
80ff6494 5892 CASE_FLT_FN (BUILT_IN_IROUND):
ef2f1a10 5893 CASE_FLT_FN (BUILT_IN_LROUND):
5894 CASE_FLT_FN (BUILT_IN_LLROUND):
ff1b14e4 5895 target = expand_builtin_int_roundingfn_2 (exp, target);
7d3afc77 5896 if (target)
5897 return target;
5898 break;
5899
4f35b1fc 5900 CASE_FLT_FN (BUILT_IN_POWI):
f97eea22 5901 target = expand_builtin_powi (exp, target);
757c219d 5902 if (target)
5903 return target;
5904 break;
5905
4f35b1fc 5906 CASE_FLT_FN (BUILT_IN_ATAN2):
5907 CASE_FLT_FN (BUILT_IN_LDEXP):
73a954a1 5908 CASE_FLT_FN (BUILT_IN_SCALB):
5909 CASE_FLT_FN (BUILT_IN_SCALBN):
5910 CASE_FLT_FN (BUILT_IN_SCALBLN):
0fd605a5 5911 if (! flag_unsafe_math_optimizations)
5912 break;
ef722005 5913
5914 CASE_FLT_FN (BUILT_IN_FMOD):
5915 CASE_FLT_FN (BUILT_IN_REMAINDER):
5916 CASE_FLT_FN (BUILT_IN_DREM):
0810ff17 5917 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 5918 target = expand_builtin_mathfn_2 (exp, target, subtarget);
5919 if (target)
5920 return target;
5921 break;
5922
d735c391 5923 CASE_FLT_FN (BUILT_IN_CEXPI):
f97eea22 5924 target = expand_builtin_cexpi (exp, target);
d735c391 5925 gcc_assert (target);
5926 return target;
5927
4f35b1fc 5928 CASE_FLT_FN (BUILT_IN_SIN):
5929 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 5930 if (! flag_unsafe_math_optimizations)
5931 break;
5932 target = expand_builtin_mathfn_3 (exp, target, subtarget);
5933 if (target)
5934 return target;
5935 break;
5936
c3147c1a 5937 CASE_FLT_FN (BUILT_IN_SINCOS):
5938 if (! flag_unsafe_math_optimizations)
5939 break;
5940 target = expand_builtin_sincos (exp);
5941 if (target)
5942 return target;
5943 break;
5944
53800dbe 5945 case BUILT_IN_APPLY_ARGS:
5946 return expand_builtin_apply_args ();
5947
5948 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
5949 FUNCTION with a copy of the parameters described by
5950 ARGUMENTS, and ARGSIZE. It returns a block of memory
5951 allocated on the stack into which is stored all the registers
5952 that might possibly be used for returning the result of a
5953 function. ARGUMENTS is the value returned by
5954 __builtin_apply_args. ARGSIZE is the number of bytes of
5955 arguments that must be copied. ??? How should this value be
5956 computed? We'll also need a safe worst case value for varargs
5957 functions. */
5958 case BUILT_IN_APPLY:
c2f47e15 5959 if (!validate_arglist (exp, POINTER_TYPE,
0eb671f7 5960 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
c2f47e15 5961 && !validate_arglist (exp, REFERENCE_TYPE,
0eb671f7 5962 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 5963 return const0_rtx;
5964 else
5965 {
53800dbe 5966 rtx ops[3];
5967
c2f47e15 5968 ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
5969 ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
5970 ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
53800dbe 5971
5972 return expand_builtin_apply (ops[0], ops[1], ops[2]);
5973 }
5974
5975 /* __builtin_return (RESULT) causes the function to return the
5976 value described by RESULT. RESULT is address of the block of
5977 memory returned by __builtin_apply. */
5978 case BUILT_IN_RETURN:
c2f47e15 5979 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
5980 expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
53800dbe 5981 return const0_rtx;
5982
5983 case BUILT_IN_SAVEREGS:
a66c9326 5984 return expand_builtin_saveregs ();
53800dbe 5985
48dc2227 5986 case BUILT_IN_VA_ARG_PACK:
5987 /* All valid uses of __builtin_va_arg_pack () are removed during
5988 inlining. */
b8c23db3 5989 error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
48dc2227 5990 return const0_rtx;
5991
4e1d7ea4 5992 case BUILT_IN_VA_ARG_PACK_LEN:
5993 /* All valid uses of __builtin_va_arg_pack_len () are removed during
5994 inlining. */
b8c23db3 5995 error ("%Kinvalid use of %<__builtin_va_arg_pack_len ()%>", exp);
4e1d7ea4 5996 return const0_rtx;
5997
53800dbe 5998 /* Return the address of the first anonymous stack arg. */
5999 case BUILT_IN_NEXT_ARG:
c2f47e15 6000 if (fold_builtin_next_arg (exp, false))
a0c938f0 6001 return const0_rtx;
79012a9d 6002 return expand_builtin_next_arg ();
53800dbe 6003
ac8fb6db 6004 case BUILT_IN_CLEAR_CACHE:
6005 target = expand_builtin___clear_cache (exp);
6006 if (target)
6007 return target;
6008 break;
6009
53800dbe 6010 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 6011 return expand_builtin_classify_type (exp);
53800dbe 6012
6013 case BUILT_IN_CONSTANT_P:
4ee9c684 6014 return const0_rtx;
53800dbe 6015
6016 case BUILT_IN_FRAME_ADDRESS:
6017 case BUILT_IN_RETURN_ADDRESS:
c2f47e15 6018 return expand_builtin_frame_address (fndecl, exp);
53800dbe 6019
6020 /* Returns the address of the area where the structure is returned.
6021 0 otherwise. */
6022 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
c2f47e15 6023 if (call_expr_nargs (exp) != 0
9342ee68 6024 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
e16ceb8e 6025 || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
9342ee68 6026 return const0_rtx;
53800dbe 6027 else
9342ee68 6028 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
53800dbe 6029
6030 case BUILT_IN_ALLOCA:
581bf1c2 6031 case BUILT_IN_ALLOCA_WITH_ALIGN:
990495a7 6032 /* If the allocation stems from the declaration of a variable-sized
6033 object, it cannot accumulate. */
a882d754 6034 target = expand_builtin_alloca (exp, CALL_ALLOCA_FOR_VAR_P (exp));
53800dbe 6035 if (target)
6036 return target;
6037 break;
6038
4ee9c684 6039 case BUILT_IN_STACK_SAVE:
6040 return expand_stack_save ();
6041
6042 case BUILT_IN_STACK_RESTORE:
c2f47e15 6043 expand_stack_restore (CALL_EXPR_ARG (exp, 0));
4ee9c684 6044 return const0_rtx;
6045
42791117 6046 case BUILT_IN_BSWAP32:
6047 case BUILT_IN_BSWAP64:
c2f47e15 6048 target = expand_builtin_bswap (exp, target, subtarget);
42791117 6049
6050 if (target)
6051 return target;
6052 break;
6053
4f35b1fc 6054 CASE_INT_FN (BUILT_IN_FFS):
5053259b 6055 case BUILT_IN_FFSIMAX:
c2f47e15 6056 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6057 subtarget, ffs_optab);
6a08d0ab 6058 if (target)
6059 return target;
6060 break;
6061
4f35b1fc 6062 CASE_INT_FN (BUILT_IN_CLZ):
5053259b 6063 case BUILT_IN_CLZIMAX:
c2f47e15 6064 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6065 subtarget, clz_optab);
6a08d0ab 6066 if (target)
6067 return target;
6068 break;
6069
4f35b1fc 6070 CASE_INT_FN (BUILT_IN_CTZ):
5053259b 6071 case BUILT_IN_CTZIMAX:
c2f47e15 6072 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6073 subtarget, ctz_optab);
6a08d0ab 6074 if (target)
6075 return target;
6076 break;
6077
d8492bd3 6078 CASE_INT_FN (BUILT_IN_CLRSB):
6079 case BUILT_IN_CLRSBIMAX:
6080 target = expand_builtin_unop (target_mode, exp, target,
6081 subtarget, clrsb_optab);
6082 if (target)
6083 return target;
6084 break;
6085
4f35b1fc 6086 CASE_INT_FN (BUILT_IN_POPCOUNT):
5053259b 6087 case BUILT_IN_POPCOUNTIMAX:
c2f47e15 6088 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6089 subtarget, popcount_optab);
6a08d0ab 6090 if (target)
6091 return target;
6092 break;
6093
4f35b1fc 6094 CASE_INT_FN (BUILT_IN_PARITY):
5053259b 6095 case BUILT_IN_PARITYIMAX:
c2f47e15 6096 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6097 subtarget, parity_optab);
53800dbe 6098 if (target)
6099 return target;
6100 break;
6101
6102 case BUILT_IN_STRLEN:
c2f47e15 6103 target = expand_builtin_strlen (exp, target, target_mode);
53800dbe 6104 if (target)
6105 return target;
6106 break;
6107
6108 case BUILT_IN_STRCPY:
a65c4d64 6109 target = expand_builtin_strcpy (exp, target);
53800dbe 6110 if (target)
6111 return target;
6112 break;
bf8e3599 6113
ed09096d 6114 case BUILT_IN_STRNCPY:
a65c4d64 6115 target = expand_builtin_strncpy (exp, target);
ed09096d 6116 if (target)
6117 return target;
6118 break;
bf8e3599 6119
3b824fa6 6120 case BUILT_IN_STPCPY:
dc369150 6121 target = expand_builtin_stpcpy (exp, target, mode);
3b824fa6 6122 if (target)
6123 return target;
6124 break;
6125
53800dbe 6126 case BUILT_IN_MEMCPY:
a65c4d64 6127 target = expand_builtin_memcpy (exp, target);
3b824fa6 6128 if (target)
6129 return target;
6130 break;
6131
6132 case BUILT_IN_MEMPCPY:
c2f47e15 6133 target = expand_builtin_mempcpy (exp, target, mode);
53800dbe 6134 if (target)
6135 return target;
6136 break;
6137
6138 case BUILT_IN_MEMSET:
c2f47e15 6139 target = expand_builtin_memset (exp, target, mode);
53800dbe 6140 if (target)
6141 return target;
6142 break;
6143
ffc83088 6144 case BUILT_IN_BZERO:
0b25db21 6145 target = expand_builtin_bzero (exp);
ffc83088 6146 if (target)
6147 return target;
6148 break;
6149
53800dbe 6150 case BUILT_IN_STRCMP:
a65c4d64 6151 target = expand_builtin_strcmp (exp, target);
53800dbe 6152 if (target)
6153 return target;
6154 break;
6155
ed09096d 6156 case BUILT_IN_STRNCMP:
6157 target = expand_builtin_strncmp (exp, target, mode);
6158 if (target)
6159 return target;
6160 break;
6161
071f1696 6162 case BUILT_IN_BCMP:
53800dbe 6163 case BUILT_IN_MEMCMP:
c2f47e15 6164 target = expand_builtin_memcmp (exp, target, mode);
53800dbe 6165 if (target)
6166 return target;
6167 break;
53800dbe 6168
6169 case BUILT_IN_SETJMP:
2c8a1497 6170 /* This should have been lowered to the builtins below. */
6171 gcc_unreachable ();
6172
6173 case BUILT_IN_SETJMP_SETUP:
6174 /* __builtin_setjmp_setup is passed a pointer to an array of five words
6175 and the receiver label. */
c2f47e15 6176 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2c8a1497 6177 {
c2f47e15 6178 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
2c8a1497 6179 VOIDmode, EXPAND_NORMAL);
c2f47e15 6180 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
2c8a1497 6181 rtx label_r = label_rtx (label);
6182
6183 /* This is copied from the handling of non-local gotos. */
6184 expand_builtin_setjmp_setup (buf_addr, label_r);
6185 nonlocal_goto_handler_labels
6186 = gen_rtx_EXPR_LIST (VOIDmode, label_r,
6187 nonlocal_goto_handler_labels);
6188 /* ??? Do not let expand_label treat us as such since we would
6189 not want to be both on the list of non-local labels and on
6190 the list of forced labels. */
6191 FORCED_LABEL (label) = 0;
6192 return const0_rtx;
6193 }
6194 break;
6195
6196 case BUILT_IN_SETJMP_DISPATCHER:
6197 /* __builtin_setjmp_dispatcher is passed the dispatcher label. */
c2f47e15 6198 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6199 {
c2f47e15 6200 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6201 rtx label_r = label_rtx (label);
6202
6203 /* Remove the dispatcher label from the list of non-local labels
6204 since the receiver labels have been added to it above. */
6205 remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels);
6206 return const0_rtx;
6207 }
6208 break;
6209
6210 case BUILT_IN_SETJMP_RECEIVER:
6211 /* __builtin_setjmp_receiver is passed the receiver label. */
c2f47e15 6212 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6213 {
c2f47e15 6214 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6215 rtx label_r = label_rtx (label);
6216
6217 expand_builtin_setjmp_receiver (label_r);
6218 return const0_rtx;
6219 }
6b7f6858 6220 break;
53800dbe 6221
6222 /* __builtin_longjmp is passed a pointer to an array of five words.
6223 It's similar to the C library longjmp function but works with
6224 __builtin_setjmp above. */
6225 case BUILT_IN_LONGJMP:
c2f47e15 6226 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 6227 {
c2f47e15 6228 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
8ec3c5c2 6229 VOIDmode, EXPAND_NORMAL);
c2f47e15 6230 rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
53800dbe 6231
6232 if (value != const1_rtx)
6233 {
1e5fcbe2 6234 error ("%<__builtin_longjmp%> second argument must be 1");
53800dbe 6235 return const0_rtx;
6236 }
6237
6238 expand_builtin_longjmp (buf_addr, value);
6239 return const0_rtx;
6240 }
2c8a1497 6241 break;
53800dbe 6242
4ee9c684 6243 case BUILT_IN_NONLOCAL_GOTO:
c2f47e15 6244 target = expand_builtin_nonlocal_goto (exp);
4ee9c684 6245 if (target)
6246 return target;
6247 break;
6248
843d08a9 6249 /* This updates the setjmp buffer that is its argument with the value
6250 of the current stack pointer. */
6251 case BUILT_IN_UPDATE_SETJMP_BUF:
c2f47e15 6252 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
843d08a9 6253 {
6254 rtx buf_addr
c2f47e15 6255 = expand_normal (CALL_EXPR_ARG (exp, 0));
843d08a9 6256
6257 expand_builtin_update_setjmp_buf (buf_addr);
6258 return const0_rtx;
6259 }
6260 break;
6261
53800dbe 6262 case BUILT_IN_TRAP:
a0ef1725 6263 expand_builtin_trap ();
53800dbe 6264 return const0_rtx;
6265
d2b48f0c 6266 case BUILT_IN_UNREACHABLE:
6267 expand_builtin_unreachable ();
6268 return const0_rtx;
6269
4f35b1fc 6270 CASE_FLT_FN (BUILT_IN_SIGNBIT):
004e23c4 6271 case BUILT_IN_SIGNBITD32:
6272 case BUILT_IN_SIGNBITD64:
6273 case BUILT_IN_SIGNBITD128:
27f261ef 6274 target = expand_builtin_signbit (exp, target);
6275 if (target)
6276 return target;
6277 break;
6278
53800dbe 6279 /* Various hooks for the DWARF 2 __throw routine. */
6280 case BUILT_IN_UNWIND_INIT:
6281 expand_builtin_unwind_init ();
6282 return const0_rtx;
6283 case BUILT_IN_DWARF_CFA:
6284 return virtual_cfa_rtx;
6285#ifdef DWARF2_UNWIND_INFO
f8f023a5 6286 case BUILT_IN_DWARF_SP_COLUMN:
6287 return expand_builtin_dwarf_sp_column ();
695e919b 6288 case BUILT_IN_INIT_DWARF_REG_SIZES:
c2f47e15 6289 expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
695e919b 6290 return const0_rtx;
53800dbe 6291#endif
6292 case BUILT_IN_FROB_RETURN_ADDR:
c2f47e15 6293 return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6294 case BUILT_IN_EXTRACT_RETURN_ADDR:
c2f47e15 6295 return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6296 case BUILT_IN_EH_RETURN:
c2f47e15 6297 expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
6298 CALL_EXPR_ARG (exp, 1));
53800dbe 6299 return const0_rtx;
df4b504c 6300#ifdef EH_RETURN_DATA_REGNO
6301 case BUILT_IN_EH_RETURN_DATA_REGNO:
c2f47e15 6302 return expand_builtin_eh_return_data_regno (exp);
df4b504c 6303#endif
26093bf4 6304 case BUILT_IN_EXTEND_POINTER:
c2f47e15 6305 return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
e38def9c 6306 case BUILT_IN_EH_POINTER:
6307 return expand_builtin_eh_pointer (exp);
6308 case BUILT_IN_EH_FILTER:
6309 return expand_builtin_eh_filter (exp);
6310 case BUILT_IN_EH_COPY_VALUES:
6311 return expand_builtin_eh_copy_values (exp);
26093bf4 6312
7ccc713a 6313 case BUILT_IN_VA_START:
c2f47e15 6314 return expand_builtin_va_start (exp);
a66c9326 6315 case BUILT_IN_VA_END:
c2f47e15 6316 return expand_builtin_va_end (exp);
a66c9326 6317 case BUILT_IN_VA_COPY:
c2f47e15 6318 return expand_builtin_va_copy (exp);
89cfe6e5 6319 case BUILT_IN_EXPECT:
c2f47e15 6320 return expand_builtin_expect (exp, target);
fca0886c 6321 case BUILT_IN_ASSUME_ALIGNED:
6322 return expand_builtin_assume_aligned (exp, target);
5e3608d8 6323 case BUILT_IN_PREFETCH:
c2f47e15 6324 expand_builtin_prefetch (exp);
5e3608d8 6325 return const0_rtx;
6326
4ee9c684 6327 case BUILT_IN_INIT_TRAMPOLINE:
c2f47e15 6328 return expand_builtin_init_trampoline (exp);
4ee9c684 6329 case BUILT_IN_ADJUST_TRAMPOLINE:
c2f47e15 6330 return expand_builtin_adjust_trampoline (exp);
4ee9c684 6331
73673831 6332 case BUILT_IN_FORK:
6333 case BUILT_IN_EXECL:
6334 case BUILT_IN_EXECV:
6335 case BUILT_IN_EXECLP:
6336 case BUILT_IN_EXECLE:
6337 case BUILT_IN_EXECVP:
6338 case BUILT_IN_EXECVE:
c2f47e15 6339 target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
73673831 6340 if (target)
6341 return target;
6342 break;
53800dbe 6343
2797f13a 6344 case BUILT_IN_SYNC_FETCH_AND_ADD_1:
6345 case BUILT_IN_SYNC_FETCH_AND_ADD_2:
6346 case BUILT_IN_SYNC_FETCH_AND_ADD_4:
6347 case BUILT_IN_SYNC_FETCH_AND_ADD_8:
6348 case BUILT_IN_SYNC_FETCH_AND_ADD_16:
6349 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_ADD_1);
1cd6e20d 6350 target = expand_builtin_sync_operation (mode, exp, PLUS, false, target);
b6a5fc45 6351 if (target)
6352 return target;
6353 break;
6354
2797f13a 6355 case BUILT_IN_SYNC_FETCH_AND_SUB_1:
6356 case BUILT_IN_SYNC_FETCH_AND_SUB_2:
6357 case BUILT_IN_SYNC_FETCH_AND_SUB_4:
6358 case BUILT_IN_SYNC_FETCH_AND_SUB_8:
6359 case BUILT_IN_SYNC_FETCH_AND_SUB_16:
6360 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_SUB_1);
1cd6e20d 6361 target = expand_builtin_sync_operation (mode, exp, MINUS, false, target);
b6a5fc45 6362 if (target)
6363 return target;
6364 break;
6365
2797f13a 6366 case BUILT_IN_SYNC_FETCH_AND_OR_1:
6367 case BUILT_IN_SYNC_FETCH_AND_OR_2:
6368 case BUILT_IN_SYNC_FETCH_AND_OR_4:
6369 case BUILT_IN_SYNC_FETCH_AND_OR_8:
6370 case BUILT_IN_SYNC_FETCH_AND_OR_16:
6371 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_OR_1);
1cd6e20d 6372 target = expand_builtin_sync_operation (mode, exp, IOR, false, target);
b6a5fc45 6373 if (target)
6374 return target;
6375 break;
6376
2797f13a 6377 case BUILT_IN_SYNC_FETCH_AND_AND_1:
6378 case BUILT_IN_SYNC_FETCH_AND_AND_2:
6379 case BUILT_IN_SYNC_FETCH_AND_AND_4:
6380 case BUILT_IN_SYNC_FETCH_AND_AND_8:
6381 case BUILT_IN_SYNC_FETCH_AND_AND_16:
6382 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_AND_1);
1cd6e20d 6383 target = expand_builtin_sync_operation (mode, exp, AND, false, target);
b6a5fc45 6384 if (target)
6385 return target;
6386 break;
6387
2797f13a 6388 case BUILT_IN_SYNC_FETCH_AND_XOR_1:
6389 case BUILT_IN_SYNC_FETCH_AND_XOR_2:
6390 case BUILT_IN_SYNC_FETCH_AND_XOR_4:
6391 case BUILT_IN_SYNC_FETCH_AND_XOR_8:
6392 case BUILT_IN_SYNC_FETCH_AND_XOR_16:
6393 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_XOR_1);
1cd6e20d 6394 target = expand_builtin_sync_operation (mode, exp, XOR, false, target);
b6a5fc45 6395 if (target)
6396 return target;
6397 break;
6398
2797f13a 6399 case BUILT_IN_SYNC_FETCH_AND_NAND_1:
6400 case BUILT_IN_SYNC_FETCH_AND_NAND_2:
6401 case BUILT_IN_SYNC_FETCH_AND_NAND_4:
6402 case BUILT_IN_SYNC_FETCH_AND_NAND_8:
6403 case BUILT_IN_SYNC_FETCH_AND_NAND_16:
6404 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_NAND_1);
1cd6e20d 6405 target = expand_builtin_sync_operation (mode, exp, NOT, false, target);
b6a5fc45 6406 if (target)
6407 return target;
6408 break;
6409
2797f13a 6410 case BUILT_IN_SYNC_ADD_AND_FETCH_1:
6411 case BUILT_IN_SYNC_ADD_AND_FETCH_2:
6412 case BUILT_IN_SYNC_ADD_AND_FETCH_4:
6413 case BUILT_IN_SYNC_ADD_AND_FETCH_8:
6414 case BUILT_IN_SYNC_ADD_AND_FETCH_16:
6415 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_ADD_AND_FETCH_1);
1cd6e20d 6416 target = expand_builtin_sync_operation (mode, exp, PLUS, true, target);
b6a5fc45 6417 if (target)
6418 return target;
6419 break;
6420
2797f13a 6421 case BUILT_IN_SYNC_SUB_AND_FETCH_1:
6422 case BUILT_IN_SYNC_SUB_AND_FETCH_2:
6423 case BUILT_IN_SYNC_SUB_AND_FETCH_4:
6424 case BUILT_IN_SYNC_SUB_AND_FETCH_8:
6425 case BUILT_IN_SYNC_SUB_AND_FETCH_16:
6426 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_SUB_AND_FETCH_1);
1cd6e20d 6427 target = expand_builtin_sync_operation (mode, exp, MINUS, true, target);
b6a5fc45 6428 if (target)
6429 return target;
6430 break;
6431
2797f13a 6432 case BUILT_IN_SYNC_OR_AND_FETCH_1:
6433 case BUILT_IN_SYNC_OR_AND_FETCH_2:
6434 case BUILT_IN_SYNC_OR_AND_FETCH_4:
6435 case BUILT_IN_SYNC_OR_AND_FETCH_8:
6436 case BUILT_IN_SYNC_OR_AND_FETCH_16:
6437 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_OR_AND_FETCH_1);
1cd6e20d 6438 target = expand_builtin_sync_operation (mode, exp, IOR, true, target);
b6a5fc45 6439 if (target)
6440 return target;
6441 break;
6442
2797f13a 6443 case BUILT_IN_SYNC_AND_AND_FETCH_1:
6444 case BUILT_IN_SYNC_AND_AND_FETCH_2:
6445 case BUILT_IN_SYNC_AND_AND_FETCH_4:
6446 case BUILT_IN_SYNC_AND_AND_FETCH_8:
6447 case BUILT_IN_SYNC_AND_AND_FETCH_16:
6448 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_AND_AND_FETCH_1);
1cd6e20d 6449 target = expand_builtin_sync_operation (mode, exp, AND, true, target);
b6a5fc45 6450 if (target)
6451 return target;
6452 break;
6453
2797f13a 6454 case BUILT_IN_SYNC_XOR_AND_FETCH_1:
6455 case BUILT_IN_SYNC_XOR_AND_FETCH_2:
6456 case BUILT_IN_SYNC_XOR_AND_FETCH_4:
6457 case BUILT_IN_SYNC_XOR_AND_FETCH_8:
6458 case BUILT_IN_SYNC_XOR_AND_FETCH_16:
6459 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_XOR_AND_FETCH_1);
1cd6e20d 6460 target = expand_builtin_sync_operation (mode, exp, XOR, true, target);
b6a5fc45 6461 if (target)
6462 return target;
6463 break;
6464
2797f13a 6465 case BUILT_IN_SYNC_NAND_AND_FETCH_1:
6466 case BUILT_IN_SYNC_NAND_AND_FETCH_2:
6467 case BUILT_IN_SYNC_NAND_AND_FETCH_4:
6468 case BUILT_IN_SYNC_NAND_AND_FETCH_8:
6469 case BUILT_IN_SYNC_NAND_AND_FETCH_16:
6470 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_NAND_AND_FETCH_1);
1cd6e20d 6471 target = expand_builtin_sync_operation (mode, exp, NOT, true, target);
b6a5fc45 6472 if (target)
6473 return target;
6474 break;
6475
2797f13a 6476 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
6477 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
6478 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
6479 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
6480 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16:
a601d32a 6481 if (mode == VOIDmode)
6482 mode = TYPE_MODE (boolean_type_node);
b6a5fc45 6483 if (!target || !register_operand (target, mode))
6484 target = gen_reg_rtx (mode);
3e272de8 6485
2797f13a 6486 mode = get_builtin_sync_mode
6487 (fcode - BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1);
c2f47e15 6488 target = expand_builtin_compare_and_swap (mode, exp, true, target);
b6a5fc45 6489 if (target)
6490 return target;
6491 break;
6492
2797f13a 6493 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
6494 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
6495 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
6496 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
6497 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
6498 mode = get_builtin_sync_mode
6499 (fcode - BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1);
c2f47e15 6500 target = expand_builtin_compare_and_swap (mode, exp, false, target);
b6a5fc45 6501 if (target)
6502 return target;
6503 break;
6504
2797f13a 6505 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
6506 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
6507 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
6508 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
6509 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16:
6510 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_TEST_AND_SET_1);
6511 target = expand_builtin_sync_lock_test_and_set (mode, exp, target);
b6a5fc45 6512 if (target)
6513 return target;
6514 break;
6515
2797f13a 6516 case BUILT_IN_SYNC_LOCK_RELEASE_1:
6517 case BUILT_IN_SYNC_LOCK_RELEASE_2:
6518 case BUILT_IN_SYNC_LOCK_RELEASE_4:
6519 case BUILT_IN_SYNC_LOCK_RELEASE_8:
6520 case BUILT_IN_SYNC_LOCK_RELEASE_16:
6521 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_RELEASE_1);
6522 expand_builtin_sync_lock_release (mode, exp);
b6a5fc45 6523 return const0_rtx;
6524
2797f13a 6525 case BUILT_IN_SYNC_SYNCHRONIZE:
6526 expand_builtin_sync_synchronize ();
b6a5fc45 6527 return const0_rtx;
6528
1cd6e20d 6529 case BUILT_IN_ATOMIC_EXCHANGE_1:
6530 case BUILT_IN_ATOMIC_EXCHANGE_2:
6531 case BUILT_IN_ATOMIC_EXCHANGE_4:
6532 case BUILT_IN_ATOMIC_EXCHANGE_8:
6533 case BUILT_IN_ATOMIC_EXCHANGE_16:
6534 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_EXCHANGE_1);
6535 target = expand_builtin_atomic_exchange (mode, exp, target);
6536 if (target)
6537 return target;
6538 break;
6539
6540 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1:
6541 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2:
6542 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4:
6543 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8:
6544 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
2c201ad1 6545 {
6546 unsigned int nargs, z;
6547 VEC(tree,gc) *vec;
6548
6549 mode =
6550 get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1);
6551 target = expand_builtin_atomic_compare_exchange (mode, exp, target);
6552 if (target)
6553 return target;
6554
6555 /* If this is turned into an external library call, the weak parameter
6556 must be dropped to match the expected parameter list. */
6557 nargs = call_expr_nargs (exp);
6558 vec = VEC_alloc (tree, gc, nargs - 1);
6559 for (z = 0; z < 3; z++)
6560 VEC_quick_push (tree, vec, CALL_EXPR_ARG (exp, z));
6561 /* Skip the boolean weak parameter. */
6562 for (z = 4; z < 6; z++)
6563 VEC_quick_push (tree, vec, CALL_EXPR_ARG (exp, z));
6564 exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), vec);
6565 break;
6566 }
1cd6e20d 6567
6568 case BUILT_IN_ATOMIC_LOAD_1:
6569 case BUILT_IN_ATOMIC_LOAD_2:
6570 case BUILT_IN_ATOMIC_LOAD_4:
6571 case BUILT_IN_ATOMIC_LOAD_8:
6572 case BUILT_IN_ATOMIC_LOAD_16:
6573 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_LOAD_1);
6574 target = expand_builtin_atomic_load (mode, exp, target);
6575 if (target)
6576 return target;
6577 break;
6578
6579 case BUILT_IN_ATOMIC_STORE_1:
6580 case BUILT_IN_ATOMIC_STORE_2:
6581 case BUILT_IN_ATOMIC_STORE_4:
6582 case BUILT_IN_ATOMIC_STORE_8:
6583 case BUILT_IN_ATOMIC_STORE_16:
6584 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_STORE_1);
6585 target = expand_builtin_atomic_store (mode, exp);
6586 if (target)
6587 return const0_rtx;
6588 break;
6589
6590 case BUILT_IN_ATOMIC_ADD_FETCH_1:
6591 case BUILT_IN_ATOMIC_ADD_FETCH_2:
6592 case BUILT_IN_ATOMIC_ADD_FETCH_4:
6593 case BUILT_IN_ATOMIC_ADD_FETCH_8:
6594 case BUILT_IN_ATOMIC_ADD_FETCH_16:
6595 {
6596 enum built_in_function lib;
6597 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1);
6598 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_ADD_1 +
6599 (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1));
6600 target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, true,
6601 ignore, lib);
6602 if (target)
6603 return target;
6604 break;
6605 }
6606 case BUILT_IN_ATOMIC_SUB_FETCH_1:
6607 case BUILT_IN_ATOMIC_SUB_FETCH_2:
6608 case BUILT_IN_ATOMIC_SUB_FETCH_4:
6609 case BUILT_IN_ATOMIC_SUB_FETCH_8:
6610 case BUILT_IN_ATOMIC_SUB_FETCH_16:
6611 {
6612 enum built_in_function lib;
6613 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1);
6614 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_SUB_1 +
6615 (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1));
6616 target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, true,
6617 ignore, lib);
6618 if (target)
6619 return target;
6620 break;
6621 }
6622 case BUILT_IN_ATOMIC_AND_FETCH_1:
6623 case BUILT_IN_ATOMIC_AND_FETCH_2:
6624 case BUILT_IN_ATOMIC_AND_FETCH_4:
6625 case BUILT_IN_ATOMIC_AND_FETCH_8:
6626 case BUILT_IN_ATOMIC_AND_FETCH_16:
6627 {
6628 enum built_in_function lib;
6629 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_AND_FETCH_1);
6630 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_AND_1 +
6631 (fcode - BUILT_IN_ATOMIC_AND_FETCH_1));
6632 target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, true,
6633 ignore, lib);
6634 if (target)
6635 return target;
6636 break;
6637 }
6638 case BUILT_IN_ATOMIC_NAND_FETCH_1:
6639 case BUILT_IN_ATOMIC_NAND_FETCH_2:
6640 case BUILT_IN_ATOMIC_NAND_FETCH_4:
6641 case BUILT_IN_ATOMIC_NAND_FETCH_8:
6642 case BUILT_IN_ATOMIC_NAND_FETCH_16:
6643 {
6644 enum built_in_function lib;
6645 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1);
6646 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_NAND_1 +
6647 (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1));
6648 target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, true,
6649 ignore, lib);
6650 if (target)
6651 return target;
6652 break;
6653 }
6654 case BUILT_IN_ATOMIC_XOR_FETCH_1:
6655 case BUILT_IN_ATOMIC_XOR_FETCH_2:
6656 case BUILT_IN_ATOMIC_XOR_FETCH_4:
6657 case BUILT_IN_ATOMIC_XOR_FETCH_8:
6658 case BUILT_IN_ATOMIC_XOR_FETCH_16:
6659 {
6660 enum built_in_function lib;
6661 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1);
6662 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_XOR_1 +
6663 (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1));
6664 target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, true,
6665 ignore, lib);
6666 if (target)
6667 return target;
6668 break;
6669 }
6670 case BUILT_IN_ATOMIC_OR_FETCH_1:
6671 case BUILT_IN_ATOMIC_OR_FETCH_2:
6672 case BUILT_IN_ATOMIC_OR_FETCH_4:
6673 case BUILT_IN_ATOMIC_OR_FETCH_8:
6674 case BUILT_IN_ATOMIC_OR_FETCH_16:
6675 {
6676 enum built_in_function lib;
6677 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_OR_FETCH_1);
6678 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_OR_1 +
6679 (fcode - BUILT_IN_ATOMIC_OR_FETCH_1));
6680 target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, true,
6681 ignore, lib);
6682 if (target)
6683 return target;
6684 break;
6685 }
6686 case BUILT_IN_ATOMIC_FETCH_ADD_1:
6687 case BUILT_IN_ATOMIC_FETCH_ADD_2:
6688 case BUILT_IN_ATOMIC_FETCH_ADD_4:
6689 case BUILT_IN_ATOMIC_FETCH_ADD_8:
6690 case BUILT_IN_ATOMIC_FETCH_ADD_16:
6691 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_ADD_1);
6692 target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, false,
6693 ignore, BUILT_IN_NONE);
6694 if (target)
6695 return target;
6696 break;
6697
6698 case BUILT_IN_ATOMIC_FETCH_SUB_1:
6699 case BUILT_IN_ATOMIC_FETCH_SUB_2:
6700 case BUILT_IN_ATOMIC_FETCH_SUB_4:
6701 case BUILT_IN_ATOMIC_FETCH_SUB_8:
6702 case BUILT_IN_ATOMIC_FETCH_SUB_16:
6703 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_SUB_1);
6704 target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, false,
6705 ignore, BUILT_IN_NONE);
6706 if (target)
6707 return target;
6708 break;
6709
6710 case BUILT_IN_ATOMIC_FETCH_AND_1:
6711 case BUILT_IN_ATOMIC_FETCH_AND_2:
6712 case BUILT_IN_ATOMIC_FETCH_AND_4:
6713 case BUILT_IN_ATOMIC_FETCH_AND_8:
6714 case BUILT_IN_ATOMIC_FETCH_AND_16:
6715 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_AND_1);
6716 target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, false,
6717 ignore, BUILT_IN_NONE);
6718 if (target)
6719 return target;
6720 break;
6721
6722 case BUILT_IN_ATOMIC_FETCH_NAND_1:
6723 case BUILT_IN_ATOMIC_FETCH_NAND_2:
6724 case BUILT_IN_ATOMIC_FETCH_NAND_4:
6725 case BUILT_IN_ATOMIC_FETCH_NAND_8:
6726 case BUILT_IN_ATOMIC_FETCH_NAND_16:
6727 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_NAND_1);
6728 target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, false,
6729 ignore, BUILT_IN_NONE);
6730 if (target)
6731 return target;
6732 break;
6733
6734 case BUILT_IN_ATOMIC_FETCH_XOR_1:
6735 case BUILT_IN_ATOMIC_FETCH_XOR_2:
6736 case BUILT_IN_ATOMIC_FETCH_XOR_4:
6737 case BUILT_IN_ATOMIC_FETCH_XOR_8:
6738 case BUILT_IN_ATOMIC_FETCH_XOR_16:
6739 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_XOR_1);
6740 target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, false,
6741 ignore, BUILT_IN_NONE);
6742 if (target)
6743 return target;
6744 break;
6745
6746 case BUILT_IN_ATOMIC_FETCH_OR_1:
6747 case BUILT_IN_ATOMIC_FETCH_OR_2:
6748 case BUILT_IN_ATOMIC_FETCH_OR_4:
6749 case BUILT_IN_ATOMIC_FETCH_OR_8:
6750 case BUILT_IN_ATOMIC_FETCH_OR_16:
6751 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_OR_1);
6752 target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, false,
6753 ignore, BUILT_IN_NONE);
6754 if (target)
6755 return target;
6756 break;
10b744a3 6757
6758 case BUILT_IN_ATOMIC_TEST_AND_SET:
7821cde1 6759 return expand_builtin_atomic_test_and_set (exp, target);
10b744a3 6760
6761 case BUILT_IN_ATOMIC_CLEAR:
6762 return expand_builtin_atomic_clear (exp);
1cd6e20d 6763
6764 case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
6765 return expand_builtin_atomic_always_lock_free (exp);
6766
6767 case BUILT_IN_ATOMIC_IS_LOCK_FREE:
6768 target = expand_builtin_atomic_is_lock_free (exp);
6769 if (target)
6770 return target;
6771 break;
6772
6773 case BUILT_IN_ATOMIC_THREAD_FENCE:
6774 expand_builtin_atomic_thread_fence (exp);
6775 return const0_rtx;
6776
6777 case BUILT_IN_ATOMIC_SIGNAL_FENCE:
6778 expand_builtin_atomic_signal_fence (exp);
6779 return const0_rtx;
6780
0a39fd54 6781 case BUILT_IN_OBJECT_SIZE:
6782 return expand_builtin_object_size (exp);
6783
6784 case BUILT_IN_MEMCPY_CHK:
6785 case BUILT_IN_MEMPCPY_CHK:
6786 case BUILT_IN_MEMMOVE_CHK:
6787 case BUILT_IN_MEMSET_CHK:
6788 target = expand_builtin_memory_chk (exp, target, mode, fcode);
6789 if (target)
6790 return target;
6791 break;
6792
6793 case BUILT_IN_STRCPY_CHK:
6794 case BUILT_IN_STPCPY_CHK:
6795 case BUILT_IN_STRNCPY_CHK:
1063acde 6796 case BUILT_IN_STPNCPY_CHK:
0a39fd54 6797 case BUILT_IN_STRCAT_CHK:
b356dfef 6798 case BUILT_IN_STRNCAT_CHK:
0a39fd54 6799 case BUILT_IN_SNPRINTF_CHK:
6800 case BUILT_IN_VSNPRINTF_CHK:
6801 maybe_emit_chk_warning (exp, fcode);
6802 break;
6803
6804 case BUILT_IN_SPRINTF_CHK:
6805 case BUILT_IN_VSPRINTF_CHK:
6806 maybe_emit_sprintf_chk_warning (exp, fcode);
6807 break;
6808
2c281b15 6809 case BUILT_IN_FREE:
f74ea1c2 6810 if (warn_free_nonheap_object)
6811 maybe_emit_free_warning (exp);
2c281b15 6812 break;
6813
92482ee0 6814 default: /* just do library call, if unknown builtin */
146c1b4f 6815 break;
53800dbe 6816 }
6817
6818 /* The switch statement above can drop through to cause the function
6819 to be called normally. */
6820 return expand_call (exp, target, ignore);
6821}
650e4c94 6822
805e22b2 6823/* Determine whether a tree node represents a call to a built-in
52203a9d 6824 function. If the tree T is a call to a built-in function with
6825 the right number of arguments of the appropriate types, return
6826 the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
6827 Otherwise the return value is END_BUILTINS. */
aecda0d6 6828
805e22b2 6829enum built_in_function
b7bf20db 6830builtin_mathfn_code (const_tree t)
805e22b2 6831{
b7bf20db 6832 const_tree fndecl, arg, parmlist;
6833 const_tree argtype, parmtype;
6834 const_call_expr_arg_iterator iter;
805e22b2 6835
6836 if (TREE_CODE (t) != CALL_EXPR
c2f47e15 6837 || TREE_CODE (CALL_EXPR_FN (t)) != ADDR_EXPR)
805e22b2 6838 return END_BUILTINS;
6839
c6e6ecb1 6840 fndecl = get_callee_fndecl (t);
6841 if (fndecl == NULL_TREE
52203a9d 6842 || TREE_CODE (fndecl) != FUNCTION_DECL
805e22b2 6843 || ! DECL_BUILT_IN (fndecl)
6844 || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
6845 return END_BUILTINS;
6846
52203a9d 6847 parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
b7bf20db 6848 init_const_call_expr_arg_iterator (t, &iter);
52203a9d 6849 for (; parmlist; parmlist = TREE_CHAIN (parmlist))
e9f80ff5 6850 {
52203a9d 6851 /* If a function doesn't take a variable number of arguments,
6852 the last element in the list will have type `void'. */
6853 parmtype = TREE_VALUE (parmlist);
6854 if (VOID_TYPE_P (parmtype))
6855 {
b7bf20db 6856 if (more_const_call_expr_args_p (&iter))
52203a9d 6857 return END_BUILTINS;
6858 return DECL_FUNCTION_CODE (fndecl);
6859 }
6860
b7bf20db 6861 if (! more_const_call_expr_args_p (&iter))
e9f80ff5 6862 return END_BUILTINS;
48e1416a 6863
b7bf20db 6864 arg = next_const_call_expr_arg (&iter);
c2f47e15 6865 argtype = TREE_TYPE (arg);
52203a9d 6866
6867 if (SCALAR_FLOAT_TYPE_P (parmtype))
6868 {
6869 if (! SCALAR_FLOAT_TYPE_P (argtype))
6870 return END_BUILTINS;
6871 }
6872 else if (COMPLEX_FLOAT_TYPE_P (parmtype))
6873 {
6874 if (! COMPLEX_FLOAT_TYPE_P (argtype))
6875 return END_BUILTINS;
6876 }
6877 else if (POINTER_TYPE_P (parmtype))
6878 {
6879 if (! POINTER_TYPE_P (argtype))
6880 return END_BUILTINS;
6881 }
6882 else if (INTEGRAL_TYPE_P (parmtype))
6883 {
6884 if (! INTEGRAL_TYPE_P (argtype))
6885 return END_BUILTINS;
6886 }
6887 else
e9f80ff5 6888 return END_BUILTINS;
e9f80ff5 6889 }
6890
52203a9d 6891 /* Variable-length argument list. */
805e22b2 6892 return DECL_FUNCTION_CODE (fndecl);
6893}
6894
c2f47e15 6895/* Fold a call to __builtin_constant_p, if we know its argument ARG will
6896 evaluate to a constant. */
650e4c94 6897
6898static tree
c2f47e15 6899fold_builtin_constant_p (tree arg)
650e4c94 6900{
650e4c94 6901 /* We return 1 for a numeric type that's known to be a constant
6902 value at compile-time or for an aggregate type that's a
6903 literal constant. */
c2f47e15 6904 STRIP_NOPS (arg);
650e4c94 6905
6906 /* If we know this is a constant, emit the constant of one. */
c2f47e15 6907 if (CONSTANT_CLASS_P (arg)
6908 || (TREE_CODE (arg) == CONSTRUCTOR
6909 && TREE_CONSTANT (arg)))
650e4c94 6910 return integer_one_node;
c2f47e15 6911 if (TREE_CODE (arg) == ADDR_EXPR)
adcfa3a3 6912 {
c2f47e15 6913 tree op = TREE_OPERAND (arg, 0);
adcfa3a3 6914 if (TREE_CODE (op) == STRING_CST
6915 || (TREE_CODE (op) == ARRAY_REF
6916 && integer_zerop (TREE_OPERAND (op, 1))
6917 && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
6918 return integer_one_node;
6919 }
650e4c94 6920
1fb4300c 6921 /* If this expression has side effects, show we don't know it to be a
6922 constant. Likewise if it's a pointer or aggregate type since in
6923 those case we only want literals, since those are only optimized
f97c71a1 6924 when generating RTL, not later.
6925 And finally, if we are compiling an initializer, not code, we
6926 need to return a definite result now; there's not going to be any
6927 more optimization done. */
c2f47e15 6928 if (TREE_SIDE_EFFECTS (arg)
6929 || AGGREGATE_TYPE_P (TREE_TYPE (arg))
6930 || POINTER_TYPE_P (TREE_TYPE (arg))
47be647d 6931 || cfun == 0
6932 || folding_initializer)
650e4c94 6933 return integer_zero_node;
6934
c2f47e15 6935 return NULL_TREE;
650e4c94 6936}
6937
76f5a783 6938/* Create builtin_expect with PRED and EXPECTED as its arguments and
6939 return it as a truthvalue. */
4ee9c684 6940
6941static tree
389dd41b 6942build_builtin_expect_predicate (location_t loc, tree pred, tree expected)
4ee9c684 6943{
76f5a783 6944 tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
4ee9c684 6945
b9a16870 6946 fn = builtin_decl_explicit (BUILT_IN_EXPECT);
76f5a783 6947 arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
6948 ret_type = TREE_TYPE (TREE_TYPE (fn));
6949 pred_type = TREE_VALUE (arg_types);
6950 expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
6951
389dd41b 6952 pred = fold_convert_loc (loc, pred_type, pred);
6953 expected = fold_convert_loc (loc, expected_type, expected);
6954 call_expr = build_call_expr_loc (loc, fn, 2, pred, expected);
76f5a783 6955
6956 return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
6957 build_int_cst (ret_type, 0));
6958}
6959
6960/* Fold a call to builtin_expect with arguments ARG0 and ARG1. Return
6961 NULL_TREE if no simplification is possible. */
6962
6963static tree
389dd41b 6964fold_builtin_expect (location_t loc, tree arg0, tree arg1)
76f5a783 6965{
083bada9 6966 tree inner, fndecl, inner_arg0;
76f5a783 6967 enum tree_code code;
6968
083bada9 6969 /* Distribute the expected value over short-circuiting operators.
6970 See through the cast from truthvalue_type_node to long. */
6971 inner_arg0 = arg0;
6972 while (TREE_CODE (inner_arg0) == NOP_EXPR
6973 && INTEGRAL_TYPE_P (TREE_TYPE (inner_arg0))
6974 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner_arg0, 0))))
6975 inner_arg0 = TREE_OPERAND (inner_arg0, 0);
6976
76f5a783 6977 /* If this is a builtin_expect within a builtin_expect keep the
6978 inner one. See through a comparison against a constant. It
6979 might have been added to create a thruthvalue. */
083bada9 6980 inner = inner_arg0;
6981
76f5a783 6982 if (COMPARISON_CLASS_P (inner)
6983 && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST)
6984 inner = TREE_OPERAND (inner, 0);
6985
6986 if (TREE_CODE (inner) == CALL_EXPR
6987 && (fndecl = get_callee_fndecl (inner))
6988 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
6989 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT)
6990 return arg0;
6991
083bada9 6992 inner = inner_arg0;
76f5a783 6993 code = TREE_CODE (inner);
6994 if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
6995 {
6996 tree op0 = TREE_OPERAND (inner, 0);
6997 tree op1 = TREE_OPERAND (inner, 1);
6998
389dd41b 6999 op0 = build_builtin_expect_predicate (loc, op0, arg1);
7000 op1 = build_builtin_expect_predicate (loc, op1, arg1);
76f5a783 7001 inner = build2 (code, TREE_TYPE (inner), op0, op1);
7002
389dd41b 7003 return fold_convert_loc (loc, TREE_TYPE (arg0), inner);
76f5a783 7004 }
7005
7006 /* If the argument isn't invariant then there's nothing else we can do. */
083bada9 7007 if (!TREE_CONSTANT (inner_arg0))
c2f47e15 7008 return NULL_TREE;
4ee9c684 7009
76f5a783 7010 /* If we expect that a comparison against the argument will fold to
7011 a constant return the constant. In practice, this means a true
7012 constant or the address of a non-weak symbol. */
083bada9 7013 inner = inner_arg0;
4ee9c684 7014 STRIP_NOPS (inner);
7015 if (TREE_CODE (inner) == ADDR_EXPR)
7016 {
7017 do
7018 {
7019 inner = TREE_OPERAND (inner, 0);
7020 }
7021 while (TREE_CODE (inner) == COMPONENT_REF
7022 || TREE_CODE (inner) == ARRAY_REF);
062b4460 7023 if ((TREE_CODE (inner) == VAR_DECL
7024 || TREE_CODE (inner) == FUNCTION_DECL)
7025 && DECL_WEAK (inner))
c2f47e15 7026 return NULL_TREE;
4ee9c684 7027 }
7028
76f5a783 7029 /* Otherwise, ARG0 already has the proper type for the return value. */
7030 return arg0;
4ee9c684 7031}
7032
c2f47e15 7033/* Fold a call to __builtin_classify_type with argument ARG. */
27d0c333 7034
539a3a92 7035static tree
c2f47e15 7036fold_builtin_classify_type (tree arg)
539a3a92 7037{
c2f47e15 7038 if (arg == 0)
7002a1c8 7039 return build_int_cst (integer_type_node, no_type_class);
539a3a92 7040
7002a1c8 7041 return build_int_cst (integer_type_node, type_to_class (TREE_TYPE (arg)));
539a3a92 7042}
7043
c2f47e15 7044/* Fold a call to __builtin_strlen with argument ARG. */
e6e27594 7045
7046static tree
c7cbde74 7047fold_builtin_strlen (location_t loc, tree type, tree arg)
e6e27594 7048{
c2f47e15 7049 if (!validate_arg (arg, POINTER_TYPE))
e6e27594 7050 return NULL_TREE;
7051 else
7052 {
c2f47e15 7053 tree len = c_strlen (arg, 0);
e6e27594 7054
7055 if (len)
c7cbde74 7056 return fold_convert_loc (loc, type, len);
e6e27594 7057
7058 return NULL_TREE;
7059 }
7060}
7061
92c43e3c 7062/* Fold a call to __builtin_inf or __builtin_huge_val. */
7063
7064static tree
389dd41b 7065fold_builtin_inf (location_t loc, tree type, int warn)
92c43e3c 7066{
aa870c1b 7067 REAL_VALUE_TYPE real;
7068
40f4dbd5 7069 /* __builtin_inff is intended to be usable to define INFINITY on all
7070 targets. If an infinity is not available, INFINITY expands "to a
7071 positive constant of type float that overflows at translation
7072 time", footnote "In this case, using INFINITY will violate the
7073 constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
7074 Thus we pedwarn to ensure this constraint violation is
7075 diagnosed. */
92c43e3c 7076 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
389dd41b 7077 pedwarn (loc, 0, "target format does not support infinity");
92c43e3c 7078
aa870c1b 7079 real_inf (&real);
7080 return build_real (type, real);
92c43e3c 7081}
7082
c2f47e15 7083/* Fold a call to __builtin_nan or __builtin_nans with argument ARG. */
b0db7939 7084
7085static tree
c2f47e15 7086fold_builtin_nan (tree arg, tree type, int quiet)
b0db7939 7087{
7088 REAL_VALUE_TYPE real;
7089 const char *str;
7090
c2f47e15 7091 if (!validate_arg (arg, POINTER_TYPE))
7092 return NULL_TREE;
7093 str = c_getstr (arg);
b0db7939 7094 if (!str)
c2f47e15 7095 return NULL_TREE;
b0db7939 7096
7097 if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
c2f47e15 7098 return NULL_TREE;
b0db7939 7099
7100 return build_real (type, real);
7101}
7102
277f8dd2 7103/* Return true if the floating point expression T has an integer value.
7104 We also allow +Inf, -Inf and NaN to be considered integer values. */
7105
7106static bool
7107integer_valued_real_p (tree t)
7108{
7109 switch (TREE_CODE (t))
7110 {
7111 case FLOAT_EXPR:
7112 return true;
7113
7114 case ABS_EXPR:
7115 case SAVE_EXPR:
277f8dd2 7116 return integer_valued_real_p (TREE_OPERAND (t, 0));
7117
7118 case COMPOUND_EXPR:
41076ef6 7119 case MODIFY_EXPR:
277f8dd2 7120 case BIND_EXPR:
75a70cf9 7121 return integer_valued_real_p (TREE_OPERAND (t, 1));
277f8dd2 7122
7123 case PLUS_EXPR:
7124 case MINUS_EXPR:
7125 case MULT_EXPR:
7126 case MIN_EXPR:
7127 case MAX_EXPR:
7128 return integer_valued_real_p (TREE_OPERAND (t, 0))
7129 && integer_valued_real_p (TREE_OPERAND (t, 1));
7130
7131 case COND_EXPR:
7132 return integer_valued_real_p (TREE_OPERAND (t, 1))
7133 && integer_valued_real_p (TREE_OPERAND (t, 2));
7134
7135 case REAL_CST:
0570334c 7136 return real_isinteger (TREE_REAL_CST_PTR (t), TYPE_MODE (TREE_TYPE (t)));
277f8dd2 7137
7138 case NOP_EXPR:
7139 {
7140 tree type = TREE_TYPE (TREE_OPERAND (t, 0));
7141 if (TREE_CODE (type) == INTEGER_TYPE)
7142 return true;
7143 if (TREE_CODE (type) == REAL_TYPE)
7144 return integer_valued_real_p (TREE_OPERAND (t, 0));
7145 break;
7146 }
7147
7148 case CALL_EXPR:
7149 switch (builtin_mathfn_code (t))
7150 {
4f35b1fc 7151 CASE_FLT_FN (BUILT_IN_CEIL):
7152 CASE_FLT_FN (BUILT_IN_FLOOR):
7153 CASE_FLT_FN (BUILT_IN_NEARBYINT):
7154 CASE_FLT_FN (BUILT_IN_RINT):
7155 CASE_FLT_FN (BUILT_IN_ROUND):
7156 CASE_FLT_FN (BUILT_IN_TRUNC):
277f8dd2 7157 return true;
7158
d4a43a03 7159 CASE_FLT_FN (BUILT_IN_FMIN):
7160 CASE_FLT_FN (BUILT_IN_FMAX):
c2f47e15 7161 return integer_valued_real_p (CALL_EXPR_ARG (t, 0))
7162 && integer_valued_real_p (CALL_EXPR_ARG (t, 1));
d4a43a03 7163
277f8dd2 7164 default:
7165 break;
7166 }
7167 break;
7168
7169 default:
7170 break;
7171 }
7172 return false;
7173}
7174
c2f47e15 7175/* FNDECL is assumed to be a builtin where truncation can be propagated
6528f4f4 7176 across (for instance floor((double)f) == (double)floorf (f).
c2f47e15 7177 Do the transformation for a call with argument ARG. */
277f8dd2 7178
6528f4f4 7179static tree
389dd41b 7180fold_trunc_transparent_mathfn (location_t loc, tree fndecl, tree arg)
6528f4f4 7181{
6528f4f4 7182 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
277f8dd2 7183
c2f47e15 7184 if (!validate_arg (arg, REAL_TYPE))
7185 return NULL_TREE;
6528f4f4 7186
277f8dd2 7187 /* Integer rounding functions are idempotent. */
7188 if (fcode == builtin_mathfn_code (arg))
7189 return arg;
7190
7191 /* If argument is already integer valued, and we don't need to worry
7192 about setting errno, there's no need to perform rounding. */
7193 if (! flag_errno_math && integer_valued_real_p (arg))
7194 return arg;
7195
7196 if (optimize)
6528f4f4 7197 {
277f8dd2 7198 tree arg0 = strip_float_extensions (arg);
2426241c 7199 tree ftype = TREE_TYPE (TREE_TYPE (fndecl));
6528f4f4 7200 tree newtype = TREE_TYPE (arg0);
7201 tree decl;
7202
7203 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7204 && (decl = mathfn_built_in (newtype, fcode)))
389dd41b 7205 return fold_convert_loc (loc, ftype,
7206 build_call_expr_loc (loc, decl, 1,
7207 fold_convert_loc (loc,
7208 newtype,
7209 arg0)));
6528f4f4 7210 }
c2f47e15 7211 return NULL_TREE;
6528f4f4 7212}
7213
c2f47e15 7214/* FNDECL is assumed to be builtin which can narrow the FP type of
7215 the argument, for instance lround((double)f) -> lroundf (f).
7216 Do the transformation for a call with argument ARG. */
9ed65c7f 7217
7218static tree
389dd41b 7219fold_fixed_mathfn (location_t loc, tree fndecl, tree arg)
9ed65c7f 7220{
9ed65c7f 7221 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9ed65c7f 7222
c2f47e15 7223 if (!validate_arg (arg, REAL_TYPE))
7224 return NULL_TREE;
9ed65c7f 7225
7226 /* If argument is already integer valued, and we don't need to worry
7227 about setting errno, there's no need to perform rounding. */
7228 if (! flag_errno_math && integer_valued_real_p (arg))
389dd41b 7229 return fold_build1_loc (loc, FIX_TRUNC_EXPR,
7230 TREE_TYPE (TREE_TYPE (fndecl)), arg);
9ed65c7f 7231
7232 if (optimize)
7233 {
7234 tree ftype = TREE_TYPE (arg);
7235 tree arg0 = strip_float_extensions (arg);
7236 tree newtype = TREE_TYPE (arg0);
7237 tree decl;
7238
7239 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7240 && (decl = mathfn_built_in (newtype, fcode)))
389dd41b 7241 return build_call_expr_loc (loc, decl, 1,
7242 fold_convert_loc (loc, newtype, arg0));
9ed65c7f 7243 }
73a0da56 7244
80ff6494 7245 /* Canonicalize iround (x) to lround (x) on ILP32 targets where
7246 sizeof (int) == sizeof (long). */
7247 if (TYPE_PRECISION (integer_type_node)
7248 == TYPE_PRECISION (long_integer_type_node))
7249 {
7250 tree newfn = NULL_TREE;
7251 switch (fcode)
7252 {
7253 CASE_FLT_FN (BUILT_IN_ICEIL):
7254 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
7255 break;
7256
7257 CASE_FLT_FN (BUILT_IN_IFLOOR):
7258 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
7259 break;
7260
7261 CASE_FLT_FN (BUILT_IN_IROUND):
7262 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
7263 break;
7264
7265 CASE_FLT_FN (BUILT_IN_IRINT):
7266 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
7267 break;
7268
7269 default:
7270 break;
7271 }
7272
7273 if (newfn)
7274 {
7275 tree newcall = build_call_expr_loc (loc, newfn, 1, arg);
7276 return fold_convert_loc (loc,
7277 TREE_TYPE (TREE_TYPE (fndecl)), newcall);
7278 }
7279 }
7280
73a0da56 7281 /* Canonicalize llround (x) to lround (x) on LP64 targets where
7282 sizeof (long long) == sizeof (long). */
7283 if (TYPE_PRECISION (long_long_integer_type_node)
7284 == TYPE_PRECISION (long_integer_type_node))
7285 {
7286 tree newfn = NULL_TREE;
7287 switch (fcode)
7288 {
7289 CASE_FLT_FN (BUILT_IN_LLCEIL):
7290 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
7291 break;
7292
7293 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7294 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
7295 break;
7296
7297 CASE_FLT_FN (BUILT_IN_LLROUND):
7298 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
7299 break;
7300
7301 CASE_FLT_FN (BUILT_IN_LLRINT):
7302 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
7303 break;
7304
7305 default:
7306 break;
7307 }
7308
7309 if (newfn)
7310 {
389dd41b 7311 tree newcall = build_call_expr_loc (loc, newfn, 1, arg);
7312 return fold_convert_loc (loc,
7313 TREE_TYPE (TREE_TYPE (fndecl)), newcall);
73a0da56 7314 }
7315 }
7316
c2f47e15 7317 return NULL_TREE;
9ed65c7f 7318}
7319
c2f47e15 7320/* Fold call to builtin cabs, cabsf or cabsl with argument ARG. TYPE is the
7321 return type. Return NULL_TREE if no simplification can be made. */
c63f4ad3 7322
7323static tree
389dd41b 7324fold_builtin_cabs (location_t loc, tree arg, tree type, tree fndecl)
c63f4ad3 7325{
c2f47e15 7326 tree res;
c63f4ad3 7327
b0ce8887 7328 if (!validate_arg (arg, COMPLEX_TYPE)
c63f4ad3 7329 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
7330 return NULL_TREE;
7331
b4725390 7332 /* Calculate the result when the argument is a constant. */
7333 if (TREE_CODE (arg) == COMPLEX_CST
7334 && (res = do_mpfr_arg2 (TREE_REALPART (arg), TREE_IMAGPART (arg),
7335 type, mpfr_hypot)))
7336 return res;
48e1416a 7337
1af0d139 7338 if (TREE_CODE (arg) == COMPLEX_EXPR)
7339 {
7340 tree real = TREE_OPERAND (arg, 0);
7341 tree imag = TREE_OPERAND (arg, 1);
48e1416a 7342
1af0d139 7343 /* If either part is zero, cabs is fabs of the other. */
7344 if (real_zerop (real))
389dd41b 7345 return fold_build1_loc (loc, ABS_EXPR, type, imag);
1af0d139 7346 if (real_zerop (imag))
389dd41b 7347 return fold_build1_loc (loc, ABS_EXPR, type, real);
1af0d139 7348
7349 /* cabs(x+xi) -> fabs(x)*sqrt(2). */
7350 if (flag_unsafe_math_optimizations
7351 && operand_equal_p (real, imag, OEP_PURE_SAME))
7352 {
2e7ca27b 7353 const REAL_VALUE_TYPE sqrt2_trunc
7910b2fb 7354 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
1af0d139 7355 STRIP_NOPS (real);
389dd41b 7356 return fold_build2_loc (loc, MULT_EXPR, type,
7357 fold_build1_loc (loc, ABS_EXPR, type, real),
2e7ca27b 7358 build_real (type, sqrt2_trunc));
1af0d139 7359 }
7360 }
c63f4ad3 7361
749891b2 7362 /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */
7363 if (TREE_CODE (arg) == NEGATE_EXPR
7364 || TREE_CODE (arg) == CONJ_EXPR)
389dd41b 7365 return build_call_expr_loc (loc, fndecl, 1, TREE_OPERAND (arg, 0));
749891b2 7366
7d3f6cc7 7367 /* Don't do this when optimizing for size. */
7368 if (flag_unsafe_math_optimizations
0bfd8d5c 7369 && optimize && optimize_function_for_speed_p (cfun))
c63f4ad3 7370 {
0da0dbfa 7371 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
c63f4ad3 7372
7373 if (sqrtfn != NULL_TREE)
7374 {
c2f47e15 7375 tree rpart, ipart, result;
c63f4ad3 7376
4ee9c684 7377 arg = builtin_save_expr (arg);
29a6518e 7378
389dd41b 7379 rpart = fold_build1_loc (loc, REALPART_EXPR, type, arg);
7380 ipart = fold_build1_loc (loc, IMAGPART_EXPR, type, arg);
c63f4ad3 7381
4ee9c684 7382 rpart = builtin_save_expr (rpart);
7383 ipart = builtin_save_expr (ipart);
c63f4ad3 7384
389dd41b 7385 result = fold_build2_loc (loc, PLUS_EXPR, type,
7386 fold_build2_loc (loc, MULT_EXPR, type,
49d00087 7387 rpart, rpart),
389dd41b 7388 fold_build2_loc (loc, MULT_EXPR, type,
49d00087 7389 ipart, ipart));
c63f4ad3 7390
389dd41b 7391 return build_call_expr_loc (loc, sqrtfn, 1, result);
c63f4ad3 7392 }
7393 }
7394
7395 return NULL_TREE;
7396}
7397
c2373fdb 7398/* Build a complex (inf +- 0i) for the result of cproj. TYPE is the
7399 complex tree type of the result. If NEG is true, the imaginary
7400 zero is negative. */
7401
7402static tree
7403build_complex_cproj (tree type, bool neg)
7404{
7405 REAL_VALUE_TYPE rinf, rzero = dconst0;
7406
7407 real_inf (&rinf);
7408 rzero.sign = neg;
7409 return build_complex (type, build_real (TREE_TYPE (type), rinf),
7410 build_real (TREE_TYPE (type), rzero));
7411}
7412
7413/* Fold call to builtin cproj, cprojf or cprojl with argument ARG. TYPE is the
7414 return type. Return NULL_TREE if no simplification can be made. */
7415
7416static tree
7417fold_builtin_cproj (location_t loc, tree arg, tree type)
7418{
7419 if (!validate_arg (arg, COMPLEX_TYPE)
7420 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
7421 return NULL_TREE;
7422
7423 /* If there are no infinities, return arg. */
7424 if (! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (type))))
7425 return non_lvalue_loc (loc, arg);
7426
7427 /* Calculate the result when the argument is a constant. */
7428 if (TREE_CODE (arg) == COMPLEX_CST)
7429 {
7430 const REAL_VALUE_TYPE *real = TREE_REAL_CST_PTR (TREE_REALPART (arg));
7431 const REAL_VALUE_TYPE *imag = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
7432
7433 if (real_isinf (real) || real_isinf (imag))
7434 return build_complex_cproj (type, imag->sign);
7435 else
7436 return arg;
7437 }
b4c7e601 7438 else if (TREE_CODE (arg) == COMPLEX_EXPR)
7439 {
7440 tree real = TREE_OPERAND (arg, 0);
7441 tree imag = TREE_OPERAND (arg, 1);
7442
7443 STRIP_NOPS (real);
7444 STRIP_NOPS (imag);
7445
7446 /* If the real part is inf and the imag part is known to be
7447 nonnegative, return (inf + 0i). Remember side-effects are
7448 possible in the imag part. */
7449 if (TREE_CODE (real) == REAL_CST
7450 && real_isinf (TREE_REAL_CST_PTR (real))
7451 && tree_expr_nonnegative_p (imag))
7452 return omit_one_operand_loc (loc, type,
7453 build_complex_cproj (type, false),
7454 arg);
7455
7456 /* If the imag part is inf, return (inf+I*copysign(0,imag)).
7457 Remember side-effects are possible in the real part. */
7458 if (TREE_CODE (imag) == REAL_CST
7459 && real_isinf (TREE_REAL_CST_PTR (imag)))
7460 return
7461 omit_one_operand_loc (loc, type,
7462 build_complex_cproj (type, TREE_REAL_CST_PTR
7463 (imag)->sign), arg);
7464 }
c2373fdb 7465
7466 return NULL_TREE;
7467}
7468
c2f47e15 7469/* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG.
7470 Return NULL_TREE if no simplification can be made. */
e6e27594 7471
7472static tree
389dd41b 7473fold_builtin_sqrt (location_t loc, tree arg, tree type)
e6e27594 7474{
7475
7476 enum built_in_function fcode;
b4e8ab0c 7477 tree res;
c2f47e15 7478
7479 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7480 return NULL_TREE;
7481
b4e8ab0c 7482 /* Calculate the result when the argument is a constant. */
7483 if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
7484 return res;
48e1416a 7485
e6e27594 7486 /* Optimize sqrt(expN(x)) = expN(x*0.5). */
7487 fcode = builtin_mathfn_code (arg);
7488 if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
7489 {
c2f47e15 7490 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
389dd41b 7491 arg = fold_build2_loc (loc, MULT_EXPR, type,
c2f47e15 7492 CALL_EXPR_ARG (arg, 0),
49d00087 7493 build_real (type, dconsthalf));
389dd41b 7494 return build_call_expr_loc (loc, expfn, 1, arg);
e6e27594 7495 }
7496
7497 /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */
7498 if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
7499 {
7500 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7501
7502 if (powfn)
7503 {
c2f47e15 7504 tree arg0 = CALL_EXPR_ARG (arg, 0);
e6e27594 7505 tree tree_root;
7506 /* The inner root was either sqrt or cbrt. */
57510da6 7507 /* This was a conditional expression but it triggered a bug
18381619 7508 in Sun C 5.5. */
ce6cd837 7509 REAL_VALUE_TYPE dconstroot;
7510 if (BUILTIN_SQRT_P (fcode))
7511 dconstroot = dconsthalf;
7512 else
7513 dconstroot = dconst_third ();
e6e27594 7514
7515 /* Adjust for the outer root. */
7516 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7517 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7518 tree_root = build_real (type, dconstroot);
389dd41b 7519 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
e6e27594 7520 }
7521 }
7522
bc33117f 7523 /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
e6e27594 7524 if (flag_unsafe_math_optimizations
7525 && (fcode == BUILT_IN_POW
7526 || fcode == BUILT_IN_POWF
7527 || fcode == BUILT_IN_POWL))
7528 {
c2f47e15 7529 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
7530 tree arg0 = CALL_EXPR_ARG (arg, 0);
7531 tree arg1 = CALL_EXPR_ARG (arg, 1);
bc33117f 7532 tree narg1;
7533 if (!tree_expr_nonnegative_p (arg0))
7534 arg0 = build1 (ABS_EXPR, type, arg0);
389dd41b 7535 narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 7536 build_real (type, dconsthalf));
389dd41b 7537 return build_call_expr_loc (loc, powfn, 2, arg0, narg1);
e6e27594 7538 }
7539
7540 return NULL_TREE;
7541}
7542
c2f47e15 7543/* Fold a builtin function call to cbrt, cbrtf, or cbrtl with argument ARG.
7544 Return NULL_TREE if no simplification can be made. */
7545
e6e27594 7546static tree
389dd41b 7547fold_builtin_cbrt (location_t loc, tree arg, tree type)
e6e27594 7548{
e6e27594 7549 const enum built_in_function fcode = builtin_mathfn_code (arg);
29f4cd78 7550 tree res;
e6e27594 7551
c2f47e15 7552 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7553 return NULL_TREE;
7554
29f4cd78 7555 /* Calculate the result when the argument is a constant. */
7556 if ((res = do_mpfr_arg1 (arg, type, mpfr_cbrt, NULL, NULL, 0)))
7557 return res;
e6e27594 7558
cdfeb715 7559 if (flag_unsafe_math_optimizations)
e6e27594 7560 {
cdfeb715 7561 /* Optimize cbrt(expN(x)) -> expN(x/3). */
7562 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 7563 {
c2f47e15 7564 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7565 const REAL_VALUE_TYPE third_trunc =
7910b2fb 7566 real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 7567 arg = fold_build2_loc (loc, MULT_EXPR, type,
c2f47e15 7568 CALL_EXPR_ARG (arg, 0),
49d00087 7569 build_real (type, third_trunc));
389dd41b 7570 return build_call_expr_loc (loc, expfn, 1, arg);
cdfeb715 7571 }
e6e27594 7572
cdfeb715 7573 /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */
7574 if (BUILTIN_SQRT_P (fcode))
a0c938f0 7575 {
cdfeb715 7576 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
e6e27594 7577
cdfeb715 7578 if (powfn)
7579 {
c2f47e15 7580 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7581 tree tree_root;
7910b2fb 7582 REAL_VALUE_TYPE dconstroot = dconst_third ();
cdfeb715 7583
7584 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7585 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7586 tree_root = build_real (type, dconstroot);
389dd41b 7587 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
cdfeb715 7588 }
e6e27594 7589 }
7590
cdfeb715 7591 /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */
7592 if (BUILTIN_CBRT_P (fcode))
a0c938f0 7593 {
c2f47e15 7594 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7595 if (tree_expr_nonnegative_p (arg0))
7596 {
7597 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7598
7599 if (powfn)
a0c938f0 7600 {
cdfeb715 7601 tree tree_root;
7602 REAL_VALUE_TYPE dconstroot;
a0c938f0 7603
3fa759a9 7604 real_arithmetic (&dconstroot, MULT_EXPR,
7910b2fb 7605 dconst_third_ptr (), dconst_third_ptr ());
cdfeb715 7606 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7607 tree_root = build_real (type, dconstroot);
389dd41b 7608 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
cdfeb715 7609 }
7610 }
7611 }
a0c938f0 7612
cdfeb715 7613 /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */
48e1416a 7614 if (fcode == BUILT_IN_POW
c2f47e15 7615 || fcode == BUILT_IN_POWF
cdfeb715 7616 || fcode == BUILT_IN_POWL)
a0c938f0 7617 {
c2f47e15 7618 tree arg00 = CALL_EXPR_ARG (arg, 0);
7619 tree arg01 = CALL_EXPR_ARG (arg, 1);
cdfeb715 7620 if (tree_expr_nonnegative_p (arg00))
7621 {
c2f47e15 7622 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7623 const REAL_VALUE_TYPE dconstroot
7910b2fb 7624 = real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 7625 tree narg01 = fold_build2_loc (loc, MULT_EXPR, type, arg01,
49d00087 7626 build_real (type, dconstroot));
389dd41b 7627 return build_call_expr_loc (loc, powfn, 2, arg00, narg01);
cdfeb715 7628 }
7629 }
e6e27594 7630 }
7631 return NULL_TREE;
7632}
7633
c2f47e15 7634/* Fold function call to builtin cos, cosf, or cosl with argument ARG.
7635 TYPE is the type of the return value. Return NULL_TREE if no
7636 simplification can be made. */
7637
e6e27594 7638static tree
389dd41b 7639fold_builtin_cos (location_t loc,
7640 tree arg, tree type, tree fndecl)
e6e27594 7641{
e6ab33d8 7642 tree res, narg;
e6e27594 7643
c2f47e15 7644 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7645 return NULL_TREE;
7646
bffb7645 7647 /* Calculate the result when the argument is a constant. */
728bac60 7648 if ((res = do_mpfr_arg1 (arg, type, mpfr_cos, NULL, NULL, 0)))
bffb7645 7649 return res;
48e1416a 7650
e6e27594 7651 /* Optimize cos(-x) into cos (x). */
e6ab33d8 7652 if ((narg = fold_strip_sign_ops (arg)))
389dd41b 7653 return build_call_expr_loc (loc, fndecl, 1, narg);
e6e27594 7654
7655 return NULL_TREE;
7656}
7657
c2f47e15 7658/* Fold function call to builtin cosh, coshf, or coshl with argument ARG.
7659 Return NULL_TREE if no simplification can be made. */
7660
cacdc1af 7661static tree
389dd41b 7662fold_builtin_cosh (location_t loc, tree arg, tree type, tree fndecl)
cacdc1af 7663{
c2f47e15 7664 if (validate_arg (arg, REAL_TYPE))
cacdc1af 7665 {
cacdc1af 7666 tree res, narg;
7667
7668 /* Calculate the result when the argument is a constant. */
7669 if ((res = do_mpfr_arg1 (arg, type, mpfr_cosh, NULL, NULL, 0)))
7670 return res;
48e1416a 7671
cacdc1af 7672 /* Optimize cosh(-x) into cosh (x). */
7673 if ((narg = fold_strip_sign_ops (arg)))
389dd41b 7674 return build_call_expr_loc (loc, fndecl, 1, narg);
cacdc1af 7675 }
48e1416a 7676
cacdc1af 7677 return NULL_TREE;
7678}
7679
239d491a 7680/* Fold function call to builtin ccos (or ccosh if HYPER is TRUE) with
7681 argument ARG. TYPE is the type of the return value. Return
7682 NULL_TREE if no simplification can be made. */
7683
7684static tree
965d0f29 7685fold_builtin_ccos (location_t loc, tree arg, tree type, tree fndecl,
7686 bool hyper)
239d491a 7687{
7688 if (validate_arg (arg, COMPLEX_TYPE)
7689 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
7690 {
7691 tree tmp;
7692
239d491a 7693 /* Calculate the result when the argument is a constant. */
7694 if ((tmp = do_mpc_arg1 (arg, type, (hyper ? mpc_cosh : mpc_cos))))
7695 return tmp;
48e1416a 7696
239d491a 7697 /* Optimize fn(-x) into fn(x). */
7698 if ((tmp = fold_strip_sign_ops (arg)))
389dd41b 7699 return build_call_expr_loc (loc, fndecl, 1, tmp);
239d491a 7700 }
7701
7702 return NULL_TREE;
7703}
7704
c2f47e15 7705/* Fold function call to builtin tan, tanf, or tanl with argument ARG.
7706 Return NULL_TREE if no simplification can be made. */
7707
e6e27594 7708static tree
c2f47e15 7709fold_builtin_tan (tree arg, tree type)
e6e27594 7710{
7711 enum built_in_function fcode;
29f4cd78 7712 tree res;
e6e27594 7713
c2f47e15 7714 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7715 return NULL_TREE;
7716
bffb7645 7717 /* Calculate the result when the argument is a constant. */
728bac60 7718 if ((res = do_mpfr_arg1 (arg, type, mpfr_tan, NULL, NULL, 0)))
bffb7645 7719 return res;
48e1416a 7720
e6e27594 7721 /* Optimize tan(atan(x)) = x. */
7722 fcode = builtin_mathfn_code (arg);
7723 if (flag_unsafe_math_optimizations
7724 && (fcode == BUILT_IN_ATAN
7725 || fcode == BUILT_IN_ATANF
7726 || fcode == BUILT_IN_ATANL))
c2f47e15 7727 return CALL_EXPR_ARG (arg, 0);
e6e27594 7728
7729 return NULL_TREE;
7730}
7731
d735c391 7732/* Fold function call to builtin sincos, sincosf, or sincosl. Return
7733 NULL_TREE if no simplification can be made. */
7734
7735static tree
389dd41b 7736fold_builtin_sincos (location_t loc,
7737 tree arg0, tree arg1, tree arg2)
d735c391 7738{
c2f47e15 7739 tree type;
d735c391 7740 tree res, fn, call;
7741
c2f47e15 7742 if (!validate_arg (arg0, REAL_TYPE)
7743 || !validate_arg (arg1, POINTER_TYPE)
7744 || !validate_arg (arg2, POINTER_TYPE))
d735c391 7745 return NULL_TREE;
7746
d735c391 7747 type = TREE_TYPE (arg0);
d735c391 7748
7749 /* Calculate the result when the argument is a constant. */
7750 if ((res = do_mpfr_sincos (arg0, arg1, arg2)))
7751 return res;
7752
7753 /* Canonicalize sincos to cexpi. */
2a6b4c77 7754 if (!TARGET_C99_FUNCTIONS)
7755 return NULL_TREE;
d735c391 7756 fn = mathfn_built_in (type, BUILT_IN_CEXPI);
7757 if (!fn)
7758 return NULL_TREE;
7759
389dd41b 7760 call = build_call_expr_loc (loc, fn, 1, arg0);
d735c391 7761 call = builtin_save_expr (call);
7762
a75b1c71 7763 return build2 (COMPOUND_EXPR, void_type_node,
d735c391 7764 build2 (MODIFY_EXPR, void_type_node,
389dd41b 7765 build_fold_indirect_ref_loc (loc, arg1),
d735c391 7766 build1 (IMAGPART_EXPR, type, call)),
7767 build2 (MODIFY_EXPR, void_type_node,
389dd41b 7768 build_fold_indirect_ref_loc (loc, arg2),
d735c391 7769 build1 (REALPART_EXPR, type, call)));
7770}
7771
c5bb2c4b 7772/* Fold function call to builtin cexp, cexpf, or cexpl. Return
7773 NULL_TREE if no simplification can be made. */
7774
7775static tree
389dd41b 7776fold_builtin_cexp (location_t loc, tree arg0, tree type)
c5bb2c4b 7777{
c2f47e15 7778 tree rtype;
c5bb2c4b 7779 tree realp, imagp, ifn;
239d491a 7780 tree res;
c5bb2c4b 7781
239d491a 7782 if (!validate_arg (arg0, COMPLEX_TYPE)
b0ce8887 7783 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) != REAL_TYPE)
c5bb2c4b 7784 return NULL_TREE;
7785
239d491a 7786 /* Calculate the result when the argument is a constant. */
7787 if ((res = do_mpc_arg1 (arg0, type, mpc_exp)))
7788 return res;
48e1416a 7789
c5bb2c4b 7790 rtype = TREE_TYPE (TREE_TYPE (arg0));
7791
7792 /* In case we can figure out the real part of arg0 and it is constant zero
7793 fold to cexpi. */
2a6b4c77 7794 if (!TARGET_C99_FUNCTIONS)
7795 return NULL_TREE;
c5bb2c4b 7796 ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI);
7797 if (!ifn)
7798 return NULL_TREE;
7799
389dd41b 7800 if ((realp = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0))
c5bb2c4b 7801 && real_zerop (realp))
7802 {
389dd41b 7803 tree narg = fold_build1_loc (loc, IMAGPART_EXPR, rtype, arg0);
7804 return build_call_expr_loc (loc, ifn, 1, narg);
c5bb2c4b 7805 }
7806
7807 /* In case we can easily decompose real and imaginary parts split cexp
7808 to exp (r) * cexpi (i). */
7809 if (flag_unsafe_math_optimizations
7810 && realp)
7811 {
7812 tree rfn, rcall, icall;
7813
7814 rfn = mathfn_built_in (rtype, BUILT_IN_EXP);
7815 if (!rfn)
7816 return NULL_TREE;
7817
389dd41b 7818 imagp = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
c5bb2c4b 7819 if (!imagp)
7820 return NULL_TREE;
7821
389dd41b 7822 icall = build_call_expr_loc (loc, ifn, 1, imagp);
c5bb2c4b 7823 icall = builtin_save_expr (icall);
389dd41b 7824 rcall = build_call_expr_loc (loc, rfn, 1, realp);
c5bb2c4b 7825 rcall = builtin_save_expr (rcall);
389dd41b 7826 return fold_build2_loc (loc, COMPLEX_EXPR, type,
7827 fold_build2_loc (loc, MULT_EXPR, rtype,
71bf42bb 7828 rcall,
389dd41b 7829 fold_build1_loc (loc, REALPART_EXPR,
7830 rtype, icall)),
7831 fold_build2_loc (loc, MULT_EXPR, rtype,
71bf42bb 7832 rcall,
389dd41b 7833 fold_build1_loc (loc, IMAGPART_EXPR,
7834 rtype, icall)));
c5bb2c4b 7835 }
7836
7837 return NULL_TREE;
7838}
7839
c2f47e15 7840/* Fold function call to builtin trunc, truncf or truncl with argument ARG.
7841 Return NULL_TREE if no simplification can be made. */
277f8dd2 7842
7843static tree
389dd41b 7844fold_builtin_trunc (location_t loc, tree fndecl, tree arg)
277f8dd2 7845{
c2f47e15 7846 if (!validate_arg (arg, REAL_TYPE))
7847 return NULL_TREE;
277f8dd2 7848
7849 /* Optimize trunc of constant value. */
f96bd2bf 7850 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7851 {
7852 REAL_VALUE_TYPE r, x;
2426241c 7853 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7854
7855 x = TREE_REAL_CST (arg);
7856 real_trunc (&r, TYPE_MODE (type), &x);
7857 return build_real (type, r);
7858 }
7859
389dd41b 7860 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7861}
7862
c2f47e15 7863/* Fold function call to builtin floor, floorf or floorl with argument ARG.
7864 Return NULL_TREE if no simplification can be made. */
277f8dd2 7865
7866static tree
389dd41b 7867fold_builtin_floor (location_t loc, tree fndecl, tree arg)
277f8dd2 7868{
c2f47e15 7869 if (!validate_arg (arg, REAL_TYPE))
7870 return NULL_TREE;
277f8dd2 7871
7872 /* Optimize floor of constant value. */
f96bd2bf 7873 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7874 {
7875 REAL_VALUE_TYPE x;
7876
7877 x = TREE_REAL_CST (arg);
7878 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7879 {
2426241c 7880 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7881 REAL_VALUE_TYPE r;
7882
7883 real_floor (&r, TYPE_MODE (type), &x);
7884 return build_real (type, r);
7885 }
7886 }
7887
acc2b92e 7888 /* Fold floor (x) where x is nonnegative to trunc (x). */
7889 if (tree_expr_nonnegative_p (arg))
30fe8286 7890 {
7891 tree truncfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_TRUNC);
7892 if (truncfn)
389dd41b 7893 return build_call_expr_loc (loc, truncfn, 1, arg);
30fe8286 7894 }
acc2b92e 7895
389dd41b 7896 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7897}
7898
c2f47e15 7899/* Fold function call to builtin ceil, ceilf or ceill with argument ARG.
7900 Return NULL_TREE if no simplification can be made. */
277f8dd2 7901
7902static tree
389dd41b 7903fold_builtin_ceil (location_t loc, tree fndecl, tree arg)
277f8dd2 7904{
c2f47e15 7905 if (!validate_arg (arg, REAL_TYPE))
7906 return NULL_TREE;
277f8dd2 7907
7908 /* Optimize ceil of constant value. */
f96bd2bf 7909 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7910 {
7911 REAL_VALUE_TYPE x;
7912
7913 x = TREE_REAL_CST (arg);
7914 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7915 {
2426241c 7916 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7917 REAL_VALUE_TYPE r;
7918
7919 real_ceil (&r, TYPE_MODE (type), &x);
7920 return build_real (type, r);
7921 }
7922 }
7923
389dd41b 7924 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7925}
7926
c2f47e15 7927/* Fold function call to builtin round, roundf or roundl with argument ARG.
7928 Return NULL_TREE if no simplification can be made. */
89ab3887 7929
7930static tree
389dd41b 7931fold_builtin_round (location_t loc, tree fndecl, tree arg)
89ab3887 7932{
c2f47e15 7933 if (!validate_arg (arg, REAL_TYPE))
7934 return NULL_TREE;
89ab3887 7935
34f17811 7936 /* Optimize round of constant value. */
f96bd2bf 7937 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
89ab3887 7938 {
7939 REAL_VALUE_TYPE x;
7940
7941 x = TREE_REAL_CST (arg);
7942 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7943 {
2426241c 7944 tree type = TREE_TYPE (TREE_TYPE (fndecl));
89ab3887 7945 REAL_VALUE_TYPE r;
7946
7947 real_round (&r, TYPE_MODE (type), &x);
7948 return build_real (type, r);
7949 }
7950 }
7951
389dd41b 7952 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
89ab3887 7953}
7954
34f17811 7955/* Fold function call to builtin lround, lroundf or lroundl (or the
c2f47e15 7956 corresponding long long versions) and other rounding functions. ARG
7957 is the argument to the call. Return NULL_TREE if no simplification
7958 can be made. */
34f17811 7959
7960static tree
389dd41b 7961fold_builtin_int_roundingfn (location_t loc, tree fndecl, tree arg)
34f17811 7962{
c2f47e15 7963 if (!validate_arg (arg, REAL_TYPE))
7964 return NULL_TREE;
34f17811 7965
7966 /* Optimize lround of constant value. */
f96bd2bf 7967 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
34f17811 7968 {
7969 const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
7970
776a7bab 7971 if (real_isfinite (&x))
34f17811 7972 {
2426241c 7973 tree itype = TREE_TYPE (TREE_TYPE (fndecl));
ca9b061d 7974 tree ftype = TREE_TYPE (arg);
a6caa15f 7975 double_int val;
34f17811 7976 REAL_VALUE_TYPE r;
7977
ad52b9b7 7978 switch (DECL_FUNCTION_CODE (fndecl))
7979 {
80ff6494 7980 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 7981 CASE_FLT_FN (BUILT_IN_LFLOOR):
7982 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 7983 real_floor (&r, TYPE_MODE (ftype), &x);
7984 break;
7985
80ff6494 7986 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 7987 CASE_FLT_FN (BUILT_IN_LCEIL):
7988 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 7989 real_ceil (&r, TYPE_MODE (ftype), &x);
7990 break;
7991
80ff6494 7992 CASE_FLT_FN (BUILT_IN_IROUND):
4f35b1fc 7993 CASE_FLT_FN (BUILT_IN_LROUND):
7994 CASE_FLT_FN (BUILT_IN_LLROUND):
ad52b9b7 7995 real_round (&r, TYPE_MODE (ftype), &x);
7996 break;
7997
7998 default:
7999 gcc_unreachable ();
8000 }
8001
a6caa15f 8002 real_to_integer2 ((HOST_WIDE_INT *)&val.low, &val.high, &r);
8003 if (double_int_fits_to_tree_p (itype, val))
8004 return double_int_to_tree (itype, val);
34f17811 8005 }
8006 }
8007
acc2b92e 8008 switch (DECL_FUNCTION_CODE (fndecl))
8009 {
8010 CASE_FLT_FN (BUILT_IN_LFLOOR):
8011 CASE_FLT_FN (BUILT_IN_LLFLOOR):
8012 /* Fold lfloor (x) where x is nonnegative to FIX_TRUNC (x). */
8013 if (tree_expr_nonnegative_p (arg))
389dd41b 8014 return fold_build1_loc (loc, FIX_TRUNC_EXPR,
8015 TREE_TYPE (TREE_TYPE (fndecl)), arg);
acc2b92e 8016 break;
8017 default:;
8018 }
8019
389dd41b 8020 return fold_fixed_mathfn (loc, fndecl, arg);
34f17811 8021}
8022
70fb4c07 8023/* Fold function call to builtin ffs, clz, ctz, popcount and parity
c2f47e15 8024 and their long and long long variants (i.e. ffsl and ffsll). ARG is
8025 the argument to the call. Return NULL_TREE if no simplification can
8026 be made. */
70fb4c07 8027
8028static tree
c2f47e15 8029fold_builtin_bitop (tree fndecl, tree arg)
70fb4c07 8030{
c2f47e15 8031 if (!validate_arg (arg, INTEGER_TYPE))
70fb4c07 8032 return NULL_TREE;
8033
8034 /* Optimize for constant argument. */
f96bd2bf 8035 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
70fb4c07 8036 {
8037 HOST_WIDE_INT hi, width, result;
8038 unsigned HOST_WIDE_INT lo;
7c446c95 8039 tree type;
70fb4c07 8040
8041 type = TREE_TYPE (arg);
8042 width = TYPE_PRECISION (type);
8043 lo = TREE_INT_CST_LOW (arg);
8044
8045 /* Clear all the bits that are beyond the type's precision. */
8046 if (width > HOST_BITS_PER_WIDE_INT)
8047 {
8048 hi = TREE_INT_CST_HIGH (arg);
8049 if (width < 2 * HOST_BITS_PER_WIDE_INT)
6aaa1f9e 8050 hi &= ~((unsigned HOST_WIDE_INT) (-1)
8051 << (width - HOST_BITS_PER_WIDE_INT));
70fb4c07 8052 }
8053 else
8054 {
8055 hi = 0;
8056 if (width < HOST_BITS_PER_WIDE_INT)
8057 lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
8058 }
8059
8060 switch (DECL_FUNCTION_CODE (fndecl))
8061 {
4f35b1fc 8062 CASE_INT_FN (BUILT_IN_FFS):
70fb4c07 8063 if (lo != 0)
7e8d812e 8064 result = ffs_hwi (lo);
70fb4c07 8065 else if (hi != 0)
7e8d812e 8066 result = HOST_BITS_PER_WIDE_INT + ffs_hwi (hi);
70fb4c07 8067 else
8068 result = 0;
8069 break;
8070
4f35b1fc 8071 CASE_INT_FN (BUILT_IN_CLZ):
70fb4c07 8072 if (hi != 0)
8073 result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
8074 else if (lo != 0)
8075 result = width - floor_log2 (lo) - 1;
8076 else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
8077 result = width;
8078 break;
8079
4f35b1fc 8080 CASE_INT_FN (BUILT_IN_CTZ):
70fb4c07 8081 if (lo != 0)
7e8d812e 8082 result = ctz_hwi (lo);
70fb4c07 8083 else if (hi != 0)
7e8d812e 8084 result = HOST_BITS_PER_WIDE_INT + ctz_hwi (hi);
70fb4c07 8085 else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
8086 result = width;
8087 break;
8088
6aaa1f9e 8089 CASE_INT_FN (BUILT_IN_CLRSB):
8090 if (width > HOST_BITS_PER_WIDE_INT
8091 && (hi & ((unsigned HOST_WIDE_INT) 1
8092 << (width - HOST_BITS_PER_WIDE_INT - 1))) != 0)
8093 {
8094 hi = ~hi & ~((unsigned HOST_WIDE_INT) (-1)
8095 << (width - HOST_BITS_PER_WIDE_INT - 1));
8096 lo = ~lo;
8097 }
8098 else if (width <= HOST_BITS_PER_WIDE_INT
8099 && (lo & ((unsigned HOST_WIDE_INT) 1 << (width - 1))) != 0)
8100 lo = ~lo & ~((unsigned HOST_WIDE_INT) (-1) << (width - 1));
8101 if (hi != 0)
8102 result = width - floor_log2 (hi) - 2 - HOST_BITS_PER_WIDE_INT;
8103 else if (lo != 0)
8104 result = width - floor_log2 (lo) - 2;
8105 else
8106 result = width - 1;
8107 break;
8108
4f35b1fc 8109 CASE_INT_FN (BUILT_IN_POPCOUNT):
70fb4c07 8110 result = 0;
8111 while (lo)
8112 result++, lo &= lo - 1;
8113 while (hi)
7e8d812e 8114 result++, hi &= (unsigned HOST_WIDE_INT) hi - 1;
70fb4c07 8115 break;
8116
4f35b1fc 8117 CASE_INT_FN (BUILT_IN_PARITY):
70fb4c07 8118 result = 0;
8119 while (lo)
8120 result++, lo &= lo - 1;
8121 while (hi)
7e8d812e 8122 result++, hi &= (unsigned HOST_WIDE_INT) hi - 1;
70fb4c07 8123 result &= 1;
8124 break;
8125
8126 default:
64db345d 8127 gcc_unreachable ();
70fb4c07 8128 }
8129
2426241c 8130 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
70fb4c07 8131 }
8132
8133 return NULL_TREE;
8134}
8135
42791117 8136/* Fold function call to builtin_bswap and the long and long long
8137 variants. Return NULL_TREE if no simplification can be made. */
8138static tree
c2f47e15 8139fold_builtin_bswap (tree fndecl, tree arg)
42791117 8140{
c2f47e15 8141 if (! validate_arg (arg, INTEGER_TYPE))
8142 return NULL_TREE;
42791117 8143
8144 /* Optimize constant value. */
f96bd2bf 8145 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
42791117 8146 {
8147 HOST_WIDE_INT hi, width, r_hi = 0;
8148 unsigned HOST_WIDE_INT lo, r_lo = 0;
8149 tree type;
8150
8151 type = TREE_TYPE (arg);
8152 width = TYPE_PRECISION (type);
8153 lo = TREE_INT_CST_LOW (arg);
8154 hi = TREE_INT_CST_HIGH (arg);
8155
8156 switch (DECL_FUNCTION_CODE (fndecl))
8157 {
8158 case BUILT_IN_BSWAP32:
8159 case BUILT_IN_BSWAP64:
8160 {
8161 int s;
8162
8163 for (s = 0; s < width; s += 8)
8164 {
8165 int d = width - s - 8;
8166 unsigned HOST_WIDE_INT byte;
8167
8168 if (s < HOST_BITS_PER_WIDE_INT)
8169 byte = (lo >> s) & 0xff;
8170 else
8171 byte = (hi >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff;
8172
8173 if (d < HOST_BITS_PER_WIDE_INT)
8174 r_lo |= byte << d;
8175 else
8176 r_hi |= byte << (d - HOST_BITS_PER_WIDE_INT);
8177 }
8178 }
8179
8180 break;
8181
8182 default:
8183 gcc_unreachable ();
8184 }
8185
8186 if (width < HOST_BITS_PER_WIDE_INT)
8187 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), r_lo);
8188 else
8189 return build_int_cst_wide (TREE_TYPE (TREE_TYPE (fndecl)), r_lo, r_hi);
8190 }
8191
8192 return NULL_TREE;
8193}
c2f47e15 8194
8918c507 8195/* A subroutine of fold_builtin to fold the various logarithmic
29f4cd78 8196 functions. Return NULL_TREE if no simplification can me made.
8197 FUNC is the corresponding MPFR logarithm function. */
8918c507 8198
8199static tree
389dd41b 8200fold_builtin_logarithm (location_t loc, tree fndecl, tree arg,
29f4cd78 8201 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8202{
c2f47e15 8203 if (validate_arg (arg, REAL_TYPE))
8918c507 8204 {
8918c507 8205 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8206 tree res;
8918c507 8207 const enum built_in_function fcode = builtin_mathfn_code (arg);
0862b7e9 8208
29f4cd78 8209 /* Calculate the result when the argument is a constant. */
8210 if ((res = do_mpfr_arg1 (arg, type, func, &dconst0, NULL, false)))
8211 return res;
8212
8918c507 8213 /* Special case, optimize logN(expN(x)) = x. */
8214 if (flag_unsafe_math_optimizations
29f4cd78 8215 && ((func == mpfr_log
8918c507 8216 && (fcode == BUILT_IN_EXP
8217 || fcode == BUILT_IN_EXPF
8218 || fcode == BUILT_IN_EXPL))
29f4cd78 8219 || (func == mpfr_log2
8918c507 8220 && (fcode == BUILT_IN_EXP2
8221 || fcode == BUILT_IN_EXP2F
8222 || fcode == BUILT_IN_EXP2L))
29f4cd78 8223 || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode)))))
389dd41b 8224 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
8918c507 8225
ca273d4a 8226 /* Optimize logN(func()) for various exponential functions. We
a0c938f0 8227 want to determine the value "x" and the power "exponent" in
8228 order to transform logN(x**exponent) into exponent*logN(x). */
8918c507 8229 if (flag_unsafe_math_optimizations)
a0c938f0 8230 {
8918c507 8231 tree exponent = 0, x = 0;
0862b7e9 8232
8918c507 8233 switch (fcode)
8234 {
4f35b1fc 8235 CASE_FLT_FN (BUILT_IN_EXP):
8918c507 8236 /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
48e1416a 8237 x = build_real (type, real_value_truncate (TYPE_MODE (type),
7910b2fb 8238 dconst_e ()));
c2f47e15 8239 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8240 break;
4f35b1fc 8241 CASE_FLT_FN (BUILT_IN_EXP2):
8918c507 8242 /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */
8243 x = build_real (type, dconst2);
c2f47e15 8244 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8245 break;
4f35b1fc 8246 CASE_FLT_FN (BUILT_IN_EXP10):
8247 CASE_FLT_FN (BUILT_IN_POW10):
8918c507 8248 /* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */
3fa759a9 8249 {
8250 REAL_VALUE_TYPE dconst10;
8251 real_from_integer (&dconst10, VOIDmode, 10, 0, 0);
8252 x = build_real (type, dconst10);
8253 }
c2f47e15 8254 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8255 break;
4f35b1fc 8256 CASE_FLT_FN (BUILT_IN_SQRT):
8918c507 8257 /* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */
c2f47e15 8258 x = CALL_EXPR_ARG (arg, 0);
8918c507 8259 exponent = build_real (type, dconsthalf);
8260 break;
4f35b1fc 8261 CASE_FLT_FN (BUILT_IN_CBRT):
8918c507 8262 /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */
c2f47e15 8263 x = CALL_EXPR_ARG (arg, 0);
8918c507 8264 exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
7910b2fb 8265 dconst_third ()));
8918c507 8266 break;
4f35b1fc 8267 CASE_FLT_FN (BUILT_IN_POW):
8918c507 8268 /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x). */
c2f47e15 8269 x = CALL_EXPR_ARG (arg, 0);
8270 exponent = CALL_EXPR_ARG (arg, 1);
8918c507 8271 break;
8272 default:
8273 break;
8274 }
8275
8276 /* Now perform the optimization. */
8277 if (x && exponent)
8278 {
389dd41b 8279 tree logfn = build_call_expr_loc (loc, fndecl, 1, x);
8280 return fold_build2_loc (loc, MULT_EXPR, type, exponent, logfn);
8918c507 8281 }
8282 }
8283 }
8284
c2f47e15 8285 return NULL_TREE;
8918c507 8286}
0862b7e9 8287
f0c477f2 8288/* Fold a builtin function call to hypot, hypotf, or hypotl. Return
8289 NULL_TREE if no simplification can be made. */
8290
8291static tree
389dd41b 8292fold_builtin_hypot (location_t loc, tree fndecl,
8293 tree arg0, tree arg1, tree type)
f0c477f2 8294{
e6ab33d8 8295 tree res, narg0, narg1;
f0c477f2 8296
c2f47e15 8297 if (!validate_arg (arg0, REAL_TYPE)
8298 || !validate_arg (arg1, REAL_TYPE))
f0c477f2 8299 return NULL_TREE;
8300
8301 /* Calculate the result when the argument is a constant. */
8302 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot)))
8303 return res;
48e1416a 8304
6c95f21c 8305 /* If either argument to hypot has a negate or abs, strip that off.
8306 E.g. hypot(-x,fabs(y)) -> hypot(x,y). */
e6ab33d8 8307 narg0 = fold_strip_sign_ops (arg0);
8308 narg1 = fold_strip_sign_ops (arg1);
8309 if (narg0 || narg1)
8310 {
48e1416a 8311 return build_call_expr_loc (loc, fndecl, 2, narg0 ? narg0 : arg0,
c2f47e15 8312 narg1 ? narg1 : arg1);
6c95f21c 8313 }
48e1416a 8314
f0c477f2 8315 /* If either argument is zero, hypot is fabs of the other. */
8316 if (real_zerop (arg0))
389dd41b 8317 return fold_build1_loc (loc, ABS_EXPR, type, arg1);
f0c477f2 8318 else if (real_zerop (arg1))
389dd41b 8319 return fold_build1_loc (loc, ABS_EXPR, type, arg0);
48e1416a 8320
6c95f21c 8321 /* hypot(x,x) -> fabs(x)*sqrt(2). */
8322 if (flag_unsafe_math_optimizations
8323 && operand_equal_p (arg0, arg1, OEP_PURE_SAME))
f0c477f2 8324 {
2e7ca27b 8325 const REAL_VALUE_TYPE sqrt2_trunc
7910b2fb 8326 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
389dd41b 8327 return fold_build2_loc (loc, MULT_EXPR, type,
8328 fold_build1_loc (loc, ABS_EXPR, type, arg0),
2e7ca27b 8329 build_real (type, sqrt2_trunc));
f0c477f2 8330 }
8331
f0c477f2 8332 return NULL_TREE;
8333}
8334
8335
e6e27594 8336/* Fold a builtin function call to pow, powf, or powl. Return
8337 NULL_TREE if no simplification can be made. */
8338static tree
389dd41b 8339fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
e6e27594 8340{
f0c477f2 8341 tree res;
e6e27594 8342
c2f47e15 8343 if (!validate_arg (arg0, REAL_TYPE)
8344 || !validate_arg (arg1, REAL_TYPE))
e6e27594 8345 return NULL_TREE;
8346
f0c477f2 8347 /* Calculate the result when the argument is a constant. */
8348 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_pow)))
8349 return res;
8350
e6e27594 8351 /* Optimize pow(1.0,y) = 1.0. */
8352 if (real_onep (arg0))
389dd41b 8353 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
e6e27594 8354
8355 if (TREE_CODE (arg1) == REAL_CST
f96bd2bf 8356 && !TREE_OVERFLOW (arg1))
e6e27594 8357 {
198d9bbe 8358 REAL_VALUE_TYPE cint;
e6e27594 8359 REAL_VALUE_TYPE c;
198d9bbe 8360 HOST_WIDE_INT n;
8361
e6e27594 8362 c = TREE_REAL_CST (arg1);
8363
8364 /* Optimize pow(x,0.0) = 1.0. */
8365 if (REAL_VALUES_EQUAL (c, dconst0))
389dd41b 8366 return omit_one_operand_loc (loc, type, build_real (type, dconst1),
e6e27594 8367 arg0);
8368
8369 /* Optimize pow(x,1.0) = x. */
8370 if (REAL_VALUES_EQUAL (c, dconst1))
8371 return arg0;
8372
8373 /* Optimize pow(x,-1.0) = 1.0/x. */
8374 if (REAL_VALUES_EQUAL (c, dconstm1))
389dd41b 8375 return fold_build2_loc (loc, RDIV_EXPR, type,
49d00087 8376 build_real (type, dconst1), arg0);
e6e27594 8377
8378 /* Optimize pow(x,0.5) = sqrt(x). */
8379 if (flag_unsafe_math_optimizations
8380 && REAL_VALUES_EQUAL (c, dconsthalf))
8381 {
8382 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
8383
8384 if (sqrtfn != NULL_TREE)
389dd41b 8385 return build_call_expr_loc (loc, sqrtfn, 1, arg0);
e6e27594 8386 }
8387
feb5b3eb 8388 /* Optimize pow(x,1.0/3.0) = cbrt(x). */
8389 if (flag_unsafe_math_optimizations)
8390 {
8391 const REAL_VALUE_TYPE dconstroot
7910b2fb 8392 = real_value_truncate (TYPE_MODE (type), dconst_third ());
feb5b3eb 8393
8394 if (REAL_VALUES_EQUAL (c, dconstroot))
8395 {
8396 tree cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT);
8397 if (cbrtfn != NULL_TREE)
389dd41b 8398 return build_call_expr_loc (loc, cbrtfn, 1, arg0);
feb5b3eb 8399 }
8400 }
8401
198d9bbe 8402 /* Check for an integer exponent. */
8403 n = real_to_integer (&c);
8404 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
8405 if (real_identical (&c, &cint))
e6e27594 8406 {
a2b30b48 8407 /* Attempt to evaluate pow at compile-time, unless this should
8408 raise an exception. */
198d9bbe 8409 if (TREE_CODE (arg0) == REAL_CST
a2b30b48 8410 && !TREE_OVERFLOW (arg0)
8411 && (n > 0
8412 || (!flag_trapping_math && !flag_errno_math)
8413 || !REAL_VALUES_EQUAL (TREE_REAL_CST (arg0), dconst0)))
e6e27594 8414 {
8415 REAL_VALUE_TYPE x;
8416 bool inexact;
8417
8418 x = TREE_REAL_CST (arg0);
8419 inexact = real_powi (&x, TYPE_MODE (type), &x, n);
8420 if (flag_unsafe_math_optimizations || !inexact)
8421 return build_real (type, x);
8422 }
198d9bbe 8423
8424 /* Strip sign ops from even integer powers. */
8425 if ((n & 1) == 0 && flag_unsafe_math_optimizations)
8426 {
8427 tree narg0 = fold_strip_sign_ops (arg0);
8428 if (narg0)
389dd41b 8429 return build_call_expr_loc (loc, fndecl, 2, narg0, arg1);
198d9bbe 8430 }
e6e27594 8431 }
8432 }
8433
cdfeb715 8434 if (flag_unsafe_math_optimizations)
e6e27594 8435 {
cdfeb715 8436 const enum built_in_function fcode = builtin_mathfn_code (arg0);
e6e27594 8437
cdfeb715 8438 /* Optimize pow(expN(x),y) = expN(x*y). */
8439 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 8440 {
c2f47e15 8441 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
8442 tree arg = CALL_EXPR_ARG (arg0, 0);
389dd41b 8443 arg = fold_build2_loc (loc, MULT_EXPR, type, arg, arg1);
8444 return build_call_expr_loc (loc, expfn, 1, arg);
cdfeb715 8445 }
e6e27594 8446
cdfeb715 8447 /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
8448 if (BUILTIN_SQRT_P (fcode))
a0c938f0 8449 {
c2f47e15 8450 tree narg0 = CALL_EXPR_ARG (arg0, 0);
389dd41b 8451 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 8452 build_real (type, dconsthalf));
389dd41b 8453 return build_call_expr_loc (loc, fndecl, 2, narg0, narg1);
cdfeb715 8454 }
8455
8456 /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */
8457 if (BUILTIN_CBRT_P (fcode))
a0c938f0 8458 {
c2f47e15 8459 tree arg = CALL_EXPR_ARG (arg0, 0);
cdfeb715 8460 if (tree_expr_nonnegative_p (arg))
8461 {
8462 const REAL_VALUE_TYPE dconstroot
7910b2fb 8463 = real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 8464 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 8465 build_real (type, dconstroot));
389dd41b 8466 return build_call_expr_loc (loc, fndecl, 2, arg, narg1);
cdfeb715 8467 }
8468 }
a0c938f0 8469
49e436b5 8470 /* Optimize pow(pow(x,y),z) = pow(x,y*z) iff x is nonnegative. */
c2f47e15 8471 if (fcode == BUILT_IN_POW
8472 || fcode == BUILT_IN_POWF
8473 || fcode == BUILT_IN_POWL)
a0c938f0 8474 {
c2f47e15 8475 tree arg00 = CALL_EXPR_ARG (arg0, 0);
49e436b5 8476 if (tree_expr_nonnegative_p (arg00))
8477 {
8478 tree arg01 = CALL_EXPR_ARG (arg0, 1);
8479 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg01, arg1);
8480 return build_call_expr_loc (loc, fndecl, 2, arg00, narg1);
8481 }
cdfeb715 8482 }
e6e27594 8483 }
cdfeb715 8484
e6e27594 8485 return NULL_TREE;
8486}
8487
c2f47e15 8488/* Fold a builtin function call to powi, powif, or powil with argument ARG.
8489 Return NULL_TREE if no simplification can be made. */
b4d0c20c 8490static tree
389dd41b 8491fold_builtin_powi (location_t loc, tree fndecl ATTRIBUTE_UNUSED,
c2f47e15 8492 tree arg0, tree arg1, tree type)
b4d0c20c 8493{
c2f47e15 8494 if (!validate_arg (arg0, REAL_TYPE)
8495 || !validate_arg (arg1, INTEGER_TYPE))
b4d0c20c 8496 return NULL_TREE;
8497
8498 /* Optimize pow(1.0,y) = 1.0. */
8499 if (real_onep (arg0))
389dd41b 8500 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
b4d0c20c 8501
8502 if (host_integerp (arg1, 0))
8503 {
8504 HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
8505
8506 /* Evaluate powi at compile-time. */
8507 if (TREE_CODE (arg0) == REAL_CST
f96bd2bf 8508 && !TREE_OVERFLOW (arg0))
b4d0c20c 8509 {
8510 REAL_VALUE_TYPE x;
8511 x = TREE_REAL_CST (arg0);
8512 real_powi (&x, TYPE_MODE (type), &x, c);
8513 return build_real (type, x);
8514 }
8515
8516 /* Optimize pow(x,0) = 1.0. */
8517 if (c == 0)
389dd41b 8518 return omit_one_operand_loc (loc, type, build_real (type, dconst1),
b4d0c20c 8519 arg0);
8520
8521 /* Optimize pow(x,1) = x. */
8522 if (c == 1)
8523 return arg0;
8524
8525 /* Optimize pow(x,-1) = 1.0/x. */
8526 if (c == -1)
389dd41b 8527 return fold_build2_loc (loc, RDIV_EXPR, type,
49d00087 8528 build_real (type, dconst1), arg0);
b4d0c20c 8529 }
8530
8531 return NULL_TREE;
8532}
8533
8918c507 8534/* A subroutine of fold_builtin to fold the various exponent
c2f47e15 8535 functions. Return NULL_TREE if no simplification can be made.
debf9994 8536 FUNC is the corresponding MPFR exponent function. */
8918c507 8537
8538static tree
389dd41b 8539fold_builtin_exponent (location_t loc, tree fndecl, tree arg,
debf9994 8540 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8541{
c2f47e15 8542 if (validate_arg (arg, REAL_TYPE))
8918c507 8543 {
8918c507 8544 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8545 tree res;
48e1416a 8546
debf9994 8547 /* Calculate the result when the argument is a constant. */
728bac60 8548 if ((res = do_mpfr_arg1 (arg, type, func, NULL, NULL, 0)))
debf9994 8549 return res;
8918c507 8550
8551 /* Optimize expN(logN(x)) = x. */
8552 if (flag_unsafe_math_optimizations)
a0c938f0 8553 {
8918c507 8554 const enum built_in_function fcode = builtin_mathfn_code (arg);
8555
debf9994 8556 if ((func == mpfr_exp
8918c507 8557 && (fcode == BUILT_IN_LOG
8558 || fcode == BUILT_IN_LOGF
8559 || fcode == BUILT_IN_LOGL))
debf9994 8560 || (func == mpfr_exp2
8918c507 8561 && (fcode == BUILT_IN_LOG2
8562 || fcode == BUILT_IN_LOG2F
8563 || fcode == BUILT_IN_LOG2L))
debf9994 8564 || (func == mpfr_exp10
8918c507 8565 && (fcode == BUILT_IN_LOG10
8566 || fcode == BUILT_IN_LOG10F
8567 || fcode == BUILT_IN_LOG10L)))
389dd41b 8568 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
8918c507 8569 }
8570 }
8571
c2f47e15 8572 return NULL_TREE;
8918c507 8573}
8574
e973ffcc 8575/* Return true if VAR is a VAR_DECL or a component thereof. */
8576
8577static bool
8578var_decl_component_p (tree var)
8579{
8580 tree inner = var;
8581 while (handled_component_p (inner))
8582 inner = TREE_OPERAND (inner, 0);
8583 return SSA_VAR_P (inner);
8584}
8585
4f46f2b9 8586/* Fold function call to builtin memset. Return
9c8a1629 8587 NULL_TREE if no simplification can be made. */
8588
8589static tree
389dd41b 8590fold_builtin_memset (location_t loc, tree dest, tree c, tree len,
8591 tree type, bool ignore)
9c8a1629 8592{
45bb3afb 8593 tree var, ret, etype;
4f46f2b9 8594 unsigned HOST_WIDE_INT length, cval;
9c8a1629 8595
c2f47e15 8596 if (! validate_arg (dest, POINTER_TYPE)
8597 || ! validate_arg (c, INTEGER_TYPE)
8598 || ! validate_arg (len, INTEGER_TYPE))
8599 return NULL_TREE;
9c8a1629 8600
4f46f2b9 8601 if (! host_integerp (len, 1))
c2f47e15 8602 return NULL_TREE;
4f46f2b9 8603
9c8a1629 8604 /* If the LEN parameter is zero, return DEST. */
8605 if (integer_zerop (len))
389dd41b 8606 return omit_one_operand_loc (loc, type, dest, c);
9c8a1629 8607
d5d2f74a 8608 if (TREE_CODE (c) != INTEGER_CST || TREE_SIDE_EFFECTS (dest))
c2f47e15 8609 return NULL_TREE;
9c8a1629 8610
4f46f2b9 8611 var = dest;
8612 STRIP_NOPS (var);
8613 if (TREE_CODE (var) != ADDR_EXPR)
c2f47e15 8614 return NULL_TREE;
4f46f2b9 8615
8616 var = TREE_OPERAND (var, 0);
8617 if (TREE_THIS_VOLATILE (var))
c2f47e15 8618 return NULL_TREE;
4f46f2b9 8619
45bb3afb 8620 etype = TREE_TYPE (var);
8621 if (TREE_CODE (etype) == ARRAY_TYPE)
8622 etype = TREE_TYPE (etype);
8623
8624 if (!INTEGRAL_TYPE_P (etype)
8625 && !POINTER_TYPE_P (etype))
c2f47e15 8626 return NULL_TREE;
4f46f2b9 8627
e973ffcc 8628 if (! var_decl_component_p (var))
c2f47e15 8629 return NULL_TREE;
e973ffcc 8630
4f46f2b9 8631 length = tree_low_cst (len, 1);
45bb3afb 8632 if (GET_MODE_SIZE (TYPE_MODE (etype)) != length
957d0361 8633 || get_pointer_alignment (dest) / BITS_PER_UNIT < length)
c2f47e15 8634 return NULL_TREE;
4f46f2b9 8635
8636 if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT)
c2f47e15 8637 return NULL_TREE;
4f46f2b9 8638
8639 if (integer_zerop (c))
8640 cval = 0;
8641 else
8642 {
8643 if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64)
c2f47e15 8644 return NULL_TREE;
4f46f2b9 8645
d5d2f74a 8646 cval = TREE_INT_CST_LOW (c);
4f46f2b9 8647 cval &= 0xff;
8648 cval |= cval << 8;
8649 cval |= cval << 16;
8650 cval |= (cval << 31) << 1;
8651 }
8652
45bb3afb 8653 ret = build_int_cst_type (etype, cval);
389dd41b 8654 var = build_fold_indirect_ref_loc (loc,
8655 fold_convert_loc (loc,
8656 build_pointer_type (etype),
8657 dest));
45bb3afb 8658 ret = build2 (MODIFY_EXPR, etype, var, ret);
4f46f2b9 8659 if (ignore)
8660 return ret;
8661
389dd41b 8662 return omit_one_operand_loc (loc, type, dest, ret);
9c8a1629 8663}
8664
4f46f2b9 8665/* Fold function call to builtin memset. Return
9c8a1629 8666 NULL_TREE if no simplification can be made. */
8667
8668static tree
389dd41b 8669fold_builtin_bzero (location_t loc, tree dest, tree size, bool ignore)
9c8a1629 8670{
c2f47e15 8671 if (! validate_arg (dest, POINTER_TYPE)
8672 || ! validate_arg (size, INTEGER_TYPE))
8673 return NULL_TREE;
9c8a1629 8674
4f46f2b9 8675 if (!ignore)
c2f47e15 8676 return NULL_TREE;
a0c938f0 8677
4f46f2b9 8678 /* New argument list transforming bzero(ptr x, int y) to
8679 memset(ptr x, int 0, size_t y). This is done this way
8680 so that if it isn't expanded inline, we fallback to
8681 calling bzero instead of memset. */
8682
389dd41b 8683 return fold_builtin_memset (loc, dest, integer_zero_node,
a0553bff 8684 fold_convert_loc (loc, size_type_node, size),
c2f47e15 8685 void_type_node, ignore);
9c8a1629 8686}
8687
4f46f2b9 8688/* Fold function call to builtin mem{{,p}cpy,move}. Return
8689 NULL_TREE if no simplification can be made.
8690 If ENDP is 0, return DEST (like memcpy).
8691 If ENDP is 1, return DEST+LEN (like mempcpy).
8692 If ENDP is 2, return DEST+LEN-1 (like stpcpy).
8693 If ENDP is 3, return DEST, additionally *SRC and *DEST may overlap
8694 (memmove). */
9c8a1629 8695
8696static tree
389dd41b 8697fold_builtin_memory_op (location_t loc, tree dest, tree src,
8698 tree len, tree type, bool ignore, int endp)
9c8a1629 8699{
c2f47e15 8700 tree destvar, srcvar, expr;
9c8a1629 8701
c2f47e15 8702 if (! validate_arg (dest, POINTER_TYPE)
8703 || ! validate_arg (src, POINTER_TYPE)
8704 || ! validate_arg (len, INTEGER_TYPE))
8705 return NULL_TREE;
9c8a1629 8706
8707 /* If the LEN parameter is zero, return DEST. */
8708 if (integer_zerop (len))
389dd41b 8709 return omit_one_operand_loc (loc, type, dest, src);
9c8a1629 8710
4f46f2b9 8711 /* If SRC and DEST are the same (and not volatile), return
8712 DEST{,+LEN,+LEN-1}. */
9c8a1629 8713 if (operand_equal_p (src, dest, 0))
4f46f2b9 8714 expr = len;
8715 else
8716 {
5a84fdd6 8717 tree srctype, desttype;
153c3b50 8718 unsigned int src_align, dest_align;
182cf5a9 8719 tree off0;
5383fb56 8720
3b1757a2 8721 if (endp == 3)
8722 {
957d0361 8723 src_align = get_pointer_alignment (src);
8724 dest_align = get_pointer_alignment (dest);
5a84fdd6 8725
48e1416a 8726 /* Both DEST and SRC must be pointer types.
3b1757a2 8727 ??? This is what old code did. Is the testing for pointer types
8728 really mandatory?
8729
8730 If either SRC is readonly or length is 1, we can use memcpy. */
3f95c690 8731 if (!dest_align || !src_align)
8732 return NULL_TREE;
8733 if (readonly_data_expr (src)
8734 || (host_integerp (len, 1)
8735 && (MIN (src_align, dest_align) / BITS_PER_UNIT
12c655b1 8736 >= (unsigned HOST_WIDE_INT) tree_low_cst (len, 1))))
3b1757a2 8737 {
b9a16870 8738 tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
3b1757a2 8739 if (!fn)
c2f47e15 8740 return NULL_TREE;
389dd41b 8741 return build_call_expr_loc (loc, fn, 3, dest, src, len);
3b1757a2 8742 }
3f95c690 8743
8744 /* If *src and *dest can't overlap, optimize into memcpy as well. */
182cf5a9 8745 if (TREE_CODE (src) == ADDR_EXPR
8746 && TREE_CODE (dest) == ADDR_EXPR)
3f95c690 8747 {
f85fb819 8748 tree src_base, dest_base, fn;
8749 HOST_WIDE_INT src_offset = 0, dest_offset = 0;
8750 HOST_WIDE_INT size = -1;
8751 HOST_WIDE_INT maxsize = -1;
8752
182cf5a9 8753 srcvar = TREE_OPERAND (src, 0);
8754 src_base = get_ref_base_and_extent (srcvar, &src_offset,
8755 &size, &maxsize);
8756 destvar = TREE_OPERAND (dest, 0);
8757 dest_base = get_ref_base_and_extent (destvar, &dest_offset,
8758 &size, &maxsize);
f85fb819 8759 if (host_integerp (len, 1))
182cf5a9 8760 maxsize = tree_low_cst (len, 1);
f85fb819 8761 else
8762 maxsize = -1;
182cf5a9 8763 src_offset /= BITS_PER_UNIT;
8764 dest_offset /= BITS_PER_UNIT;
f85fb819 8765 if (SSA_VAR_P (src_base)
8766 && SSA_VAR_P (dest_base))
8767 {
8768 if (operand_equal_p (src_base, dest_base, 0)
8769 && ranges_overlap_p (src_offset, maxsize,
8770 dest_offset, maxsize))
8771 return NULL_TREE;
8772 }
182cf5a9 8773 else if (TREE_CODE (src_base) == MEM_REF
8774 && TREE_CODE (dest_base) == MEM_REF)
f85fb819 8775 {
182cf5a9 8776 double_int off;
f85fb819 8777 if (! operand_equal_p (TREE_OPERAND (src_base, 0),
182cf5a9 8778 TREE_OPERAND (dest_base, 0), 0))
8779 return NULL_TREE;
8780 off = double_int_add (mem_ref_offset (src_base),
8781 shwi_to_double_int (src_offset));
8782 if (!double_int_fits_in_shwi_p (off))
8783 return NULL_TREE;
8784 src_offset = off.low;
8785 off = double_int_add (mem_ref_offset (dest_base),
8786 shwi_to_double_int (dest_offset));
8787 if (!double_int_fits_in_shwi_p (off))
8788 return NULL_TREE;
8789 dest_offset = off.low;
8790 if (ranges_overlap_p (src_offset, maxsize,
8791 dest_offset, maxsize))
f85fb819 8792 return NULL_TREE;
8793 }
8794 else
8795 return NULL_TREE;
8796
b9a16870 8797 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
3f95c690 8798 if (!fn)
8799 return NULL_TREE;
389dd41b 8800 return build_call_expr_loc (loc, fn, 3, dest, src, len);
3f95c690 8801 }
c4222b63 8802
8803 /* If the destination and source do not alias optimize into
8804 memcpy as well. */
8805 if ((is_gimple_min_invariant (dest)
8806 || TREE_CODE (dest) == SSA_NAME)
8807 && (is_gimple_min_invariant (src)
8808 || TREE_CODE (src) == SSA_NAME))
8809 {
8810 ao_ref destr, srcr;
8811 ao_ref_init_from_ptr_and_size (&destr, dest, len);
8812 ao_ref_init_from_ptr_and_size (&srcr, src, len);
8813 if (!refs_may_alias_p_1 (&destr, &srcr, false))
8814 {
8815 tree fn;
b9a16870 8816 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
c4222b63 8817 if (!fn)
8818 return NULL_TREE;
8819 return build_call_expr_loc (loc, fn, 3, dest, src, len);
8820 }
8821 }
8822
c2f47e15 8823 return NULL_TREE;
3b1757a2 8824 }
4f46f2b9 8825
5a84fdd6 8826 if (!host_integerp (len, 0))
c2f47e15 8827 return NULL_TREE;
5a84fdd6 8828 /* FIXME:
8829 This logic lose for arguments like (type *)malloc (sizeof (type)),
8830 since we strip the casts of up to VOID return value from malloc.
8831 Perhaps we ought to inherit type from non-VOID argument here? */
8832 STRIP_NOPS (src);
8833 STRIP_NOPS (dest);
e07c7898 8834 if (!POINTER_TYPE_P (TREE_TYPE (src))
8835 || !POINTER_TYPE_P (TREE_TYPE (dest)))
8836 return NULL_TREE;
45bb3afb 8837 /* As we fold (void *)(p + CST) to (void *)p + CST undo this here. */
8838 if (TREE_CODE (src) == POINTER_PLUS_EXPR)
8839 {
8840 tree tem = TREE_OPERAND (src, 0);
8841 STRIP_NOPS (tem);
8842 if (tem != TREE_OPERAND (src, 0))
8843 src = build1 (NOP_EXPR, TREE_TYPE (tem), src);
8844 }
8845 if (TREE_CODE (dest) == POINTER_PLUS_EXPR)
8846 {
8847 tree tem = TREE_OPERAND (dest, 0);
8848 STRIP_NOPS (tem);
8849 if (tem != TREE_OPERAND (dest, 0))
8850 dest = build1 (NOP_EXPR, TREE_TYPE (tem), dest);
8851 }
5a84fdd6 8852 srctype = TREE_TYPE (TREE_TYPE (src));
e07c7898 8853 if (TREE_CODE (srctype) == ARRAY_TYPE
97d4c6a6 8854 && !tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
45bb3afb 8855 {
8856 srctype = TREE_TYPE (srctype);
8857 STRIP_NOPS (src);
8858 src = build1 (NOP_EXPR, build_pointer_type (srctype), src);
8859 }
5a84fdd6 8860 desttype = TREE_TYPE (TREE_TYPE (dest));
e07c7898 8861 if (TREE_CODE (desttype) == ARRAY_TYPE
97d4c6a6 8862 && !tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
45bb3afb 8863 {
8864 desttype = TREE_TYPE (desttype);
8865 STRIP_NOPS (dest);
8866 dest = build1 (NOP_EXPR, build_pointer_type (desttype), dest);
8867 }
e07c7898 8868 if (TREE_ADDRESSABLE (srctype)
8869 || TREE_ADDRESSABLE (desttype))
c2f47e15 8870 return NULL_TREE;
4f46f2b9 8871
957d0361 8872 src_align = get_pointer_alignment (src);
8873 dest_align = get_pointer_alignment (dest);
153c3b50 8874 if (dest_align < TYPE_ALIGN (desttype)
8875 || src_align < TYPE_ALIGN (srctype))
c2f47e15 8876 return NULL_TREE;
e973ffcc 8877
5a84fdd6 8878 if (!ignore)
8879 dest = builtin_save_expr (dest);
4f46f2b9 8880
182cf5a9 8881 /* Build accesses at offset zero with a ref-all character type. */
8882 off0 = build_int_cst (build_pointer_type_for_mode (char_type_node,
8883 ptr_mode, true), 0);
4f46f2b9 8884
182cf5a9 8885 destvar = dest;
8886 STRIP_NOPS (destvar);
8887 if (TREE_CODE (destvar) == ADDR_EXPR
8888 && var_decl_component_p (TREE_OPERAND (destvar, 0))
8889 && tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
8890 destvar = fold_build2 (MEM_REF, desttype, destvar, off0);
8891 else
8892 destvar = NULL_TREE;
8893
8894 srcvar = src;
8895 STRIP_NOPS (srcvar);
8896 if (TREE_CODE (srcvar) == ADDR_EXPR
8897 && var_decl_component_p (TREE_OPERAND (srcvar, 0))
5b99ff01 8898 && tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
8899 {
8900 if (!destvar
8901 || src_align >= TYPE_ALIGN (desttype))
8902 srcvar = fold_build2 (MEM_REF, destvar ? desttype : srctype,
8903 srcvar, off0);
8904 else if (!STRICT_ALIGNMENT)
8905 {
8906 srctype = build_aligned_type (TYPE_MAIN_VARIANT (desttype),
8907 src_align);
8908 srcvar = fold_build2 (MEM_REF, srctype, srcvar, off0);
8909 }
8910 else
8911 srcvar = NULL_TREE;
8912 }
182cf5a9 8913 else
8914 srcvar = NULL_TREE;
5383fb56 8915
8916 if (srcvar == NULL_TREE && destvar == NULL_TREE)
c2f47e15 8917 return NULL_TREE;
4f46f2b9 8918
5383fb56 8919 if (srcvar == NULL_TREE)
8920 {
182cf5a9 8921 STRIP_NOPS (src);
5b99ff01 8922 if (src_align >= TYPE_ALIGN (desttype))
8923 srcvar = fold_build2 (MEM_REF, desttype, src, off0);
8924 else
8925 {
8926 if (STRICT_ALIGNMENT)
8927 return NULL_TREE;
8928 srctype = build_aligned_type (TYPE_MAIN_VARIANT (desttype),
8929 src_align);
8930 srcvar = fold_build2 (MEM_REF, srctype, src, off0);
8931 }
5383fb56 8932 }
8933 else if (destvar == NULL_TREE)
8934 {
182cf5a9 8935 STRIP_NOPS (dest);
5b99ff01 8936 if (dest_align >= TYPE_ALIGN (srctype))
8937 destvar = fold_build2 (MEM_REF, srctype, dest, off0);
8938 else
8939 {
8940 if (STRICT_ALIGNMENT)
8941 return NULL_TREE;
8942 desttype = build_aligned_type (TYPE_MAIN_VARIANT (srctype),
8943 dest_align);
8944 destvar = fold_build2 (MEM_REF, desttype, dest, off0);
8945 }
5383fb56 8946 }
8947
182cf5a9 8948 expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, srcvar);
4f46f2b9 8949 }
8950
8951 if (ignore)
8952 return expr;
8953
8954 if (endp == 0 || endp == 3)
389dd41b 8955 return omit_one_operand_loc (loc, type, dest, expr);
4f46f2b9 8956
8957 if (expr == len)
c2f47e15 8958 expr = NULL_TREE;
4f46f2b9 8959
8960 if (endp == 2)
389dd41b 8961 len = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (len), len,
4f46f2b9 8962 ssize_int (1));
8963
2cc66f2a 8964 dest = fold_build_pointer_plus_loc (loc, dest, len);
389dd41b 8965 dest = fold_convert_loc (loc, type, dest);
4f46f2b9 8966 if (expr)
389dd41b 8967 dest = omit_one_operand_loc (loc, type, dest, expr);
4f46f2b9 8968 return dest;
8969}
8970
c2f47e15 8971/* Fold function call to builtin strcpy with arguments DEST and SRC.
8972 If LEN is not NULL, it represents the length of the string to be
8973 copied. Return NULL_TREE if no simplification can be made. */
9c8a1629 8974
f0613857 8975tree
389dd41b 8976fold_builtin_strcpy (location_t loc, tree fndecl, tree dest, tree src, tree len)
9c8a1629 8977{
c2f47e15 8978 tree fn;
9c8a1629 8979
c2f47e15 8980 if (!validate_arg (dest, POINTER_TYPE)
8981 || !validate_arg (src, POINTER_TYPE))
8982 return NULL_TREE;
9c8a1629 8983
8984 /* If SRC and DEST are the same (and not volatile), return DEST. */
8985 if (operand_equal_p (src, dest, 0))
389dd41b 8986 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
9c8a1629 8987
0bfd8d5c 8988 if (optimize_function_for_size_p (cfun))
c2f47e15 8989 return NULL_TREE;
f0613857 8990
b9a16870 8991 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
f0613857 8992 if (!fn)
c2f47e15 8993 return NULL_TREE;
f0613857 8994
8995 if (!len)
8996 {
8997 len = c_strlen (src, 1);
8998 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 8999 return NULL_TREE;
f0613857 9000 }
9001
bd6dcc04 9002 len = fold_convert_loc (loc, size_type_node, len);
9003 len = size_binop_loc (loc, PLUS_EXPR, len, build_int_cst (size_type_node, 1));
389dd41b 9004 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
9005 build_call_expr_loc (loc, fn, 3, dest, src, len));
9c8a1629 9006}
9007
a65c4d64 9008/* Fold function call to builtin stpcpy with arguments DEST and SRC.
9009 Return NULL_TREE if no simplification can be made. */
9010
9011static tree
9012fold_builtin_stpcpy (location_t loc, tree fndecl, tree dest, tree src)
9013{
9014 tree fn, len, lenp1, call, type;
9015
9016 if (!validate_arg (dest, POINTER_TYPE)
9017 || !validate_arg (src, POINTER_TYPE))
9018 return NULL_TREE;
9019
9020 len = c_strlen (src, 1);
9021 if (!len
9022 || TREE_CODE (len) != INTEGER_CST)
9023 return NULL_TREE;
9024
9025 if (optimize_function_for_size_p (cfun)
9026 /* If length is zero it's small enough. */
9027 && !integer_zerop (len))
9028 return NULL_TREE;
9029
b9a16870 9030 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
a65c4d64 9031 if (!fn)
9032 return NULL_TREE;
9033
bd6dcc04 9034 lenp1 = size_binop_loc (loc, PLUS_EXPR,
9035 fold_convert_loc (loc, size_type_node, len),
9036 build_int_cst (size_type_node, 1));
a65c4d64 9037 /* We use dest twice in building our expression. Save it from
9038 multiple expansions. */
9039 dest = builtin_save_expr (dest);
9040 call = build_call_expr_loc (loc, fn, 3, dest, src, lenp1);
9041
9042 type = TREE_TYPE (TREE_TYPE (fndecl));
2cc66f2a 9043 dest = fold_build_pointer_plus_loc (loc, dest, len);
a65c4d64 9044 dest = fold_convert_loc (loc, type, dest);
9045 dest = omit_one_operand_loc (loc, type, dest, call);
9046 return dest;
9047}
9048
c2f47e15 9049/* Fold function call to builtin strncpy with arguments DEST, SRC, and LEN.
9050 If SLEN is not NULL, it represents the length of the source string.
9051 Return NULL_TREE if no simplification can be made. */
9c8a1629 9052
f0613857 9053tree
389dd41b 9054fold_builtin_strncpy (location_t loc, tree fndecl, tree dest,
9055 tree src, tree len, tree slen)
9c8a1629 9056{
c2f47e15 9057 tree fn;
9c8a1629 9058
c2f47e15 9059 if (!validate_arg (dest, POINTER_TYPE)
9060 || !validate_arg (src, POINTER_TYPE)
9061 || !validate_arg (len, INTEGER_TYPE))
9062 return NULL_TREE;
9c8a1629 9063
9064 /* If the LEN parameter is zero, return DEST. */
9065 if (integer_zerop (len))
389dd41b 9066 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
9c8a1629 9067
19226313 9068 /* We can't compare slen with len as constants below if len is not a
9069 constant. */
9070 if (len == 0 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 9071 return NULL_TREE;
19226313 9072
f0613857 9073 if (!slen)
9074 slen = c_strlen (src, 1);
9075
9076 /* Now, we must be passed a constant src ptr parameter. */
9077 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
c2f47e15 9078 return NULL_TREE;
f0613857 9079
389dd41b 9080 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
f0613857 9081
9082 /* We do not support simplification of this case, though we do
9083 support it when expanding trees into RTL. */
9084 /* FIXME: generate a call to __builtin_memset. */
9085 if (tree_int_cst_lt (slen, len))
c2f47e15 9086 return NULL_TREE;
f0613857 9087
9088 /* OK transform into builtin memcpy. */
b9a16870 9089 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
f0613857 9090 if (!fn)
c2f47e15 9091 return NULL_TREE;
bd6dcc04 9092
9093 len = fold_convert_loc (loc, size_type_node, len);
389dd41b 9094 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
9095 build_call_expr_loc (loc, fn, 3, dest, src, len));
9c8a1629 9096}
9097
7959b13b 9098/* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the
9099 arguments to the call, and TYPE is its return type.
9100 Return NULL_TREE if no simplification can be made. */
9101
9102static tree
389dd41b 9103fold_builtin_memchr (location_t loc, tree arg1, tree arg2, tree len, tree type)
7959b13b 9104{
9105 if (!validate_arg (arg1, POINTER_TYPE)
9106 || !validate_arg (arg2, INTEGER_TYPE)
9107 || !validate_arg (len, INTEGER_TYPE))
9108 return NULL_TREE;
9109 else
9110 {
9111 const char *p1;
9112
9113 if (TREE_CODE (arg2) != INTEGER_CST
9114 || !host_integerp (len, 1))
9115 return NULL_TREE;
9116
9117 p1 = c_getstr (arg1);
9118 if (p1 && compare_tree_int (len, strlen (p1) + 1) <= 0)
9119 {
9120 char c;
9121 const char *r;
9122 tree tem;
9123
9124 if (target_char_cast (arg2, &c))
9125 return NULL_TREE;
9126
609cab98 9127 r = (const char *) memchr (p1, c, tree_low_cst (len, 1));
7959b13b 9128
9129 if (r == NULL)
9130 return build_int_cst (TREE_TYPE (arg1), 0);
9131
2cc66f2a 9132 tem = fold_build_pointer_plus_hwi_loc (loc, arg1, r - p1);
389dd41b 9133 return fold_convert_loc (loc, type, tem);
7959b13b 9134 }
9135 return NULL_TREE;
9136 }
9137}
9138
c2f47e15 9139/* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
9140 Return NULL_TREE if no simplification can be made. */
9c8a1629 9141
9142static tree
389dd41b 9143fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
9c8a1629 9144{
c4fef134 9145 const char *p1, *p2;
9c8a1629 9146
c2f47e15 9147 if (!validate_arg (arg1, POINTER_TYPE)
9148 || !validate_arg (arg2, POINTER_TYPE)
9149 || !validate_arg (len, INTEGER_TYPE))
9150 return NULL_TREE;
9c8a1629 9151
9152 /* If the LEN parameter is zero, return zero. */
9153 if (integer_zerop (len))
389dd41b 9154 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
c4fef134 9155 arg1, arg2);
9c8a1629 9156
9157 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9158 if (operand_equal_p (arg1, arg2, 0))
389dd41b 9159 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
c4fef134 9160
9161 p1 = c_getstr (arg1);
9162 p2 = c_getstr (arg2);
9163
9164 /* If all arguments are constant, and the value of len is not greater
9165 than the lengths of arg1 and arg2, evaluate at compile-time. */
9166 if (host_integerp (len, 1) && p1 && p2
9167 && compare_tree_int (len, strlen (p1) + 1) <= 0
9168 && compare_tree_int (len, strlen (p2) + 1) <= 0)
9169 {
9170 const int r = memcmp (p1, p2, tree_low_cst (len, 1));
9171
9172 if (r > 0)
9173 return integer_one_node;
9174 else if (r < 0)
9175 return integer_minus_one_node;
9176 else
9177 return integer_zero_node;
9178 }
9179
9180 /* If len parameter is one, return an expression corresponding to
9181 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
9182 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
9183 {
9184 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9185 tree cst_uchar_ptr_node
9186 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9187
389dd41b 9188 tree ind1
9189 = fold_convert_loc (loc, integer_type_node,
9190 build1 (INDIRECT_REF, cst_uchar_node,
9191 fold_convert_loc (loc,
9192 cst_uchar_ptr_node,
c4fef134 9193 arg1)));
389dd41b 9194 tree ind2
9195 = fold_convert_loc (loc, integer_type_node,
9196 build1 (INDIRECT_REF, cst_uchar_node,
9197 fold_convert_loc (loc,
9198 cst_uchar_ptr_node,
c4fef134 9199 arg2)));
389dd41b 9200 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
c4fef134 9201 }
9c8a1629 9202
c2f47e15 9203 return NULL_TREE;
9c8a1629 9204}
9205
c2f47e15 9206/* Fold function call to builtin strcmp with arguments ARG1 and ARG2.
9207 Return NULL_TREE if no simplification can be made. */
9c8a1629 9208
9209static tree
389dd41b 9210fold_builtin_strcmp (location_t loc, tree arg1, tree arg2)
9c8a1629 9211{
9c8a1629 9212 const char *p1, *p2;
9213
c2f47e15 9214 if (!validate_arg (arg1, POINTER_TYPE)
9215 || !validate_arg (arg2, POINTER_TYPE))
9216 return NULL_TREE;
9c8a1629 9217
9218 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9219 if (operand_equal_p (arg1, arg2, 0))
c4fef134 9220 return integer_zero_node;
9c8a1629 9221
9222 p1 = c_getstr (arg1);
9223 p2 = c_getstr (arg2);
9224
9225 if (p1 && p2)
9226 {
9c8a1629 9227 const int i = strcmp (p1, p2);
9228 if (i < 0)
c4fef134 9229 return integer_minus_one_node;
9c8a1629 9230 else if (i > 0)
c4fef134 9231 return integer_one_node;
9c8a1629 9232 else
c4fef134 9233 return integer_zero_node;
9234 }
9235
9236 /* If the second arg is "", return *(const unsigned char*)arg1. */
9237 if (p2 && *p2 == '\0')
9238 {
9239 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9240 tree cst_uchar_ptr_node
9241 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9242
389dd41b 9243 return fold_convert_loc (loc, integer_type_node,
9244 build1 (INDIRECT_REF, cst_uchar_node,
9245 fold_convert_loc (loc,
9246 cst_uchar_ptr_node,
9247 arg1)));
c4fef134 9248 }
9249
9250 /* If the first arg is "", return -*(const unsigned char*)arg2. */
9251 if (p1 && *p1 == '\0')
9252 {
9253 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9254 tree cst_uchar_ptr_node
9255 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9256
389dd41b 9257 tree temp
9258 = fold_convert_loc (loc, integer_type_node,
9259 build1 (INDIRECT_REF, cst_uchar_node,
9260 fold_convert_loc (loc,
9261 cst_uchar_ptr_node,
c4fef134 9262 arg2)));
389dd41b 9263 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp);
9c8a1629 9264 }
9265
c2f47e15 9266 return NULL_TREE;
9c8a1629 9267}
9268
c2f47e15 9269/* Fold function call to builtin strncmp with arguments ARG1, ARG2, and LEN.
9270 Return NULL_TREE if no simplification can be made. */
9c8a1629 9271
9272static tree
389dd41b 9273fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len)
9c8a1629 9274{
9c8a1629 9275 const char *p1, *p2;
9276
c2f47e15 9277 if (!validate_arg (arg1, POINTER_TYPE)
9278 || !validate_arg (arg2, POINTER_TYPE)
9279 || !validate_arg (len, INTEGER_TYPE))
9280 return NULL_TREE;
9c8a1629 9281
9282 /* If the LEN parameter is zero, return zero. */
9283 if (integer_zerop (len))
389dd41b 9284 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
c4fef134 9285 arg1, arg2);
9c8a1629 9286
9287 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9288 if (operand_equal_p (arg1, arg2, 0))
389dd41b 9289 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
9c8a1629 9290
9291 p1 = c_getstr (arg1);
9292 p2 = c_getstr (arg2);
9293
9294 if (host_integerp (len, 1) && p1 && p2)
9295 {
9c8a1629 9296 const int i = strncmp (p1, p2, tree_low_cst (len, 1));
c4fef134 9297 if (i > 0)
9298 return integer_one_node;
9299 else if (i < 0)
9300 return integer_minus_one_node;
9c8a1629 9301 else
c4fef134 9302 return integer_zero_node;
9303 }
9304
9305 /* If the second arg is "", and the length is greater than zero,
9306 return *(const unsigned char*)arg1. */
9307 if (p2 && *p2 == '\0'
9308 && TREE_CODE (len) == INTEGER_CST
9309 && tree_int_cst_sgn (len) == 1)
9310 {
9311 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9312 tree cst_uchar_ptr_node
9313 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9314
389dd41b 9315 return fold_convert_loc (loc, integer_type_node,
9316 build1 (INDIRECT_REF, cst_uchar_node,
9317 fold_convert_loc (loc,
9318 cst_uchar_ptr_node,
9319 arg1)));
c4fef134 9320 }
9321
9322 /* If the first arg is "", and the length is greater than zero,
9323 return -*(const unsigned char*)arg2. */
9324 if (p1 && *p1 == '\0'
9325 && TREE_CODE (len) == INTEGER_CST
9326 && tree_int_cst_sgn (len) == 1)
9327 {
9328 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9329 tree cst_uchar_ptr_node
9330 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9331
389dd41b 9332 tree temp = fold_convert_loc (loc, integer_type_node,
9333 build1 (INDIRECT_REF, cst_uchar_node,
9334 fold_convert_loc (loc,
9335 cst_uchar_ptr_node,
9336 arg2)));
9337 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp);
c4fef134 9338 }
9339
9340 /* If len parameter is one, return an expression corresponding to
9341 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
9342 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
9343 {
9344 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9345 tree cst_uchar_ptr_node
9346 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9347
389dd41b 9348 tree ind1 = fold_convert_loc (loc, integer_type_node,
9349 build1 (INDIRECT_REF, cst_uchar_node,
9350 fold_convert_loc (loc,
9351 cst_uchar_ptr_node,
9352 arg1)));
9353 tree ind2 = fold_convert_loc (loc, integer_type_node,
9354 build1 (INDIRECT_REF, cst_uchar_node,
9355 fold_convert_loc (loc,
9356 cst_uchar_ptr_node,
9357 arg2)));
9358 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
9c8a1629 9359 }
9360
c2f47e15 9361 return NULL_TREE;
9c8a1629 9362}
9363
c2f47e15 9364/* Fold function call to builtin signbit, signbitf or signbitl with argument
9365 ARG. Return NULL_TREE if no simplification can be made. */
27f261ef 9366
9367static tree
389dd41b 9368fold_builtin_signbit (location_t loc, tree arg, tree type)
27f261ef 9369{
c2f47e15 9370 if (!validate_arg (arg, REAL_TYPE))
27f261ef 9371 return NULL_TREE;
9372
27f261ef 9373 /* If ARG is a compile-time constant, determine the result. */
9374 if (TREE_CODE (arg) == REAL_CST
f96bd2bf 9375 && !TREE_OVERFLOW (arg))
27f261ef 9376 {
9377 REAL_VALUE_TYPE c;
9378
9379 c = TREE_REAL_CST (arg);
385f3f36 9380 return (REAL_VALUE_NEGATIVE (c)
9381 ? build_one_cst (type)
9382 : build_zero_cst (type));
27f261ef 9383 }
9384
9385 /* If ARG is non-negative, the result is always zero. */
9386 if (tree_expr_nonnegative_p (arg))
389dd41b 9387 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
27f261ef 9388
9389 /* If ARG's format doesn't have signed zeros, return "arg < 0.0". */
9390 if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
de67cbb8 9391 return fold_convert (type,
9392 fold_build2_loc (loc, LT_EXPR, boolean_type_node, arg,
9393 build_real (TREE_TYPE (arg), dconst0)));
27f261ef 9394
9395 return NULL_TREE;
9396}
9397
c2f47e15 9398/* Fold function call to builtin copysign, copysignf or copysignl with
9399 arguments ARG1 and ARG2. Return NULL_TREE if no simplification can
9400 be made. */
467214fd 9401
9402static tree
389dd41b 9403fold_builtin_copysign (location_t loc, tree fndecl,
9404 tree arg1, tree arg2, tree type)
467214fd 9405{
c2f47e15 9406 tree tem;
467214fd 9407
c2f47e15 9408 if (!validate_arg (arg1, REAL_TYPE)
9409 || !validate_arg (arg2, REAL_TYPE))
467214fd 9410 return NULL_TREE;
9411
467214fd 9412 /* copysign(X,X) is X. */
9413 if (operand_equal_p (arg1, arg2, 0))
389dd41b 9414 return fold_convert_loc (loc, type, arg1);
467214fd 9415
9416 /* If ARG1 and ARG2 are compile-time constants, determine the result. */
9417 if (TREE_CODE (arg1) == REAL_CST
9418 && TREE_CODE (arg2) == REAL_CST
f96bd2bf 9419 && !TREE_OVERFLOW (arg1)
9420 && !TREE_OVERFLOW (arg2))
467214fd 9421 {
9422 REAL_VALUE_TYPE c1, c2;
9423
9424 c1 = TREE_REAL_CST (arg1);
9425 c2 = TREE_REAL_CST (arg2);
749680e2 9426 /* c1.sign := c2.sign. */
467214fd 9427 real_copysign (&c1, &c2);
9428 return build_real (type, c1);
467214fd 9429 }
9430
9431 /* copysign(X, Y) is fabs(X) when Y is always non-negative.
9432 Remember to evaluate Y for side-effects. */
9433 if (tree_expr_nonnegative_p (arg2))
389dd41b 9434 return omit_one_operand_loc (loc, type,
9435 fold_build1_loc (loc, ABS_EXPR, type, arg1),
467214fd 9436 arg2);
9437
198d9bbe 9438 /* Strip sign changing operations for the first argument. */
9439 tem = fold_strip_sign_ops (arg1);
9440 if (tem)
389dd41b 9441 return build_call_expr_loc (loc, fndecl, 2, tem, arg2);
198d9bbe 9442
467214fd 9443 return NULL_TREE;
9444}
9445
c2f47e15 9446/* Fold a call to builtin isascii with argument ARG. */
d49367d4 9447
9448static tree
389dd41b 9449fold_builtin_isascii (location_t loc, tree arg)
d49367d4 9450{
c2f47e15 9451 if (!validate_arg (arg, INTEGER_TYPE))
9452 return NULL_TREE;
d49367d4 9453 else
9454 {
9455 /* Transform isascii(c) -> ((c & ~0x7f) == 0). */
c90b5d40 9456 arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
7002a1c8 9457 build_int_cst (integer_type_node,
c90b5d40 9458 ~ (unsigned HOST_WIDE_INT) 0x7f));
389dd41b 9459 return fold_build2_loc (loc, EQ_EXPR, integer_type_node,
7002a1c8 9460 arg, integer_zero_node);
d49367d4 9461 }
9462}
9463
c2f47e15 9464/* Fold a call to builtin toascii with argument ARG. */
d49367d4 9465
9466static tree
389dd41b 9467fold_builtin_toascii (location_t loc, tree arg)
d49367d4 9468{
c2f47e15 9469 if (!validate_arg (arg, INTEGER_TYPE))
9470 return NULL_TREE;
48e1416a 9471
c2f47e15 9472 /* Transform toascii(c) -> (c & 0x7f). */
389dd41b 9473 return fold_build2_loc (loc, BIT_AND_EXPR, integer_type_node, arg,
7002a1c8 9474 build_int_cst (integer_type_node, 0x7f));
d49367d4 9475}
9476
c2f47e15 9477/* Fold a call to builtin isdigit with argument ARG. */
df1cf42e 9478
9479static tree
389dd41b 9480fold_builtin_isdigit (location_t loc, tree arg)
df1cf42e 9481{
c2f47e15 9482 if (!validate_arg (arg, INTEGER_TYPE))
9483 return NULL_TREE;
df1cf42e 9484 else
9485 {
9486 /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */
624d37a6 9487 /* According to the C standard, isdigit is unaffected by locale.
9488 However, it definitely is affected by the target character set. */
624d37a6 9489 unsigned HOST_WIDE_INT target_digit0
9490 = lang_hooks.to_target_charset ('0');
9491
9492 if (target_digit0 == 0)
9493 return NULL_TREE;
9494
389dd41b 9495 arg = fold_convert_loc (loc, unsigned_type_node, arg);
c90b5d40 9496 arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg,
9497 build_int_cst (unsigned_type_node, target_digit0));
389dd41b 9498 return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg,
f2532264 9499 build_int_cst (unsigned_type_node, 9));
df1cf42e 9500 }
9501}
27f261ef 9502
c2f47e15 9503/* Fold a call to fabs, fabsf or fabsl with argument ARG. */
d1aade50 9504
9505static tree
389dd41b 9506fold_builtin_fabs (location_t loc, tree arg, tree type)
d1aade50 9507{
c2f47e15 9508 if (!validate_arg (arg, REAL_TYPE))
9509 return NULL_TREE;
d1aade50 9510
389dd41b 9511 arg = fold_convert_loc (loc, type, arg);
d1aade50 9512 if (TREE_CODE (arg) == REAL_CST)
9513 return fold_abs_const (arg, type);
389dd41b 9514 return fold_build1_loc (loc, ABS_EXPR, type, arg);
d1aade50 9515}
9516
c2f47e15 9517/* Fold a call to abs, labs, llabs or imaxabs with argument ARG. */
d1aade50 9518
9519static tree
389dd41b 9520fold_builtin_abs (location_t loc, tree arg, tree type)
d1aade50 9521{
c2f47e15 9522 if (!validate_arg (arg, INTEGER_TYPE))
9523 return NULL_TREE;
d1aade50 9524
389dd41b 9525 arg = fold_convert_loc (loc, type, arg);
d1aade50 9526 if (TREE_CODE (arg) == INTEGER_CST)
9527 return fold_abs_const (arg, type);
389dd41b 9528 return fold_build1_loc (loc, ABS_EXPR, type, arg);
d1aade50 9529}
9530
b9be572e 9531/* Fold a fma operation with arguments ARG[012]. */
9532
9533tree
9534fold_fma (location_t loc ATTRIBUTE_UNUSED,
9535 tree type, tree arg0, tree arg1, tree arg2)
9536{
9537 if (TREE_CODE (arg0) == REAL_CST
9538 && TREE_CODE (arg1) == REAL_CST
9539 && TREE_CODE (arg2) == REAL_CST)
9540 return do_mpfr_arg3 (arg0, arg1, arg2, type, mpfr_fma);
9541
9542 return NULL_TREE;
9543}
9544
9545/* Fold a call to fma, fmaf, or fmal with arguments ARG[012]. */
9546
9547static tree
9548fold_builtin_fma (location_t loc, tree arg0, tree arg1, tree arg2, tree type)
9549{
9550 if (validate_arg (arg0, REAL_TYPE)
9551 && validate_arg(arg1, REAL_TYPE)
9552 && validate_arg(arg2, REAL_TYPE))
9553 {
9554 tree tem = fold_fma (loc, type, arg0, arg1, arg2);
9555 if (tem)
9556 return tem;
9557
9558 /* ??? Only expand to FMA_EXPR if it's directly supported. */
9559 if (optab_handler (fma_optab, TYPE_MODE (type)) != CODE_FOR_nothing)
9560 return fold_build3_loc (loc, FMA_EXPR, type, arg0, arg1, arg2);
9561 }
9562 return NULL_TREE;
9563}
9564
d4a43a03 9565/* Fold a call to builtin fmin or fmax. */
9566
9567static tree
389dd41b 9568fold_builtin_fmin_fmax (location_t loc, tree arg0, tree arg1,
9569 tree type, bool max)
d4a43a03 9570{
c2f47e15 9571 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, REAL_TYPE))
d4a43a03 9572 {
d4a43a03 9573 /* Calculate the result when the argument is a constant. */
9574 tree res = do_mpfr_arg2 (arg0, arg1, type, (max ? mpfr_max : mpfr_min));
9575
9576 if (res)
9577 return res;
9578
61fe3555 9579 /* If either argument is NaN, return the other one. Avoid the
9580 transformation if we get (and honor) a signalling NaN. Using
9581 omit_one_operand() ensures we create a non-lvalue. */
9582 if (TREE_CODE (arg0) == REAL_CST
9583 && real_isnan (&TREE_REAL_CST (arg0))
9584 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
9585 || ! TREE_REAL_CST (arg0).signalling))
389dd41b 9586 return omit_one_operand_loc (loc, type, arg1, arg0);
61fe3555 9587 if (TREE_CODE (arg1) == REAL_CST
9588 && real_isnan (&TREE_REAL_CST (arg1))
9589 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
9590 || ! TREE_REAL_CST (arg1).signalling))
389dd41b 9591 return omit_one_operand_loc (loc, type, arg0, arg1);
61fe3555 9592
d4a43a03 9593 /* Transform fmin/fmax(x,x) -> x. */
9594 if (operand_equal_p (arg0, arg1, OEP_PURE_SAME))
389dd41b 9595 return omit_one_operand_loc (loc, type, arg0, arg1);
48e1416a 9596
d4a43a03 9597 /* Convert fmin/fmax to MIN_EXPR/MAX_EXPR. C99 requires these
9598 functions to return the numeric arg if the other one is NaN.
9599 These tree codes don't honor that, so only transform if
9600 -ffinite-math-only is set. C99 doesn't require -0.0 to be
9601 handled, so we don't have to worry about it either. */
9602 if (flag_finite_math_only)
389dd41b 9603 return fold_build2_loc (loc, (max ? MAX_EXPR : MIN_EXPR), type,
9604 fold_convert_loc (loc, type, arg0),
9605 fold_convert_loc (loc, type, arg1));
d4a43a03 9606 }
9607 return NULL_TREE;
9608}
9609
abe4dcf6 9610/* Fold a call to builtin carg(a+bi) -> atan2(b,a). */
9611
9612static tree
389dd41b 9613fold_builtin_carg (location_t loc, tree arg, tree type)
abe4dcf6 9614{
239d491a 9615 if (validate_arg (arg, COMPLEX_TYPE)
9616 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
abe4dcf6 9617 {
9618 tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
48e1416a 9619
abe4dcf6 9620 if (atan2_fn)
9621 {
c2f47e15 9622 tree new_arg = builtin_save_expr (arg);
389dd41b 9623 tree r_arg = fold_build1_loc (loc, REALPART_EXPR, type, new_arg);
9624 tree i_arg = fold_build1_loc (loc, IMAGPART_EXPR, type, new_arg);
9625 return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg);
abe4dcf6 9626 }
9627 }
48e1416a 9628
abe4dcf6 9629 return NULL_TREE;
9630}
9631
cb2b9385 9632/* Fold a call to builtin logb/ilogb. */
9633
9634static tree
389dd41b 9635fold_builtin_logb (location_t loc, tree arg, tree rettype)
cb2b9385 9636{
9637 if (! validate_arg (arg, REAL_TYPE))
9638 return NULL_TREE;
48e1416a 9639
cb2b9385 9640 STRIP_NOPS (arg);
48e1416a 9641
cb2b9385 9642 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9643 {
9644 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
48e1416a 9645
cb2b9385 9646 switch (value->cl)
9647 {
9648 case rvc_nan:
9649 case rvc_inf:
9650 /* If arg is Inf or NaN and we're logb, return it. */
9651 if (TREE_CODE (rettype) == REAL_TYPE)
389dd41b 9652 return fold_convert_loc (loc, rettype, arg);
cb2b9385 9653 /* Fall through... */
9654 case rvc_zero:
9655 /* Zero may set errno and/or raise an exception for logb, also
9656 for ilogb we don't know FP_ILOGB0. */
9657 return NULL_TREE;
9658 case rvc_normal:
9659 /* For normal numbers, proceed iff radix == 2. In GCC,
9660 normalized significands are in the range [0.5, 1.0). We
9661 want the exponent as if they were [1.0, 2.0) so get the
9662 exponent and subtract 1. */
9663 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
389dd41b 9664 return fold_convert_loc (loc, rettype,
7002a1c8 9665 build_int_cst (integer_type_node,
389dd41b 9666 REAL_EXP (value)-1));
cb2b9385 9667 break;
9668 }
9669 }
48e1416a 9670
cb2b9385 9671 return NULL_TREE;
9672}
9673
9674/* Fold a call to builtin significand, if radix == 2. */
9675
9676static tree
389dd41b 9677fold_builtin_significand (location_t loc, tree arg, tree rettype)
cb2b9385 9678{
9679 if (! validate_arg (arg, REAL_TYPE))
9680 return NULL_TREE;
48e1416a 9681
cb2b9385 9682 STRIP_NOPS (arg);
48e1416a 9683
cb2b9385 9684 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9685 {
9686 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
48e1416a 9687
cb2b9385 9688 switch (value->cl)
9689 {
9690 case rvc_zero:
9691 case rvc_nan:
9692 case rvc_inf:
9693 /* If arg is +-0, +-Inf or +-NaN, then return it. */
389dd41b 9694 return fold_convert_loc (loc, rettype, arg);
cb2b9385 9695 case rvc_normal:
9696 /* For normal numbers, proceed iff radix == 2. */
9697 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
9698 {
9699 REAL_VALUE_TYPE result = *value;
9700 /* In GCC, normalized significands are in the range [0.5,
9701 1.0). We want them to be [1.0, 2.0) so set the
9702 exponent to 1. */
9703 SET_REAL_EXP (&result, 1);
9704 return build_real (rettype, result);
9705 }
9706 break;
9707 }
9708 }
48e1416a 9709
cb2b9385 9710 return NULL_TREE;
9711}
9712
3838b9ae 9713/* Fold a call to builtin frexp, we can assume the base is 2. */
9714
9715static tree
389dd41b 9716fold_builtin_frexp (location_t loc, tree arg0, tree arg1, tree rettype)
3838b9ae 9717{
9718 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9719 return NULL_TREE;
48e1416a 9720
3838b9ae 9721 STRIP_NOPS (arg0);
48e1416a 9722
3838b9ae 9723 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9724 return NULL_TREE;
48e1416a 9725
389dd41b 9726 arg1 = build_fold_indirect_ref_loc (loc, arg1);
3838b9ae 9727
9728 /* Proceed if a valid pointer type was passed in. */
9729 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
9730 {
9731 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9732 tree frac, exp;
48e1416a 9733
3838b9ae 9734 switch (value->cl)
9735 {
9736 case rvc_zero:
9737 /* For +-0, return (*exp = 0, +-0). */
9738 exp = integer_zero_node;
9739 frac = arg0;
9740 break;
9741 case rvc_nan:
9742 case rvc_inf:
9743 /* For +-NaN or +-Inf, *exp is unspecified, return arg0. */
389dd41b 9744 return omit_one_operand_loc (loc, rettype, arg0, arg1);
3838b9ae 9745 case rvc_normal:
9746 {
9747 /* Since the frexp function always expects base 2, and in
9748 GCC normalized significands are already in the range
9749 [0.5, 1.0), we have exactly what frexp wants. */
9750 REAL_VALUE_TYPE frac_rvt = *value;
9751 SET_REAL_EXP (&frac_rvt, 0);
9752 frac = build_real (rettype, frac_rvt);
7002a1c8 9753 exp = build_int_cst (integer_type_node, REAL_EXP (value));
3838b9ae 9754 }
9755 break;
9756 default:
9757 gcc_unreachable ();
9758 }
48e1416a 9759
3838b9ae 9760 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
389dd41b 9761 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, exp);
3838b9ae 9762 TREE_SIDE_EFFECTS (arg1) = 1;
389dd41b 9763 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1, frac);
3838b9ae 9764 }
9765
9766 return NULL_TREE;
9767}
9768
7587301b 9769/* Fold a call to builtin ldexp or scalbn/scalbln. If LDEXP is true
9770 then we can assume the base is two. If it's false, then we have to
9771 check the mode of the TYPE parameter in certain cases. */
9772
9773static tree
389dd41b 9774fold_builtin_load_exponent (location_t loc, tree arg0, tree arg1,
9775 tree type, bool ldexp)
7587301b 9776{
9777 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, INTEGER_TYPE))
9778 {
9779 STRIP_NOPS (arg0);
9780 STRIP_NOPS (arg1);
9781
9782 /* If arg0 is 0, Inf or NaN, or if arg1 is 0, then return arg0. */
9783 if (real_zerop (arg0) || integer_zerop (arg1)
9784 || (TREE_CODE (arg0) == REAL_CST
776a7bab 9785 && !real_isfinite (&TREE_REAL_CST (arg0))))
389dd41b 9786 return omit_one_operand_loc (loc, type, arg0, arg1);
48e1416a 9787
7587301b 9788 /* If both arguments are constant, then try to evaluate it. */
9789 if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2)
9790 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
9791 && host_integerp (arg1, 0))
9792 {
9793 /* Bound the maximum adjustment to twice the range of the
9794 mode's valid exponents. Use abs to ensure the range is
9795 positive as a sanity check. */
48e1416a 9796 const long max_exp_adj = 2 *
7587301b 9797 labs (REAL_MODE_FORMAT (TYPE_MODE (type))->emax
9798 - REAL_MODE_FORMAT (TYPE_MODE (type))->emin);
9799
9800 /* Get the user-requested adjustment. */
9801 const HOST_WIDE_INT req_exp_adj = tree_low_cst (arg1, 0);
48e1416a 9802
7587301b 9803 /* The requested adjustment must be inside this range. This
9804 is a preliminary cap to avoid things like overflow, we
9805 may still fail to compute the result for other reasons. */
9806 if (-max_exp_adj < req_exp_adj && req_exp_adj < max_exp_adj)
9807 {
9808 REAL_VALUE_TYPE initial_result;
48e1416a 9809
7587301b 9810 real_ldexp (&initial_result, &TREE_REAL_CST (arg0), req_exp_adj);
9811
9812 /* Ensure we didn't overflow. */
9813 if (! real_isinf (&initial_result))
9814 {
9815 const REAL_VALUE_TYPE trunc_result
9816 = real_value_truncate (TYPE_MODE (type), initial_result);
48e1416a 9817
7587301b 9818 /* Only proceed if the target mode can hold the
9819 resulting value. */
9820 if (REAL_VALUES_EQUAL (initial_result, trunc_result))
9821 return build_real (type, trunc_result);
9822 }
9823 }
9824 }
9825 }
9826
9827 return NULL_TREE;
9828}
9829
ebf8b4f5 9830/* Fold a call to builtin modf. */
9831
9832static tree
389dd41b 9833fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
ebf8b4f5 9834{
9835 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9836 return NULL_TREE;
48e1416a 9837
ebf8b4f5 9838 STRIP_NOPS (arg0);
48e1416a 9839
ebf8b4f5 9840 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9841 return NULL_TREE;
48e1416a 9842
389dd41b 9843 arg1 = build_fold_indirect_ref_loc (loc, arg1);
ebf8b4f5 9844
9845 /* Proceed if a valid pointer type was passed in. */
9846 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
9847 {
9848 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9849 REAL_VALUE_TYPE trunc, frac;
9850
9851 switch (value->cl)
9852 {
9853 case rvc_nan:
9854 case rvc_zero:
9855 /* For +-NaN or +-0, return (*arg1 = arg0, arg0). */
9856 trunc = frac = *value;
9857 break;
9858 case rvc_inf:
9859 /* For +-Inf, return (*arg1 = arg0, +-0). */
9860 frac = dconst0;
9861 frac.sign = value->sign;
9862 trunc = *value;
9863 break;
9864 case rvc_normal:
9865 /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)). */
9866 real_trunc (&trunc, VOIDmode, value);
9867 real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
9868 /* If the original number was negative and already
9869 integral, then the fractional part is -0.0. */
9870 if (value->sign && frac.cl == rvc_zero)
9871 frac.sign = value->sign;
9872 break;
9873 }
48e1416a 9874
ebf8b4f5 9875 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
389dd41b 9876 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1,
ebf8b4f5 9877 build_real (rettype, trunc));
9878 TREE_SIDE_EFFECTS (arg1) = 1;
389dd41b 9879 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1,
ebf8b4f5 9880 build_real (rettype, frac));
9881 }
48e1416a 9882
ebf8b4f5 9883 return NULL_TREE;
9884}
9885
a65c4d64 9886/* Given a location LOC, an interclass builtin function decl FNDECL
9887 and its single argument ARG, return an folded expression computing
9888 the same, or NULL_TREE if we either couldn't or didn't want to fold
9889 (the latter happen if there's an RTL instruction available). */
9890
9891static tree
9892fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
9893{
9894 enum machine_mode mode;
9895
9896 if (!validate_arg (arg, REAL_TYPE))
9897 return NULL_TREE;
9898
9899 if (interclass_mathfn_icode (arg, fndecl) != CODE_FOR_nothing)
9900 return NULL_TREE;
9901
9902 mode = TYPE_MODE (TREE_TYPE (arg));
9903
9904 /* If there is no optab, try generic code. */
9905 switch (DECL_FUNCTION_CODE (fndecl))
9906 {
9907 tree result;
9908
9909 CASE_FLT_FN (BUILT_IN_ISINF):
9910 {
9911 /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
b9a16870 9912 tree const isgr_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
a65c4d64 9913 tree const type = TREE_TYPE (arg);
9914 REAL_VALUE_TYPE r;
9915 char buf[128];
9916
9917 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9918 real_from_string (&r, buf);
9919 result = build_call_expr (isgr_fn, 2,
9920 fold_build1_loc (loc, ABS_EXPR, type, arg),
9921 build_real (type, r));
9922 return result;
9923 }
9924 CASE_FLT_FN (BUILT_IN_FINITE):
9925 case BUILT_IN_ISFINITE:
9926 {
9927 /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
b9a16870 9928 tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
a65c4d64 9929 tree const type = TREE_TYPE (arg);
9930 REAL_VALUE_TYPE r;
9931 char buf[128];
9932
9933 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9934 real_from_string (&r, buf);
9935 result = build_call_expr (isle_fn, 2,
9936 fold_build1_loc (loc, ABS_EXPR, type, arg),
9937 build_real (type, r));
9938 /*result = fold_build2_loc (loc, UNGT_EXPR,
9939 TREE_TYPE (TREE_TYPE (fndecl)),
9940 fold_build1_loc (loc, ABS_EXPR, type, arg),
9941 build_real (type, r));
9942 result = fold_build1_loc (loc, TRUTH_NOT_EXPR,
9943 TREE_TYPE (TREE_TYPE (fndecl)),
9944 result);*/
9945 return result;
9946 }
9947 case BUILT_IN_ISNORMAL:
9948 {
9949 /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
9950 islessequal(fabs(x),DBL_MAX). */
b9a16870 9951 tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
9952 tree const isge_fn = builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL);
a65c4d64 9953 tree const type = TREE_TYPE (arg);
9954 REAL_VALUE_TYPE rmax, rmin;
9955 char buf[128];
9956
9957 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9958 real_from_string (&rmax, buf);
9959 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
9960 real_from_string (&rmin, buf);
9961 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
9962 result = build_call_expr (isle_fn, 2, arg,
9963 build_real (type, rmax));
9964 result = fold_build2 (BIT_AND_EXPR, integer_type_node, result,
9965 build_call_expr (isge_fn, 2, arg,
9966 build_real (type, rmin)));
9967 return result;
9968 }
9969 default:
9970 break;
9971 }
9972
9973 return NULL_TREE;
9974}
9975
726069ba 9976/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
c2f47e15 9977 ARG is the argument for the call. */
726069ba 9978
9979static tree
389dd41b 9980fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
726069ba 9981{
726069ba 9982 tree type = TREE_TYPE (TREE_TYPE (fndecl));
726069ba 9983 REAL_VALUE_TYPE r;
9984
c2f47e15 9985 if (!validate_arg (arg, REAL_TYPE))
d43cee80 9986 return NULL_TREE;
726069ba 9987
726069ba 9988 switch (builtin_index)
9989 {
9990 case BUILT_IN_ISINF:
b70bfd00 9991 if (!HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 9992 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
726069ba 9993
9994 if (TREE_CODE (arg) == REAL_CST)
9995 {
9996 r = TREE_REAL_CST (arg);
9997 if (real_isinf (&r))
9998 return real_compare (GT_EXPR, &r, &dconst0)
9999 ? integer_one_node : integer_minus_one_node;
10000 else
10001 return integer_zero_node;
10002 }
10003
10004 return NULL_TREE;
10005
c319d56a 10006 case BUILT_IN_ISINF_SIGN:
10007 {
10008 /* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */
10009 /* In a boolean context, GCC will fold the inner COND_EXPR to
10010 1. So e.g. "if (isinf_sign(x))" would be folded to just
10011 "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
10012 tree signbit_fn = mathfn_built_in_1 (TREE_TYPE (arg), BUILT_IN_SIGNBIT, 0);
b9a16870 10013 tree isinf_fn = builtin_decl_explicit (BUILT_IN_ISINF);
c319d56a 10014 tree tmp = NULL_TREE;
10015
10016 arg = builtin_save_expr (arg);
10017
10018 if (signbit_fn && isinf_fn)
10019 {
389dd41b 10020 tree signbit_call = build_call_expr_loc (loc, signbit_fn, 1, arg);
10021 tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg);
c319d56a 10022
389dd41b 10023 signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
c319d56a 10024 signbit_call, integer_zero_node);
389dd41b 10025 isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
c319d56a 10026 isinf_call, integer_zero_node);
48e1416a 10027
389dd41b 10028 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call,
c319d56a 10029 integer_minus_one_node, integer_one_node);
389dd41b 10030 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
10031 isinf_call, tmp,
c319d56a 10032 integer_zero_node);
10033 }
10034
10035 return tmp;
10036 }
10037
cde061c1 10038 case BUILT_IN_ISFINITE:
b70bfd00 10039 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
10040 && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 10041 return omit_one_operand_loc (loc, type, integer_one_node, arg);
726069ba 10042
10043 if (TREE_CODE (arg) == REAL_CST)
10044 {
10045 r = TREE_REAL_CST (arg);
776a7bab 10046 return real_isfinite (&r) ? integer_one_node : integer_zero_node;
726069ba 10047 }
10048
10049 return NULL_TREE;
10050
10051 case BUILT_IN_ISNAN:
b70bfd00 10052 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 10053 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
726069ba 10054
10055 if (TREE_CODE (arg) == REAL_CST)
10056 {
10057 r = TREE_REAL_CST (arg);
10058 return real_isnan (&r) ? integer_one_node : integer_zero_node;
10059 }
10060
10061 arg = builtin_save_expr (arg);
389dd41b 10062 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
726069ba 10063
10064 default:
64db345d 10065 gcc_unreachable ();
726069ba 10066 }
10067}
10068
19fbe3a4 10069/* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...).
10070 This builtin will generate code to return the appropriate floating
10071 point classification depending on the value of the floating point
10072 number passed in. The possible return values must be supplied as
921b27c0 10073 int arguments to the call in the following order: FP_NAN, FP_INFINITE,
19fbe3a4 10074 FP_NORMAL, FP_SUBNORMAL and FP_ZERO. The ellipses is for exactly
10075 one floating point argument which is "type generic". */
10076
10077static tree
389dd41b 10078fold_builtin_fpclassify (location_t loc, tree exp)
19fbe3a4 10079{
921b27c0 10080 tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
10081 arg, type, res, tmp;
19fbe3a4 10082 enum machine_mode mode;
10083 REAL_VALUE_TYPE r;
10084 char buf[128];
48e1416a 10085
19fbe3a4 10086 /* Verify the required arguments in the original call. */
10087 if (!validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE,
10088 INTEGER_TYPE, INTEGER_TYPE,
10089 INTEGER_TYPE, REAL_TYPE, VOID_TYPE))
10090 return NULL_TREE;
48e1416a 10091
19fbe3a4 10092 fp_nan = CALL_EXPR_ARG (exp, 0);
921b27c0 10093 fp_infinite = CALL_EXPR_ARG (exp, 1);
19fbe3a4 10094 fp_normal = CALL_EXPR_ARG (exp, 2);
10095 fp_subnormal = CALL_EXPR_ARG (exp, 3);
10096 fp_zero = CALL_EXPR_ARG (exp, 4);
10097 arg = CALL_EXPR_ARG (exp, 5);
10098 type = TREE_TYPE (arg);
10099 mode = TYPE_MODE (type);
389dd41b 10100 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
19fbe3a4 10101
48e1416a 10102 /* fpclassify(x) ->
19fbe3a4 10103 isnan(x) ? FP_NAN :
921b27c0 10104 (fabs(x) == Inf ? FP_INFINITE :
19fbe3a4 10105 (fabs(x) >= DBL_MIN ? FP_NORMAL :
10106 (x == 0 ? FP_ZERO : FP_SUBNORMAL))). */
48e1416a 10107
389dd41b 10108 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
19fbe3a4 10109 build_real (type, dconst0));
389dd41b 10110 res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
10111 tmp, fp_zero, fp_subnormal);
19fbe3a4 10112
10113 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
10114 real_from_string (&r, buf);
389dd41b 10115 tmp = fold_build2_loc (loc, GE_EXPR, integer_type_node,
10116 arg, build_real (type, r));
10117 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, fp_normal, res);
48e1416a 10118
19fbe3a4 10119 if (HONOR_INFINITIES (mode))
10120 {
10121 real_inf (&r);
389dd41b 10122 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
19fbe3a4 10123 build_real (type, r));
389dd41b 10124 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
10125 fp_infinite, res);
19fbe3a4 10126 }
10127
10128 if (HONOR_NANS (mode))
10129 {
389dd41b 10130 tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
10131 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, res, fp_nan);
19fbe3a4 10132 }
48e1416a 10133
19fbe3a4 10134 return res;
10135}
10136
9bc9f15f 10137/* Fold a call to an unordered comparison function such as
d5019fe8 10138 __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function
c2f47e15 10139 being called and ARG0 and ARG1 are the arguments for the call.
726069ba 10140 UNORDERED_CODE and ORDERED_CODE are comparison codes that give
10141 the opposite of the desired result. UNORDERED_CODE is used
10142 for modes that can hold NaNs and ORDERED_CODE is used for
10143 the rest. */
9bc9f15f 10144
10145static tree
389dd41b 10146fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
9bc9f15f 10147 enum tree_code unordered_code,
10148 enum tree_code ordered_code)
10149{
859f903a 10150 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9bc9f15f 10151 enum tree_code code;
6978db0d 10152 tree type0, type1;
10153 enum tree_code code0, code1;
10154 tree cmp_type = NULL_TREE;
9bc9f15f 10155
6978db0d 10156 type0 = TREE_TYPE (arg0);
10157 type1 = TREE_TYPE (arg1);
a0c938f0 10158
6978db0d 10159 code0 = TREE_CODE (type0);
10160 code1 = TREE_CODE (type1);
a0c938f0 10161
6978db0d 10162 if (code0 == REAL_TYPE && code1 == REAL_TYPE)
10163 /* Choose the wider of two real types. */
10164 cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
10165 ? type0 : type1;
10166 else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
10167 cmp_type = type0;
10168 else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
10169 cmp_type = type1;
a0c938f0 10170
389dd41b 10171 arg0 = fold_convert_loc (loc, cmp_type, arg0);
10172 arg1 = fold_convert_loc (loc, cmp_type, arg1);
859f903a 10173
10174 if (unordered_code == UNORDERED_EXPR)
10175 {
b70bfd00 10176 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
389dd41b 10177 return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
10178 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
859f903a 10179 }
9bc9f15f 10180
b70bfd00 10181 code = HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
10182 : ordered_code;
389dd41b 10183 return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
10184 fold_build2_loc (loc, code, type, arg0, arg1));
9bc9f15f 10185}
10186
c2f47e15 10187/* Fold a call to built-in function FNDECL with 0 arguments.
10188 IGNORE is true if the result of the function call is ignored. This
10189 function returns NULL_TREE if no simplification was possible. */
650e4c94 10190
4ee9c684 10191static tree
389dd41b 10192fold_builtin_0 (location_t loc, tree fndecl, bool ignore ATTRIBUTE_UNUSED)
650e4c94 10193{
e9f80ff5 10194 tree type = TREE_TYPE (TREE_TYPE (fndecl));
c2f47e15 10195 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
189b3398 10196 switch (fcode)
650e4c94 10197 {
c2f47e15 10198 CASE_FLT_FN (BUILT_IN_INF):
10199 case BUILT_IN_INFD32:
10200 case BUILT_IN_INFD64:
10201 case BUILT_IN_INFD128:
389dd41b 10202 return fold_builtin_inf (loc, type, true);
7c2f0500 10203
c2f47e15 10204 CASE_FLT_FN (BUILT_IN_HUGE_VAL):
389dd41b 10205 return fold_builtin_inf (loc, type, false);
7c2f0500 10206
c2f47e15 10207 case BUILT_IN_CLASSIFY_TYPE:
10208 return fold_builtin_classify_type (NULL_TREE);
7c2f0500 10209
c2f47e15 10210 default:
10211 break;
10212 }
10213 return NULL_TREE;
10214}
7c2f0500 10215
c2f47e15 10216/* Fold a call to built-in function FNDECL with 1 argument, ARG0.
10217 IGNORE is true if the result of the function call is ignored. This
10218 function returns NULL_TREE if no simplification was possible. */
7c2f0500 10219
c2f47e15 10220static tree
389dd41b 10221fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
c2f47e15 10222{
10223 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10224 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10225 switch (fcode)
10226 {
650e4c94 10227 case BUILT_IN_CONSTANT_P:
7c2f0500 10228 {
c2f47e15 10229 tree val = fold_builtin_constant_p (arg0);
7c2f0500 10230
7c2f0500 10231 /* Gimplification will pull the CALL_EXPR for the builtin out of
10232 an if condition. When not optimizing, we'll not CSE it back.
10233 To avoid link error types of regressions, return false now. */
10234 if (!val && !optimize)
10235 val = integer_zero_node;
10236
10237 return val;
10238 }
650e4c94 10239
539a3a92 10240 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 10241 return fold_builtin_classify_type (arg0);
539a3a92 10242
650e4c94 10243 case BUILT_IN_STRLEN:
c7cbde74 10244 return fold_builtin_strlen (loc, type, arg0);
650e4c94 10245
4f35b1fc 10246 CASE_FLT_FN (BUILT_IN_FABS):
389dd41b 10247 return fold_builtin_fabs (loc, arg0, type);
d1aade50 10248
10249 case BUILT_IN_ABS:
10250 case BUILT_IN_LABS:
10251 case BUILT_IN_LLABS:
10252 case BUILT_IN_IMAXABS:
389dd41b 10253 return fold_builtin_abs (loc, arg0, type);
c63f4ad3 10254
4f35b1fc 10255 CASE_FLT_FN (BUILT_IN_CONJ):
239d491a 10256 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10257 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10258 return fold_build1_loc (loc, CONJ_EXPR, type, arg0);
c2f47e15 10259 break;
36d3581d 10260
4f35b1fc 10261 CASE_FLT_FN (BUILT_IN_CREAL):
239d491a 10262 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10263 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10264 return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));;
c2f47e15 10265 break;
36d3581d 10266
4f35b1fc 10267 CASE_FLT_FN (BUILT_IN_CIMAG):
b0ce8887 10268 if (validate_arg (arg0, COMPLEX_TYPE)
10269 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10270 return non_lvalue_loc (loc, fold_build1_loc (loc, IMAGPART_EXPR, type, arg0));
c2f47e15 10271 break;
36d3581d 10272
503733d5 10273 CASE_FLT_FN (BUILT_IN_CCOS):
389dd41b 10274 return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ false);
48e1416a 10275
503733d5 10276 CASE_FLT_FN (BUILT_IN_CCOSH):
389dd41b 10277 return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ true);
48e1416a 10278
c2373fdb 10279 CASE_FLT_FN (BUILT_IN_CPROJ):
10280 return fold_builtin_cproj(loc, arg0, type);
10281
239d491a 10282 CASE_FLT_FN (BUILT_IN_CSIN):
10283 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10284 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10285 return do_mpc_arg1 (arg0, type, mpc_sin);
c2f47e15 10286 break;
48e1416a 10287
239d491a 10288 CASE_FLT_FN (BUILT_IN_CSINH):
10289 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10290 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10291 return do_mpc_arg1 (arg0, type, mpc_sinh);
10292 break;
48e1416a 10293
239d491a 10294 CASE_FLT_FN (BUILT_IN_CTAN):
10295 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10296 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10297 return do_mpc_arg1 (arg0, type, mpc_tan);
10298 break;
48e1416a 10299
239d491a 10300 CASE_FLT_FN (BUILT_IN_CTANH):
10301 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10302 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10303 return do_mpc_arg1 (arg0, type, mpc_tanh);
10304 break;
48e1416a 10305
239d491a 10306 CASE_FLT_FN (BUILT_IN_CLOG):
10307 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10308 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10309 return do_mpc_arg1 (arg0, type, mpc_log);
10310 break;
48e1416a 10311
239d491a 10312 CASE_FLT_FN (BUILT_IN_CSQRT):
10313 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10314 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10315 return do_mpc_arg1 (arg0, type, mpc_sqrt);
10316 break;
48e1416a 10317
0e7e6e7f 10318 CASE_FLT_FN (BUILT_IN_CASIN):
10319 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10320 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10321 return do_mpc_arg1 (arg0, type, mpc_asin);
10322 break;
48e1416a 10323
0e7e6e7f 10324 CASE_FLT_FN (BUILT_IN_CACOS):
10325 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10326 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10327 return do_mpc_arg1 (arg0, type, mpc_acos);
10328 break;
48e1416a 10329
0e7e6e7f 10330 CASE_FLT_FN (BUILT_IN_CATAN):
10331 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10332 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10333 return do_mpc_arg1 (arg0, type, mpc_atan);
10334 break;
48e1416a 10335
0e7e6e7f 10336 CASE_FLT_FN (BUILT_IN_CASINH):
10337 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10338 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10339 return do_mpc_arg1 (arg0, type, mpc_asinh);
10340 break;
48e1416a 10341
0e7e6e7f 10342 CASE_FLT_FN (BUILT_IN_CACOSH):
10343 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10344 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10345 return do_mpc_arg1 (arg0, type, mpc_acosh);
10346 break;
48e1416a 10347
0e7e6e7f 10348 CASE_FLT_FN (BUILT_IN_CATANH):
10349 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10350 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10351 return do_mpc_arg1 (arg0, type, mpc_atanh);
10352 break;
48e1416a 10353
4f35b1fc 10354 CASE_FLT_FN (BUILT_IN_CABS):
389dd41b 10355 return fold_builtin_cabs (loc, arg0, type, fndecl);
c63f4ad3 10356
abe4dcf6 10357 CASE_FLT_FN (BUILT_IN_CARG):
389dd41b 10358 return fold_builtin_carg (loc, arg0, type);
abe4dcf6 10359
4f35b1fc 10360 CASE_FLT_FN (BUILT_IN_SQRT):
389dd41b 10361 return fold_builtin_sqrt (loc, arg0, type);
805e22b2 10362
4f35b1fc 10363 CASE_FLT_FN (BUILT_IN_CBRT):
389dd41b 10364 return fold_builtin_cbrt (loc, arg0, type);
3bc5c41b 10365
728bac60 10366 CASE_FLT_FN (BUILT_IN_ASIN):
c2f47e15 10367 if (validate_arg (arg0, REAL_TYPE))
10368 return do_mpfr_arg1 (arg0, type, mpfr_asin,
728bac60 10369 &dconstm1, &dconst1, true);
10370 break;
10371
10372 CASE_FLT_FN (BUILT_IN_ACOS):
c2f47e15 10373 if (validate_arg (arg0, REAL_TYPE))
10374 return do_mpfr_arg1 (arg0, type, mpfr_acos,
728bac60 10375 &dconstm1, &dconst1, true);
10376 break;
10377
10378 CASE_FLT_FN (BUILT_IN_ATAN):
c2f47e15 10379 if (validate_arg (arg0, REAL_TYPE))
10380 return do_mpfr_arg1 (arg0, type, mpfr_atan, NULL, NULL, 0);
728bac60 10381 break;
10382
10383 CASE_FLT_FN (BUILT_IN_ASINH):
c2f47e15 10384 if (validate_arg (arg0, REAL_TYPE))
10385 return do_mpfr_arg1 (arg0, type, mpfr_asinh, NULL, NULL, 0);
728bac60 10386 break;
10387
10388 CASE_FLT_FN (BUILT_IN_ACOSH):
c2f47e15 10389 if (validate_arg (arg0, REAL_TYPE))
10390 return do_mpfr_arg1 (arg0, type, mpfr_acosh,
728bac60 10391 &dconst1, NULL, true);
10392 break;
10393
10394 CASE_FLT_FN (BUILT_IN_ATANH):
c2f47e15 10395 if (validate_arg (arg0, REAL_TYPE))
10396 return do_mpfr_arg1 (arg0, type, mpfr_atanh,
728bac60 10397 &dconstm1, &dconst1, false);
10398 break;
10399
4f35b1fc 10400 CASE_FLT_FN (BUILT_IN_SIN):
c2f47e15 10401 if (validate_arg (arg0, REAL_TYPE))
10402 return do_mpfr_arg1 (arg0, type, mpfr_sin, NULL, NULL, 0);
728bac60 10403 break;
77e89269 10404
4f35b1fc 10405 CASE_FLT_FN (BUILT_IN_COS):
389dd41b 10406 return fold_builtin_cos (loc, arg0, type, fndecl);
77e89269 10407
728bac60 10408 CASE_FLT_FN (BUILT_IN_TAN):
c2f47e15 10409 return fold_builtin_tan (arg0, type);
d735c391 10410
c5bb2c4b 10411 CASE_FLT_FN (BUILT_IN_CEXP):
389dd41b 10412 return fold_builtin_cexp (loc, arg0, type);
c5bb2c4b 10413
d735c391 10414 CASE_FLT_FN (BUILT_IN_CEXPI):
c2f47e15 10415 if (validate_arg (arg0, REAL_TYPE))
10416 return do_mpfr_sincos (arg0, NULL_TREE, NULL_TREE);
10417 break;
d92f994c 10418
728bac60 10419 CASE_FLT_FN (BUILT_IN_SINH):
c2f47e15 10420 if (validate_arg (arg0, REAL_TYPE))
10421 return do_mpfr_arg1 (arg0, type, mpfr_sinh, NULL, NULL, 0);
728bac60 10422 break;
10423
10424 CASE_FLT_FN (BUILT_IN_COSH):
389dd41b 10425 return fold_builtin_cosh (loc, arg0, type, fndecl);
728bac60 10426
10427 CASE_FLT_FN (BUILT_IN_TANH):
c2f47e15 10428 if (validate_arg (arg0, REAL_TYPE))
10429 return do_mpfr_arg1 (arg0, type, mpfr_tanh, NULL, NULL, 0);
728bac60 10430 break;
10431
29f4cd78 10432 CASE_FLT_FN (BUILT_IN_ERF):
c2f47e15 10433 if (validate_arg (arg0, REAL_TYPE))
10434 return do_mpfr_arg1 (arg0, type, mpfr_erf, NULL, NULL, 0);
29f4cd78 10435 break;
10436
10437 CASE_FLT_FN (BUILT_IN_ERFC):
c2f47e15 10438 if (validate_arg (arg0, REAL_TYPE))
10439 return do_mpfr_arg1 (arg0, type, mpfr_erfc, NULL, NULL, 0);
29f4cd78 10440 break;
10441
32dba52b 10442 CASE_FLT_FN (BUILT_IN_TGAMMA):
c2f47e15 10443 if (validate_arg (arg0, REAL_TYPE))
10444 return do_mpfr_arg1 (arg0, type, mpfr_gamma, NULL, NULL, 0);
32dba52b 10445 break;
48e1416a 10446
4f35b1fc 10447 CASE_FLT_FN (BUILT_IN_EXP):
389dd41b 10448 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp);
467214fd 10449
4f35b1fc 10450 CASE_FLT_FN (BUILT_IN_EXP2):
389dd41b 10451 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp2);
467214fd 10452
4f35b1fc 10453 CASE_FLT_FN (BUILT_IN_EXP10):
10454 CASE_FLT_FN (BUILT_IN_POW10):
389dd41b 10455 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp10);
467214fd 10456
29f4cd78 10457 CASE_FLT_FN (BUILT_IN_EXPM1):
c2f47e15 10458 if (validate_arg (arg0, REAL_TYPE))
10459 return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0);
29f4cd78 10460 break;
48e1416a 10461
4f35b1fc 10462 CASE_FLT_FN (BUILT_IN_LOG):
389dd41b 10463 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log);
467214fd 10464
4f35b1fc 10465 CASE_FLT_FN (BUILT_IN_LOG2):
389dd41b 10466 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log2);
467214fd 10467
4f35b1fc 10468 CASE_FLT_FN (BUILT_IN_LOG10):
389dd41b 10469 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log10);
29f4cd78 10470
10471 CASE_FLT_FN (BUILT_IN_LOG1P):
c2f47e15 10472 if (validate_arg (arg0, REAL_TYPE))
10473 return do_mpfr_arg1 (arg0, type, mpfr_log1p,
29f4cd78 10474 &dconstm1, NULL, false);
10475 break;
805e22b2 10476
65dd1378 10477 CASE_FLT_FN (BUILT_IN_J0):
10478 if (validate_arg (arg0, REAL_TYPE))
10479 return do_mpfr_arg1 (arg0, type, mpfr_j0,
10480 NULL, NULL, 0);
10481 break;
10482
10483 CASE_FLT_FN (BUILT_IN_J1):
10484 if (validate_arg (arg0, REAL_TYPE))
10485 return do_mpfr_arg1 (arg0, type, mpfr_j1,
10486 NULL, NULL, 0);
10487 break;
6ff9eeff 10488
10489 CASE_FLT_FN (BUILT_IN_Y0):
10490 if (validate_arg (arg0, REAL_TYPE))
10491 return do_mpfr_arg1 (arg0, type, mpfr_y0,
10492 &dconst0, NULL, false);
10493 break;
10494
10495 CASE_FLT_FN (BUILT_IN_Y1):
10496 if (validate_arg (arg0, REAL_TYPE))
10497 return do_mpfr_arg1 (arg0, type, mpfr_y1,
10498 &dconst0, NULL, false);
10499 break;
65dd1378 10500
4f35b1fc 10501 CASE_FLT_FN (BUILT_IN_NAN):
c4503c0a 10502 case BUILT_IN_NAND32:
10503 case BUILT_IN_NAND64:
10504 case BUILT_IN_NAND128:
c2f47e15 10505 return fold_builtin_nan (arg0, type, true);
b0db7939 10506
4f35b1fc 10507 CASE_FLT_FN (BUILT_IN_NANS):
c2f47e15 10508 return fold_builtin_nan (arg0, type, false);
b0db7939 10509
4f35b1fc 10510 CASE_FLT_FN (BUILT_IN_FLOOR):
389dd41b 10511 return fold_builtin_floor (loc, fndecl, arg0);
277f8dd2 10512
4f35b1fc 10513 CASE_FLT_FN (BUILT_IN_CEIL):
389dd41b 10514 return fold_builtin_ceil (loc, fndecl, arg0);
277f8dd2 10515
4f35b1fc 10516 CASE_FLT_FN (BUILT_IN_TRUNC):
389dd41b 10517 return fold_builtin_trunc (loc, fndecl, arg0);
277f8dd2 10518
4f35b1fc 10519 CASE_FLT_FN (BUILT_IN_ROUND):
389dd41b 10520 return fold_builtin_round (loc, fndecl, arg0);
89ab3887 10521
4f35b1fc 10522 CASE_FLT_FN (BUILT_IN_NEARBYINT):
10523 CASE_FLT_FN (BUILT_IN_RINT):
389dd41b 10524 return fold_trunc_transparent_mathfn (loc, fndecl, arg0);
6528f4f4 10525
80ff6494 10526 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 10527 CASE_FLT_FN (BUILT_IN_LCEIL):
10528 CASE_FLT_FN (BUILT_IN_LLCEIL):
10529 CASE_FLT_FN (BUILT_IN_LFLOOR):
80ff6494 10530 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 10531 CASE_FLT_FN (BUILT_IN_LLFLOOR):
80ff6494 10532 CASE_FLT_FN (BUILT_IN_IROUND):
a0c938f0 10533 CASE_FLT_FN (BUILT_IN_LROUND):
4f35b1fc 10534 CASE_FLT_FN (BUILT_IN_LLROUND):
389dd41b 10535 return fold_builtin_int_roundingfn (loc, fndecl, arg0);
34f17811 10536
80ff6494 10537 CASE_FLT_FN (BUILT_IN_IRINT):
4f35b1fc 10538 CASE_FLT_FN (BUILT_IN_LRINT):
10539 CASE_FLT_FN (BUILT_IN_LLRINT):
389dd41b 10540 return fold_fixed_mathfn (loc, fndecl, arg0);
9ed65c7f 10541
42791117 10542 case BUILT_IN_BSWAP32:
10543 case BUILT_IN_BSWAP64:
c2f47e15 10544 return fold_builtin_bswap (fndecl, arg0);
42791117 10545
4f35b1fc 10546 CASE_INT_FN (BUILT_IN_FFS):
10547 CASE_INT_FN (BUILT_IN_CLZ):
10548 CASE_INT_FN (BUILT_IN_CTZ):
6aaa1f9e 10549 CASE_INT_FN (BUILT_IN_CLRSB):
4f35b1fc 10550 CASE_INT_FN (BUILT_IN_POPCOUNT):
10551 CASE_INT_FN (BUILT_IN_PARITY):
c2f47e15 10552 return fold_builtin_bitop (fndecl, arg0);
9c8a1629 10553
4f35b1fc 10554 CASE_FLT_FN (BUILT_IN_SIGNBIT):
389dd41b 10555 return fold_builtin_signbit (loc, arg0, type);
27f261ef 10556
cb2b9385 10557 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
389dd41b 10558 return fold_builtin_significand (loc, arg0, type);
cb2b9385 10559
10560 CASE_FLT_FN (BUILT_IN_ILOGB):
10561 CASE_FLT_FN (BUILT_IN_LOGB):
389dd41b 10562 return fold_builtin_logb (loc, arg0, type);
cb2b9385 10563
d49367d4 10564 case BUILT_IN_ISASCII:
389dd41b 10565 return fold_builtin_isascii (loc, arg0);
d49367d4 10566
10567 case BUILT_IN_TOASCII:
389dd41b 10568 return fold_builtin_toascii (loc, arg0);
d49367d4 10569
df1cf42e 10570 case BUILT_IN_ISDIGIT:
389dd41b 10571 return fold_builtin_isdigit (loc, arg0);
467214fd 10572
4f35b1fc 10573 CASE_FLT_FN (BUILT_IN_FINITE):
c4503c0a 10574 case BUILT_IN_FINITED32:
10575 case BUILT_IN_FINITED64:
10576 case BUILT_IN_FINITED128:
cde061c1 10577 case BUILT_IN_ISFINITE:
a65c4d64 10578 {
10579 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISFINITE);
10580 if (ret)
10581 return ret;
10582 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10583 }
726069ba 10584
4f35b1fc 10585 CASE_FLT_FN (BUILT_IN_ISINF):
c4503c0a 10586 case BUILT_IN_ISINFD32:
10587 case BUILT_IN_ISINFD64:
10588 case BUILT_IN_ISINFD128:
a65c4d64 10589 {
10590 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF);
10591 if (ret)
10592 return ret;
10593 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10594 }
10595
10596 case BUILT_IN_ISNORMAL:
10597 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
726069ba 10598
c319d56a 10599 case BUILT_IN_ISINF_SIGN:
389dd41b 10600 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF_SIGN);
c319d56a 10601
4f35b1fc 10602 CASE_FLT_FN (BUILT_IN_ISNAN):
c4503c0a 10603 case BUILT_IN_ISNAND32:
10604 case BUILT_IN_ISNAND64:
10605 case BUILT_IN_ISNAND128:
389dd41b 10606 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
c2f47e15 10607
10608 case BUILT_IN_PRINTF:
10609 case BUILT_IN_PRINTF_UNLOCKED:
10610 case BUILT_IN_VPRINTF:
389dd41b 10611 return fold_builtin_printf (loc, fndecl, arg0, NULL_TREE, ignore, fcode);
c2f47e15 10612
663870fc 10613 case BUILT_IN_FREE:
10614 if (integer_zerop (arg0))
10615 return build_empty_stmt (loc);
10616 break;
10617
c2f47e15 10618 default:
10619 break;
10620 }
10621
10622 return NULL_TREE;
10623
10624}
10625
10626/* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1.
10627 IGNORE is true if the result of the function call is ignored. This
10628 function returns NULL_TREE if no simplification was possible. */
10629
10630static tree
389dd41b 10631fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore)
c2f47e15 10632{
10633 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10634 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10635
10636 switch (fcode)
10637 {
65dd1378 10638 CASE_FLT_FN (BUILT_IN_JN):
10639 if (validate_arg (arg0, INTEGER_TYPE)
10640 && validate_arg (arg1, REAL_TYPE))
10641 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_jn, NULL, 0);
10642 break;
6ff9eeff 10643
10644 CASE_FLT_FN (BUILT_IN_YN):
10645 if (validate_arg (arg0, INTEGER_TYPE)
10646 && validate_arg (arg1, REAL_TYPE))
10647 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_yn,
10648 &dconst0, false);
10649 break;
e5407ca6 10650
10651 CASE_FLT_FN (BUILT_IN_DREM):
10652 CASE_FLT_FN (BUILT_IN_REMAINDER):
10653 if (validate_arg (arg0, REAL_TYPE)
10654 && validate_arg(arg1, REAL_TYPE))
10655 return do_mpfr_arg2 (arg0, arg1, type, mpfr_remainder);
10656 break;
e84da7c1 10657
10658 CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
10659 CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
10660 if (validate_arg (arg0, REAL_TYPE)
10661 && validate_arg(arg1, POINTER_TYPE))
10662 return do_mpfr_lgamma_r (arg0, arg1, type);
10663 break;
c2f47e15 10664
10665 CASE_FLT_FN (BUILT_IN_ATAN2):
10666 if (validate_arg (arg0, REAL_TYPE)
10667 && validate_arg(arg1, REAL_TYPE))
10668 return do_mpfr_arg2 (arg0, arg1, type, mpfr_atan2);
10669 break;
10670
10671 CASE_FLT_FN (BUILT_IN_FDIM):
10672 if (validate_arg (arg0, REAL_TYPE)
10673 && validate_arg(arg1, REAL_TYPE))
10674 return do_mpfr_arg2 (arg0, arg1, type, mpfr_dim);
10675 break;
10676
10677 CASE_FLT_FN (BUILT_IN_HYPOT):
389dd41b 10678 return fold_builtin_hypot (loc, fndecl, arg0, arg1, type);
c2f47e15 10679
c699fab8 10680 CASE_FLT_FN (BUILT_IN_CPOW):
10681 if (validate_arg (arg0, COMPLEX_TYPE)
10682 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
10683 && validate_arg (arg1, COMPLEX_TYPE)
48e1416a 10684 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE)
652d9409 10685 return do_mpc_arg2 (arg0, arg1, type, /*do_nonfinite=*/ 0, mpc_pow);
c699fab8 10686 break;
c699fab8 10687
7587301b 10688 CASE_FLT_FN (BUILT_IN_LDEXP):
389dd41b 10689 return fold_builtin_load_exponent (loc, arg0, arg1, type, /*ldexp=*/true);
7587301b 10690 CASE_FLT_FN (BUILT_IN_SCALBN):
10691 CASE_FLT_FN (BUILT_IN_SCALBLN):
389dd41b 10692 return fold_builtin_load_exponent (loc, arg0, arg1,
10693 type, /*ldexp=*/false);
7587301b 10694
3838b9ae 10695 CASE_FLT_FN (BUILT_IN_FREXP):
389dd41b 10696 return fold_builtin_frexp (loc, arg0, arg1, type);
3838b9ae 10697
ebf8b4f5 10698 CASE_FLT_FN (BUILT_IN_MODF):
389dd41b 10699 return fold_builtin_modf (loc, arg0, arg1, type);
ebf8b4f5 10700
c2f47e15 10701 case BUILT_IN_BZERO:
389dd41b 10702 return fold_builtin_bzero (loc, arg0, arg1, ignore);
c2f47e15 10703
10704 case BUILT_IN_FPUTS:
389dd41b 10705 return fold_builtin_fputs (loc, arg0, arg1, ignore, false, NULL_TREE);
c2f47e15 10706
10707 case BUILT_IN_FPUTS_UNLOCKED:
389dd41b 10708 return fold_builtin_fputs (loc, arg0, arg1, ignore, true, NULL_TREE);
c2f47e15 10709
10710 case BUILT_IN_STRSTR:
389dd41b 10711 return fold_builtin_strstr (loc, arg0, arg1, type);
c2f47e15 10712
10713 case BUILT_IN_STRCAT:
389dd41b 10714 return fold_builtin_strcat (loc, arg0, arg1);
c2f47e15 10715
10716 case BUILT_IN_STRSPN:
389dd41b 10717 return fold_builtin_strspn (loc, arg0, arg1);
c2f47e15 10718
10719 case BUILT_IN_STRCSPN:
389dd41b 10720 return fold_builtin_strcspn (loc, arg0, arg1);
c2f47e15 10721
10722 case BUILT_IN_STRCHR:
10723 case BUILT_IN_INDEX:
389dd41b 10724 return fold_builtin_strchr (loc, arg0, arg1, type);
c2f47e15 10725
10726 case BUILT_IN_STRRCHR:
10727 case BUILT_IN_RINDEX:
389dd41b 10728 return fold_builtin_strrchr (loc, arg0, arg1, type);
c2f47e15 10729
10730 case BUILT_IN_STRCPY:
389dd41b 10731 return fold_builtin_strcpy (loc, fndecl, arg0, arg1, NULL_TREE);
c2f47e15 10732
c8b17b2e 10733 case BUILT_IN_STPCPY:
10734 if (ignore)
10735 {
b9a16870 10736 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
c8b17b2e 10737 if (!fn)
10738 break;
10739
389dd41b 10740 return build_call_expr_loc (loc, fn, 2, arg0, arg1);
c8b17b2e 10741 }
a65c4d64 10742 else
10743 return fold_builtin_stpcpy (loc, fndecl, arg0, arg1);
c8b17b2e 10744 break;
10745
c2f47e15 10746 case BUILT_IN_STRCMP:
389dd41b 10747 return fold_builtin_strcmp (loc, arg0, arg1);
c2f47e15 10748
10749 case BUILT_IN_STRPBRK:
389dd41b 10750 return fold_builtin_strpbrk (loc, arg0, arg1, type);
c2f47e15 10751
10752 case BUILT_IN_EXPECT:
389dd41b 10753 return fold_builtin_expect (loc, arg0, arg1);
c2f47e15 10754
10755 CASE_FLT_FN (BUILT_IN_POW):
389dd41b 10756 return fold_builtin_pow (loc, fndecl, arg0, arg1, type);
c2f47e15 10757
10758 CASE_FLT_FN (BUILT_IN_POWI):
389dd41b 10759 return fold_builtin_powi (loc, fndecl, arg0, arg1, type);
c2f47e15 10760
10761 CASE_FLT_FN (BUILT_IN_COPYSIGN):
389dd41b 10762 return fold_builtin_copysign (loc, fndecl, arg0, arg1, type);
c2f47e15 10763
10764 CASE_FLT_FN (BUILT_IN_FMIN):
389dd41b 10765 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/false);
c2f47e15 10766
10767 CASE_FLT_FN (BUILT_IN_FMAX):
389dd41b 10768 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/true);
726069ba 10769
9bc9f15f 10770 case BUILT_IN_ISGREATER:
389dd41b 10771 return fold_builtin_unordered_cmp (loc, fndecl,
10772 arg0, arg1, UNLE_EXPR, LE_EXPR);
9bc9f15f 10773 case BUILT_IN_ISGREATEREQUAL:
389dd41b 10774 return fold_builtin_unordered_cmp (loc, fndecl,
10775 arg0, arg1, UNLT_EXPR, LT_EXPR);
9bc9f15f 10776 case BUILT_IN_ISLESS:
389dd41b 10777 return fold_builtin_unordered_cmp (loc, fndecl,
10778 arg0, arg1, UNGE_EXPR, GE_EXPR);
9bc9f15f 10779 case BUILT_IN_ISLESSEQUAL:
389dd41b 10780 return fold_builtin_unordered_cmp (loc, fndecl,
10781 arg0, arg1, UNGT_EXPR, GT_EXPR);
9bc9f15f 10782 case BUILT_IN_ISLESSGREATER:
389dd41b 10783 return fold_builtin_unordered_cmp (loc, fndecl,
10784 arg0, arg1, UNEQ_EXPR, EQ_EXPR);
9bc9f15f 10785 case BUILT_IN_ISUNORDERED:
389dd41b 10786 return fold_builtin_unordered_cmp (loc, fndecl,
10787 arg0, arg1, UNORDERED_EXPR,
d5019fe8 10788 NOP_EXPR);
9bc9f15f 10789
7c2f0500 10790 /* We do the folding for va_start in the expander. */
10791 case BUILT_IN_VA_START:
10792 break;
f0613857 10793
c2f47e15 10794 case BUILT_IN_SPRINTF:
389dd41b 10795 return fold_builtin_sprintf (loc, arg0, arg1, NULL_TREE, ignore);
c2f47e15 10796
0a39fd54 10797 case BUILT_IN_OBJECT_SIZE:
c2f47e15 10798 return fold_builtin_object_size (arg0, arg1);
0a39fd54 10799
10800 case BUILT_IN_PRINTF:
10801 case BUILT_IN_PRINTF_UNLOCKED:
10802 case BUILT_IN_VPRINTF:
389dd41b 10803 return fold_builtin_printf (loc, fndecl, arg0, arg1, ignore, fcode);
c2f47e15 10804
0a39fd54 10805 case BUILT_IN_PRINTF_CHK:
10806 case BUILT_IN_VPRINTF_CHK:
c2f47e15 10807 if (!validate_arg (arg0, INTEGER_TYPE)
10808 || TREE_SIDE_EFFECTS (arg0))
10809 return NULL_TREE;
10810 else
389dd41b 10811 return fold_builtin_printf (loc, fndecl,
10812 arg1, NULL_TREE, ignore, fcode);
c2f47e15 10813 break;
0a39fd54 10814
10815 case BUILT_IN_FPRINTF:
10816 case BUILT_IN_FPRINTF_UNLOCKED:
10817 case BUILT_IN_VFPRINTF:
389dd41b 10818 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, NULL_TREE,
c2f47e15 10819 ignore, fcode);
10820
1cd6e20d 10821 case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
10822 return fold_builtin_atomic_always_lock_free (arg0, arg1);
10823
10824 case BUILT_IN_ATOMIC_IS_LOCK_FREE:
10825 return fold_builtin_atomic_is_lock_free (arg0, arg1);
10826
c2f47e15 10827 default:
10828 break;
10829 }
10830 return NULL_TREE;
10831}
10832
10833/* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
10834 and ARG2. IGNORE is true if the result of the function call is ignored.
10835 This function returns NULL_TREE if no simplification was possible. */
10836
10837static tree
389dd41b 10838fold_builtin_3 (location_t loc, tree fndecl,
10839 tree arg0, tree arg1, tree arg2, bool ignore)
c2f47e15 10840{
10841 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10842 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10843 switch (fcode)
10844 {
10845
10846 CASE_FLT_FN (BUILT_IN_SINCOS):
389dd41b 10847 return fold_builtin_sincos (loc, arg0, arg1, arg2);
c2f47e15 10848
10849 CASE_FLT_FN (BUILT_IN_FMA):
b9be572e 10850 return fold_builtin_fma (loc, arg0, arg1, arg2, type);
c2f47e15 10851 break;
10852
e5407ca6 10853 CASE_FLT_FN (BUILT_IN_REMQUO):
10854 if (validate_arg (arg0, REAL_TYPE)
10855 && validate_arg(arg1, REAL_TYPE)
10856 && validate_arg(arg2, POINTER_TYPE))
10857 return do_mpfr_remquo (arg0, arg1, arg2);
10858 break;
e5407ca6 10859
c2f47e15 10860 case BUILT_IN_MEMSET:
389dd41b 10861 return fold_builtin_memset (loc, arg0, arg1, arg2, type, ignore);
c2f47e15 10862
10863 case BUILT_IN_BCOPY:
389dd41b 10864 return fold_builtin_memory_op (loc, arg1, arg0, arg2,
10865 void_type_node, true, /*endp=*/3);
c2f47e15 10866
10867 case BUILT_IN_MEMCPY:
389dd41b 10868 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10869 type, ignore, /*endp=*/0);
c2f47e15 10870
10871 case BUILT_IN_MEMPCPY:
389dd41b 10872 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10873 type, ignore, /*endp=*/1);
c2f47e15 10874
10875 case BUILT_IN_MEMMOVE:
389dd41b 10876 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10877 type, ignore, /*endp=*/3);
c2f47e15 10878
10879 case BUILT_IN_STRNCAT:
389dd41b 10880 return fold_builtin_strncat (loc, arg0, arg1, arg2);
c2f47e15 10881
10882 case BUILT_IN_STRNCPY:
389dd41b 10883 return fold_builtin_strncpy (loc, fndecl, arg0, arg1, arg2, NULL_TREE);
c2f47e15 10884
10885 case BUILT_IN_STRNCMP:
389dd41b 10886 return fold_builtin_strncmp (loc, arg0, arg1, arg2);
c2f47e15 10887
7959b13b 10888 case BUILT_IN_MEMCHR:
389dd41b 10889 return fold_builtin_memchr (loc, arg0, arg1, arg2, type);
7959b13b 10890
c2f47e15 10891 case BUILT_IN_BCMP:
10892 case BUILT_IN_MEMCMP:
389dd41b 10893 return fold_builtin_memcmp (loc, arg0, arg1, arg2);;
c2f47e15 10894
10895 case BUILT_IN_SPRINTF:
389dd41b 10896 return fold_builtin_sprintf (loc, arg0, arg1, arg2, ignore);
c2f47e15 10897
750d7b16 10898 case BUILT_IN_SNPRINTF:
10899 return fold_builtin_snprintf (loc, arg0, arg1, arg2, NULL_TREE, ignore);
10900
c2f47e15 10901 case BUILT_IN_STRCPY_CHK:
10902 case BUILT_IN_STPCPY_CHK:
389dd41b 10903 return fold_builtin_stxcpy_chk (loc, fndecl, arg0, arg1, arg2, NULL_TREE,
c2f47e15 10904 ignore, fcode);
10905
10906 case BUILT_IN_STRCAT_CHK:
389dd41b 10907 return fold_builtin_strcat_chk (loc, fndecl, arg0, arg1, arg2);
c2f47e15 10908
10909 case BUILT_IN_PRINTF_CHK:
10910 case BUILT_IN_VPRINTF_CHK:
10911 if (!validate_arg (arg0, INTEGER_TYPE)
10912 || TREE_SIDE_EFFECTS (arg0))
10913 return NULL_TREE;
10914 else
389dd41b 10915 return fold_builtin_printf (loc, fndecl, arg1, arg2, ignore, fcode);
c2f47e15 10916 break;
10917
10918 case BUILT_IN_FPRINTF:
10919 case BUILT_IN_FPRINTF_UNLOCKED:
10920 case BUILT_IN_VFPRINTF:
389dd41b 10921 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, arg2,
10922 ignore, fcode);
c2f47e15 10923
0a39fd54 10924 case BUILT_IN_FPRINTF_CHK:
10925 case BUILT_IN_VFPRINTF_CHK:
c2f47e15 10926 if (!validate_arg (arg1, INTEGER_TYPE)
10927 || TREE_SIDE_EFFECTS (arg1))
10928 return NULL_TREE;
10929 else
389dd41b 10930 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, NULL_TREE,
c2f47e15 10931 ignore, fcode);
0a39fd54 10932
650e4c94 10933 default:
10934 break;
10935 }
c2f47e15 10936 return NULL_TREE;
10937}
650e4c94 10938
c2f47e15 10939/* Fold a call to built-in function FNDECL with 4 arguments, ARG0, ARG1,
10940 ARG2, and ARG3. IGNORE is true if the result of the function call is
10941 ignored. This function returns NULL_TREE if no simplification was
10942 possible. */
48e1416a 10943
c2f47e15 10944static tree
389dd41b 10945fold_builtin_4 (location_t loc, tree fndecl,
10946 tree arg0, tree arg1, tree arg2, tree arg3, bool ignore)
c2f47e15 10947{
10948 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10949
10950 switch (fcode)
10951 {
10952 case BUILT_IN_MEMCPY_CHK:
10953 case BUILT_IN_MEMPCPY_CHK:
10954 case BUILT_IN_MEMMOVE_CHK:
10955 case BUILT_IN_MEMSET_CHK:
389dd41b 10956 return fold_builtin_memory_chk (loc, fndecl, arg0, arg1, arg2, arg3,
c2f47e15 10957 NULL_TREE, ignore,
10958 DECL_FUNCTION_CODE (fndecl));
10959
10960 case BUILT_IN_STRNCPY_CHK:
1063acde 10961 case BUILT_IN_STPNCPY_CHK:
10962 return fold_builtin_stxncpy_chk (loc, arg0, arg1, arg2, arg3, NULL_TREE,
10963 ignore, fcode);
c2f47e15 10964
10965 case BUILT_IN_STRNCAT_CHK:
389dd41b 10966 return fold_builtin_strncat_chk (loc, fndecl, arg0, arg1, arg2, arg3);
c2f47e15 10967
750d7b16 10968 case BUILT_IN_SNPRINTF:
10969 return fold_builtin_snprintf (loc, arg0, arg1, arg2, arg3, ignore);
10970
c2f47e15 10971 case BUILT_IN_FPRINTF_CHK:
10972 case BUILT_IN_VFPRINTF_CHK:
10973 if (!validate_arg (arg1, INTEGER_TYPE)
10974 || TREE_SIDE_EFFECTS (arg1))
10975 return NULL_TREE;
10976 else
389dd41b 10977 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, arg3,
c2f47e15 10978 ignore, fcode);
10979 break;
10980
10981 default:
10982 break;
10983 }
10984 return NULL_TREE;
10985}
10986
10987/* Fold a call to built-in function FNDECL. ARGS is an array of NARGS
10988 arguments, where NARGS <= 4. IGNORE is true if the result of the
10989 function call is ignored. This function returns NULL_TREE if no
10990 simplification was possible. Note that this only folds builtins with
10991 fixed argument patterns. Foldings that do varargs-to-varargs
10992 transformations, or that match calls with more than 4 arguments,
10993 need to be handled with fold_builtin_varargs instead. */
48e1416a 10994
c2f47e15 10995#define MAX_ARGS_TO_FOLD_BUILTIN 4
48e1416a 10996
c2f47e15 10997static tree
389dd41b 10998fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool ignore)
c2f47e15 10999{
11000 tree ret = NULL_TREE;
a7f5bb2d 11001
c2f47e15 11002 switch (nargs)
11003 {
11004 case 0:
389dd41b 11005 ret = fold_builtin_0 (loc, fndecl, ignore);
c2f47e15 11006 break;
11007 case 1:
389dd41b 11008 ret = fold_builtin_1 (loc, fndecl, args[0], ignore);
c2f47e15 11009 break;
11010 case 2:
389dd41b 11011 ret = fold_builtin_2 (loc, fndecl, args[0], args[1], ignore);
c2f47e15 11012 break;
11013 case 3:
389dd41b 11014 ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2], ignore);
c2f47e15 11015 break;
11016 case 4:
389dd41b 11017 ret = fold_builtin_4 (loc, fndecl, args[0], args[1], args[2], args[3],
c2f47e15 11018 ignore);
11019 break;
11020 default:
11021 break;
11022 }
11023 if (ret)
11024 {
75a70cf9 11025 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
389dd41b 11026 SET_EXPR_LOCATION (ret, loc);
c2f47e15 11027 TREE_NO_WARNING (ret) = 1;
11028 return ret;
11029 }
11030 return NULL_TREE;
11031}
11032
11033/* Builtins with folding operations that operate on "..." arguments
11034 need special handling; we need to store the arguments in a convenient
11035 data structure before attempting any folding. Fortunately there are
11036 only a few builtins that fall into this category. FNDECL is the
11037 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
11038 result of the function call is ignored. */
11039
11040static tree
389dd41b 11041fold_builtin_varargs (location_t loc, tree fndecl, tree exp,
11042 bool ignore ATTRIBUTE_UNUSED)
c2f47e15 11043{
11044 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
11045 tree ret = NULL_TREE;
11046
11047 switch (fcode)
11048 {
11049 case BUILT_IN_SPRINTF_CHK:
11050 case BUILT_IN_VSPRINTF_CHK:
389dd41b 11051 ret = fold_builtin_sprintf_chk (loc, exp, fcode);
c2f47e15 11052 break;
11053
11054 case BUILT_IN_SNPRINTF_CHK:
11055 case BUILT_IN_VSNPRINTF_CHK:
389dd41b 11056 ret = fold_builtin_snprintf_chk (loc, exp, NULL_TREE, fcode);
19fbe3a4 11057 break;
11058
11059 case BUILT_IN_FPCLASSIFY:
389dd41b 11060 ret = fold_builtin_fpclassify (loc, exp);
19fbe3a4 11061 break;
c2f47e15 11062
11063 default:
11064 break;
11065 }
11066 if (ret)
11067 {
11068 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
389dd41b 11069 SET_EXPR_LOCATION (ret, loc);
c2f47e15 11070 TREE_NO_WARNING (ret) = 1;
11071 return ret;
11072 }
11073 return NULL_TREE;
650e4c94 11074}
7e15618b 11075
198622c0 11076/* Return true if FNDECL shouldn't be folded right now.
11077 If a built-in function has an inline attribute always_inline
11078 wrapper, defer folding it after always_inline functions have
11079 been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
11080 might not be performed. */
11081
51d2c51e 11082bool
198622c0 11083avoid_folding_inline_builtin (tree fndecl)
11084{
11085 return (DECL_DECLARED_INLINE_P (fndecl)
11086 && DECL_DISREGARD_INLINE_LIMITS (fndecl)
11087 && cfun
11088 && !cfun->always_inline_functions_inlined
11089 && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)));
11090}
11091
4ee9c684 11092/* A wrapper function for builtin folding that prevents warnings for
491e04ef 11093 "statement without effect" and the like, caused by removing the
4ee9c684 11094 call node earlier than the warning is generated. */
11095
11096tree
389dd41b 11097fold_call_expr (location_t loc, tree exp, bool ignore)
4ee9c684 11098{
c2f47e15 11099 tree ret = NULL_TREE;
11100 tree fndecl = get_callee_fndecl (exp);
11101 if (fndecl
11102 && TREE_CODE (fndecl) == FUNCTION_DECL
48dc2227 11103 && DECL_BUILT_IN (fndecl)
11104 /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
11105 yet. Defer folding until we see all the arguments
11106 (after inlining). */
11107 && !CALL_EXPR_VA_ARG_PACK (exp))
11108 {
11109 int nargs = call_expr_nargs (exp);
11110
11111 /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
11112 instead last argument is __builtin_va_arg_pack (). Defer folding
11113 even in that case, until arguments are finalized. */
11114 if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
11115 {
11116 tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1));
11117 if (fndecl2
11118 && TREE_CODE (fndecl2) == FUNCTION_DECL
11119 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
11120 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
11121 return NULL_TREE;
11122 }
11123
198622c0 11124 if (avoid_folding_inline_builtin (fndecl))
11125 return NULL_TREE;
11126
c2f47e15 11127 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
97d67146 11128 return targetm.fold_builtin (fndecl, call_expr_nargs (exp),
11129 CALL_EXPR_ARGP (exp), ignore);
c2f47e15 11130 else
11131 {
c2f47e15 11132 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
11133 {
11134 tree *args = CALL_EXPR_ARGP (exp);
389dd41b 11135 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
c2f47e15 11136 }
11137 if (!ret)
389dd41b 11138 ret = fold_builtin_varargs (loc, fndecl, exp, ignore);
c2f47e15 11139 if (ret)
389dd41b 11140 return ret;
c2f47e15 11141 }
4ee9c684 11142 }
c2f47e15 11143 return NULL_TREE;
11144}
48e1416a 11145
c2f47e15 11146/* Conveniently construct a function call expression. FNDECL names the
414c3a2c 11147 function to be called and N arguments are passed in the array
11148 ARGARRAY. */
48e1416a 11149
c2f47e15 11150tree
414c3a2c 11151build_call_expr_loc_array (location_t loc, tree fndecl, int n, tree *argarray)
c2f47e15 11152{
11153 tree fntype = TREE_TYPE (fndecl);
11154 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
414c3a2c 11155
389dd41b 11156 return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray);
c2f47e15 11157}
11158
414c3a2c 11159/* Conveniently construct a function call expression. FNDECL names the
11160 function to be called and the arguments are passed in the vector
11161 VEC. */
11162
11163tree
11164build_call_expr_loc_vec (location_t loc, tree fndecl, VEC(tree,gc) *vec)
11165{
11166 return build_call_expr_loc_array (loc, fndecl, VEC_length (tree, vec),
11167 VEC_address (tree, vec));
11168}
11169
11170
c2f47e15 11171/* Conveniently construct a function call expression. FNDECL names the
11172 function to be called, N is the number of arguments, and the "..."
11173 parameters are the argument expressions. */
48e1416a 11174
c2f47e15 11175tree
389dd41b 11176build_call_expr_loc (location_t loc, tree fndecl, int n, ...)
c2f47e15 11177{
11178 va_list ap;
414c3a2c 11179 tree *argarray = XALLOCAVEC (tree, n);
d01f58f9 11180 int i;
c2f47e15 11181
11182 va_start (ap, n);
d01f58f9 11183 for (i = 0; i < n; i++)
11184 argarray[i] = va_arg (ap, tree);
c2f47e15 11185 va_end (ap);
414c3a2c 11186 return build_call_expr_loc_array (loc, fndecl, n, argarray);
4ee9c684 11187}
11188
0568e9c1 11189/* Like build_call_expr_loc (UNKNOWN_LOCATION, ...). Duplicated because
11190 varargs macros aren't supported by all bootstrap compilers. */
11191
11192tree
11193build_call_expr (tree fndecl, int n, ...)
11194{
11195 va_list ap;
414c3a2c 11196 tree *argarray = XALLOCAVEC (tree, n);
0568e9c1 11197 int i;
11198
11199 va_start (ap, n);
11200 for (i = 0; i < n; i++)
11201 argarray[i] = va_arg (ap, tree);
11202 va_end (ap);
414c3a2c 11203 return build_call_expr_loc_array (UNKNOWN_LOCATION, fndecl, n, argarray);
0568e9c1 11204}
11205
c2f47e15 11206/* Construct a CALL_EXPR with type TYPE with FN as the function expression.
d01f58f9 11207 N arguments are passed in the array ARGARRAY. */
805e22b2 11208
11209tree
389dd41b 11210fold_builtin_call_array (location_t loc, tree type,
d01f58f9 11211 tree fn,
11212 int n,
11213 tree *argarray)
7e15618b 11214{
c2f47e15 11215 tree ret = NULL_TREE;
c2f47e15 11216 tree exp;
11217
11218 if (TREE_CODE (fn) == ADDR_EXPR)
11219 {
11220 tree fndecl = TREE_OPERAND (fn, 0);
11221 if (TREE_CODE (fndecl) == FUNCTION_DECL
11222 && DECL_BUILT_IN (fndecl))
11223 {
48dc2227 11224 /* If last argument is __builtin_va_arg_pack (), arguments to this
11225 function are not finalized yet. Defer folding until they are. */
11226 if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
11227 {
11228 tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
11229 if (fndecl2
11230 && TREE_CODE (fndecl2) == FUNCTION_DECL
11231 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
11232 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
389dd41b 11233 return build_call_array_loc (loc, type, fn, n, argarray);
48dc2227 11234 }
198622c0 11235 if (avoid_folding_inline_builtin (fndecl))
389dd41b 11236 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 11237 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
11238 {
97d67146 11239 ret = targetm.fold_builtin (fndecl, n, argarray, false);
11240 if (ret)
11241 return ret;
11242
389dd41b 11243 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 11244 }
11245 else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
11246 {
11247 /* First try the transformations that don't require consing up
11248 an exp. */
389dd41b 11249 ret = fold_builtin_n (loc, fndecl, argarray, n, false);
c2f47e15 11250 if (ret)
11251 return ret;
11252 }
11253
11254 /* If we got this far, we need to build an exp. */
389dd41b 11255 exp = build_call_array_loc (loc, type, fn, n, argarray);
11256 ret = fold_builtin_varargs (loc, fndecl, exp, false);
c2f47e15 11257 return ret ? ret : exp;
11258 }
11259 }
11260
389dd41b 11261 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 11262}
11263
af1409ad 11264/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
11265 list ARGS along with N new arguments in NEWARGS. SKIP is the number
11266 of arguments in ARGS to be omitted. OLDNARGS is the number of
11267 elements in ARGS. */
c2f47e15 11268
11269static tree
af1409ad 11270rewrite_call_expr_valist (location_t loc, int oldnargs, tree *args,
11271 int skip, tree fndecl, int n, va_list newargs)
c2f47e15 11272{
c2f47e15 11273 int nargs = oldnargs - skip + n;
c2f47e15 11274 tree *buffer;
11275
11276 if (n > 0)
11277 {
11278 int i, j;
7e15618b 11279
364c0c59 11280 buffer = XALLOCAVEC (tree, nargs);
c2f47e15 11281 for (i = 0; i < n; i++)
af1409ad 11282 buffer[i] = va_arg (newargs, tree);
c2f47e15 11283 for (j = skip; j < oldnargs; j++, i++)
af1409ad 11284 buffer[i] = args[j];
c2f47e15 11285 }
48e1416a 11286 else
af1409ad 11287 buffer = args + skip;
11288
11289 return build_call_expr_loc_array (loc, fndecl, nargs, buffer);
11290}
11291
11292/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
11293 list ARGS along with N new arguments specified as the "..."
11294 parameters. SKIP is the number of arguments in ARGS to be omitted.
11295 OLDNARGS is the number of elements in ARGS. */
11296
11297static tree
11298rewrite_call_expr_array (location_t loc, int oldnargs, tree *args,
11299 int skip, tree fndecl, int n, ...)
11300{
11301 va_list ap;
11302 tree t;
11303
11304 va_start (ap, n);
11305 t = rewrite_call_expr_valist (loc, oldnargs, args, skip, fndecl, n, ap);
11306 va_end (ap);
11307
11308 return t;
11309}
11310
11311/* Construct a new CALL_EXPR using the tail of the argument list of EXP
11312 along with N new arguments specified as the "..." parameters. SKIP
11313 is the number of arguments in EXP to be omitted. This function is used
11314 to do varargs-to-varargs transformations. */
11315
11316static tree
11317rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...)
11318{
11319 va_list ap;
11320 tree t;
11321
11322 va_start (ap, n);
11323 t = rewrite_call_expr_valist (loc, call_expr_nargs (exp),
11324 CALL_EXPR_ARGP (exp), skip, fndecl, n, ap);
11325 va_end (ap);
c2f47e15 11326
af1409ad 11327 return t;
c2f47e15 11328}
11329
11330/* Validate a single argument ARG against a tree code CODE representing
11331 a type. */
48e1416a 11332
c2f47e15 11333static bool
b7bf20db 11334validate_arg (const_tree arg, enum tree_code code)
c2f47e15 11335{
11336 if (!arg)
11337 return false;
11338 else if (code == POINTER_TYPE)
11339 return POINTER_TYPE_P (TREE_TYPE (arg));
c7f617c2 11340 else if (code == INTEGER_TYPE)
11341 return INTEGRAL_TYPE_P (TREE_TYPE (arg));
c2f47e15 11342 return code == TREE_CODE (TREE_TYPE (arg));
7e15618b 11343}
0eb671f7 11344
75a70cf9 11345/* This function validates the types of a function call argument list
11346 against a specified list of tree_codes. If the last specifier is a 0,
11347 that represents an ellipses, otherwise the last specifier must be a
11348 VOID_TYPE.
11349
11350 This is the GIMPLE version of validate_arglist. Eventually we want to
11351 completely convert builtins.c to work from GIMPLEs and the tree based
11352 validate_arglist will then be removed. */
11353
11354bool
11355validate_gimple_arglist (const_gimple call, ...)
11356{
11357 enum tree_code code;
11358 bool res = 0;
11359 va_list ap;
11360 const_tree arg;
11361 size_t i;
11362
11363 va_start (ap, call);
11364 i = 0;
11365
11366 do
11367 {
d62e827b 11368 code = (enum tree_code) va_arg (ap, int);
75a70cf9 11369 switch (code)
11370 {
11371 case 0:
11372 /* This signifies an ellipses, any further arguments are all ok. */
11373 res = true;
11374 goto end;
11375 case VOID_TYPE:
11376 /* This signifies an endlink, if no arguments remain, return
11377 true, otherwise return false. */
11378 res = (i == gimple_call_num_args (call));
11379 goto end;
11380 default:
11381 /* If no parameters remain or the parameter's code does not
11382 match the specified code, return false. Otherwise continue
11383 checking any remaining arguments. */
11384 arg = gimple_call_arg (call, i++);
11385 if (!validate_arg (arg, code))
11386 goto end;
11387 break;
11388 }
11389 }
11390 while (1);
11391
11392 /* We need gotos here since we can only have one VA_CLOSE in a
11393 function. */
11394 end: ;
11395 va_end (ap);
11396
11397 return res;
11398}
11399
0eb671f7 11400/* This function validates the types of a function call argument list
c2f47e15 11401 against a specified list of tree_codes. If the last specifier is a 0,
11402 that represents an ellipses, otherwise the last specifier must be a
11403 VOID_TYPE. */
27d0c333 11404
c2f47e15 11405bool
b7bf20db 11406validate_arglist (const_tree callexpr, ...)
0eb671f7 11407{
0eb671f7 11408 enum tree_code code;
c2f47e15 11409 bool res = 0;
ee582a61 11410 va_list ap;
b7bf20db 11411 const_call_expr_arg_iterator iter;
11412 const_tree arg;
aecda0d6 11413
c2f47e15 11414 va_start (ap, callexpr);
b7bf20db 11415 init_const_call_expr_arg_iterator (callexpr, &iter);
0eb671f7 11416
f0ce3b1f 11417 do
0eb671f7 11418 {
d62e827b 11419 code = (enum tree_code) va_arg (ap, int);
f0ce3b1f 11420 switch (code)
11421 {
11422 case 0:
11423 /* This signifies an ellipses, any further arguments are all ok. */
c2f47e15 11424 res = true;
f0ce3b1f 11425 goto end;
11426 case VOID_TYPE:
11427 /* This signifies an endlink, if no arguments remain, return
11428 true, otherwise return false. */
b7bf20db 11429 res = !more_const_call_expr_args_p (&iter);
f0ce3b1f 11430 goto end;
11431 default:
11432 /* If no parameters remain or the parameter's code does not
11433 match the specified code, return false. Otherwise continue
11434 checking any remaining arguments. */
b7bf20db 11435 arg = next_const_call_expr_arg (&iter);
c2f47e15 11436 if (!validate_arg (arg, code))
f0ce3b1f 11437 goto end;
11438 break;
11439 }
0eb671f7 11440 }
f0ce3b1f 11441 while (1);
0903457a 11442
11443 /* We need gotos here since we can only have one VA_CLOSE in a
11444 function. */
11445 end: ;
ee582a61 11446 va_end (ap);
0903457a 11447
11448 return res;
0eb671f7 11449}
fc2a2dcb 11450
fc2a2dcb 11451/* Default target-specific builtin expander that does nothing. */
11452
11453rtx
aecda0d6 11454default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
11455 rtx target ATTRIBUTE_UNUSED,
11456 rtx subtarget ATTRIBUTE_UNUSED,
11457 enum machine_mode mode ATTRIBUTE_UNUSED,
11458 int ignore ATTRIBUTE_UNUSED)
fc2a2dcb 11459{
11460 return NULL_RTX;
11461}
c7926a82 11462
01537105 11463/* Returns true is EXP represents data that would potentially reside
11464 in a readonly section. */
11465
11466static bool
11467readonly_data_expr (tree exp)
11468{
11469 STRIP_NOPS (exp);
11470
9ff0637e 11471 if (TREE_CODE (exp) != ADDR_EXPR)
11472 return false;
11473
11474 exp = get_base_address (TREE_OPERAND (exp, 0));
11475 if (!exp)
11476 return false;
11477
11478 /* Make sure we call decl_readonly_section only for trees it
11479 can handle (since it returns true for everything it doesn't
11480 understand). */
491e04ef 11481 if (TREE_CODE (exp) == STRING_CST
9ff0637e 11482 || TREE_CODE (exp) == CONSTRUCTOR
11483 || (TREE_CODE (exp) == VAR_DECL && TREE_STATIC (exp)))
11484 return decl_readonly_section (exp, 0);
01537105 11485 else
11486 return false;
11487}
4ee9c684 11488
c2f47e15 11489/* Simplify a call to the strstr builtin. S1 and S2 are the arguments
11490 to the call, and TYPE is its return type.
4ee9c684 11491
c2f47e15 11492 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11493 simplified form of the call as a tree.
11494
11495 The simplified form may be a constant or other expression which
11496 computes the same value, but in a more efficient manner (including
11497 calls to other builtin functions).
11498
11499 The call may contain arguments which need to be evaluated, but
11500 which are not useful to determine the result of the call. In
11501 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11502 COMPOUND_EXPR will be an argument which must be evaluated.
11503 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11504 COMPOUND_EXPR in the chain will contain the tree for the simplified
11505 form of the builtin function call. */
11506
11507static tree
389dd41b 11508fold_builtin_strstr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11509{
c2f47e15 11510 if (!validate_arg (s1, POINTER_TYPE)
11511 || !validate_arg (s2, POINTER_TYPE))
11512 return NULL_TREE;
4ee9c684 11513 else
11514 {
4ee9c684 11515 tree fn;
11516 const char *p1, *p2;
11517
11518 p2 = c_getstr (s2);
11519 if (p2 == NULL)
c2f47e15 11520 return NULL_TREE;
4ee9c684 11521
11522 p1 = c_getstr (s1);
11523 if (p1 != NULL)
11524 {
11525 const char *r = strstr (p1, p2);
daa1d5f5 11526 tree tem;
4ee9c684 11527
4ee9c684 11528 if (r == NULL)
779b4c41 11529 return build_int_cst (TREE_TYPE (s1), 0);
c0c67e38 11530
11531 /* Return an offset into the constant string argument. */
2cc66f2a 11532 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11533 return fold_convert_loc (loc, type, tem);
4ee9c684 11534 }
11535
7efa231c 11536 /* The argument is const char *, and the result is char *, so we need
11537 a type conversion here to avoid a warning. */
4ee9c684 11538 if (p2[0] == '\0')
389dd41b 11539 return fold_convert_loc (loc, type, s1);
4ee9c684 11540
11541 if (p2[1] != '\0')
c2f47e15 11542 return NULL_TREE;
4ee9c684 11543
b9a16870 11544 fn = builtin_decl_implicit (BUILT_IN_STRCHR);
4ee9c684 11545 if (!fn)
c2f47e15 11546 return NULL_TREE;
4ee9c684 11547
11548 /* New argument list transforming strstr(s1, s2) to
11549 strchr(s1, s2[0]). */
7002a1c8 11550 return build_call_expr_loc (loc, fn, 2, s1,
11551 build_int_cst (integer_type_node, p2[0]));
4ee9c684 11552 }
11553}
11554
c2f47e15 11555/* Simplify a call to the strchr builtin. S1 and S2 are the arguments to
11556 the call, and TYPE is its return type.
4ee9c684 11557
c2f47e15 11558 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11559 simplified form of the call as a tree.
11560
11561 The simplified form may be a constant or other expression which
11562 computes the same value, but in a more efficient manner (including
11563 calls to other builtin functions).
11564
11565 The call may contain arguments which need to be evaluated, but
11566 which are not useful to determine the result of the call. In
11567 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11568 COMPOUND_EXPR will be an argument which must be evaluated.
11569 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11570 COMPOUND_EXPR in the chain will contain the tree for the simplified
11571 form of the builtin function call. */
11572
11573static tree
389dd41b 11574fold_builtin_strchr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11575{
c2f47e15 11576 if (!validate_arg (s1, POINTER_TYPE)
11577 || !validate_arg (s2, INTEGER_TYPE))
11578 return NULL_TREE;
4ee9c684 11579 else
11580 {
4ee9c684 11581 const char *p1;
11582
11583 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 11584 return NULL_TREE;
4ee9c684 11585
11586 p1 = c_getstr (s1);
11587 if (p1 != NULL)
11588 {
11589 char c;
11590 const char *r;
daa1d5f5 11591 tree tem;
4ee9c684 11592
11593 if (target_char_cast (s2, &c))
c2f47e15 11594 return NULL_TREE;
4ee9c684 11595
11596 r = strchr (p1, c);
11597
11598 if (r == NULL)
779b4c41 11599 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11600
11601 /* Return an offset into the constant string argument. */
2cc66f2a 11602 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11603 return fold_convert_loc (loc, type, tem);
4ee9c684 11604 }
c2f47e15 11605 return NULL_TREE;
4ee9c684 11606 }
11607}
11608
c2f47e15 11609/* Simplify a call to the strrchr builtin. S1 and S2 are the arguments to
11610 the call, and TYPE is its return type.
4ee9c684 11611
c2f47e15 11612 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11613 simplified form of the call as a tree.
11614
11615 The simplified form may be a constant or other expression which
11616 computes the same value, but in a more efficient manner (including
11617 calls to other builtin functions).
11618
11619 The call may contain arguments which need to be evaluated, but
11620 which are not useful to determine the result of the call. In
11621 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11622 COMPOUND_EXPR will be an argument which must be evaluated.
11623 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11624 COMPOUND_EXPR in the chain will contain the tree for the simplified
11625 form of the builtin function call. */
11626
11627static tree
389dd41b 11628fold_builtin_strrchr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11629{
c2f47e15 11630 if (!validate_arg (s1, POINTER_TYPE)
11631 || !validate_arg (s2, INTEGER_TYPE))
11632 return NULL_TREE;
4ee9c684 11633 else
11634 {
4ee9c684 11635 tree fn;
11636 const char *p1;
11637
11638 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 11639 return NULL_TREE;
4ee9c684 11640
11641 p1 = c_getstr (s1);
11642 if (p1 != NULL)
11643 {
11644 char c;
11645 const char *r;
daa1d5f5 11646 tree tem;
4ee9c684 11647
11648 if (target_char_cast (s2, &c))
c2f47e15 11649 return NULL_TREE;
4ee9c684 11650
11651 r = strrchr (p1, c);
11652
11653 if (r == NULL)
779b4c41 11654 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11655
11656 /* Return an offset into the constant string argument. */
2cc66f2a 11657 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11658 return fold_convert_loc (loc, type, tem);
4ee9c684 11659 }
11660
11661 if (! integer_zerop (s2))
c2f47e15 11662 return NULL_TREE;
4ee9c684 11663
b9a16870 11664 fn = builtin_decl_implicit (BUILT_IN_STRCHR);
4ee9c684 11665 if (!fn)
c2f47e15 11666 return NULL_TREE;
4ee9c684 11667
11668 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
389dd41b 11669 return build_call_expr_loc (loc, fn, 2, s1, s2);
4ee9c684 11670 }
11671}
11672
c2f47e15 11673/* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments
11674 to the call, and TYPE is its return type.
4ee9c684 11675
c2f47e15 11676 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11677 simplified form of the call as a tree.
11678
11679 The simplified form may be a constant or other expression which
11680 computes the same value, but in a more efficient manner (including
11681 calls to other builtin functions).
11682
11683 The call may contain arguments which need to be evaluated, but
11684 which are not useful to determine the result of the call. In
11685 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11686 COMPOUND_EXPR will be an argument which must be evaluated.
11687 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11688 COMPOUND_EXPR in the chain will contain the tree for the simplified
11689 form of the builtin function call. */
11690
11691static tree
389dd41b 11692fold_builtin_strpbrk (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11693{
c2f47e15 11694 if (!validate_arg (s1, POINTER_TYPE)
11695 || !validate_arg (s2, POINTER_TYPE))
11696 return NULL_TREE;
4ee9c684 11697 else
11698 {
4ee9c684 11699 tree fn;
11700 const char *p1, *p2;
11701
11702 p2 = c_getstr (s2);
11703 if (p2 == NULL)
c2f47e15 11704 return NULL_TREE;
4ee9c684 11705
11706 p1 = c_getstr (s1);
11707 if (p1 != NULL)
11708 {
11709 const char *r = strpbrk (p1, p2);
daa1d5f5 11710 tree tem;
4ee9c684 11711
11712 if (r == NULL)
779b4c41 11713 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11714
11715 /* Return an offset into the constant string argument. */
2cc66f2a 11716 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11717 return fold_convert_loc (loc, type, tem);
4ee9c684 11718 }
11719
11720 if (p2[0] == '\0')
05abc81b 11721 /* strpbrk(x, "") == NULL.
11722 Evaluate and ignore s1 in case it had side-effects. */
389dd41b 11723 return omit_one_operand_loc (loc, TREE_TYPE (s1), integer_zero_node, s1);
4ee9c684 11724
11725 if (p2[1] != '\0')
c2f47e15 11726 return NULL_TREE; /* Really call strpbrk. */
4ee9c684 11727
b9a16870 11728 fn = builtin_decl_implicit (BUILT_IN_STRCHR);
4ee9c684 11729 if (!fn)
c2f47e15 11730 return NULL_TREE;
4ee9c684 11731
11732 /* New argument list transforming strpbrk(s1, s2) to
11733 strchr(s1, s2[0]). */
7002a1c8 11734 return build_call_expr_loc (loc, fn, 2, s1,
11735 build_int_cst (integer_type_node, p2[0]));
4ee9c684 11736 }
11737}
11738
c2f47e15 11739/* Simplify a call to the strcat builtin. DST and SRC are the arguments
11740 to the call.
4ee9c684 11741
c2f47e15 11742 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11743 simplified form of the call as a tree.
11744
11745 The simplified form may be a constant or other expression which
11746 computes the same value, but in a more efficient manner (including
11747 calls to other builtin functions).
11748
11749 The call may contain arguments which need to be evaluated, but
11750 which are not useful to determine the result of the call. In
11751 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11752 COMPOUND_EXPR will be an argument which must be evaluated.
11753 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11754 COMPOUND_EXPR in the chain will contain the tree for the simplified
11755 form of the builtin function call. */
11756
11757static tree
389dd41b 11758fold_builtin_strcat (location_t loc ATTRIBUTE_UNUSED, tree dst, tree src)
4ee9c684 11759{
c2f47e15 11760 if (!validate_arg (dst, POINTER_TYPE)
11761 || !validate_arg (src, POINTER_TYPE))
11762 return NULL_TREE;
4ee9c684 11763 else
11764 {
4ee9c684 11765 const char *p = c_getstr (src);
11766
11767 /* If the string length is zero, return the dst parameter. */
11768 if (p && *p == '\0')
11769 return dst;
11770
a65c4d64 11771 if (optimize_insn_for_speed_p ())
11772 {
11773 /* See if we can store by pieces into (dst + strlen(dst)). */
11774 tree newdst, call;
b9a16870 11775 tree strlen_fn = builtin_decl_implicit (BUILT_IN_STRLEN);
11776 tree strcpy_fn = builtin_decl_implicit (BUILT_IN_STRCPY);
a65c4d64 11777
11778 if (!strlen_fn || !strcpy_fn)
11779 return NULL_TREE;
11780
11781 /* If we don't have a movstr we don't want to emit an strcpy
11782 call. We have to do that if the length of the source string
11783 isn't computable (in that case we can use memcpy probably
48e1416a 11784 later expanding to a sequence of mov instructions). If we
a65c4d64 11785 have movstr instructions we can emit strcpy calls. */
11786 if (!HAVE_movstr)
11787 {
11788 tree len = c_strlen (src, 1);
11789 if (! len || TREE_SIDE_EFFECTS (len))
11790 return NULL_TREE;
11791 }
11792
11793 /* Stabilize the argument list. */
11794 dst = builtin_save_expr (dst);
11795
11796 /* Create strlen (dst). */
11797 newdst = build_call_expr_loc (loc, strlen_fn, 1, dst);
11798 /* Create (dst p+ strlen (dst)). */
11799
2cc66f2a 11800 newdst = fold_build_pointer_plus_loc (loc, dst, newdst);
a65c4d64 11801 newdst = builtin_save_expr (newdst);
11802
11803 call = build_call_expr_loc (loc, strcpy_fn, 2, newdst, src);
11804 return build2 (COMPOUND_EXPR, TREE_TYPE (dst), call, dst);
11805 }
c2f47e15 11806 return NULL_TREE;
4ee9c684 11807 }
11808}
11809
c2f47e15 11810/* Simplify a call to the strncat builtin. DST, SRC, and LEN are the
11811 arguments to the call.
4ee9c684 11812
c2f47e15 11813 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11814 simplified form of the call as a tree.
11815
11816 The simplified form may be a constant or other expression which
11817 computes the same value, but in a more efficient manner (including
11818 calls to other builtin functions).
11819
11820 The call may contain arguments which need to be evaluated, but
11821 which are not useful to determine the result of the call. In
11822 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11823 COMPOUND_EXPR will be an argument which must be evaluated.
11824 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11825 COMPOUND_EXPR in the chain will contain the tree for the simplified
11826 form of the builtin function call. */
11827
11828static tree
389dd41b 11829fold_builtin_strncat (location_t loc, tree dst, tree src, tree len)
4ee9c684 11830{
c2f47e15 11831 if (!validate_arg (dst, POINTER_TYPE)
11832 || !validate_arg (src, POINTER_TYPE)
11833 || !validate_arg (len, INTEGER_TYPE))
11834 return NULL_TREE;
4ee9c684 11835 else
11836 {
4ee9c684 11837 const char *p = c_getstr (src);
11838
11839 /* If the requested length is zero, or the src parameter string
0a39fd54 11840 length is zero, return the dst parameter. */
4ee9c684 11841 if (integer_zerop (len) || (p && *p == '\0'))
389dd41b 11842 return omit_two_operands_loc (loc, TREE_TYPE (dst), dst, src, len);
4ee9c684 11843
11844 /* If the requested len is greater than or equal to the string
a0c938f0 11845 length, call strcat. */
4ee9c684 11846 if (TREE_CODE (len) == INTEGER_CST && p
11847 && compare_tree_int (len, strlen (p)) >= 0)
11848 {
b9a16870 11849 tree fn = builtin_decl_implicit (BUILT_IN_STRCAT);
4ee9c684 11850
11851 /* If the replacement _DECL isn't initialized, don't do the
11852 transformation. */
11853 if (!fn)
c2f47e15 11854 return NULL_TREE;
4ee9c684 11855
389dd41b 11856 return build_call_expr_loc (loc, fn, 2, dst, src);
4ee9c684 11857 }
c2f47e15 11858 return NULL_TREE;
4ee9c684 11859 }
11860}
11861
c2f47e15 11862/* Simplify a call to the strspn builtin. S1 and S2 are the arguments
11863 to the call.
4ee9c684 11864
c2f47e15 11865 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11866 simplified form of the call as a tree.
11867
11868 The simplified form may be a constant or other expression which
11869 computes the same value, but in a more efficient manner (including
11870 calls to other builtin functions).
11871
11872 The call may contain arguments which need to be evaluated, but
11873 which are not useful to determine the result of the call. In
11874 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11875 COMPOUND_EXPR will be an argument which must be evaluated.
11876 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11877 COMPOUND_EXPR in the chain will contain the tree for the simplified
11878 form of the builtin function call. */
11879
11880static tree
389dd41b 11881fold_builtin_strspn (location_t loc, tree s1, tree s2)
4ee9c684 11882{
c2f47e15 11883 if (!validate_arg (s1, POINTER_TYPE)
11884 || !validate_arg (s2, POINTER_TYPE))
11885 return NULL_TREE;
4ee9c684 11886 else
11887 {
4ee9c684 11888 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11889
11890 /* If both arguments are constants, evaluate at compile-time. */
11891 if (p1 && p2)
11892 {
11893 const size_t r = strspn (p1, p2);
11894 return size_int (r);
11895 }
11896
c2f47e15 11897 /* If either argument is "", return NULL_TREE. */
4ee9c684 11898 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9bc9f15f 11899 /* Evaluate and ignore both arguments in case either one has
11900 side-effects. */
389dd41b 11901 return omit_two_operands_loc (loc, size_type_node, size_zero_node,
9bc9f15f 11902 s1, s2);
c2f47e15 11903 return NULL_TREE;
4ee9c684 11904 }
11905}
11906
c2f47e15 11907/* Simplify a call to the strcspn builtin. S1 and S2 are the arguments
11908 to the call.
4ee9c684 11909
c2f47e15 11910 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11911 simplified form of the call as a tree.
11912
11913 The simplified form may be a constant or other expression which
11914 computes the same value, but in a more efficient manner (including
11915 calls to other builtin functions).
11916
11917 The call may contain arguments which need to be evaluated, but
11918 which are not useful to determine the result of the call. In
11919 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11920 COMPOUND_EXPR will be an argument which must be evaluated.
11921 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11922 COMPOUND_EXPR in the chain will contain the tree for the simplified
11923 form of the builtin function call. */
11924
11925static tree
389dd41b 11926fold_builtin_strcspn (location_t loc, tree s1, tree s2)
4ee9c684 11927{
c2f47e15 11928 if (!validate_arg (s1, POINTER_TYPE)
11929 || !validate_arg (s2, POINTER_TYPE))
11930 return NULL_TREE;
4ee9c684 11931 else
11932 {
4ee9c684 11933 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11934
11935 /* If both arguments are constants, evaluate at compile-time. */
11936 if (p1 && p2)
11937 {
11938 const size_t r = strcspn (p1, p2);
11939 return size_int (r);
11940 }
11941
c2f47e15 11942 /* If the first argument is "", return NULL_TREE. */
4ee9c684 11943 if (p1 && *p1 == '\0')
11944 {
11945 /* Evaluate and ignore argument s2 in case it has
11946 side-effects. */
389dd41b 11947 return omit_one_operand_loc (loc, size_type_node,
39761420 11948 size_zero_node, s2);
4ee9c684 11949 }
11950
11951 /* If the second argument is "", return __builtin_strlen(s1). */
11952 if (p2 && *p2 == '\0')
11953 {
b9a16870 11954 tree fn = builtin_decl_implicit (BUILT_IN_STRLEN);
4ee9c684 11955
11956 /* If the replacement _DECL isn't initialized, don't do the
11957 transformation. */
11958 if (!fn)
c2f47e15 11959 return NULL_TREE;
4ee9c684 11960
389dd41b 11961 return build_call_expr_loc (loc, fn, 1, s1);
4ee9c684 11962 }
c2f47e15 11963 return NULL_TREE;
4ee9c684 11964 }
11965}
11966
c2f47e15 11967/* Fold a call to the fputs builtin. ARG0 and ARG1 are the arguments
11968 to the call. IGNORE is true if the value returned
f0613857 11969 by the builtin will be ignored. UNLOCKED is true is true if this
11970 actually a call to fputs_unlocked. If LEN in non-NULL, it represents
11971 the known length of the string. Return NULL_TREE if no simplification
11972 was possible. */
4ee9c684 11973
11974tree
389dd41b 11975fold_builtin_fputs (location_t loc, tree arg0, tree arg1,
11976 bool ignore, bool unlocked, tree len)
4ee9c684 11977{
6d77ed92 11978 /* If we're using an unlocked function, assume the other unlocked
11979 functions exist explicitly. */
b9a16870 11980 tree const fn_fputc = (unlocked
11981 ? builtin_decl_explicit (BUILT_IN_FPUTC_UNLOCKED)
11982 : builtin_decl_implicit (BUILT_IN_FPUTC));
11983 tree const fn_fwrite = (unlocked
11984 ? builtin_decl_explicit (BUILT_IN_FWRITE_UNLOCKED)
11985 : builtin_decl_implicit (BUILT_IN_FWRITE));
4ee9c684 11986
c403edd4 11987 /* If the return value is used, don't do the transformation. */
11988 if (!ignore)
c2f47e15 11989 return NULL_TREE;
4ee9c684 11990
11991 /* Verify the arguments in the original call. */
c2f47e15 11992 if (!validate_arg (arg0, POINTER_TYPE)
11993 || !validate_arg (arg1, POINTER_TYPE))
11994 return NULL_TREE;
4ee9c684 11995
f0613857 11996 if (! len)
c2f47e15 11997 len = c_strlen (arg0, 0);
4ee9c684 11998
11999 /* Get the length of the string passed to fputs. If the length
12000 can't be determined, punt. */
12001 if (!len
12002 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 12003 return NULL_TREE;
4ee9c684 12004
12005 switch (compare_tree_int (len, 1))
12006 {
12007 case -1: /* length is 0, delete the call entirely . */
389dd41b 12008 return omit_one_operand_loc (loc, integer_type_node,
12009 integer_zero_node, arg1);;
05abc81b 12010
4ee9c684 12011 case 0: /* length is 1, call fputc. */
12012 {
c2f47e15 12013 const char *p = c_getstr (arg0);
4ee9c684 12014
12015 if (p != NULL)
12016 {
c2f47e15 12017 if (fn_fputc)
389dd41b 12018 return build_call_expr_loc (loc, fn_fputc, 2,
7002a1c8 12019 build_int_cst
12020 (integer_type_node, p[0]), arg1);
c2f47e15 12021 else
12022 return NULL_TREE;
4ee9c684 12023 }
12024 }
12025 /* FALLTHROUGH */
12026 case 1: /* length is greater than 1, call fwrite. */
12027 {
0bed3869 12028 /* If optimizing for size keep fputs. */
0bfd8d5c 12029 if (optimize_function_for_size_p (cfun))
c2f47e15 12030 return NULL_TREE;
4ee9c684 12031 /* New argument list transforming fputs(string, stream) to
12032 fwrite(string, 1, len, stream). */
c2f47e15 12033 if (fn_fwrite)
389dd41b 12034 return build_call_expr_loc (loc, fn_fwrite, 4, arg0,
12035 size_one_node, len, arg1);
c2f47e15 12036 else
12037 return NULL_TREE;
4ee9c684 12038 }
12039 default:
64db345d 12040 gcc_unreachable ();
4ee9c684 12041 }
c2f47e15 12042 return NULL_TREE;
4ee9c684 12043}
12044
c2f47e15 12045/* Fold the next_arg or va_start call EXP. Returns true if there was an error
743b0c6a 12046 produced. False otherwise. This is done so that we don't output the error
12047 or warning twice or three times. */
75a70cf9 12048
743b0c6a 12049bool
c2f47e15 12050fold_builtin_next_arg (tree exp, bool va_start_p)
4ee9c684 12051{
12052 tree fntype = TREE_TYPE (current_function_decl);
c2f47e15 12053 int nargs = call_expr_nargs (exp);
12054 tree arg;
4ee9c684 12055
257d99c3 12056 if (!stdarg_p (fntype))
743b0c6a 12057 {
12058 error ("%<va_start%> used in function with fixed args");
12059 return true;
12060 }
c2f47e15 12061
12062 if (va_start_p)
79012a9d 12063 {
c2f47e15 12064 if (va_start_p && (nargs != 2))
12065 {
12066 error ("wrong number of arguments to function %<va_start%>");
12067 return true;
12068 }
12069 arg = CALL_EXPR_ARG (exp, 1);
79012a9d 12070 }
12071 /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
12072 when we checked the arguments and if needed issued a warning. */
c2f47e15 12073 else
4ee9c684 12074 {
c2f47e15 12075 if (nargs == 0)
12076 {
12077 /* Evidently an out of date version of <stdarg.h>; can't validate
12078 va_start's second argument, but can still work as intended. */
12079 warning (0, "%<__builtin_next_arg%> called without an argument");
12080 return true;
12081 }
12082 else if (nargs > 1)
a0c938f0 12083 {
c2f47e15 12084 error ("wrong number of arguments to function %<__builtin_next_arg%>");
a0c938f0 12085 return true;
12086 }
c2f47e15 12087 arg = CALL_EXPR_ARG (exp, 0);
12088 }
12089
a8dd994c 12090 if (TREE_CODE (arg) == SSA_NAME)
12091 arg = SSA_NAME_VAR (arg);
12092
c2f47e15 12093 /* We destructively modify the call to be __builtin_va_start (ap, 0)
48e1416a 12094 or __builtin_next_arg (0) the first time we see it, after checking
c2f47e15 12095 the arguments and if needed issuing a warning. */
12096 if (!integer_zerop (arg))
12097 {
12098 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
79012a9d 12099
4ee9c684 12100 /* Strip off all nops for the sake of the comparison. This
12101 is not quite the same as STRIP_NOPS. It does more.
12102 We must also strip off INDIRECT_EXPR for C++ reference
12103 parameters. */
72dd6141 12104 while (CONVERT_EXPR_P (arg)
4ee9c684 12105 || TREE_CODE (arg) == INDIRECT_REF)
12106 arg = TREE_OPERAND (arg, 0);
12107 if (arg != last_parm)
a0c938f0 12108 {
b08cf617 12109 /* FIXME: Sometimes with the tree optimizers we can get the
12110 not the last argument even though the user used the last
12111 argument. We just warn and set the arg to be the last
12112 argument so that we will get wrong-code because of
12113 it. */
c3ceba8e 12114 warning (0, "second parameter of %<va_start%> not last named argument");
743b0c6a 12115 }
24158ad7 12116
12117 /* Undefined by C99 7.15.1.4p4 (va_start):
12118 "If the parameter parmN is declared with the register storage
12119 class, with a function or array type, or with a type that is
12120 not compatible with the type that results after application of
12121 the default argument promotions, the behavior is undefined."
12122 */
12123 else if (DECL_REGISTER (arg))
12124 warning (0, "undefined behaviour when second parameter of "
12125 "%<va_start%> is declared with %<register%> storage");
12126
79012a9d 12127 /* We want to verify the second parameter just once before the tree
a0c938f0 12128 optimizers are run and then avoid keeping it in the tree,
12129 as otherwise we could warn even for correct code like:
12130 void foo (int i, ...)
12131 { va_list ap; i++; va_start (ap, i); va_end (ap); } */
c2f47e15 12132 if (va_start_p)
12133 CALL_EXPR_ARG (exp, 1) = integer_zero_node;
12134 else
12135 CALL_EXPR_ARG (exp, 0) = integer_zero_node;
743b0c6a 12136 }
12137 return false;
4ee9c684 12138}
12139
12140
c2f47e15 12141/* Simplify a call to the sprintf builtin with arguments DEST, FMT, and ORIG.
12142 ORIG may be null if this is a 2-argument call. We don't attempt to
12143 simplify calls with more than 3 arguments.
4ee9c684 12144
c2f47e15 12145 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 12146 simplified form of the call as a tree. If IGNORED is true, it means that
12147 the caller does not use the returned value of the function. */
12148
12149static tree
389dd41b 12150fold_builtin_sprintf (location_t loc, tree dest, tree fmt,
12151 tree orig, int ignored)
4ee9c684 12152{
c2f47e15 12153 tree call, retval;
4ee9c684 12154 const char *fmt_str = NULL;
12155
12156 /* Verify the required arguments in the original call. We deal with two
12157 types of sprintf() calls: 'sprintf (str, fmt)' and
12158 'sprintf (dest, "%s", orig)'. */
c2f47e15 12159 if (!validate_arg (dest, POINTER_TYPE)
12160 || !validate_arg (fmt, POINTER_TYPE))
12161 return NULL_TREE;
12162 if (orig && !validate_arg (orig, POINTER_TYPE))
4ee9c684 12163 return NULL_TREE;
4ee9c684 12164
12165 /* Check whether the format is a literal string constant. */
12166 fmt_str = c_getstr (fmt);
12167 if (fmt_str == NULL)
12168 return NULL_TREE;
12169
12170 call = NULL_TREE;
12171 retval = NULL_TREE;
12172
d4473c84 12173 if (!init_target_chars ())
c2f47e15 12174 return NULL_TREE;
99eabcc1 12175
4ee9c684 12176 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 12177 if (strchr (fmt_str, target_percent) == NULL)
4ee9c684 12178 {
b9a16870 12179 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
4ee9c684 12180
12181 if (!fn)
12182 return NULL_TREE;
12183
72dfb3f2 12184 /* Don't optimize sprintf (buf, "abc", ptr++). */
c2f47e15 12185 if (orig)
72dfb3f2 12186 return NULL_TREE;
12187
4ee9c684 12188 /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
12189 'format' is known to contain no % formats. */
389dd41b 12190 call = build_call_expr_loc (loc, fn, 2, dest, fmt);
4ee9c684 12191 if (!ignored)
7002a1c8 12192 retval = build_int_cst (integer_type_node, strlen (fmt_str));
4ee9c684 12193 }
12194
12195 /* If the format is "%s", use strcpy if the result isn't used. */
99eabcc1 12196 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
4ee9c684 12197 {
c2f47e15 12198 tree fn;
b9a16870 12199 fn = builtin_decl_implicit (BUILT_IN_STRCPY);
4ee9c684 12200
12201 if (!fn)
12202 return NULL_TREE;
12203
72dfb3f2 12204 /* Don't crash on sprintf (str1, "%s"). */
c2f47e15 12205 if (!orig)
72dfb3f2 12206 return NULL_TREE;
12207
4ee9c684 12208 /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2). */
4ee9c684 12209 if (!ignored)
12210 {
12211 retval = c_strlen (orig, 1);
12212 if (!retval || TREE_CODE (retval) != INTEGER_CST)
12213 return NULL_TREE;
12214 }
389dd41b 12215 call = build_call_expr_loc (loc, fn, 2, dest, orig);
4ee9c684 12216 }
12217
12218 if (call && retval)
12219 {
389dd41b 12220 retval = fold_convert_loc
b9a16870 12221 (loc, TREE_TYPE (TREE_TYPE (builtin_decl_implicit (BUILT_IN_SPRINTF))),
4ee9c684 12222 retval);
05abc81b 12223 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
4ee9c684 12224 }
12225 else
12226 return call;
12227}
0a39fd54 12228
750d7b16 12229/* Simplify a call to the snprintf builtin with arguments DEST, DESTSIZE,
12230 FMT, and ORIG. ORIG may be null if this is a 3-argument call. We don't
12231 attempt to simplify calls with more than 4 arguments.
12232
12233 Return NULL_TREE if no simplification was possible, otherwise return the
12234 simplified form of the call as a tree. If IGNORED is true, it means that
12235 the caller does not use the returned value of the function. */
12236
12237static tree
12238fold_builtin_snprintf (location_t loc, tree dest, tree destsize, tree fmt,
12239 tree orig, int ignored)
12240{
12241 tree call, retval;
12242 const char *fmt_str = NULL;
12243 unsigned HOST_WIDE_INT destlen;
12244
12245 /* Verify the required arguments in the original call. We deal with two
12246 types of snprintf() calls: 'snprintf (str, cst, fmt)' and
12247 'snprintf (dest, cst, "%s", orig)'. */
12248 if (!validate_arg (dest, POINTER_TYPE)
12249 || !validate_arg (destsize, INTEGER_TYPE)
12250 || !validate_arg (fmt, POINTER_TYPE))
12251 return NULL_TREE;
12252 if (orig && !validate_arg (orig, POINTER_TYPE))
12253 return NULL_TREE;
12254
12255 if (!host_integerp (destsize, 1))
12256 return NULL_TREE;
12257
12258 /* Check whether the format is a literal string constant. */
12259 fmt_str = c_getstr (fmt);
12260 if (fmt_str == NULL)
12261 return NULL_TREE;
12262
12263 call = NULL_TREE;
12264 retval = NULL_TREE;
12265
12266 if (!init_target_chars ())
12267 return NULL_TREE;
12268
12269 destlen = tree_low_cst (destsize, 1);
12270
12271 /* If the format doesn't contain % args or %%, use strcpy. */
12272 if (strchr (fmt_str, target_percent) == NULL)
12273 {
b9a16870 12274 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
750d7b16 12275 size_t len = strlen (fmt_str);
12276
12277 /* Don't optimize snprintf (buf, 4, "abc", ptr++). */
12278 if (orig)
12279 return NULL_TREE;
12280
12281 /* We could expand this as
12282 memcpy (str, fmt, cst - 1); str[cst - 1] = '\0';
12283 or to
12284 memcpy (str, fmt_with_nul_at_cstm1, cst);
12285 but in the former case that might increase code size
12286 and in the latter case grow .rodata section too much.
12287 So punt for now. */
12288 if (len >= destlen)
12289 return NULL_TREE;
12290
12291 if (!fn)
12292 return NULL_TREE;
12293
12294 /* Convert snprintf (str, cst, fmt) into strcpy (str, fmt) when
12295 'format' is known to contain no % formats and
12296 strlen (fmt) < cst. */
12297 call = build_call_expr_loc (loc, fn, 2, dest, fmt);
12298
12299 if (!ignored)
7002a1c8 12300 retval = build_int_cst (integer_type_node, strlen (fmt_str));
750d7b16 12301 }
12302
12303 /* If the format is "%s", use strcpy if the result isn't used. */
12304 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
12305 {
b9a16870 12306 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
750d7b16 12307 unsigned HOST_WIDE_INT origlen;
12308
12309 /* Don't crash on snprintf (str1, cst, "%s"). */
12310 if (!orig)
12311 return NULL_TREE;
12312
12313 retval = c_strlen (orig, 1);
12314 if (!retval || !host_integerp (retval, 1))
12315 return NULL_TREE;
12316
12317 origlen = tree_low_cst (retval, 1);
12318 /* We could expand this as
12319 memcpy (str1, str2, cst - 1); str1[cst - 1] = '\0';
12320 or to
12321 memcpy (str1, str2_with_nul_at_cstm1, cst);
12322 but in the former case that might increase code size
12323 and in the latter case grow .rodata section too much.
12324 So punt for now. */
12325 if (origlen >= destlen)
12326 return NULL_TREE;
12327
12328 /* Convert snprintf (str1, cst, "%s", str2) into
12329 strcpy (str1, str2) if strlen (str2) < cst. */
12330 if (!fn)
12331 return NULL_TREE;
12332
12333 call = build_call_expr_loc (loc, fn, 2, dest, orig);
12334
12335 if (ignored)
12336 retval = NULL_TREE;
12337 }
12338
12339 if (call && retval)
12340 {
b9a16870 12341 tree fn = builtin_decl_explicit (BUILT_IN_SNPRINTF);
1914d98e 12342 retval = fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fn)), retval);
750d7b16 12343 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
12344 }
12345 else
12346 return call;
12347}
12348
c2f47e15 12349/* Expand a call EXP to __builtin_object_size. */
0a39fd54 12350
12351rtx
12352expand_builtin_object_size (tree exp)
12353{
12354 tree ost;
12355 int object_size_type;
12356 tree fndecl = get_callee_fndecl (exp);
0a39fd54 12357
c2f47e15 12358 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
0a39fd54 12359 {
b8c23db3 12360 error ("%Kfirst argument of %D must be a pointer, second integer constant",
12361 exp, fndecl);
0a39fd54 12362 expand_builtin_trap ();
12363 return const0_rtx;
12364 }
12365
c2f47e15 12366 ost = CALL_EXPR_ARG (exp, 1);
0a39fd54 12367 STRIP_NOPS (ost);
12368
12369 if (TREE_CODE (ost) != INTEGER_CST
12370 || tree_int_cst_sgn (ost) < 0
12371 || compare_tree_int (ost, 3) > 0)
12372 {
b8c23db3 12373 error ("%Klast argument of %D is not integer constant between 0 and 3",
12374 exp, fndecl);
0a39fd54 12375 expand_builtin_trap ();
12376 return const0_rtx;
12377 }
12378
12379 object_size_type = tree_low_cst (ost, 0);
12380
12381 return object_size_type < 2 ? constm1_rtx : const0_rtx;
12382}
12383
12384/* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
12385 FCODE is the BUILT_IN_* to use.
c2f47e15 12386 Return NULL_RTX if we failed; the caller should emit a normal call,
0a39fd54 12387 otherwise try to get the result in TARGET, if convenient (and in
12388 mode MODE if that's convenient). */
12389
12390static rtx
12391expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
12392 enum built_in_function fcode)
12393{
0a39fd54 12394 tree dest, src, len, size;
12395
c2f47e15 12396 if (!validate_arglist (exp,
0a39fd54 12397 POINTER_TYPE,
12398 fcode == BUILT_IN_MEMSET_CHK
12399 ? INTEGER_TYPE : POINTER_TYPE,
12400 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
c2f47e15 12401 return NULL_RTX;
0a39fd54 12402
c2f47e15 12403 dest = CALL_EXPR_ARG (exp, 0);
12404 src = CALL_EXPR_ARG (exp, 1);
12405 len = CALL_EXPR_ARG (exp, 2);
12406 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 12407
12408 if (! host_integerp (size, 1))
c2f47e15 12409 return NULL_RTX;
0a39fd54 12410
12411 if (host_integerp (len, 1) || integer_all_onesp (size))
12412 {
12413 tree fn;
12414
12415 if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
12416 {
b430e8d9 12417 warning_at (tree_nonartificial_location (exp),
12418 0, "%Kcall to %D will always overflow destination buffer",
12419 exp, get_callee_fndecl (exp));
c2f47e15 12420 return NULL_RTX;
0a39fd54 12421 }
12422
0a39fd54 12423 fn = NULL_TREE;
12424 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
12425 mem{cpy,pcpy,move,set} is available. */
12426 switch (fcode)
12427 {
12428 case BUILT_IN_MEMCPY_CHK:
b9a16870 12429 fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
0a39fd54 12430 break;
12431 case BUILT_IN_MEMPCPY_CHK:
b9a16870 12432 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
0a39fd54 12433 break;
12434 case BUILT_IN_MEMMOVE_CHK:
b9a16870 12435 fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
0a39fd54 12436 break;
12437 case BUILT_IN_MEMSET_CHK:
b9a16870 12438 fn = builtin_decl_explicit (BUILT_IN_MEMSET);
0a39fd54 12439 break;
12440 default:
12441 break;
12442 }
12443
12444 if (! fn)
c2f47e15 12445 return NULL_RTX;
0a39fd54 12446
0568e9c1 12447 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 3, dest, src, len);
a65c4d64 12448 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
12449 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0a39fd54 12450 return expand_expr (fn, target, mode, EXPAND_NORMAL);
12451 }
12452 else if (fcode == BUILT_IN_MEMSET_CHK)
c2f47e15 12453 return NULL_RTX;
0a39fd54 12454 else
12455 {
957d0361 12456 unsigned int dest_align = get_pointer_alignment (dest);
0a39fd54 12457
12458 /* If DEST is not a pointer type, call the normal function. */
12459 if (dest_align == 0)
c2f47e15 12460 return NULL_RTX;
0a39fd54 12461
12462 /* If SRC and DEST are the same (and not volatile), do nothing. */
12463 if (operand_equal_p (src, dest, 0))
12464 {
12465 tree expr;
12466
12467 if (fcode != BUILT_IN_MEMPCPY_CHK)
12468 {
12469 /* Evaluate and ignore LEN in case it has side-effects. */
12470 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
12471 return expand_expr (dest, target, mode, EXPAND_NORMAL);
12472 }
12473
2cc66f2a 12474 expr = fold_build_pointer_plus (dest, len);
0a39fd54 12475 return expand_expr (expr, target, mode, EXPAND_NORMAL);
12476 }
12477
12478 /* __memmove_chk special case. */
12479 if (fcode == BUILT_IN_MEMMOVE_CHK)
12480 {
957d0361 12481 unsigned int src_align = get_pointer_alignment (src);
0a39fd54 12482
12483 if (src_align == 0)
c2f47e15 12484 return NULL_RTX;
0a39fd54 12485
12486 /* If src is categorized for a readonly section we can use
12487 normal __memcpy_chk. */
12488 if (readonly_data_expr (src))
12489 {
b9a16870 12490 tree fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
0a39fd54 12491 if (!fn)
c2f47e15 12492 return NULL_RTX;
0568e9c1 12493 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 4,
12494 dest, src, len, size);
a65c4d64 12495 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
12496 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0a39fd54 12497 return expand_expr (fn, target, mode, EXPAND_NORMAL);
12498 }
12499 }
c2f47e15 12500 return NULL_RTX;
0a39fd54 12501 }
12502}
12503
12504/* Emit warning if a buffer overflow is detected at compile time. */
12505
12506static void
12507maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
12508{
c2f47e15 12509 int is_strlen = 0;
0a39fd54 12510 tree len, size;
b430e8d9 12511 location_t loc = tree_nonartificial_location (exp);
0a39fd54 12512
12513 switch (fcode)
12514 {
12515 case BUILT_IN_STRCPY_CHK:
12516 case BUILT_IN_STPCPY_CHK:
12517 /* For __strcat_chk the warning will be emitted only if overflowing
12518 by at least strlen (dest) + 1 bytes. */
12519 case BUILT_IN_STRCAT_CHK:
c2f47e15 12520 len = CALL_EXPR_ARG (exp, 1);
12521 size = CALL_EXPR_ARG (exp, 2);
0a39fd54 12522 is_strlen = 1;
12523 break;
b356dfef 12524 case BUILT_IN_STRNCAT_CHK:
0a39fd54 12525 case BUILT_IN_STRNCPY_CHK:
1063acde 12526 case BUILT_IN_STPNCPY_CHK:
c2f47e15 12527 len = CALL_EXPR_ARG (exp, 2);
12528 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 12529 break;
12530 case BUILT_IN_SNPRINTF_CHK:
12531 case BUILT_IN_VSNPRINTF_CHK:
c2f47e15 12532 len = CALL_EXPR_ARG (exp, 1);
12533 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 12534 break;
12535 default:
12536 gcc_unreachable ();
12537 }
12538
0a39fd54 12539 if (!len || !size)
12540 return;
12541
0a39fd54 12542 if (! host_integerp (size, 1) || integer_all_onesp (size))
12543 return;
12544
12545 if (is_strlen)
12546 {
12547 len = c_strlen (len, 1);
12548 if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
12549 return;
12550 }
b356dfef 12551 else if (fcode == BUILT_IN_STRNCAT_CHK)
12552 {
c2f47e15 12553 tree src = CALL_EXPR_ARG (exp, 1);
b356dfef 12554 if (! src || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
12555 return;
12556 src = c_strlen (src, 1);
12557 if (! src || ! host_integerp (src, 1))
12558 {
b430e8d9 12559 warning_at (loc, 0, "%Kcall to %D might overflow destination buffer",
12560 exp, get_callee_fndecl (exp));
b356dfef 12561 return;
12562 }
12563 else if (tree_int_cst_lt (src, size))
12564 return;
12565 }
0a39fd54 12566 else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
12567 return;
12568
b430e8d9 12569 warning_at (loc, 0, "%Kcall to %D will always overflow destination buffer",
12570 exp, get_callee_fndecl (exp));
0a39fd54 12571}
12572
12573/* Emit warning if a buffer overflow is detected at compile time
12574 in __sprintf_chk/__vsprintf_chk calls. */
12575
12576static void
12577maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
12578{
1e4adcfc 12579 tree size, len, fmt;
0a39fd54 12580 const char *fmt_str;
c2f47e15 12581 int nargs = call_expr_nargs (exp);
0a39fd54 12582
12583 /* Verify the required arguments in the original call. */
48e1416a 12584
c2f47e15 12585 if (nargs < 4)
0a39fd54 12586 return;
c2f47e15 12587 size = CALL_EXPR_ARG (exp, 2);
12588 fmt = CALL_EXPR_ARG (exp, 3);
0a39fd54 12589
12590 if (! host_integerp (size, 1) || integer_all_onesp (size))
12591 return;
12592
12593 /* Check whether the format is a literal string constant. */
12594 fmt_str = c_getstr (fmt);
12595 if (fmt_str == NULL)
12596 return;
12597
d4473c84 12598 if (!init_target_chars ())
99eabcc1 12599 return;
12600
0a39fd54 12601 /* If the format doesn't contain % args or %%, we know its size. */
99eabcc1 12602 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 12603 len = build_int_cstu (size_type_node, strlen (fmt_str));
12604 /* If the format is "%s" and first ... argument is a string literal,
12605 we know it too. */
c2f47e15 12606 else if (fcode == BUILT_IN_SPRINTF_CHK
12607 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12608 {
12609 tree arg;
12610
c2f47e15 12611 if (nargs < 5)
0a39fd54 12612 return;
c2f47e15 12613 arg = CALL_EXPR_ARG (exp, 4);
0a39fd54 12614 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
12615 return;
12616
12617 len = c_strlen (arg, 1);
12618 if (!len || ! host_integerp (len, 1))
12619 return;
12620 }
12621 else
12622 return;
12623
12624 if (! tree_int_cst_lt (len, size))
b430e8d9 12625 warning_at (tree_nonartificial_location (exp),
12626 0, "%Kcall to %D will always overflow destination buffer",
12627 exp, get_callee_fndecl (exp));
0a39fd54 12628}
12629
2c281b15 12630/* Emit warning if a free is called with address of a variable. */
12631
12632static void
12633maybe_emit_free_warning (tree exp)
12634{
12635 tree arg = CALL_EXPR_ARG (exp, 0);
12636
12637 STRIP_NOPS (arg);
12638 if (TREE_CODE (arg) != ADDR_EXPR)
12639 return;
12640
12641 arg = get_base_address (TREE_OPERAND (arg, 0));
182cf5a9 12642 if (arg == NULL || INDIRECT_REF_P (arg) || TREE_CODE (arg) == MEM_REF)
2c281b15 12643 return;
12644
12645 if (SSA_VAR_P (arg))
f74ea1c2 12646 warning_at (tree_nonartificial_location (exp), OPT_Wfree_nonheap_object,
12647 "%Kattempt to free a non-heap object %qD", exp, arg);
2c281b15 12648 else
f74ea1c2 12649 warning_at (tree_nonartificial_location (exp), OPT_Wfree_nonheap_object,
12650 "%Kattempt to free a non-heap object", exp);
2c281b15 12651}
12652
c2f47e15 12653/* Fold a call to __builtin_object_size with arguments PTR and OST,
12654 if possible. */
0a39fd54 12655
12656tree
c2f47e15 12657fold_builtin_object_size (tree ptr, tree ost)
0a39fd54 12658{
a6caa15f 12659 unsigned HOST_WIDE_INT bytes;
0a39fd54 12660 int object_size_type;
12661
c2f47e15 12662 if (!validate_arg (ptr, POINTER_TYPE)
12663 || !validate_arg (ost, INTEGER_TYPE))
12664 return NULL_TREE;
0a39fd54 12665
0a39fd54 12666 STRIP_NOPS (ost);
12667
12668 if (TREE_CODE (ost) != INTEGER_CST
12669 || tree_int_cst_sgn (ost) < 0
12670 || compare_tree_int (ost, 3) > 0)
c2f47e15 12671 return NULL_TREE;
0a39fd54 12672
12673 object_size_type = tree_low_cst (ost, 0);
12674
12675 /* __builtin_object_size doesn't evaluate side-effects in its arguments;
12676 if there are any side-effects, it returns (size_t) -1 for types 0 and 1
12677 and (size_t) 0 for types 2 and 3. */
12678 if (TREE_SIDE_EFFECTS (ptr))
697bbc3f 12679 return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
0a39fd54 12680
12681 if (TREE_CODE (ptr) == ADDR_EXPR)
a6caa15f 12682 {
12683 bytes = compute_builtin_object_size (ptr, object_size_type);
12684 if (double_int_fits_to_tree_p (size_type_node,
12685 uhwi_to_double_int (bytes)))
12686 return build_int_cstu (size_type_node, bytes);
12687 }
0a39fd54 12688 else if (TREE_CODE (ptr) == SSA_NAME)
12689 {
0a39fd54 12690 /* If object size is not known yet, delay folding until
12691 later. Maybe subsequent passes will help determining
12692 it. */
12693 bytes = compute_builtin_object_size (ptr, object_size_type);
a6caa15f 12694 if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2 ? -1 : 0)
12695 && double_int_fits_to_tree_p (size_type_node,
12696 uhwi_to_double_int (bytes)))
12697 return build_int_cstu (size_type_node, bytes);
0a39fd54 12698 }
12699
a6caa15f 12700 return NULL_TREE;
0a39fd54 12701}
12702
12703/* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
c2f47e15 12704 DEST, SRC, LEN, and SIZE are the arguments to the call.
0a39fd54 12705 IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_*
12706 code of the builtin. If MAXLEN is not NULL, it is maximum length
12707 passed as third argument. */
12708
12709tree
389dd41b 12710fold_builtin_memory_chk (location_t loc, tree fndecl,
c2f47e15 12711 tree dest, tree src, tree len, tree size,
12712 tree maxlen, bool ignore,
0a39fd54 12713 enum built_in_function fcode)
12714{
c2f47e15 12715 tree fn;
0a39fd54 12716
c2f47e15 12717 if (!validate_arg (dest, POINTER_TYPE)
12718 || !validate_arg (src,
12719 (fcode == BUILT_IN_MEMSET_CHK
12720 ? INTEGER_TYPE : POINTER_TYPE))
12721 || !validate_arg (len, INTEGER_TYPE)
12722 || !validate_arg (size, INTEGER_TYPE))
12723 return NULL_TREE;
0a39fd54 12724
12725 /* If SRC and DEST are the same (and not volatile), return DEST
12726 (resp. DEST+LEN for __mempcpy_chk). */
12727 if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
12728 {
12729 if (fcode != BUILT_IN_MEMPCPY_CHK)
389dd41b 12730 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
12731 dest, len);
0a39fd54 12732 else
12733 {
2cc66f2a 12734 tree temp = fold_build_pointer_plus_loc (loc, dest, len);
389dd41b 12735 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), temp);
0a39fd54 12736 }
12737 }
12738
12739 if (! host_integerp (size, 1))
c2f47e15 12740 return NULL_TREE;
0a39fd54 12741
12742 if (! integer_all_onesp (size))
12743 {
12744 if (! host_integerp (len, 1))
12745 {
12746 /* If LEN is not constant, try MAXLEN too.
12747 For MAXLEN only allow optimizing into non-_ocs function
12748 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12749 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
12750 {
12751 if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
12752 {
12753 /* (void) __mempcpy_chk () can be optimized into
12754 (void) __memcpy_chk (). */
b9a16870 12755 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
0a39fd54 12756 if (!fn)
c2f47e15 12757 return NULL_TREE;
0a39fd54 12758
389dd41b 12759 return build_call_expr_loc (loc, fn, 4, dest, src, len, size);
0a39fd54 12760 }
c2f47e15 12761 return NULL_TREE;
0a39fd54 12762 }
0a39fd54 12763 }
ad89623c 12764 else
12765 maxlen = len;
0a39fd54 12766
ad89623c 12767 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12768 return NULL_TREE;
0a39fd54 12769 }
12770
0a39fd54 12771 fn = NULL_TREE;
12772 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
12773 mem{cpy,pcpy,move,set} is available. */
12774 switch (fcode)
12775 {
12776 case BUILT_IN_MEMCPY_CHK:
b9a16870 12777 fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
0a39fd54 12778 break;
12779 case BUILT_IN_MEMPCPY_CHK:
b9a16870 12780 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
0a39fd54 12781 break;
12782 case BUILT_IN_MEMMOVE_CHK:
b9a16870 12783 fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
0a39fd54 12784 break;
12785 case BUILT_IN_MEMSET_CHK:
b9a16870 12786 fn = builtin_decl_explicit (BUILT_IN_MEMSET);
0a39fd54 12787 break;
12788 default:
12789 break;
12790 }
12791
12792 if (!fn)
c2f47e15 12793 return NULL_TREE;
0a39fd54 12794
389dd41b 12795 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12796}
12797
12798/* Fold a call to the __st[rp]cpy_chk builtin.
c2f47e15 12799 DEST, SRC, and SIZE are the arguments to the call.
12800 IGNORE is true if return value can be ignored. FCODE is the BUILT_IN_*
0a39fd54 12801 code of the builtin. If MAXLEN is not NULL, it is maximum length of
12802 strings passed as second argument. */
12803
12804tree
389dd41b 12805fold_builtin_stxcpy_chk (location_t loc, tree fndecl, tree dest,
12806 tree src, tree size,
c2f47e15 12807 tree maxlen, bool ignore,
0a39fd54 12808 enum built_in_function fcode)
12809{
c2f47e15 12810 tree len, fn;
0a39fd54 12811
c2f47e15 12812 if (!validate_arg (dest, POINTER_TYPE)
12813 || !validate_arg (src, POINTER_TYPE)
12814 || !validate_arg (size, INTEGER_TYPE))
12815 return NULL_TREE;
0a39fd54 12816
12817 /* If SRC and DEST are the same (and not volatile), return DEST. */
12818 if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
389dd41b 12819 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
a0c938f0 12820
0a39fd54 12821 if (! host_integerp (size, 1))
c2f47e15 12822 return NULL_TREE;
0a39fd54 12823
12824 if (! integer_all_onesp (size))
12825 {
12826 len = c_strlen (src, 1);
12827 if (! len || ! host_integerp (len, 1))
12828 {
12829 /* If LEN is not constant, try MAXLEN too.
12830 For MAXLEN only allow optimizing into non-_ocs function
12831 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12832 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
12833 {
12834 if (fcode == BUILT_IN_STPCPY_CHK)
12835 {
12836 if (! ignore)
c2f47e15 12837 return NULL_TREE;
0a39fd54 12838
12839 /* If return value of __stpcpy_chk is ignored,
12840 optimize into __strcpy_chk. */
b9a16870 12841 fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
0a39fd54 12842 if (!fn)
c2f47e15 12843 return NULL_TREE;
0a39fd54 12844
389dd41b 12845 return build_call_expr_loc (loc, fn, 3, dest, src, size);
0a39fd54 12846 }
12847
12848 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 12849 return NULL_TREE;
0a39fd54 12850
12851 /* If c_strlen returned something, but not a constant,
12852 transform __strcpy_chk into __memcpy_chk. */
b9a16870 12853 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
0a39fd54 12854 if (!fn)
c2f47e15 12855 return NULL_TREE;
0a39fd54 12856
bd6dcc04 12857 len = fold_convert_loc (loc, size_type_node, len);
12858 len = size_binop_loc (loc, PLUS_EXPR, len,
12859 build_int_cst (size_type_node, 1));
389dd41b 12860 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
12861 build_call_expr_loc (loc, fn, 4,
12862 dest, src, len, size));
0a39fd54 12863 }
0a39fd54 12864 }
ad89623c 12865 else
12866 maxlen = len;
12867
12868 if (! tree_int_cst_lt (maxlen, size))
c2f47e15 12869 return NULL_TREE;
0a39fd54 12870 }
12871
0a39fd54 12872 /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available. */
b9a16870 12873 fn = builtin_decl_explicit (fcode == BUILT_IN_STPCPY_CHK
12874 ? BUILT_IN_STPCPY : BUILT_IN_STRCPY);
0a39fd54 12875 if (!fn)
c2f47e15 12876 return NULL_TREE;
0a39fd54 12877
389dd41b 12878 return build_call_expr_loc (loc, fn, 2, dest, src);
0a39fd54 12879}
12880
1063acde 12881/* Fold a call to the __st{r,p}ncpy_chk builtin. DEST, SRC, LEN, and SIZE
c2f47e15 12882 are the arguments to the call. If MAXLEN is not NULL, it is maximum
1063acde 12883 length passed as third argument. IGNORE is true if return value can be
12884 ignored. FCODE is the BUILT_IN_* code of the builtin. */
0a39fd54 12885
12886tree
1063acde 12887fold_builtin_stxncpy_chk (location_t loc, tree dest, tree src,
12888 tree len, tree size, tree maxlen, bool ignore,
12889 enum built_in_function fcode)
0a39fd54 12890{
c2f47e15 12891 tree fn;
0a39fd54 12892
c2f47e15 12893 if (!validate_arg (dest, POINTER_TYPE)
12894 || !validate_arg (src, POINTER_TYPE)
12895 || !validate_arg (len, INTEGER_TYPE)
12896 || !validate_arg (size, INTEGER_TYPE))
12897 return NULL_TREE;
0a39fd54 12898
1063acde 12899 if (fcode == BUILT_IN_STPNCPY_CHK && ignore)
12900 {
12901 /* If return value of __stpncpy_chk is ignored,
12902 optimize into __strncpy_chk. */
12903 fn = builtin_decl_explicit (BUILT_IN_STRNCPY_CHK);
12904 if (fn)
12905 return build_call_expr_loc (loc, fn, 4, dest, src, len, size);
12906 }
12907
0a39fd54 12908 if (! host_integerp (size, 1))
c2f47e15 12909 return NULL_TREE;
0a39fd54 12910
12911 if (! integer_all_onesp (size))
12912 {
12913 if (! host_integerp (len, 1))
12914 {
12915 /* If LEN is not constant, try MAXLEN too.
12916 For MAXLEN only allow optimizing into non-_ocs function
12917 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12918 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 12919 return NULL_TREE;
0a39fd54 12920 }
ad89623c 12921 else
12922 maxlen = len;
0a39fd54 12923
ad89623c 12924 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12925 return NULL_TREE;
0a39fd54 12926 }
12927
1063acde 12928 /* If __builtin_st{r,p}ncpy_chk is used, assume st{r,p}ncpy is available. */
12929 fn = builtin_decl_explicit (fcode == BUILT_IN_STPNCPY_CHK
12930 ? BUILT_IN_STPNCPY : BUILT_IN_STRNCPY);
0a39fd54 12931 if (!fn)
c2f47e15 12932 return NULL_TREE;
0a39fd54 12933
389dd41b 12934 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12935}
12936
c2f47e15 12937/* Fold a call to the __strcat_chk builtin FNDECL. DEST, SRC, and SIZE
12938 are the arguments to the call. */
0a39fd54 12939
12940static tree
389dd41b 12941fold_builtin_strcat_chk (location_t loc, tree fndecl, tree dest,
12942 tree src, tree size)
0a39fd54 12943{
c2f47e15 12944 tree fn;
0a39fd54 12945 const char *p;
12946
c2f47e15 12947 if (!validate_arg (dest, POINTER_TYPE)
12948 || !validate_arg (src, POINTER_TYPE)
12949 || !validate_arg (size, INTEGER_TYPE))
12950 return NULL_TREE;
0a39fd54 12951
12952 p = c_getstr (src);
12953 /* If the SRC parameter is "", return DEST. */
12954 if (p && *p == '\0')
389dd41b 12955 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
0a39fd54 12956
12957 if (! host_integerp (size, 1) || ! integer_all_onesp (size))
c2f47e15 12958 return NULL_TREE;
0a39fd54 12959
12960 /* If __builtin_strcat_chk is used, assume strcat is available. */
b9a16870 12961 fn = builtin_decl_explicit (BUILT_IN_STRCAT);
0a39fd54 12962 if (!fn)
c2f47e15 12963 return NULL_TREE;
0a39fd54 12964
389dd41b 12965 return build_call_expr_loc (loc, fn, 2, dest, src);
0a39fd54 12966}
12967
c2f47e15 12968/* Fold a call to the __strncat_chk builtin with arguments DEST, SRC,
12969 LEN, and SIZE. */
0a39fd54 12970
12971static tree
389dd41b 12972fold_builtin_strncat_chk (location_t loc, tree fndecl,
c2f47e15 12973 tree dest, tree src, tree len, tree size)
0a39fd54 12974{
c2f47e15 12975 tree fn;
0a39fd54 12976 const char *p;
12977
c2f47e15 12978 if (!validate_arg (dest, POINTER_TYPE)
12979 || !validate_arg (src, POINTER_TYPE)
12980 || !validate_arg (size, INTEGER_TYPE)
12981 || !validate_arg (size, INTEGER_TYPE))
12982 return NULL_TREE;
0a39fd54 12983
12984 p = c_getstr (src);
12985 /* If the SRC parameter is "" or if LEN is 0, return DEST. */
12986 if (p && *p == '\0')
389dd41b 12987 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
0a39fd54 12988 else if (integer_zerop (len))
389dd41b 12989 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
0a39fd54 12990
12991 if (! host_integerp (size, 1))
c2f47e15 12992 return NULL_TREE;
0a39fd54 12993
12994 if (! integer_all_onesp (size))
12995 {
12996 tree src_len = c_strlen (src, 1);
12997 if (src_len
12998 && host_integerp (src_len, 1)
12999 && host_integerp (len, 1)
13000 && ! tree_int_cst_lt (len, src_len))
13001 {
13002 /* If LEN >= strlen (SRC), optimize into __strcat_chk. */
b9a16870 13003 fn = builtin_decl_explicit (BUILT_IN_STRCAT_CHK);
0a39fd54 13004 if (!fn)
c2f47e15 13005 return NULL_TREE;
0a39fd54 13006
389dd41b 13007 return build_call_expr_loc (loc, fn, 3, dest, src, size);
0a39fd54 13008 }
c2f47e15 13009 return NULL_TREE;
0a39fd54 13010 }
13011
0a39fd54 13012 /* If __builtin_strncat_chk is used, assume strncat is available. */
b9a16870 13013 fn = builtin_decl_explicit (BUILT_IN_STRNCAT);
0a39fd54 13014 if (!fn)
c2f47e15 13015 return NULL_TREE;
0a39fd54 13016
389dd41b 13017 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 13018}
13019
af1409ad 13020/* Fold a call EXP to __{,v}sprintf_chk having NARGS passed as ARGS.
13021 Return NULL_TREE if a normal call should be emitted rather than
13022 expanding the function inline. FCODE is either BUILT_IN_SPRINTF_CHK
13023 or BUILT_IN_VSPRINTF_CHK. */
0a39fd54 13024
13025static tree
af1409ad 13026fold_builtin_sprintf_chk_1 (location_t loc, int nargs, tree *args,
13027 enum built_in_function fcode)
0a39fd54 13028{
13029 tree dest, size, len, fn, fmt, flag;
13030 const char *fmt_str;
13031
13032 /* Verify the required arguments in the original call. */
c2f47e15 13033 if (nargs < 4)
13034 return NULL_TREE;
af1409ad 13035 dest = args[0];
c2f47e15 13036 if (!validate_arg (dest, POINTER_TYPE))
13037 return NULL_TREE;
af1409ad 13038 flag = args[1];
c2f47e15 13039 if (!validate_arg (flag, INTEGER_TYPE))
13040 return NULL_TREE;
af1409ad 13041 size = args[2];
c2f47e15 13042 if (!validate_arg (size, INTEGER_TYPE))
13043 return NULL_TREE;
af1409ad 13044 fmt = args[3];
c2f47e15 13045 if (!validate_arg (fmt, POINTER_TYPE))
13046 return NULL_TREE;
0a39fd54 13047
13048 if (! host_integerp (size, 1))
c2f47e15 13049 return NULL_TREE;
0a39fd54 13050
13051 len = NULL_TREE;
13052
d4473c84 13053 if (!init_target_chars ())
c2f47e15 13054 return NULL_TREE;
99eabcc1 13055
0a39fd54 13056 /* Check whether the format is a literal string constant. */
13057 fmt_str = c_getstr (fmt);
13058 if (fmt_str != NULL)
13059 {
13060 /* If the format doesn't contain % args or %%, we know the size. */
99eabcc1 13061 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 13062 {
c2f47e15 13063 if (fcode != BUILT_IN_SPRINTF_CHK || nargs == 4)
0a39fd54 13064 len = build_int_cstu (size_type_node, strlen (fmt_str));
13065 }
13066 /* If the format is "%s" and first ... argument is a string literal,
13067 we know the size too. */
c2f47e15 13068 else if (fcode == BUILT_IN_SPRINTF_CHK
13069 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 13070 {
13071 tree arg;
13072
c2f47e15 13073 if (nargs == 5)
0a39fd54 13074 {
af1409ad 13075 arg = args[4];
c2f47e15 13076 if (validate_arg (arg, POINTER_TYPE))
0a39fd54 13077 {
13078 len = c_strlen (arg, 1);
13079 if (! len || ! host_integerp (len, 1))
13080 len = NULL_TREE;
13081 }
13082 }
13083 }
13084 }
13085
13086 if (! integer_all_onesp (size))
13087 {
13088 if (! len || ! tree_int_cst_lt (len, size))
c2f47e15 13089 return NULL_TREE;
0a39fd54 13090 }
13091
13092 /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
13093 or if format doesn't contain % chars or is "%s". */
13094 if (! integer_zerop (flag))
13095 {
13096 if (fmt_str == NULL)
c2f47e15 13097 return NULL_TREE;
13098 if (strchr (fmt_str, target_percent) != NULL
13099 && strcmp (fmt_str, target_percent_s))
13100 return NULL_TREE;
0a39fd54 13101 }
13102
0a39fd54 13103 /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
b9a16870 13104 fn = builtin_decl_explicit (fcode == BUILT_IN_VSPRINTF_CHK
13105 ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF);
0a39fd54 13106 if (!fn)
c2f47e15 13107 return NULL_TREE;
0a39fd54 13108
af1409ad 13109 return rewrite_call_expr_array (loc, nargs, args, 4, fn, 2, dest, fmt);
0a39fd54 13110}
13111
af1409ad 13112/* Fold a call EXP to __{,v}sprintf_chk. Return NULL_TREE if
0a39fd54 13113 a normal call should be emitted rather than expanding the function
af1409ad 13114 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
13115
13116static tree
13117fold_builtin_sprintf_chk (location_t loc, tree exp,
13118 enum built_in_function fcode)
13119{
13120 return fold_builtin_sprintf_chk_1 (loc, call_expr_nargs (exp),
13121 CALL_EXPR_ARGP (exp), fcode);
13122}
13123
13124/* Fold a call EXP to {,v}snprintf having NARGS passed as ARGS. Return
13125 NULL_TREE if a normal call should be emitted rather than expanding
13126 the function inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
0a39fd54 13127 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
13128 passed as second argument. */
13129
af1409ad 13130static tree
13131fold_builtin_snprintf_chk_1 (location_t loc, int nargs, tree *args,
13132 tree maxlen, enum built_in_function fcode)
0a39fd54 13133{
13134 tree dest, size, len, fn, fmt, flag;
13135 const char *fmt_str;
13136
13137 /* Verify the required arguments in the original call. */
af1409ad 13138 if (nargs < 5)
c2f47e15 13139 return NULL_TREE;
af1409ad 13140 dest = args[0];
c2f47e15 13141 if (!validate_arg (dest, POINTER_TYPE))
13142 return NULL_TREE;
af1409ad 13143 len = args[1];
c2f47e15 13144 if (!validate_arg (len, INTEGER_TYPE))
13145 return NULL_TREE;
af1409ad 13146 flag = args[2];
c2f47e15 13147 if (!validate_arg (flag, INTEGER_TYPE))
13148 return NULL_TREE;
af1409ad 13149 size = args[3];
c2f47e15 13150 if (!validate_arg (size, INTEGER_TYPE))
13151 return NULL_TREE;
af1409ad 13152 fmt = args[4];
c2f47e15 13153 if (!validate_arg (fmt, POINTER_TYPE))
13154 return NULL_TREE;
0a39fd54 13155
13156 if (! host_integerp (size, 1))
c2f47e15 13157 return NULL_TREE;
0a39fd54 13158
13159 if (! integer_all_onesp (size))
13160 {
13161 if (! host_integerp (len, 1))
13162 {
13163 /* If LEN is not constant, try MAXLEN too.
13164 For MAXLEN only allow optimizing into non-_ocs function
13165 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
13166 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 13167 return NULL_TREE;
0a39fd54 13168 }
ad89623c 13169 else
13170 maxlen = len;
0a39fd54 13171
ad89623c 13172 if (tree_int_cst_lt (size, maxlen))
c2f47e15 13173 return NULL_TREE;
0a39fd54 13174 }
13175
d4473c84 13176 if (!init_target_chars ())
c2f47e15 13177 return NULL_TREE;
99eabcc1 13178
0a39fd54 13179 /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
13180 or if format doesn't contain % chars or is "%s". */
13181 if (! integer_zerop (flag))
13182 {
13183 fmt_str = c_getstr (fmt);
13184 if (fmt_str == NULL)
c2f47e15 13185 return NULL_TREE;
13186 if (strchr (fmt_str, target_percent) != NULL
13187 && strcmp (fmt_str, target_percent_s))
13188 return NULL_TREE;
0a39fd54 13189 }
13190
0a39fd54 13191 /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
13192 available. */
b9a16870 13193 fn = builtin_decl_explicit (fcode == BUILT_IN_VSNPRINTF_CHK
13194 ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF);
0a39fd54 13195 if (!fn)
c2f47e15 13196 return NULL_TREE;
0a39fd54 13197
af1409ad 13198 return rewrite_call_expr_array (loc, nargs, args, 5, fn, 3, dest, len, fmt);
13199}
13200
13201/* Fold a call EXP to {,v}snprintf. Return NULL_TREE if
13202 a normal call should be emitted rather than expanding the function
13203 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
13204 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
13205 passed as second argument. */
13206
13207tree
13208fold_builtin_snprintf_chk (location_t loc, tree exp, tree maxlen,
13209 enum built_in_function fcode)
13210{
13211 return fold_builtin_snprintf_chk_1 (loc, call_expr_nargs (exp),
13212 CALL_EXPR_ARGP (exp), maxlen, fcode);
0a39fd54 13213}
13214
13215/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 13216 FMT and ARG are the arguments to the call; we don't fold cases with
13217 more than 2 arguments, and ARG may be null if this is a 1-argument case.
0a39fd54 13218
c2f47e15 13219 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 13220 simplified form of the call as a tree. FCODE is the BUILT_IN_*
13221 code of the function to be simplified. */
13222
13223static tree
389dd41b 13224fold_builtin_printf (location_t loc, tree fndecl, tree fmt,
13225 tree arg, bool ignore,
0a39fd54 13226 enum built_in_function fcode)
13227{
c2f47e15 13228 tree fn_putchar, fn_puts, newarg, call = NULL_TREE;
0a39fd54 13229 const char *fmt_str = NULL;
13230
13231 /* If the return value is used, don't do the transformation. */
13232 if (! ignore)
c2f47e15 13233 return NULL_TREE;
0a39fd54 13234
13235 /* Verify the required arguments in the original call. */
c2f47e15 13236 if (!validate_arg (fmt, POINTER_TYPE))
13237 return NULL_TREE;
0a39fd54 13238
13239 /* Check whether the format is a literal string constant. */
13240 fmt_str = c_getstr (fmt);
13241 if (fmt_str == NULL)
13242 return NULL_TREE;
13243
13244 if (fcode == BUILT_IN_PRINTF_UNLOCKED)
13245 {
6d77ed92 13246 /* If we're using an unlocked function, assume the other
13247 unlocked functions exist explicitly. */
b9a16870 13248 fn_putchar = builtin_decl_explicit (BUILT_IN_PUTCHAR_UNLOCKED);
13249 fn_puts = builtin_decl_explicit (BUILT_IN_PUTS_UNLOCKED);
0a39fd54 13250 }
13251 else
13252 {
b9a16870 13253 fn_putchar = builtin_decl_implicit (BUILT_IN_PUTCHAR);
13254 fn_puts = builtin_decl_implicit (BUILT_IN_PUTS);
0a39fd54 13255 }
13256
d4473c84 13257 if (!init_target_chars ())
c2f47e15 13258 return NULL_TREE;
a0c938f0 13259
c2f47e15 13260 if (strcmp (fmt_str, target_percent_s) == 0
13261 || strchr (fmt_str, target_percent) == NULL)
0a39fd54 13262 {
13263 const char *str;
13264
99eabcc1 13265 if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 13266 {
13267 if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 13268 return NULL_TREE;
0a39fd54 13269
c2f47e15 13270 if (!arg || !validate_arg (arg, POINTER_TYPE))
13271 return NULL_TREE;
0a39fd54 13272
c2f47e15 13273 str = c_getstr (arg);
0a39fd54 13274 if (str == NULL)
c2f47e15 13275 return NULL_TREE;
0a39fd54 13276 }
13277 else
13278 {
13279 /* The format specifier doesn't contain any '%' characters. */
13280 if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
c2f47e15 13281 && arg)
13282 return NULL_TREE;
0a39fd54 13283 str = fmt_str;
13284 }
13285
13286 /* If the string was "", printf does nothing. */
13287 if (str[0] == '\0')
13288 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
13289
13290 /* If the string has length of 1, call putchar. */
13291 if (str[1] == '\0')
13292 {
13293 /* Given printf("c"), (where c is any one character,)
13294 convert "c"[0] to an int and pass that to the replacement
13295 function. */
7002a1c8 13296 newarg = build_int_cst (integer_type_node, str[0]);
c2f47e15 13297 if (fn_putchar)
389dd41b 13298 call = build_call_expr_loc (loc, fn_putchar, 1, newarg);
0a39fd54 13299 }
13300 else
13301 {
13302 /* If the string was "string\n", call puts("string"). */
13303 size_t len = strlen (str);
663dbd5e 13304 if ((unsigned char)str[len - 1] == target_newline
13305 && (size_t) (int) len == len
13306 && (int) len > 0)
0a39fd54 13307 {
663dbd5e 13308 char *newstr;
13309 tree offset_node, string_cst;
13310
0a39fd54 13311 /* Create a NUL-terminated string that's one char shorter
13312 than the original, stripping off the trailing '\n'. */
663dbd5e 13313 newarg = build_string_literal (len, str);
13314 string_cst = string_constant (newarg, &offset_node);
13315 gcc_checking_assert (string_cst
13316 && (TREE_STRING_LENGTH (string_cst)
13317 == (int) len)
13318 && integer_zerop (offset_node)
13319 && (unsigned char)
13320 TREE_STRING_POINTER (string_cst)[len - 1]
13321 == target_newline);
13322 /* build_string_literal creates a new STRING_CST,
13323 modify it in place to avoid double copying. */
13324 newstr = CONST_CAST (char *, TREE_STRING_POINTER (string_cst));
13325 newstr[len - 1] = '\0';
c2f47e15 13326 if (fn_puts)
389dd41b 13327 call = build_call_expr_loc (loc, fn_puts, 1, newarg);
0a39fd54 13328 }
13329 else
13330 /* We'd like to arrange to call fputs(string,stdout) here,
13331 but we need stdout and don't have a way to get it yet. */
c2f47e15 13332 return NULL_TREE;
0a39fd54 13333 }
13334 }
13335
13336 /* The other optimizations can be done only on the non-va_list variants. */
13337 else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 13338 return NULL_TREE;
0a39fd54 13339
13340 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
99eabcc1 13341 else if (strcmp (fmt_str, target_percent_s_newline) == 0)
0a39fd54 13342 {
c2f47e15 13343 if (!arg || !validate_arg (arg, POINTER_TYPE))
13344 return NULL_TREE;
13345 if (fn_puts)
389dd41b 13346 call = build_call_expr_loc (loc, fn_puts, 1, arg);
0a39fd54 13347 }
13348
13349 /* If the format specifier was "%c", call __builtin_putchar(arg). */
99eabcc1 13350 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 13351 {
c2f47e15 13352 if (!arg || !validate_arg (arg, INTEGER_TYPE))
13353 return NULL_TREE;
13354 if (fn_putchar)
389dd41b 13355 call = build_call_expr_loc (loc, fn_putchar, 1, arg);
0a39fd54 13356 }
13357
c2f47e15 13358 if (!call)
13359 return NULL_TREE;
0a39fd54 13360
389dd41b 13361 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
0a39fd54 13362}
13363
13364/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 13365 FP, FMT, and ARG are the arguments to the call. We don't fold calls with
13366 more than 3 arguments, and ARG may be null in the 2-argument case.
0a39fd54 13367
c2f47e15 13368 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 13369 simplified form of the call as a tree. FCODE is the BUILT_IN_*
13370 code of the function to be simplified. */
13371
13372static tree
389dd41b 13373fold_builtin_fprintf (location_t loc, tree fndecl, tree fp,
13374 tree fmt, tree arg, bool ignore,
0a39fd54 13375 enum built_in_function fcode)
13376{
c2f47e15 13377 tree fn_fputc, fn_fputs, call = NULL_TREE;
0a39fd54 13378 const char *fmt_str = NULL;
13379
13380 /* If the return value is used, don't do the transformation. */
13381 if (! ignore)
c2f47e15 13382 return NULL_TREE;
0a39fd54 13383
13384 /* Verify the required arguments in the original call. */
c2f47e15 13385 if (!validate_arg (fp, POINTER_TYPE))
13386 return NULL_TREE;
13387 if (!validate_arg (fmt, POINTER_TYPE))
13388 return NULL_TREE;
0a39fd54 13389
13390 /* Check whether the format is a literal string constant. */
13391 fmt_str = c_getstr (fmt);
13392 if (fmt_str == NULL)
13393 return NULL_TREE;
13394
13395 if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
13396 {
6d77ed92 13397 /* If we're using an unlocked function, assume the other
13398 unlocked functions exist explicitly. */
b9a16870 13399 fn_fputc = builtin_decl_explicit (BUILT_IN_FPUTC_UNLOCKED);
13400 fn_fputs = builtin_decl_explicit (BUILT_IN_FPUTS_UNLOCKED);
0a39fd54 13401 }
13402 else
13403 {
b9a16870 13404 fn_fputc = builtin_decl_implicit (BUILT_IN_FPUTC);
13405 fn_fputs = builtin_decl_implicit (BUILT_IN_FPUTS);
0a39fd54 13406 }
13407
d4473c84 13408 if (!init_target_chars ())
c2f47e15 13409 return NULL_TREE;
a0c938f0 13410
0a39fd54 13411 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 13412 if (strchr (fmt_str, target_percent) == NULL)
0a39fd54 13413 {
13414 if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
c2f47e15 13415 && arg)
13416 return NULL_TREE;
0a39fd54 13417
13418 /* If the format specifier was "", fprintf does nothing. */
13419 if (fmt_str[0] == '\0')
13420 {
13421 /* If FP has side-effects, just wait until gimplification is
13422 done. */
13423 if (TREE_SIDE_EFFECTS (fp))
c2f47e15 13424 return NULL_TREE;
0a39fd54 13425
13426 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
13427 }
13428
13429 /* When "string" doesn't contain %, replace all cases of
13430 fprintf (fp, string) with fputs (string, fp). The fputs
13431 builtin will take care of special cases like length == 1. */
c2f47e15 13432 if (fn_fputs)
389dd41b 13433 call = build_call_expr_loc (loc, fn_fputs, 2, fmt, fp);
0a39fd54 13434 }
13435
13436 /* The other optimizations can be done only on the non-va_list variants. */
13437 else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
c2f47e15 13438 return NULL_TREE;
0a39fd54 13439
13440 /* If the format specifier was "%s", call __builtin_fputs (arg, fp). */
99eabcc1 13441 else if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 13442 {
c2f47e15 13443 if (!arg || !validate_arg (arg, POINTER_TYPE))
13444 return NULL_TREE;
13445 if (fn_fputs)
389dd41b 13446 call = build_call_expr_loc (loc, fn_fputs, 2, arg, fp);
0a39fd54 13447 }
13448
13449 /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */
99eabcc1 13450 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 13451 {
c2f47e15 13452 if (!arg || !validate_arg (arg, INTEGER_TYPE))
13453 return NULL_TREE;
13454 if (fn_fputc)
389dd41b 13455 call = build_call_expr_loc (loc, fn_fputc, 2, arg, fp);
0a39fd54 13456 }
13457
c2f47e15 13458 if (!call)
13459 return NULL_TREE;
389dd41b 13460 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
0a39fd54 13461}
99eabcc1 13462
13463/* Initialize format string characters in the target charset. */
13464
13465static bool
13466init_target_chars (void)
13467{
13468 static bool init;
13469 if (!init)
13470 {
13471 target_newline = lang_hooks.to_target_charset ('\n');
13472 target_percent = lang_hooks.to_target_charset ('%');
13473 target_c = lang_hooks.to_target_charset ('c');
13474 target_s = lang_hooks.to_target_charset ('s');
13475 if (target_newline == 0 || target_percent == 0 || target_c == 0
13476 || target_s == 0)
13477 return false;
13478
13479 target_percent_c[0] = target_percent;
13480 target_percent_c[1] = target_c;
13481 target_percent_c[2] = '\0';
13482
13483 target_percent_s[0] = target_percent;
13484 target_percent_s[1] = target_s;
13485 target_percent_s[2] = '\0';
13486
13487 target_percent_s_newline[0] = target_percent;
13488 target_percent_s_newline[1] = target_s;
13489 target_percent_s_newline[2] = target_newline;
13490 target_percent_s_newline[3] = '\0';
a0c938f0 13491
99eabcc1 13492 init = true;
13493 }
13494 return true;
13495}
bffb7645 13496
f0c477f2 13497/* Helper function for do_mpfr_arg*(). Ensure M is a normal number
13498 and no overflow/underflow occurred. INEXACT is true if M was not
fa7637bd 13499 exactly calculated. TYPE is the tree type for the result. This
f0c477f2 13500 function assumes that you cleared the MPFR flags and then
13501 calculated M to see if anything subsequently set a flag prior to
13502 entering this function. Return NULL_TREE if any checks fail. */
13503
13504static tree
d4473c84 13505do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
f0c477f2 13506{
13507 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
13508 overflow/underflow occurred. If -frounding-math, proceed iff the
13509 result of calling FUNC was exact. */
d4473c84 13510 if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
f0c477f2 13511 && (!flag_rounding_math || !inexact))
13512 {
13513 REAL_VALUE_TYPE rr;
13514
66fa16e6 13515 real_from_mpfr (&rr, m, type, GMP_RNDN);
f0c477f2 13516 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
13517 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
13518 but the mpft_t is not, then we underflowed in the
13519 conversion. */
776a7bab 13520 if (real_isfinite (&rr)
f0c477f2 13521 && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
13522 {
13523 REAL_VALUE_TYPE rmode;
13524
13525 real_convert (&rmode, TYPE_MODE (type), &rr);
13526 /* Proceed iff the specified mode can hold the value. */
13527 if (real_identical (&rmode, &rr))
13528 return build_real (type, rmode);
13529 }
13530 }
13531 return NULL_TREE;
13532}
13533
239d491a 13534/* Helper function for do_mpc_arg*(). Ensure M is a normal complex
13535 number and no overflow/underflow occurred. INEXACT is true if M
13536 was not exactly calculated. TYPE is the tree type for the result.
13537 This function assumes that you cleared the MPFR flags and then
13538 calculated M to see if anything subsequently set a flag prior to
652d9409 13539 entering this function. Return NULL_TREE if any checks fail, if
13540 FORCE_CONVERT is true, then bypass the checks. */
239d491a 13541
13542static tree
652d9409 13543do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert)
239d491a 13544{
13545 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
13546 overflow/underflow occurred. If -frounding-math, proceed iff the
13547 result of calling FUNC was exact. */
652d9409 13548 if (force_convert
13549 || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m))
13550 && !mpfr_overflow_p () && !mpfr_underflow_p ()
13551 && (!flag_rounding_math || !inexact)))
239d491a 13552 {
13553 REAL_VALUE_TYPE re, im;
13554
b0e7c4d4 13555 real_from_mpfr (&re, mpc_realref (m), TREE_TYPE (type), GMP_RNDN);
13556 real_from_mpfr (&im, mpc_imagref (m), TREE_TYPE (type), GMP_RNDN);
239d491a 13557 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
13558 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
13559 but the mpft_t is not, then we underflowed in the
13560 conversion. */
652d9409 13561 if (force_convert
13562 || (real_isfinite (&re) && real_isfinite (&im)
13563 && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0)
13564 && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0)))
239d491a 13565 {
13566 REAL_VALUE_TYPE re_mode, im_mode;
13567
13568 real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re);
13569 real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im);
13570 /* Proceed iff the specified mode can hold the value. */
652d9409 13571 if (force_convert
13572 || (real_identical (&re_mode, &re)
13573 && real_identical (&im_mode, &im)))
239d491a 13574 return build_complex (type, build_real (TREE_TYPE (type), re_mode),
13575 build_real (TREE_TYPE (type), im_mode));
13576 }
13577 }
13578 return NULL_TREE;
13579}
239d491a 13580
bffb7645 13581/* If argument ARG is a REAL_CST, call the one-argument mpfr function
13582 FUNC on it and return the resulting value as a tree with type TYPE.
728bac60 13583 If MIN and/or MAX are not NULL, then the supplied ARG must be
13584 within those bounds. If INCLUSIVE is true, then MIN/MAX are
13585 acceptable values, otherwise they are not. The mpfr precision is
13586 set to the precision of TYPE. We assume that function FUNC returns
13587 zero if the result could be calculated exactly within the requested
13588 precision. */
bffb7645 13589
13590static tree
728bac60 13591do_mpfr_arg1 (tree arg, tree type, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
13592 const REAL_VALUE_TYPE *min, const REAL_VALUE_TYPE *max,
13593 bool inclusive)
bffb7645 13594{
13595 tree result = NULL_TREE;
48e1416a 13596
bffb7645 13597 STRIP_NOPS (arg);
13598
bd7d6fa4 13599 /* To proceed, MPFR must exactly represent the target floating point
13600 format, which only happens when the target base equals two. */
13601 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13602 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
bffb7645 13603 {
f0c477f2 13604 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
bffb7645 13605
776a7bab 13606 if (real_isfinite (ra)
f0c477f2 13607 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min))
13608 && (!max || real_compare (inclusive ? LE_EXPR: LT_EXPR , ra, max)))
bffb7645 13609 {
e2eb2b7f 13610 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13611 const int prec = fmt->p;
13612 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
debf9994 13613 int inexact;
bffb7645 13614 mpfr_t m;
13615
13616 mpfr_init2 (m, prec);
66fa16e6 13617 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 13618 mpfr_clear_flags ();
e2eb2b7f 13619 inexact = func (m, m, rnd);
f0c477f2 13620 result = do_mpfr_ckconv (m, type, inexact);
bffb7645 13621 mpfr_clear (m);
13622 }
13623 }
48e1416a 13624
bffb7645 13625 return result;
13626}
f0c477f2 13627
13628/* If argument ARG is a REAL_CST, call the two-argument mpfr function
13629 FUNC on it and return the resulting value as a tree with type TYPE.
13630 The mpfr precision is set to the precision of TYPE. We assume that
13631 function FUNC returns zero if the result could be calculated
13632 exactly within the requested precision. */
13633
13634static tree
13635do_mpfr_arg2 (tree arg1, tree arg2, tree type,
13636 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
13637{
13638 tree result = NULL_TREE;
48e1416a 13639
f0c477f2 13640 STRIP_NOPS (arg1);
13641 STRIP_NOPS (arg2);
13642
bd7d6fa4 13643 /* To proceed, MPFR must exactly represent the target floating point
13644 format, which only happens when the target base equals two. */
13645 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13646 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
13647 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
f0c477f2 13648 {
13649 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
13650 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
13651
776a7bab 13652 if (real_isfinite (ra1) && real_isfinite (ra2))
f0c477f2 13653 {
e2eb2b7f 13654 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13655 const int prec = fmt->p;
13656 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
f0c477f2 13657 int inexact;
13658 mpfr_t m1, m2;
13659
13660 mpfr_inits2 (prec, m1, m2, NULL);
66fa16e6 13661 mpfr_from_real (m1, ra1, GMP_RNDN);
13662 mpfr_from_real (m2, ra2, GMP_RNDN);
d4473c84 13663 mpfr_clear_flags ();
e2eb2b7f 13664 inexact = func (m1, m1, m2, rnd);
f0c477f2 13665 result = do_mpfr_ckconv (m1, type, inexact);
13666 mpfr_clears (m1, m2, NULL);
13667 }
13668 }
48e1416a 13669
f0c477f2 13670 return result;
13671}
d92f994c 13672
9917422b 13673/* If argument ARG is a REAL_CST, call the three-argument mpfr function
13674 FUNC on it and return the resulting value as a tree with type TYPE.
13675 The mpfr precision is set to the precision of TYPE. We assume that
13676 function FUNC returns zero if the result could be calculated
13677 exactly within the requested precision. */
13678
13679static tree
13680do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type,
13681 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
13682{
13683 tree result = NULL_TREE;
48e1416a 13684
9917422b 13685 STRIP_NOPS (arg1);
13686 STRIP_NOPS (arg2);
13687 STRIP_NOPS (arg3);
13688
bd7d6fa4 13689 /* To proceed, MPFR must exactly represent the target floating point
13690 format, which only happens when the target base equals two. */
13691 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13692 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
13693 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2)
13694 && TREE_CODE (arg3) == REAL_CST && !TREE_OVERFLOW (arg3))
9917422b 13695 {
13696 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
13697 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
13698 const REAL_VALUE_TYPE *const ra3 = &TREE_REAL_CST (arg3);
13699
776a7bab 13700 if (real_isfinite (ra1) && real_isfinite (ra2) && real_isfinite (ra3))
9917422b 13701 {
e2eb2b7f 13702 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13703 const int prec = fmt->p;
13704 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
9917422b 13705 int inexact;
13706 mpfr_t m1, m2, m3;
13707
13708 mpfr_inits2 (prec, m1, m2, m3, NULL);
66fa16e6 13709 mpfr_from_real (m1, ra1, GMP_RNDN);
13710 mpfr_from_real (m2, ra2, GMP_RNDN);
13711 mpfr_from_real (m3, ra3, GMP_RNDN);
d4473c84 13712 mpfr_clear_flags ();
e2eb2b7f 13713 inexact = func (m1, m1, m2, m3, rnd);
9917422b 13714 result = do_mpfr_ckconv (m1, type, inexact);
13715 mpfr_clears (m1, m2, m3, NULL);
13716 }
13717 }
48e1416a 13718
9917422b 13719 return result;
13720}
13721
d92f994c 13722/* If argument ARG is a REAL_CST, call mpfr_sin_cos() on it and set
13723 the pointers *(ARG_SINP) and *(ARG_COSP) to the resulting values.
d735c391 13724 If ARG_SINP and ARG_COSP are NULL then the result is returned
13725 as a complex value.
d92f994c 13726 The type is taken from the type of ARG and is used for setting the
13727 precision of the calculation and results. */
13728
13729static tree
13730do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp)
13731{
bd7d6fa4 13732 tree const type = TREE_TYPE (arg);
d92f994c 13733 tree result = NULL_TREE;
48e1416a 13734
d92f994c 13735 STRIP_NOPS (arg);
48e1416a 13736
bd7d6fa4 13737 /* To proceed, MPFR must exactly represent the target floating point
13738 format, which only happens when the target base equals two. */
13739 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13740 && TREE_CODE (arg) == REAL_CST
13741 && !TREE_OVERFLOW (arg))
d92f994c 13742 {
13743 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
13744
776a7bab 13745 if (real_isfinite (ra))
d92f994c 13746 {
e2eb2b7f 13747 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13748 const int prec = fmt->p;
13749 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
d92f994c 13750 tree result_s, result_c;
13751 int inexact;
13752 mpfr_t m, ms, mc;
13753
13754 mpfr_inits2 (prec, m, ms, mc, NULL);
66fa16e6 13755 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 13756 mpfr_clear_flags ();
e2eb2b7f 13757 inexact = mpfr_sin_cos (ms, mc, m, rnd);
d92f994c 13758 result_s = do_mpfr_ckconv (ms, type, inexact);
13759 result_c = do_mpfr_ckconv (mc, type, inexact);
13760 mpfr_clears (m, ms, mc, NULL);
13761 if (result_s && result_c)
13762 {
d735c391 13763 /* If we are to return in a complex value do so. */
13764 if (!arg_sinp && !arg_cosp)
13765 return build_complex (build_complex_type (type),
13766 result_c, result_s);
13767
d92f994c 13768 /* Dereference the sin/cos pointer arguments. */
13769 arg_sinp = build_fold_indirect_ref (arg_sinp);
13770 arg_cosp = build_fold_indirect_ref (arg_cosp);
13771 /* Proceed if valid pointer type were passed in. */
13772 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_sinp)) == TYPE_MAIN_VARIANT (type)
13773 && TYPE_MAIN_VARIANT (TREE_TYPE (arg_cosp)) == TYPE_MAIN_VARIANT (type))
13774 {
13775 /* Set the values. */
41076ef6 13776 result_s = fold_build2 (MODIFY_EXPR, type, arg_sinp,
35cc02b5 13777 result_s);
d92f994c 13778 TREE_SIDE_EFFECTS (result_s) = 1;
41076ef6 13779 result_c = fold_build2 (MODIFY_EXPR, type, arg_cosp,
35cc02b5 13780 result_c);
d92f994c 13781 TREE_SIDE_EFFECTS (result_c) = 1;
13782 /* Combine the assignments into a compound expr. */
13783 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13784 result_s, result_c));
13785 }
13786 }
13787 }
13788 }
13789 return result;
13790}
65dd1378 13791
65dd1378 13792/* If argument ARG1 is an INTEGER_CST and ARG2 is a REAL_CST, call the
13793 two-argument mpfr order N Bessel function FUNC on them and return
13794 the resulting value as a tree with type TYPE. The mpfr precision
13795 is set to the precision of TYPE. We assume that function FUNC
13796 returns zero if the result could be calculated exactly within the
13797 requested precision. */
13798static tree
13799do_mpfr_bessel_n (tree arg1, tree arg2, tree type,
13800 int (*func)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
13801 const REAL_VALUE_TYPE *min, bool inclusive)
13802{
13803 tree result = NULL_TREE;
13804
13805 STRIP_NOPS (arg1);
13806 STRIP_NOPS (arg2);
13807
13808 /* To proceed, MPFR must exactly represent the target floating point
13809 format, which only happens when the target base equals two. */
13810 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13811 && host_integerp (arg1, 0)
13812 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
13813 {
13814 const HOST_WIDE_INT n = tree_low_cst(arg1, 0);
13815 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg2);
13816
13817 if (n == (long)n
776a7bab 13818 && real_isfinite (ra)
65dd1378 13819 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min)))
13820 {
e2eb2b7f 13821 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13822 const int prec = fmt->p;
13823 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
65dd1378 13824 int inexact;
13825 mpfr_t m;
13826
13827 mpfr_init2 (m, prec);
13828 mpfr_from_real (m, ra, GMP_RNDN);
13829 mpfr_clear_flags ();
e2eb2b7f 13830 inexact = func (m, n, m, rnd);
65dd1378 13831 result = do_mpfr_ckconv (m, type, inexact);
13832 mpfr_clear (m);
13833 }
13834 }
48e1416a 13835
65dd1378 13836 return result;
13837}
e5407ca6 13838
13839/* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
13840 the pointer *(ARG_QUO) and return the result. The type is taken
13841 from the type of ARG0 and is used for setting the precision of the
13842 calculation and results. */
13843
13844static tree
13845do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
13846{
13847 tree const type = TREE_TYPE (arg0);
13848 tree result = NULL_TREE;
48e1416a 13849
e5407ca6 13850 STRIP_NOPS (arg0);
13851 STRIP_NOPS (arg1);
48e1416a 13852
e5407ca6 13853 /* To proceed, MPFR must exactly represent the target floating point
13854 format, which only happens when the target base equals two. */
13855 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13856 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
13857 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
13858 {
13859 const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
13860 const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
13861
776a7bab 13862 if (real_isfinite (ra0) && real_isfinite (ra1))
e5407ca6 13863 {
e2eb2b7f 13864 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13865 const int prec = fmt->p;
13866 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
e5407ca6 13867 tree result_rem;
13868 long integer_quo;
13869 mpfr_t m0, m1;
13870
13871 mpfr_inits2 (prec, m0, m1, NULL);
13872 mpfr_from_real (m0, ra0, GMP_RNDN);
13873 mpfr_from_real (m1, ra1, GMP_RNDN);
13874 mpfr_clear_flags ();
e2eb2b7f 13875 mpfr_remquo (m0, &integer_quo, m0, m1, rnd);
e5407ca6 13876 /* Remquo is independent of the rounding mode, so pass
13877 inexact=0 to do_mpfr_ckconv(). */
13878 result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
13879 mpfr_clears (m0, m1, NULL);
13880 if (result_rem)
13881 {
13882 /* MPFR calculates quo in the host's long so it may
13883 return more bits in quo than the target int can hold
13884 if sizeof(host long) > sizeof(target int). This can
13885 happen even for native compilers in LP64 mode. In
13886 these cases, modulo the quo value with the largest
13887 number that the target int can hold while leaving one
13888 bit for the sign. */
13889 if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
13890 integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
13891
13892 /* Dereference the quo pointer argument. */
13893 arg_quo = build_fold_indirect_ref (arg_quo);
13894 /* Proceed iff a valid pointer type was passed in. */
13895 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
13896 {
13897 /* Set the value. */
7002a1c8 13898 tree result_quo
13899 = fold_build2 (MODIFY_EXPR, TREE_TYPE (arg_quo), arg_quo,
13900 build_int_cst (TREE_TYPE (arg_quo),
13901 integer_quo));
e5407ca6 13902 TREE_SIDE_EFFECTS (result_quo) = 1;
13903 /* Combine the quo assignment with the rem. */
13904 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13905 result_quo, result_rem));
13906 }
13907 }
13908 }
13909 }
13910 return result;
13911}
e84da7c1 13912
13913/* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
13914 resulting value as a tree with type TYPE. The mpfr precision is
13915 set to the precision of TYPE. We assume that this mpfr function
13916 returns zero if the result could be calculated exactly within the
13917 requested precision. In addition, the integer pointer represented
13918 by ARG_SG will be dereferenced and set to the appropriate signgam
13919 (-1,1) value. */
13920
13921static tree
13922do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
13923{
13924 tree result = NULL_TREE;
13925
13926 STRIP_NOPS (arg);
48e1416a 13927
e84da7c1 13928 /* To proceed, MPFR must exactly represent the target floating point
13929 format, which only happens when the target base equals two. Also
13930 verify ARG is a constant and that ARG_SG is an int pointer. */
13931 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13932 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
13933 && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
13934 && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
13935 {
13936 const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
13937
13938 /* In addition to NaN and Inf, the argument cannot be zero or a
13939 negative integer. */
776a7bab 13940 if (real_isfinite (ra)
e84da7c1 13941 && ra->cl != rvc_zero
13942 && !(real_isneg(ra) && real_isinteger(ra, TYPE_MODE (type))))
13943 {
e2eb2b7f 13944 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13945 const int prec = fmt->p;
13946 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
e84da7c1 13947 int inexact, sg;
13948 mpfr_t m;
13949 tree result_lg;
13950
13951 mpfr_init2 (m, prec);
13952 mpfr_from_real (m, ra, GMP_RNDN);
13953 mpfr_clear_flags ();
e2eb2b7f 13954 inexact = mpfr_lgamma (m, &sg, m, rnd);
e84da7c1 13955 result_lg = do_mpfr_ckconv (m, type, inexact);
13956 mpfr_clear (m);
13957 if (result_lg)
13958 {
13959 tree result_sg;
13960
13961 /* Dereference the arg_sg pointer argument. */
13962 arg_sg = build_fold_indirect_ref (arg_sg);
13963 /* Assign the signgam value into *arg_sg. */
13964 result_sg = fold_build2 (MODIFY_EXPR,
13965 TREE_TYPE (arg_sg), arg_sg,
7002a1c8 13966 build_int_cst (TREE_TYPE (arg_sg), sg));
e84da7c1 13967 TREE_SIDE_EFFECTS (result_sg) = 1;
13968 /* Combine the signgam assignment with the lgamma result. */
13969 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13970 result_sg, result_lg));
13971 }
13972 }
13973 }
13974
13975 return result;
13976}
75a70cf9 13977
239d491a 13978/* If argument ARG is a COMPLEX_CST, call the one-argument mpc
13979 function FUNC on it and return the resulting value as a tree with
13980 type TYPE. The mpfr precision is set to the precision of TYPE. We
13981 assume that function FUNC returns zero if the result could be
13982 calculated exactly within the requested precision. */
13983
13984static tree
13985do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t))
13986{
13987 tree result = NULL_TREE;
48e1416a 13988
239d491a 13989 STRIP_NOPS (arg);
13990
13991 /* To proceed, MPFR must exactly represent the target floating point
13992 format, which only happens when the target base equals two. */
13993 if (TREE_CODE (arg) == COMPLEX_CST && !TREE_OVERFLOW (arg)
13994 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE
13995 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))))->b == 2)
13996 {
13997 const REAL_VALUE_TYPE *const re = TREE_REAL_CST_PTR (TREE_REALPART (arg));
13998 const REAL_VALUE_TYPE *const im = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
13999
14000 if (real_isfinite (re) && real_isfinite (im))
14001 {
14002 const struct real_format *const fmt =
14003 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
14004 const int prec = fmt->p;
14005 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
44d89feb 14006 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
239d491a 14007 int inexact;
14008 mpc_t m;
48e1416a 14009
239d491a 14010 mpc_init2 (m, prec);
c3cfad90 14011 mpfr_from_real (mpc_realref(m), re, rnd);
14012 mpfr_from_real (mpc_imagref(m), im, rnd);
239d491a 14013 mpfr_clear_flags ();
44d89feb 14014 inexact = func (m, m, crnd);
652d9409 14015 result = do_mpc_ckconv (m, type, inexact, /*force_convert=*/ 0);
239d491a 14016 mpc_clear (m);
14017 }
14018 }
14019
14020 return result;
14021}
c699fab8 14022
14023/* If arguments ARG0 and ARG1 are a COMPLEX_CST, call the two-argument
14024 mpc function FUNC on it and return the resulting value as a tree
14025 with type TYPE. The mpfr precision is set to the precision of
14026 TYPE. We assume that function FUNC returns zero if the result
652d9409 14027 could be calculated exactly within the requested precision. If
14028 DO_NONFINITE is true, then fold expressions containing Inf or NaN
14029 in the arguments and/or results. */
c699fab8 14030
63e89698 14031tree
652d9409 14032do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
c699fab8 14033 int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
14034{
14035 tree result = NULL_TREE;
48e1416a 14036
c699fab8 14037 STRIP_NOPS (arg0);
14038 STRIP_NOPS (arg1);
14039
14040 /* To proceed, MPFR must exactly represent the target floating point
14041 format, which only happens when the target base equals two. */
14042 if (TREE_CODE (arg0) == COMPLEX_CST && !TREE_OVERFLOW (arg0)
14043 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
14044 && TREE_CODE (arg1) == COMPLEX_CST && !TREE_OVERFLOW (arg1)
14045 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE
14046 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))))->b == 2)
14047 {
14048 const REAL_VALUE_TYPE *const re0 = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
14049 const REAL_VALUE_TYPE *const im0 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
14050 const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1));
14051 const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1));
14052
652d9409 14053 if (do_nonfinite
14054 || (real_isfinite (re0) && real_isfinite (im0)
14055 && real_isfinite (re1) && real_isfinite (im1)))
c699fab8 14056 {
14057 const struct real_format *const fmt =
14058 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
14059 const int prec = fmt->p;
14060 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
14061 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
14062 int inexact;
14063 mpc_t m0, m1;
48e1416a 14064
c699fab8 14065 mpc_init2 (m0, prec);
14066 mpc_init2 (m1, prec);
14067 mpfr_from_real (mpc_realref(m0), re0, rnd);
14068 mpfr_from_real (mpc_imagref(m0), im0, rnd);
14069 mpfr_from_real (mpc_realref(m1), re1, rnd);
14070 mpfr_from_real (mpc_imagref(m1), im1, rnd);
14071 mpfr_clear_flags ();
14072 inexact = func (m0, m0, m1, crnd);
652d9409 14073 result = do_mpc_ckconv (m0, type, inexact, do_nonfinite);
c699fab8 14074 mpc_clear (m0);
14075 mpc_clear (m1);
14076 }
14077 }
14078
14079 return result;
14080}
239d491a 14081
75a70cf9 14082/* Fold a call STMT to __{,v}sprintf_chk. Return NULL_TREE if
14083 a normal call should be emitted rather than expanding the function
14084 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
14085
14086static tree
14087gimple_fold_builtin_sprintf_chk (gimple stmt, enum built_in_function fcode)
14088{
75a70cf9 14089 int nargs = gimple_call_num_args (stmt);
14090
af1409ad 14091 return fold_builtin_sprintf_chk_1 (gimple_location (stmt), nargs,
14092 (nargs > 0
14093 ? gimple_call_arg_ptr (stmt, 0)
14094 : &error_mark_node), fcode);
75a70cf9 14095}
14096
14097/* Fold a call STMT to {,v}snprintf. Return NULL_TREE if
14098 a normal call should be emitted rather than expanding the function
14099 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
14100 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
14101 passed as second argument. */
14102
14103tree
14104gimple_fold_builtin_snprintf_chk (gimple stmt, tree maxlen,
14105 enum built_in_function fcode)
14106{
af1409ad 14107 int nargs = gimple_call_num_args (stmt);
75a70cf9 14108
af1409ad 14109 return fold_builtin_snprintf_chk_1 (gimple_location (stmt), nargs,
14110 (nargs > 0
14111 ? gimple_call_arg_ptr (stmt, 0)
14112 : &error_mark_node), maxlen, fcode);
75a70cf9 14113}
14114
14115/* Builtins with folding operations that operate on "..." arguments
14116 need special handling; we need to store the arguments in a convenient
14117 data structure before attempting any folding. Fortunately there are
14118 only a few builtins that fall into this category. FNDECL is the
14119 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
14120 result of the function call is ignored. */
14121
14122static tree
389dd41b 14123gimple_fold_builtin_varargs (tree fndecl, gimple stmt,
14124 bool ignore ATTRIBUTE_UNUSED)
75a70cf9 14125{
14126 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
14127 tree ret = NULL_TREE;
14128
14129 switch (fcode)
14130 {
14131 case BUILT_IN_SPRINTF_CHK:
14132 case BUILT_IN_VSPRINTF_CHK:
14133 ret = gimple_fold_builtin_sprintf_chk (stmt, fcode);
14134 break;
14135
14136 case BUILT_IN_SNPRINTF_CHK:
14137 case BUILT_IN_VSNPRINTF_CHK:
14138 ret = gimple_fold_builtin_snprintf_chk (stmt, NULL_TREE, fcode);
14139
14140 default:
14141 break;
14142 }
14143 if (ret)
14144 {
14145 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
14146 TREE_NO_WARNING (ret) = 1;
14147 return ret;
14148 }
14149 return NULL_TREE;
14150}
14151
14152/* A wrapper function for builtin folding that prevents warnings for
14153 "statement without effect" and the like, caused by removing the
14154 call node earlier than the warning is generated. */
14155
14156tree
14157fold_call_stmt (gimple stmt, bool ignore)
14158{
14159 tree ret = NULL_TREE;
14160 tree fndecl = gimple_call_fndecl (stmt);
389dd41b 14161 location_t loc = gimple_location (stmt);
75a70cf9 14162 if (fndecl
14163 && TREE_CODE (fndecl) == FUNCTION_DECL
14164 && DECL_BUILT_IN (fndecl)
14165 && !gimple_call_va_arg_pack_p (stmt))
14166 {
14167 int nargs = gimple_call_num_args (stmt);
9845fb99 14168 tree *args = (nargs > 0
14169 ? gimple_call_arg_ptr (stmt, 0)
14170 : &error_mark_node);
75a70cf9 14171
198622c0 14172 if (avoid_folding_inline_builtin (fndecl))
14173 return NULL_TREE;
75a70cf9 14174 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
14175 {
9845fb99 14176 return targetm.fold_builtin (fndecl, nargs, args, ignore);
75a70cf9 14177 }
14178 else
14179 {
14180 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
9845fb99 14181 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
75a70cf9 14182 if (!ret)
14183 ret = gimple_fold_builtin_varargs (fndecl, stmt, ignore);
14184 if (ret)
14185 {
14186 /* Propagate location information from original call to
14187 expansion of builtin. Otherwise things like
14188 maybe_emit_chk_warning, that operate on the expansion
14189 of a builtin, will use the wrong location information. */
14190 if (gimple_has_location (stmt))
14191 {
14192 tree realret = ret;
14193 if (TREE_CODE (ret) == NOP_EXPR)
14194 realret = TREE_OPERAND (ret, 0);
14195 if (CAN_HAVE_LOCATION_P (realret)
14196 && !EXPR_HAS_LOCATION (realret))
389dd41b 14197 SET_EXPR_LOCATION (realret, loc);
75a70cf9 14198 return realret;
14199 }
14200 return ret;
14201 }
14202 }
14203 }
14204 return NULL_TREE;
14205}
7bfefa9d 14206
b9a16870 14207/* Look up the function in builtin_decl that corresponds to DECL
7bfefa9d 14208 and set ASMSPEC as its user assembler name. DECL must be a
14209 function decl that declares a builtin. */
14210
14211void
14212set_builtin_user_assembler_name (tree decl, const char *asmspec)
14213{
14214 tree builtin;
14215 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
14216 && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
14217 && asmspec != 0);
14218
b9a16870 14219 builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
4d8e0d6d 14220 set_user_assembler_name (builtin, asmspec);
7bfefa9d 14221 switch (DECL_FUNCTION_CODE (decl))
14222 {
14223 case BUILT_IN_MEMCPY:
14224 init_block_move_fn (asmspec);
14225 memcpy_libfunc = set_user_assembler_libfunc ("memcpy", asmspec);
14226 break;
14227 case BUILT_IN_MEMSET:
14228 init_block_clear_fn (asmspec);
14229 memset_libfunc = set_user_assembler_libfunc ("memset", asmspec);
14230 break;
14231 case BUILT_IN_MEMMOVE:
14232 memmove_libfunc = set_user_assembler_libfunc ("memmove", asmspec);
14233 break;
14234 case BUILT_IN_MEMCMP:
14235 memcmp_libfunc = set_user_assembler_libfunc ("memcmp", asmspec);
14236 break;
14237 case BUILT_IN_ABORT:
14238 abort_libfunc = set_user_assembler_libfunc ("abort", asmspec);
14239 break;
5a80a58b 14240 case BUILT_IN_FFS:
14241 if (INT_TYPE_SIZE < BITS_PER_WORD)
14242 {
14243 set_user_assembler_libfunc ("ffs", asmspec);
14244 set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE,
14245 MODE_INT, 0), "ffs");
14246 }
14247 break;
7bfefa9d 14248 default:
14249 break;
14250 }
14251}
a6b74a67 14252
14253/* Return true if DECL is a builtin that expands to a constant or similarly
14254 simple code. */
14255bool
14256is_simple_builtin (tree decl)
14257{
14258 if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
14259 switch (DECL_FUNCTION_CODE (decl))
14260 {
14261 /* Builtins that expand to constants. */
14262 case BUILT_IN_CONSTANT_P:
14263 case BUILT_IN_EXPECT:
14264 case BUILT_IN_OBJECT_SIZE:
14265 case BUILT_IN_UNREACHABLE:
14266 /* Simple register moves or loads from stack. */
fca0886c 14267 case BUILT_IN_ASSUME_ALIGNED:
a6b74a67 14268 case BUILT_IN_RETURN_ADDRESS:
14269 case BUILT_IN_EXTRACT_RETURN_ADDR:
14270 case BUILT_IN_FROB_RETURN_ADDR:
14271 case BUILT_IN_RETURN:
14272 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
14273 case BUILT_IN_FRAME_ADDRESS:
14274 case BUILT_IN_VA_END:
14275 case BUILT_IN_STACK_SAVE:
14276 case BUILT_IN_STACK_RESTORE:
14277 /* Exception state returns or moves registers around. */
14278 case BUILT_IN_EH_FILTER:
14279 case BUILT_IN_EH_POINTER:
14280 case BUILT_IN_EH_COPY_VALUES:
14281 return true;
14282
14283 default:
14284 return false;
14285 }
14286
14287 return false;
14288}
14289
14290/* Return true if DECL is a builtin that is not expensive, i.e., they are
14291 most probably expanded inline into reasonably simple code. This is a
14292 superset of is_simple_builtin. */
14293bool
14294is_inexpensive_builtin (tree decl)
14295{
14296 if (!decl)
14297 return false;
14298 else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_MD)
14299 return true;
14300 else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
14301 switch (DECL_FUNCTION_CODE (decl))
14302 {
14303 case BUILT_IN_ABS:
14304 case BUILT_IN_ALLOCA:
581bf1c2 14305 case BUILT_IN_ALLOCA_WITH_ALIGN:
a6b74a67 14306 case BUILT_IN_BSWAP32:
14307 case BUILT_IN_BSWAP64:
14308 case BUILT_IN_CLZ:
14309 case BUILT_IN_CLZIMAX:
14310 case BUILT_IN_CLZL:
14311 case BUILT_IN_CLZLL:
14312 case BUILT_IN_CTZ:
14313 case BUILT_IN_CTZIMAX:
14314 case BUILT_IN_CTZL:
14315 case BUILT_IN_CTZLL:
14316 case BUILT_IN_FFS:
14317 case BUILT_IN_FFSIMAX:
14318 case BUILT_IN_FFSL:
14319 case BUILT_IN_FFSLL:
14320 case BUILT_IN_IMAXABS:
14321 case BUILT_IN_FINITE:
14322 case BUILT_IN_FINITEF:
14323 case BUILT_IN_FINITEL:
14324 case BUILT_IN_FINITED32:
14325 case BUILT_IN_FINITED64:
14326 case BUILT_IN_FINITED128:
14327 case BUILT_IN_FPCLASSIFY:
14328 case BUILT_IN_ISFINITE:
14329 case BUILT_IN_ISINF_SIGN:
14330 case BUILT_IN_ISINF:
14331 case BUILT_IN_ISINFF:
14332 case BUILT_IN_ISINFL:
14333 case BUILT_IN_ISINFD32:
14334 case BUILT_IN_ISINFD64:
14335 case BUILT_IN_ISINFD128:
14336 case BUILT_IN_ISNAN:
14337 case BUILT_IN_ISNANF:
14338 case BUILT_IN_ISNANL:
14339 case BUILT_IN_ISNAND32:
14340 case BUILT_IN_ISNAND64:
14341 case BUILT_IN_ISNAND128:
14342 case BUILT_IN_ISNORMAL:
14343 case BUILT_IN_ISGREATER:
14344 case BUILT_IN_ISGREATEREQUAL:
14345 case BUILT_IN_ISLESS:
14346 case BUILT_IN_ISLESSEQUAL:
14347 case BUILT_IN_ISLESSGREATER:
14348 case BUILT_IN_ISUNORDERED:
14349 case BUILT_IN_VA_ARG_PACK:
14350 case BUILT_IN_VA_ARG_PACK_LEN:
14351 case BUILT_IN_VA_COPY:
14352 case BUILT_IN_TRAP:
14353 case BUILT_IN_SAVEREGS:
14354 case BUILT_IN_POPCOUNTL:
14355 case BUILT_IN_POPCOUNTLL:
14356 case BUILT_IN_POPCOUNTIMAX:
14357 case BUILT_IN_POPCOUNT:
14358 case BUILT_IN_PARITYL:
14359 case BUILT_IN_PARITYLL:
14360 case BUILT_IN_PARITYIMAX:
14361 case BUILT_IN_PARITY:
14362 case BUILT_IN_LABS:
14363 case BUILT_IN_LLABS:
14364 case BUILT_IN_PREFETCH:
14365 return true;
14366
14367 default:
14368 return is_simple_builtin (decl);
14369 }
14370
14371 return false;
14372}