]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/builtins.c
gcc/
[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. */
d2d4bdde 78tree built_in_decls[(int) END_BUILTINS];
0a68165a 79/* Declarations used when constructing the builtin implicitly in the compiler.
80 It may be NULL_TREE when this is invalid (for instance runtime is not
4ee9c684 81 required to implement the function call in all cases). */
0a68165a 82tree implicit_built_in_decls[(int) END_BUILTINS];
df94cd3b 83
aecda0d6 84static const char *c_getstr (tree);
85static rtx c_readstr (const char *, enum machine_mode);
86static int target_char_cast (tree, char *);
d8ae1baa 87static rtx get_memory_rtx (tree, tree);
aecda0d6 88static int apply_args_size (void);
89static int apply_result_size (void);
d8c9779c 90#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
aecda0d6 91static rtx result_vector (int, rtx);
d8c9779c 92#endif
843d08a9 93static void expand_builtin_update_setjmp_buf (rtx);
aecda0d6 94static void expand_builtin_prefetch (tree);
95static rtx expand_builtin_apply_args (void);
96static rtx expand_builtin_apply_args_1 (void);
97static rtx expand_builtin_apply (rtx, rtx, rtx);
98static void expand_builtin_return (rtx);
99static enum type_class type_to_class (tree);
100static rtx expand_builtin_classify_type (tree);
101static void expand_errno_check (tree, rtx);
102static rtx expand_builtin_mathfn (tree, rtx, rtx);
103static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
6b43bae4 104static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
7e0713b1 105static rtx expand_builtin_mathfn_ternary (tree, rtx, rtx);
f97eea22 106static rtx expand_builtin_interclass_mathfn (tree, rtx);
c3147c1a 107static rtx expand_builtin_sincos (tree);
f97eea22 108static rtx expand_builtin_cexpi (tree, rtx);
ff1b14e4 109static rtx expand_builtin_int_roundingfn (tree, rtx);
110static rtx expand_builtin_int_roundingfn_2 (tree, rtx);
79012a9d 111static rtx expand_builtin_next_arg (void);
aecda0d6 112static rtx expand_builtin_va_start (tree);
113static rtx expand_builtin_va_end (tree);
114static rtx expand_builtin_va_copy (tree);
c2f47e15 115static rtx expand_builtin_memcmp (tree, rtx, enum machine_mode);
a65c4d64 116static rtx expand_builtin_strcmp (tree, rtx);
aecda0d6 117static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
118static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
a65c4d64 119static rtx expand_builtin_memcpy (tree, rtx);
c2f47e15 120static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode);
48e1416a 121static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx,
c2f47e15 122 enum machine_mode, int);
a65c4d64 123static rtx expand_builtin_strcpy (tree, rtx);
124static rtx expand_builtin_strcpy_args (tree, tree, rtx);
aecda0d6 125static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
a65c4d64 126static rtx expand_builtin_strncpy (tree, rtx);
aecda0d6 127static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
c2f47e15 128static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
129static rtx expand_builtin_memset_args (tree, tree, tree, rtx, enum machine_mode, tree);
aecda0d6 130static rtx expand_builtin_bzero (tree);
131static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
5be42b39 132static rtx expand_builtin_alloca (tree, bool);
aecda0d6 133static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
134static rtx expand_builtin_frame_address (tree, tree);
389dd41b 135static tree stabilize_va_list_loc (location_t, tree, int);
aecda0d6 136static rtx expand_builtin_expect (tree, rtx);
137static tree fold_builtin_constant_p (tree);
389dd41b 138static tree fold_builtin_expect (location_t, tree, tree);
aecda0d6 139static tree fold_builtin_classify_type (tree);
c7cbde74 140static tree fold_builtin_strlen (location_t, tree, tree);
389dd41b 141static tree fold_builtin_inf (location_t, tree, int);
aecda0d6 142static tree fold_builtin_nan (tree, tree, int);
389dd41b 143static tree rewrite_call_expr (location_t, tree, int, tree, int, ...);
b7bf20db 144static bool validate_arg (const_tree, enum tree_code code);
277f8dd2 145static bool integer_valued_real_p (tree);
389dd41b 146static tree fold_trunc_transparent_mathfn (location_t, tree, tree);
aecda0d6 147static bool readonly_data_expr (tree);
148static rtx expand_builtin_fabs (tree, rtx, rtx);
27f261ef 149static rtx expand_builtin_signbit (tree, rtx);
389dd41b 150static tree fold_builtin_sqrt (location_t, tree, tree);
151static tree fold_builtin_cbrt (location_t, tree, tree);
152static tree fold_builtin_pow (location_t, tree, tree, tree, tree);
153static tree fold_builtin_powi (location_t, tree, tree, tree, tree);
154static tree fold_builtin_cos (location_t, tree, tree, tree);
155static tree fold_builtin_cosh (location_t, tree, tree, tree);
bffb7645 156static tree fold_builtin_tan (tree, tree);
389dd41b 157static tree fold_builtin_trunc (location_t, tree, tree);
158static tree fold_builtin_floor (location_t, tree, tree);
159static tree fold_builtin_ceil (location_t, tree, tree);
160static tree fold_builtin_round (location_t, tree, tree);
161static tree fold_builtin_int_roundingfn (location_t, tree, tree);
10b9666f 162static tree fold_builtin_bitop (tree, tree);
389dd41b 163static tree fold_builtin_memory_op (location_t, tree, tree, tree, tree, bool, int);
164static tree fold_builtin_strchr (location_t, tree, tree, tree);
165static tree fold_builtin_memchr (location_t, tree, tree, tree, tree);
166static tree fold_builtin_memcmp (location_t, tree, tree, tree);
167static tree fold_builtin_strcmp (location_t, tree, tree);
168static tree fold_builtin_strncmp (location_t, tree, tree, tree);
169static tree fold_builtin_signbit (location_t, tree, tree);
170static tree fold_builtin_copysign (location_t, tree, tree, tree, tree);
171static tree fold_builtin_isascii (location_t, tree);
172static tree fold_builtin_toascii (location_t, tree);
173static tree fold_builtin_isdigit (location_t, tree);
174static tree fold_builtin_fabs (location_t, tree, tree);
175static tree fold_builtin_abs (location_t, tree, tree);
176static tree fold_builtin_unordered_cmp (location_t, tree, tree, tree, enum tree_code,
d5019fe8 177 enum tree_code);
389dd41b 178static tree fold_builtin_n (location_t, tree, tree *, int, bool);
179static tree fold_builtin_0 (location_t, tree, bool);
180static tree fold_builtin_1 (location_t, tree, tree, bool);
181static tree fold_builtin_2 (location_t, tree, tree, tree, bool);
182static tree fold_builtin_3 (location_t, tree, tree, tree, tree, bool);
183static tree fold_builtin_4 (location_t, tree, tree, tree, tree, tree, bool);
184static tree fold_builtin_varargs (location_t, tree, tree, bool);
185
186static tree fold_builtin_strpbrk (location_t, tree, tree, tree);
187static tree fold_builtin_strstr (location_t, tree, tree, tree);
188static tree fold_builtin_strrchr (location_t, tree, tree, tree);
189static tree fold_builtin_strcat (location_t, tree, tree);
190static tree fold_builtin_strncat (location_t, tree, tree, tree);
191static tree fold_builtin_strspn (location_t, tree, tree);
192static tree fold_builtin_strcspn (location_t, tree, tree);
193static tree fold_builtin_sprintf (location_t, tree, tree, tree, int);
750d7b16 194static tree fold_builtin_snprintf (location_t, tree, tree, tree, tree, int);
4ee9c684 195
0a39fd54 196static rtx expand_builtin_object_size (tree);
197static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
198 enum built_in_function);
199static void maybe_emit_chk_warning (tree, enum built_in_function);
200static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
2c281b15 201static void maybe_emit_free_warning (tree);
c2f47e15 202static tree fold_builtin_object_size (tree, tree);
389dd41b 203static tree fold_builtin_strcat_chk (location_t, tree, tree, tree, tree);
204static tree fold_builtin_strncat_chk (location_t, tree, tree, tree, tree, tree);
205static tree fold_builtin_sprintf_chk (location_t, tree, enum built_in_function);
206static tree fold_builtin_printf (location_t, tree, tree, tree, bool, enum built_in_function);
207static tree fold_builtin_fprintf (location_t, tree, tree, tree, tree, bool,
c2f47e15 208 enum built_in_function);
99eabcc1 209static bool init_target_chars (void);
210
211static unsigned HOST_WIDE_INT target_newline;
212static unsigned HOST_WIDE_INT target_percent;
213static unsigned HOST_WIDE_INT target_c;
214static unsigned HOST_WIDE_INT target_s;
215static char target_percent_c[3];
216static char target_percent_s[3];
217static char target_percent_s_newline[4];
728bac60 218static tree do_mpfr_arg1 (tree, tree, int (*)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
219 const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, bool);
f0c477f2 220static tree do_mpfr_arg2 (tree, tree, tree,
221 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
9917422b 222static tree do_mpfr_arg3 (tree, tree, tree, tree,
223 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
d92f994c 224static tree do_mpfr_sincos (tree, tree, tree);
65dd1378 225static tree do_mpfr_bessel_n (tree, tree, tree,
226 int (*)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
227 const REAL_VALUE_TYPE *, bool);
e5407ca6 228static tree do_mpfr_remquo (tree, tree, tree);
e84da7c1 229static tree do_mpfr_lgamma_r (tree, tree, tree);
0a39fd54 230
7bfefa9d 231/* Return true if NAME starts with __builtin_ or __sync_. */
232
1c47b3e8 233bool
234is_builtin_name (const char *name)
b6a5fc45 235{
b6a5fc45 236 if (strncmp (name, "__builtin_", 10) == 0)
237 return true;
238 if (strncmp (name, "__sync_", 7) == 0)
239 return true;
240 return false;
241}
4ee9c684 242
7bfefa9d 243
244/* Return true if DECL is a function symbol representing a built-in. */
245
246bool
247is_builtin_fn (tree decl)
248{
249 return TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl);
250}
251
252
1c47b3e8 253/* Return true if NODE should be considered for inline expansion regardless
254 of the optimization level. This means whenever a function is invoked with
255 its "internal" name, which normally contains the prefix "__builtin". */
256
257static bool
258called_as_built_in (tree node)
259{
260 /* Note that we must use DECL_NAME, not DECL_ASSEMBLER_NAME_SET_P since
261 we want the name used to call the function, not the name it
262 will have. */
263 const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
264 return is_builtin_name (name);
265}
266
0d8f7716 267/* Compute values M and N such that M divides (address of EXP - N) and
268 such that N < M. Store N in *BITPOSP and return M.
269
270 Note that the address (and thus the alignment) computed here is based
271 on the address to which a symbol resolves, whereas DECL_ALIGN is based
272 on the address at which an object is actually located. These two
273 addresses are not always the same. For example, on ARM targets,
274 the address &foo of a Thumb function foo() has the lowest bit set,
275 whereas foo() itself starts on an even address. */
698537d1 276
98ab9e8f 277unsigned int
0c883ef3 278get_object_alignment_1 (tree exp, unsigned HOST_WIDE_INT *bitposp)
698537d1 279{
98ab9e8f 280 HOST_WIDE_INT bitsize, bitpos;
281 tree offset;
282 enum machine_mode mode;
283 int unsignedp, volatilep;
284 unsigned int align, inner;
698537d1 285
98ab9e8f 286 /* Get the innermost object and the constant (bitpos) and possibly
287 variable (offset) offset of the access. */
288 exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
289 &mode, &unsignedp, &volatilep, true);
290
291 /* Extract alignment information from the innermost object and
292 possibly adjust bitpos and offset. */
0ea95334 293 if (TREE_CODE (exp) == CONST_DECL)
294 exp = DECL_INITIAL (exp);
e064ace6 295 if (DECL_P (exp)
296 && TREE_CODE (exp) != LABEL_DECL)
0d8f7716 297 {
298 if (TREE_CODE (exp) == FUNCTION_DECL)
299 {
300 /* Function addresses can encode extra information besides their
301 alignment. However, if TARGET_PTRMEMFUNC_VBIT_LOCATION
302 allows the low bit to be used as a virtual bit, we know
303 that the address itself must be 2-byte aligned. */
304 if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn)
305 align = 2 * BITS_PER_UNIT;
306 else
307 align = BITS_PER_UNIT;
308 }
309 else
310 align = DECL_ALIGN (exp);
311 }
698537d1 312 else if (CONSTANT_CLASS_P (exp))
98ab9e8f 313 {
314 align = TYPE_ALIGN (TREE_TYPE (exp));
315#ifdef CONSTANT_ALIGNMENT
316 align = (unsigned)CONSTANT_ALIGNMENT (exp, align);
698537d1 317#endif
98ab9e8f 318 }
319 else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR)
320 align = TYPE_ALIGN (TREE_TYPE (exp));
321 else if (TREE_CODE (exp) == INDIRECT_REF)
322 align = TYPE_ALIGN (TREE_TYPE (exp));
98ab9e8f 323 else if (TREE_CODE (exp) == MEM_REF)
324 {
325 tree addr = TREE_OPERAND (exp, 0);
153c3b50 326 struct ptr_info_def *pi;
98ab9e8f 327 if (TREE_CODE (addr) == BIT_AND_EXPR
328 && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
329 {
330 align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))
331 & -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)));
332 align *= BITS_PER_UNIT;
333 addr = TREE_OPERAND (addr, 0);
334 }
335 else
336 align = BITS_PER_UNIT;
153c3b50 337 if (TREE_CODE (addr) == SSA_NAME
338 && (pi = SSA_NAME_PTR_INFO (addr)))
339 {
340 bitpos += (pi->misalign * BITS_PER_UNIT) & ~(align - 1);
341 align = MAX (pi->align * BITS_PER_UNIT, align);
342 }
343 else if (TREE_CODE (addr) == ADDR_EXPR)
0c883ef3 344 align = MAX (align, get_object_alignment (TREE_OPERAND (addr, 0), ~0U));
98ab9e8f 345 bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT;
346 }
28daba6f 347 else if (TREE_CODE (exp) == TARGET_MEM_REF)
153c3b50 348 {
349 struct ptr_info_def *pi;
350 tree addr = TMR_BASE (exp);
351 if (TREE_CODE (addr) == BIT_AND_EXPR
352 && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
353 {
354 align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))
355 & -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)));
356 align *= BITS_PER_UNIT;
357 addr = TREE_OPERAND (addr, 0);
358 }
359 else
360 align = BITS_PER_UNIT;
361 if (TREE_CODE (addr) == SSA_NAME
362 && (pi = SSA_NAME_PTR_INFO (addr)))
363 {
364 bitpos += (pi->misalign * BITS_PER_UNIT) & ~(align - 1);
365 align = MAX (pi->align * BITS_PER_UNIT, align);
366 }
367 else if (TREE_CODE (addr) == ADDR_EXPR)
0c883ef3 368 align = MAX (align, get_object_alignment (TREE_OPERAND (addr, 0), ~0U));
153c3b50 369 if (TMR_OFFSET (exp))
370 bitpos += TREE_INT_CST_LOW (TMR_OFFSET (exp)) * BITS_PER_UNIT;
371 if (TMR_INDEX (exp) && TMR_STEP (exp))
372 {
373 unsigned HOST_WIDE_INT step = TREE_INT_CST_LOW (TMR_STEP (exp));
374 align = MIN (align, (step & -step) * BITS_PER_UNIT);
375 }
376 else if (TMR_INDEX (exp))
377 align = BITS_PER_UNIT;
28daba6f 378 if (TMR_INDEX2 (exp))
e077c79b 379 align = BITS_PER_UNIT;
98ab9e8f 380 }
698537d1 381 else
98ab9e8f 382 align = BITS_PER_UNIT;
383
384 /* If there is a non-constant offset part extract the maximum
385 alignment that can prevail. */
0c883ef3 386 inner = ~0U;
98ab9e8f 387 while (offset)
388 {
389 tree next_offset;
390
391 if (TREE_CODE (offset) == PLUS_EXPR)
392 {
393 next_offset = TREE_OPERAND (offset, 0);
394 offset = TREE_OPERAND (offset, 1);
395 }
396 else
397 next_offset = NULL;
398 if (host_integerp (offset, 1))
399 {
400 /* Any overflow in calculating offset_bits won't change
401 the alignment. */
402 unsigned offset_bits
403 = ((unsigned) tree_low_cst (offset, 1) * BITS_PER_UNIT);
404
405 if (offset_bits)
406 inner = MIN (inner, (offset_bits & -offset_bits));
407 }
408 else if (TREE_CODE (offset) == MULT_EXPR
409 && host_integerp (TREE_OPERAND (offset, 1), 1))
410 {
411 /* Any overflow in calculating offset_factor won't change
412 the alignment. */
413 unsigned offset_factor
414 = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
415 * BITS_PER_UNIT);
416
417 if (offset_factor)
418 inner = MIN (inner, (offset_factor & -offset_factor));
419 }
420 else
421 {
422 inner = MIN (inner, BITS_PER_UNIT);
423 break;
424 }
425 offset = next_offset;
426 }
427
428 /* Alignment is innermost object alignment adjusted by the constant
429 and non-constant offset parts. */
430 align = MIN (align, inner);
431 bitpos = bitpos & (align - 1);
432
0c883ef3 433 *bitposp = bitpos;
434 return align;
435}
436
437/* Return the alignment in bits of EXP, an object.
438 Don't return more than MAX_ALIGN no matter what. */
439
440unsigned int
441get_object_alignment (tree exp, unsigned int max_align)
442{
443 unsigned HOST_WIDE_INT bitpos = 0;
444 unsigned int align;
445
446 align = get_object_alignment_1 (exp, &bitpos);
447
98ab9e8f 448 /* align and bitpos now specify known low bits of the pointer.
449 ptr & (align - 1) == bitpos. */
450
451 if (bitpos != 0)
452 align = (bitpos & -bitpos);
453
698537d1 454 return MIN (align, max_align);
455}
456
7abca321 457/* Returns true iff we can trust that alignment information has been
458 calculated properly. */
459
460bool
461can_trust_pointer_alignment (void)
462{
463 /* We rely on TER to compute accurate alignment information. */
464 return (optimize && flag_tree_ter);
465}
466
53800dbe 467/* Return the alignment in bits of EXP, a pointer valued expression.
468 But don't return more than MAX_ALIGN no matter what.
469 The alignment returned is, by default, the alignment of the thing that
27d0c333 470 EXP points to. If it is not a POINTER_TYPE, 0 is returned.
53800dbe 471
472 Otherwise, look at the expression to see if we can do better, i.e., if the
473 expression is actually pointing at an object whose alignment is tighter. */
474
153c3b50 475unsigned int
aecda0d6 476get_pointer_alignment (tree exp, unsigned int max_align)
53800dbe 477{
153c3b50 478 STRIP_NOPS (exp);
535e2026 479
153c3b50 480 if (TREE_CODE (exp) == ADDR_EXPR)
481 return get_object_alignment (TREE_OPERAND (exp, 0), max_align);
482 else if (TREE_CODE (exp) == SSA_NAME
483 && POINTER_TYPE_P (TREE_TYPE (exp)))
53800dbe 484 {
153c3b50 485 struct ptr_info_def *pi = SSA_NAME_PTR_INFO (exp);
486 unsigned align;
487 if (!pi)
488 return BITS_PER_UNIT;
489 if (pi->misalign != 0)
490 align = (pi->misalign & -pi->misalign);
491 else
492 align = pi->align;
493 return MIN (max_align, align * BITS_PER_UNIT);
53800dbe 494 }
153c3b50 495
496 return POINTER_TYPE_P (TREE_TYPE (exp)) ? BITS_PER_UNIT : 0;
53800dbe 497}
498
499/* Compute the length of a C string. TREE_STRING_LENGTH is not the right
500 way, because it could contain a zero byte in the middle.
501 TREE_STRING_LENGTH is the size of the character array, not the string.
502
4172d65e 503 ONLY_VALUE should be nonzero if the result is not going to be emitted
c09841f6 504 into the instruction stream and zero if it is going to be expanded.
4172d65e 505 E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
681fab1e 506 is returned, otherwise NULL, since
507 len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
508 evaluate the side-effects.
509
902de8ed 510 The value returned is of type `ssizetype'.
511
53800dbe 512 Unfortunately, string_constant can't access the values of const char
513 arrays with initializers, so neither can we do so here. */
514
4ee9c684 515tree
681fab1e 516c_strlen (tree src, int only_value)
53800dbe 517{
518 tree offset_node;
27d0c333 519 HOST_WIDE_INT offset;
520 int max;
44acf429 521 const char *ptr;
da136652 522 location_t loc;
53800dbe 523
681fab1e 524 STRIP_NOPS (src);
525 if (TREE_CODE (src) == COND_EXPR
526 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
527 {
528 tree len1, len2;
529
530 len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
531 len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
0862b7e9 532 if (tree_int_cst_equal (len1, len2))
681fab1e 533 return len1;
534 }
535
536 if (TREE_CODE (src) == COMPOUND_EXPR
537 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
538 return c_strlen (TREE_OPERAND (src, 1), only_value);
539
8637f1db 540 loc = EXPR_LOC_OR_HERE (src);
da136652 541
53800dbe 542 src = string_constant (src, &offset_node);
543 if (src == 0)
c2f47e15 544 return NULL_TREE;
902de8ed 545
83d79705 546 max = TREE_STRING_LENGTH (src) - 1;
53800dbe 547 ptr = TREE_STRING_POINTER (src);
902de8ed 548
53800dbe 549 if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
550 {
551 /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
552 compute the offset to the following null if we don't know where to
553 start searching for it. */
554 int i;
902de8ed 555
53800dbe 556 for (i = 0; i < max; i++)
557 if (ptr[i] == 0)
c2f47e15 558 return NULL_TREE;
902de8ed 559
53800dbe 560 /* We don't know the starting offset, but we do know that the string
561 has no internal zero bytes. We can assume that the offset falls
562 within the bounds of the string; otherwise, the programmer deserves
563 what he gets. Subtract the offset from the length of the string,
902de8ed 564 and return that. This would perhaps not be valid if we were dealing
565 with named arrays in addition to literal string constants. */
566
da136652 567 return size_diffop_loc (loc, size_int (max), offset_node);
53800dbe 568 }
569
570 /* We have a known offset into the string. Start searching there for
27d0c333 571 a null character if we can represent it as a single HOST_WIDE_INT. */
dabc4084 572 if (offset_node == 0)
53800dbe 573 offset = 0;
dabc4084 574 else if (! host_integerp (offset_node, 0))
575 offset = -1;
53800dbe 576 else
27d0c333 577 offset = tree_low_cst (offset_node, 0);
902de8ed 578
1f63a7d6 579 /* If the offset is known to be out of bounds, warn, and call strlen at
580 runtime. */
53800dbe 581 if (offset < 0 || offset > max)
582 {
1f63a7d6 583 /* Suppress multiple warnings for propagated constant strings. */
584 if (! TREE_NO_WARNING (src))
585 {
da136652 586 warning_at (loc, 0, "offset outside bounds of constant string");
1f63a7d6 587 TREE_NO_WARNING (src) = 1;
588 }
c2f47e15 589 return NULL_TREE;
53800dbe 590 }
902de8ed 591
53800dbe 592 /* Use strlen to search for the first zero byte. Since any strings
593 constructed with build_string will have nulls appended, we win even
594 if we get handed something like (char[4])"abcd".
595
596 Since OFFSET is our starting index into the string, no further
597 calculation is needed. */
902de8ed 598 return ssize_int (strlen (ptr + offset));
53800dbe 599}
600
83d79705 601/* Return a char pointer for a C string if it is a string constant
602 or sum of string constant and integer constant. */
603
604static const char *
aecda0d6 605c_getstr (tree src)
83d79705 606{
607 tree offset_node;
83d79705 608
609 src = string_constant (src, &offset_node);
610 if (src == 0)
611 return 0;
612
8c85fcb7 613 if (offset_node == 0)
614 return TREE_STRING_POINTER (src);
615 else if (!host_integerp (offset_node, 1)
616 || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
83d79705 617 return 0;
83d79705 618
8c85fcb7 619 return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
83d79705 620}
621
8c85fcb7 622/* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
623 GET_MODE_BITSIZE (MODE) bits from string constant STR. */
ecc318ff 624
6840589f 625static rtx
aecda0d6 626c_readstr (const char *str, enum machine_mode mode)
6840589f 627{
628 HOST_WIDE_INT c[2];
629 HOST_WIDE_INT ch;
630 unsigned int i, j;
631
64db345d 632 gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
7d3f6cc7 633
6840589f 634 c[0] = 0;
635 c[1] = 0;
636 ch = 1;
637 for (i = 0; i < GET_MODE_SIZE (mode); i++)
638 {
639 j = i;
640 if (WORDS_BIG_ENDIAN)
641 j = GET_MODE_SIZE (mode) - i - 1;
642 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
ad8f8e52 643 && GET_MODE_SIZE (mode) >= UNITS_PER_WORD)
6840589f 644 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
645 j *= BITS_PER_UNIT;
e212f99a 646 gcc_assert (j < 2 * HOST_BITS_PER_WIDE_INT);
7d3f6cc7 647
6840589f 648 if (ch)
649 ch = (unsigned char) str[i];
650 c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
651 }
652 return immed_double_const (c[0], c[1], mode);
653}
654
ecc318ff 655/* Cast a target constant CST to target CHAR and if that value fits into
5206b159 656 host char type, return zero and put that value into variable pointed to by
ecc318ff 657 P. */
658
659static int
aecda0d6 660target_char_cast (tree cst, char *p)
ecc318ff 661{
662 unsigned HOST_WIDE_INT val, hostval;
663
c19686c5 664 if (TREE_CODE (cst) != INTEGER_CST
ecc318ff 665 || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
666 return 1;
667
c19686c5 668 val = TREE_INT_CST_LOW (cst);
ecc318ff 669 if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
670 val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
671
672 hostval = val;
673 if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
674 hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
675
676 if (val != hostval)
677 return 1;
678
679 *p = hostval;
680 return 0;
681}
682
4ee9c684 683/* Similar to save_expr, but assumes that arbitrary code is not executed
684 in between the multiple evaluations. In particular, we assume that a
685 non-addressable local variable will not be modified. */
686
687static tree
688builtin_save_expr (tree exp)
689{
f6c35aa4 690 if (TREE_CODE (exp) == SSA_NAME
691 || (TREE_ADDRESSABLE (exp) == 0
692 && (TREE_CODE (exp) == PARM_DECL
693 || (TREE_CODE (exp) == VAR_DECL && !TREE_STATIC (exp)))))
4ee9c684 694 return exp;
695
696 return save_expr (exp);
697}
698
53800dbe 699/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
700 times to get the address of either a higher stack frame, or a return
701 address located within it (depending on FNDECL_CODE). */
902de8ed 702
c626df3d 703static rtx
869d0ef0 704expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
53800dbe 705{
706 int i;
707
869d0ef0 708#ifdef INITIAL_FRAME_ADDRESS_RTX
709 rtx tem = INITIAL_FRAME_ADDRESS_RTX;
710#else
e3e15c50 711 rtx tem;
712
1b74fde7 713 /* For a zero count with __builtin_return_address, we don't care what
714 frame address we return, because target-specific definitions will
715 override us. Therefore frame pointer elimination is OK, and using
716 the soft frame pointer is OK.
717
fa7637bd 718 For a nonzero count, or a zero count with __builtin_frame_address,
1b74fde7 719 we require a stable offset from the current frame pointer to the
720 previous one, so we must use the hard frame pointer, and
e3e15c50 721 we must disable frame pointer elimination. */
1b74fde7 722 if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
e3e15c50 723 tem = frame_pointer_rtx;
a0c938f0 724 else
e3e15c50 725 {
726 tem = hard_frame_pointer_rtx;
727
728 /* Tell reload not to eliminate the frame pointer. */
18d50ae6 729 crtl->accesses_prior_frames = 1;
e3e15c50 730 }
869d0ef0 731#endif
732
53800dbe 733 /* Some machines need special handling before we can access
3a69c60c 734 arbitrary frames. For example, on the SPARC, we must first flush
53800dbe 735 all register windows to the stack. */
736#ifdef SETUP_FRAME_ADDRESSES
737 if (count > 0)
738 SETUP_FRAME_ADDRESSES ();
739#endif
740
3a69c60c 741 /* On the SPARC, the return address is not in the frame, it is in a
53800dbe 742 register. There is no way to access it off of the current frame
743 pointer, but it can be accessed off the previous frame pointer by
744 reading the value from the register window save area. */
745#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
746 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
747 count--;
748#endif
749
750 /* Scan back COUNT frames to the specified frame. */
751 for (i = 0; i < count; i++)
752 {
753 /* Assume the dynamic chain pointer is in the word that the
754 frame address points to, unless otherwise specified. */
755#ifdef DYNAMIC_CHAIN_ADDRESS
756 tem = DYNAMIC_CHAIN_ADDRESS (tem);
757#endif
758 tem = memory_address (Pmode, tem);
00060fc2 759 tem = gen_frame_mem (Pmode, tem);
83fc1478 760 tem = copy_to_reg (tem);
53800dbe 761 }
762
3a69c60c 763 /* For __builtin_frame_address, return what we've got. But, on
764 the SPARC for example, we may have to add a bias. */
53800dbe 765 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
3a69c60c 766#ifdef FRAME_ADDR_RTX
767 return FRAME_ADDR_RTX (tem);
768#else
53800dbe 769 return tem;
3a69c60c 770#endif
53800dbe 771
3a69c60c 772 /* For __builtin_return_address, get the return address from that frame. */
53800dbe 773#ifdef RETURN_ADDR_RTX
774 tem = RETURN_ADDR_RTX (count, tem);
775#else
776 tem = memory_address (Pmode,
777 plus_constant (tem, GET_MODE_SIZE (Pmode)));
00060fc2 778 tem = gen_frame_mem (Pmode, tem);
53800dbe 779#endif
780 return tem;
781}
782
f7c44134 783/* Alias set used for setjmp buffer. */
32c2fdea 784static alias_set_type setjmp_alias_set = -1;
f7c44134 785
6b7f6858 786/* Construct the leading half of a __builtin_setjmp call. Control will
2c8a1497 787 return to RECEIVER_LABEL. This is also called directly by the SJLJ
788 exception handling code. */
53800dbe 789
6b7f6858 790void
aecda0d6 791expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
53800dbe 792{
53800dbe 793 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
53800dbe 794 rtx stack_save;
f7c44134 795 rtx mem;
53800dbe 796
f7c44134 797 if (setjmp_alias_set == -1)
798 setjmp_alias_set = new_alias_set ();
799
85d654dd 800 buf_addr = convert_memory_address (Pmode, buf_addr);
53800dbe 801
37ae8504 802 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
53800dbe 803
6b7f6858 804 /* We store the frame pointer and the address of receiver_label in
805 the buffer and use the rest of it for the stack save area, which
806 is machine-dependent. */
53800dbe 807
f7c44134 808 mem = gen_rtx_MEM (Pmode, buf_addr);
ab6ab77e 809 set_mem_alias_set (mem, setjmp_alias_set);
e3e026e8 810 emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
f7c44134 811
812 mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
ab6ab77e 813 set_mem_alias_set (mem, setjmp_alias_set);
f7c44134 814
815 emit_move_insn (validize_mem (mem),
6b7f6858 816 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
53800dbe 817
818 stack_save = gen_rtx_MEM (sa_mode,
819 plus_constant (buf_addr,
820 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 821 set_mem_alias_set (stack_save, setjmp_alias_set);
e9c97615 822 emit_stack_save (SAVE_NONLOCAL, &stack_save);
53800dbe 823
824 /* If there is further processing to do, do it. */
825#ifdef HAVE_builtin_setjmp_setup
826 if (HAVE_builtin_setjmp_setup)
827 emit_insn (gen_builtin_setjmp_setup (buf_addr));
828#endif
829
29f09705 830 /* We have a nonlocal label. */
18d50ae6 831 cfun->has_nonlocal_label = 1;
6b7f6858 832}
53800dbe 833
2c8a1497 834/* Construct the trailing part of a __builtin_setjmp call. This is
835 also called directly by the SJLJ exception handling code. */
6b7f6858 836
837void
aecda0d6 838expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
6b7f6858 839{
82c7907c 840 rtx chain;
841
53800dbe 842 /* Clobber the FP when we get here, so we have to make sure it's
843 marked as used by this function. */
18b42941 844 emit_use (hard_frame_pointer_rtx);
53800dbe 845
846 /* Mark the static chain as clobbered here so life information
847 doesn't get messed up for it. */
82c7907c 848 chain = targetm.calls.static_chain (current_function_decl, true);
849 if (chain && REG_P (chain))
850 emit_clobber (chain);
53800dbe 851
852 /* Now put in the code to restore the frame pointer, and argument
491e04ef 853 pointer, if needed. */
53800dbe 854#ifdef HAVE_nonlocal_goto
855 if (! HAVE_nonlocal_goto)
856#endif
5a1c3f40 857 {
858 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
859 /* This might change the hard frame pointer in ways that aren't
860 apparent to early optimization passes, so force a clobber. */
18b42941 861 emit_clobber (hard_frame_pointer_rtx);
5a1c3f40 862 }
53800dbe 863
5ae82d58 864#if !HARD_FRAME_POINTER_IS_ARG_POINTER
53800dbe 865 if (fixed_regs[ARG_POINTER_REGNUM])
866 {
867#ifdef ELIMINABLE_REGS
868 size_t i;
e99c3a1d 869 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
53800dbe 870
3098b2d3 871 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
53800dbe 872 if (elim_regs[i].from == ARG_POINTER_REGNUM
873 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
874 break;
875
3098b2d3 876 if (i == ARRAY_SIZE (elim_regs))
53800dbe 877#endif
878 {
879 /* Now restore our arg pointer from the address at which it
05927e40 880 was saved in our stack frame. */
27a7a23a 881 emit_move_insn (crtl->args.internal_arg_pointer,
b079a207 882 copy_to_reg (get_arg_pointer_save_area ()));
53800dbe 883 }
884 }
885#endif
886
887#ifdef HAVE_builtin_setjmp_receiver
888 if (HAVE_builtin_setjmp_receiver)
6b7f6858 889 emit_insn (gen_builtin_setjmp_receiver (receiver_label));
53800dbe 890 else
891#endif
892#ifdef HAVE_nonlocal_goto_receiver
893 if (HAVE_nonlocal_goto_receiver)
894 emit_insn (gen_nonlocal_goto_receiver ());
895 else
896#endif
6b7f6858 897 { /* Nothing */ }
57f6bb94 898
3072d30e 899 /* We must not allow the code we just generated to be reordered by
900 scheduling. Specifically, the update of the frame pointer must
901 happen immediately, not later. */
902 emit_insn (gen_blockage ());
6b7f6858 903}
53800dbe 904
53800dbe 905/* __builtin_longjmp is passed a pointer to an array of five words (not
906 all will be used on all machines). It operates similarly to the C
907 library function of the same name, but is more efficient. Much of
2c8a1497 908 the code below is copied from the handling of non-local gotos. */
53800dbe 909
c626df3d 910static void
aecda0d6 911expand_builtin_longjmp (rtx buf_addr, rtx value)
53800dbe 912{
4712c7d6 913 rtx fp, lab, stack, insn, last;
53800dbe 914 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
915
48e1416a 916 /* DRAP is needed for stack realign if longjmp is expanded to current
27a7a23a 917 function */
918 if (SUPPORTS_STACK_ALIGNMENT)
919 crtl->need_drap = true;
920
f7c44134 921 if (setjmp_alias_set == -1)
922 setjmp_alias_set = new_alias_set ();
923
85d654dd 924 buf_addr = convert_memory_address (Pmode, buf_addr);
479e4d5e 925
53800dbe 926 buf_addr = force_reg (Pmode, buf_addr);
927
82c7907c 928 /* We require that the user must pass a second argument of 1, because
929 that is what builtin_setjmp will return. */
64db345d 930 gcc_assert (value == const1_rtx);
53800dbe 931
4712c7d6 932 last = get_last_insn ();
53800dbe 933#ifdef HAVE_builtin_longjmp
934 if (HAVE_builtin_longjmp)
935 emit_insn (gen_builtin_longjmp (buf_addr));
936 else
937#endif
938 {
939 fp = gen_rtx_MEM (Pmode, buf_addr);
940 lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
941 GET_MODE_SIZE (Pmode)));
942
943 stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
944 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 945 set_mem_alias_set (fp, setjmp_alias_set);
946 set_mem_alias_set (lab, setjmp_alias_set);
947 set_mem_alias_set (stack, setjmp_alias_set);
53800dbe 948
949 /* Pick up FP, label, and SP from the block and jump. This code is
950 from expand_goto in stmt.c; see there for detailed comments. */
03fd9d2c 951#ifdef HAVE_nonlocal_goto
53800dbe 952 if (HAVE_nonlocal_goto)
953 /* We have to pass a value to the nonlocal_goto pattern that will
954 get copied into the static_chain pointer, but it does not matter
955 what that value is, because builtin_setjmp does not use it. */
28d202a8 956 emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
53800dbe 957 else
958#endif
959 {
960 lab = copy_to_reg (lab);
961
18b42941 962 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
963 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
2a871ad1 964
53800dbe 965 emit_move_insn (hard_frame_pointer_rtx, fp);
e9c97615 966 emit_stack_restore (SAVE_NONLOCAL, stack);
53800dbe 967
18b42941 968 emit_use (hard_frame_pointer_rtx);
969 emit_use (stack_pointer_rtx);
53800dbe 970 emit_indirect_jump (lab);
971 }
972 }
615166bb 973
974 /* Search backwards and mark the jump insn as a non-local goto.
975 Note that this precludes the use of __builtin_longjmp to a
976 __builtin_setjmp target in the same function. However, we've
977 already cautioned the user that these functions are for
978 internal exception handling use only. */
449c0509 979 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
980 {
64db345d 981 gcc_assert (insn != last);
7d3f6cc7 982
6d7dc5b9 983 if (JUMP_P (insn))
449c0509 984 {
a1ddb869 985 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
449c0509 986 break;
987 }
6d7dc5b9 988 else if (CALL_P (insn))
9342ee68 989 break;
449c0509 990 }
53800dbe 991}
992
4ee9c684 993/* Expand a call to __builtin_nonlocal_goto. We're passed the target label
994 and the address of the save area. */
995
996static rtx
c2f47e15 997expand_builtin_nonlocal_goto (tree exp)
4ee9c684 998{
999 tree t_label, t_save_area;
1000 rtx r_label, r_save_area, r_fp, r_sp, insn;
1001
c2f47e15 1002 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4ee9c684 1003 return NULL_RTX;
1004
c2f47e15 1005 t_label = CALL_EXPR_ARG (exp, 0);
1006 t_save_area = CALL_EXPR_ARG (exp, 1);
4ee9c684 1007
8ec3c5c2 1008 r_label = expand_normal (t_label);
3dce56cc 1009 r_label = convert_memory_address (Pmode, r_label);
8ec3c5c2 1010 r_save_area = expand_normal (t_save_area);
3dce56cc 1011 r_save_area = convert_memory_address (Pmode, r_save_area);
d1ff492e 1012 /* Copy the address of the save location to a register just in case it was
1013 based on the frame pointer. */
51adbc8a 1014 r_save_area = copy_to_reg (r_save_area);
4ee9c684 1015 r_fp = gen_rtx_MEM (Pmode, r_save_area);
1016 r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
1017 plus_constant (r_save_area, GET_MODE_SIZE (Pmode)));
1018
18d50ae6 1019 crtl->has_nonlocal_goto = 1;
4ee9c684 1020
03fd9d2c 1021#ifdef HAVE_nonlocal_goto
4ee9c684 1022 /* ??? We no longer need to pass the static chain value, afaik. */
1023 if (HAVE_nonlocal_goto)
1024 emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
1025 else
1026#endif
1027 {
1028 r_label = copy_to_reg (r_label);
1029
18b42941 1030 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
1031 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
491e04ef 1032
d1ff492e 1033 /* Restore frame pointer for containing function. */
4ee9c684 1034 emit_move_insn (hard_frame_pointer_rtx, r_fp);
e9c97615 1035 emit_stack_restore (SAVE_NONLOCAL, r_sp);
491e04ef 1036
4ee9c684 1037 /* USE of hard_frame_pointer_rtx added for consistency;
1038 not clear if really needed. */
18b42941 1039 emit_use (hard_frame_pointer_rtx);
1040 emit_use (stack_pointer_rtx);
ad0d0af8 1041
1042 /* If the architecture is using a GP register, we must
1043 conservatively assume that the target function makes use of it.
1044 The prologue of functions with nonlocal gotos must therefore
1045 initialize the GP register to the appropriate value, and we
1046 must then make sure that this value is live at the point
1047 of the jump. (Note that this doesn't necessarily apply
1048 to targets with a nonlocal_goto pattern; they are free
1049 to implement it in their own way. Note also that this is
1050 a no-op if the GP register is a global invariant.) */
1051 if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
1052 && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
18b42941 1053 emit_use (pic_offset_table_rtx);
ad0d0af8 1054
4ee9c684 1055 emit_indirect_jump (r_label);
1056 }
491e04ef 1057
4ee9c684 1058 /* Search backwards to the jump insn and mark it as a
1059 non-local goto. */
1060 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
1061 {
6d7dc5b9 1062 if (JUMP_P (insn))
4ee9c684 1063 {
a1ddb869 1064 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
4ee9c684 1065 break;
1066 }
6d7dc5b9 1067 else if (CALL_P (insn))
4ee9c684 1068 break;
1069 }
1070
1071 return const0_rtx;
1072}
1073
843d08a9 1074/* __builtin_update_setjmp_buf is passed a pointer to an array of five words
1075 (not all will be used on all machines) that was passed to __builtin_setjmp.
1076 It updates the stack pointer in that block to correspond to the current
1077 stack pointer. */
1078
1079static void
1080expand_builtin_update_setjmp_buf (rtx buf_addr)
1081{
d1ff492e 1082 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
1083 rtx stack_save
843d08a9 1084 = gen_rtx_MEM (sa_mode,
1085 memory_address
1086 (sa_mode,
1087 plus_constant (buf_addr, 2 * GET_MODE_SIZE (Pmode))));
1088
e9c97615 1089 emit_stack_save (SAVE_NONLOCAL, &stack_save);
843d08a9 1090}
1091
5e3608d8 1092/* Expand a call to __builtin_prefetch. For a target that does not support
1093 data prefetch, evaluate the memory address argument in case it has side
1094 effects. */
1095
1096static void
c2f47e15 1097expand_builtin_prefetch (tree exp)
5e3608d8 1098{
1099 tree arg0, arg1, arg2;
c2f47e15 1100 int nargs;
5e3608d8 1101 rtx op0, op1, op2;
1102
c2f47e15 1103 if (!validate_arglist (exp, POINTER_TYPE, 0))
26a5cadb 1104 return;
1105
c2f47e15 1106 arg0 = CALL_EXPR_ARG (exp, 0);
1107
26a5cadb 1108 /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
1109 zero (read) and argument 2 (locality) defaults to 3 (high degree of
1110 locality). */
c2f47e15 1111 nargs = call_expr_nargs (exp);
1112 if (nargs > 1)
1113 arg1 = CALL_EXPR_ARG (exp, 1);
26a5cadb 1114 else
c2f47e15 1115 arg1 = integer_zero_node;
1116 if (nargs > 2)
1117 arg2 = CALL_EXPR_ARG (exp, 2);
1118 else
2512209b 1119 arg2 = integer_three_node;
5e3608d8 1120
1121 /* Argument 0 is an address. */
1122 op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
1123
1124 /* Argument 1 (read/write flag) must be a compile-time constant int. */
1125 if (TREE_CODE (arg1) != INTEGER_CST)
1126 {
07e3a3d2 1127 error ("second argument to %<__builtin_prefetch%> must be a constant");
9342ee68 1128 arg1 = integer_zero_node;
5e3608d8 1129 }
8ec3c5c2 1130 op1 = expand_normal (arg1);
5e3608d8 1131 /* Argument 1 must be either zero or one. */
1132 if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
1133 {
c3ceba8e 1134 warning (0, "invalid second argument to %<__builtin_prefetch%>;"
07e3a3d2 1135 " using zero");
5e3608d8 1136 op1 = const0_rtx;
1137 }
1138
1139 /* Argument 2 (locality) must be a compile-time constant int. */
1140 if (TREE_CODE (arg2) != INTEGER_CST)
1141 {
07e3a3d2 1142 error ("third argument to %<__builtin_prefetch%> must be a constant");
5e3608d8 1143 arg2 = integer_zero_node;
1144 }
8ec3c5c2 1145 op2 = expand_normal (arg2);
5e3608d8 1146 /* Argument 2 must be 0, 1, 2, or 3. */
1147 if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
1148 {
c3ceba8e 1149 warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
5e3608d8 1150 op2 = const0_rtx;
1151 }
1152
1153#ifdef HAVE_prefetch
1154 if (HAVE_prefetch)
1155 {
8786db1e 1156 struct expand_operand ops[3];
1157
1158 create_address_operand (&ops[0], op0);
1159 create_integer_operand (&ops[1], INTVAL (op1));
1160 create_integer_operand (&ops[2], INTVAL (op2));
1161 if (maybe_expand_insn (CODE_FOR_prefetch, 3, ops))
1162 return;
5e3608d8 1163 }
5e3608d8 1164#endif
0a534ba7 1165
f0ce3b1f 1166 /* Don't do anything with direct references to volatile memory, but
1167 generate code to handle other side effects. */
e16ceb8e 1168 if (!MEM_P (op0) && side_effects_p (op0))
f0ce3b1f 1169 emit_insn (op0);
5e3608d8 1170}
1171
f7c44134 1172/* Get a MEM rtx for expression EXP which is the address of an operand
d8ae1baa 1173 to be used in a string instruction (cmpstrsi, movmemsi, ..). LEN is
1174 the maximum length of the block of memory that might be accessed or
1175 NULL if unknown. */
f7c44134 1176
53800dbe 1177static rtx
d8ae1baa 1178get_memory_rtx (tree exp, tree len)
53800dbe 1179{
ad0a178f 1180 tree orig_exp = exp;
1181 rtx addr, mem;
1182 HOST_WIDE_INT off;
1183
1184 /* When EXP is not resolved SAVE_EXPR, MEM_ATTRS can be still derived
1185 from its expression, for expr->a.b only <variable>.a.b is recorded. */
1186 if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp))
1187 exp = TREE_OPERAND (exp, 0);
1188
1189 addr = expand_expr (orig_exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
1190 mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
2a631e19 1191
f7c44134 1192 /* Get an expression we can use to find the attributes to assign to MEM.
1193 If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
1194 we can. First remove any nops. */
72dd6141 1195 while (CONVERT_EXPR_P (exp)
f7c44134 1196 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
1197 exp = TREE_OPERAND (exp, 0);
1198
ad0a178f 1199 off = 0;
1200 if (TREE_CODE (exp) == POINTER_PLUS_EXPR
1201 && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
1202 && host_integerp (TREE_OPERAND (exp, 1), 0)
1203 && (off = tree_low_cst (TREE_OPERAND (exp, 1), 0)) > 0)
1204 exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
1205 else if (TREE_CODE (exp) == ADDR_EXPR)
a1a25d19 1206 exp = TREE_OPERAND (exp, 0);
f7c44134 1207 else if (POINTER_TYPE_P (TREE_TYPE (exp)))
a1a25d19 1208 exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
1209 else
1210 exp = NULL;
1211
1212 /* Honor attributes derived from exp, except for the alias set
1213 (as builtin stringops may alias with anything) and the size
1214 (as stringops may access multiple array elements). */
1215 if (exp)
eec8e941 1216 {
a1a25d19 1217 set_mem_attributes (mem, exp, 0);
d8ae1baa 1218
ad0a178f 1219 if (off)
1220 mem = adjust_automodify_address_nv (mem, BLKmode, NULL, off);
1221
d8ae1baa 1222 /* Allow the string and memory builtins to overflow from one
1223 field into another, see http://gcc.gnu.org/PR23561.
1224 Thus avoid COMPONENT_REFs in MEM_EXPR unless we know the whole
1225 memory accessed by the string or memory builtin will fit
1226 within the field. */
1227 if (MEM_EXPR (mem) && TREE_CODE (MEM_EXPR (mem)) == COMPONENT_REF)
1228 {
1229 tree mem_expr = MEM_EXPR (mem);
1230 HOST_WIDE_INT offset = -1, length = -1;
1231 tree inner = exp;
1232
1233 while (TREE_CODE (inner) == ARRAY_REF
72dd6141 1234 || CONVERT_EXPR_P (inner)
d8ae1baa 1235 || TREE_CODE (inner) == VIEW_CONVERT_EXPR
1236 || TREE_CODE (inner) == SAVE_EXPR)
1237 inner = TREE_OPERAND (inner, 0);
1238
1239 gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
1240
1241 if (MEM_OFFSET (mem)
971ba038 1242 && CONST_INT_P (MEM_OFFSET (mem)))
d8ae1baa 1243 offset = INTVAL (MEM_OFFSET (mem));
1244
1245 if (offset >= 0 && len && host_integerp (len, 0))
1246 length = tree_low_cst (len, 0);
1247
1248 while (TREE_CODE (inner) == COMPONENT_REF)
1249 {
1250 tree field = TREE_OPERAND (inner, 1);
d8ae1baa 1251 gcc_assert (TREE_CODE (mem_expr) == COMPONENT_REF);
1252 gcc_assert (field == TREE_OPERAND (mem_expr, 1));
1253
6933ebec 1254 /* Bitfields are generally not byte-addressable. */
1255 gcc_assert (!DECL_BIT_FIELD (field)
1256 || ((tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
1257 % BITS_PER_UNIT) == 0
1258 && host_integerp (DECL_SIZE (field), 0)
1259 && (TREE_INT_CST_LOW (DECL_SIZE (field))
1260 % BITS_PER_UNIT) == 0));
1261
b2f0b2a3 1262 /* If we can prove that the memory starting at XEXP (mem, 0) and
1263 ending at XEXP (mem, 0) + LENGTH will fit into this field, we
1264 can keep the COMPONENT_REF in MEM_EXPR. But be careful with
1265 fields without DECL_SIZE_UNIT like flexible array members. */
d8ae1baa 1266 if (length >= 0
b2f0b2a3 1267 && DECL_SIZE_UNIT (field)
6933ebec 1268 && host_integerp (DECL_SIZE_UNIT (field), 0))
d8ae1baa 1269 {
1270 HOST_WIDE_INT size
6933ebec 1271 = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
d8ae1baa 1272 if (offset <= size
1273 && length <= size
1274 && offset + length <= size)
1275 break;
1276 }
1277
1278 if (offset >= 0
1279 && host_integerp (DECL_FIELD_OFFSET (field), 0))
6933ebec 1280 offset += TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
d8ae1baa 1281 + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
1282 / BITS_PER_UNIT;
1283 else
1284 {
1285 offset = -1;
1286 length = -1;
1287 }
1288
1289 mem_expr = TREE_OPERAND (mem_expr, 0);
1290 inner = TREE_OPERAND (inner, 0);
d8ae1baa 1291 }
1292
1293 if (mem_expr == NULL)
1294 offset = -1;
1295 if (mem_expr != MEM_EXPR (mem))
1296 {
1297 set_mem_expr (mem, mem_expr);
1298 set_mem_offset (mem, offset >= 0 ? GEN_INT (offset) : NULL_RTX);
1299 }
1300 }
eec8e941 1301 set_mem_alias_set (mem, 0);
a1a25d19 1302 set_mem_size (mem, NULL_RTX);
eec8e941 1303 }
53800dbe 1304
53800dbe 1305 return mem;
1306}
1307\f
1308/* Built-in functions to perform an untyped call and return. */
1309
3b9c3a16 1310#define apply_args_mode \
1311 (this_target_builtins->x_apply_args_mode)
1312#define apply_result_mode \
1313 (this_target_builtins->x_apply_result_mode)
53800dbe 1314
53800dbe 1315/* Return the size required for the block returned by __builtin_apply_args,
1316 and initialize apply_args_mode. */
1317
1318static int
aecda0d6 1319apply_args_size (void)
53800dbe 1320{
1321 static int size = -1;
58e9ce8f 1322 int align;
1323 unsigned int regno;
53800dbe 1324 enum machine_mode mode;
1325
1326 /* The values computed by this function never change. */
1327 if (size < 0)
1328 {
1329 /* The first value is the incoming arg-pointer. */
1330 size = GET_MODE_SIZE (Pmode);
1331
1332 /* The second value is the structure value address unless this is
1333 passed as an "invisible" first argument. */
6812c89e 1334 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1335 size += GET_MODE_SIZE (Pmode);
1336
1337 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1338 if (FUNCTION_ARG_REGNO_P (regno))
1339 {
4bac51c9 1340 mode = targetm.calls.get_raw_arg_mode (regno);
0862b7e9 1341
64db345d 1342 gcc_assert (mode != VOIDmode);
53800dbe 1343
1344 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1345 if (size % align != 0)
1346 size = CEIL (size, align) * align;
53800dbe 1347 size += GET_MODE_SIZE (mode);
1348 apply_args_mode[regno] = mode;
1349 }
1350 else
1351 {
1352 apply_args_mode[regno] = VOIDmode;
53800dbe 1353 }
1354 }
1355 return size;
1356}
1357
1358/* Return the size required for the block returned by __builtin_apply,
1359 and initialize apply_result_mode. */
1360
1361static int
aecda0d6 1362apply_result_size (void)
53800dbe 1363{
1364 static int size = -1;
1365 int align, regno;
1366 enum machine_mode mode;
1367
1368 /* The values computed by this function never change. */
1369 if (size < 0)
1370 {
1371 size = 0;
1372
1373 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
e1ce1485 1374 if (targetm.calls.function_value_regno_p (regno))
53800dbe 1375 {
4bac51c9 1376 mode = targetm.calls.get_raw_result_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;
1383 size += GET_MODE_SIZE (mode);
1384 apply_result_mode[regno] = mode;
1385 }
1386 else
1387 apply_result_mode[regno] = VOIDmode;
1388
1389 /* Allow targets that use untyped_call and untyped_return to override
1390 the size so that machine-specific information can be stored here. */
1391#ifdef APPLY_RESULT_SIZE
1392 size = APPLY_RESULT_SIZE;
1393#endif
1394 }
1395 return size;
1396}
1397
1398#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1399/* Create a vector describing the result block RESULT. If SAVEP is true,
1400 the result block is used to save the values; otherwise it is used to
1401 restore the values. */
1402
1403static rtx
aecda0d6 1404result_vector (int savep, rtx result)
53800dbe 1405{
1406 int regno, size, align, nelts;
1407 enum machine_mode mode;
1408 rtx reg, mem;
364c0c59 1409 rtx *savevec = XALLOCAVEC (rtx, FIRST_PSEUDO_REGISTER);
bf8e3599 1410
53800dbe 1411 size = nelts = 0;
1412 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1413 if ((mode = apply_result_mode[regno]) != VOIDmode)
1414 {
1415 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1416 if (size % align != 0)
1417 size = CEIL (size, align) * align;
1418 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
e513d163 1419 mem = adjust_address (result, mode, size);
53800dbe 1420 savevec[nelts++] = (savep
1421 ? gen_rtx_SET (VOIDmode, mem, reg)
1422 : gen_rtx_SET (VOIDmode, reg, mem));
1423 size += GET_MODE_SIZE (mode);
1424 }
1425 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1426}
1427#endif /* HAVE_untyped_call or HAVE_untyped_return */
1428
1429/* Save the state required to perform an untyped call with the same
1430 arguments as were passed to the current function. */
1431
1432static rtx
aecda0d6 1433expand_builtin_apply_args_1 (void)
53800dbe 1434{
1c7e61a7 1435 rtx registers, tem;
53800dbe 1436 int size, align, regno;
1437 enum machine_mode mode;
6812c89e 1438 rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
53800dbe 1439
1440 /* Create a block where the arg-pointer, structure value address,
1441 and argument registers can be saved. */
1442 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1443
1444 /* Walk past the arg-pointer and structure value address. */
1445 size = GET_MODE_SIZE (Pmode);
6812c89e 1446 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1447 size += GET_MODE_SIZE (Pmode);
1448
1449 /* Save each register used in calling a function to the block. */
1450 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1451 if ((mode = apply_args_mode[regno]) != VOIDmode)
1452 {
53800dbe 1453 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1454 if (size % align != 0)
1455 size = CEIL (size, align) * align;
1456
1457 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1458
e513d163 1459 emit_move_insn (adjust_address (registers, mode, size), tem);
53800dbe 1460 size += GET_MODE_SIZE (mode);
1461 }
1462
1463 /* Save the arg pointer to the block. */
27a7a23a 1464 tem = copy_to_reg (crtl->args.internal_arg_pointer);
f083a92b 1465#ifdef STACK_GROWS_DOWNWARD
1c7e61a7 1466 /* We need the pointer as the caller actually passed them to us, not
9d4b544c 1467 as we might have pretended they were passed. Make sure it's a valid
1468 operand, as emit_move_insn isn't expected to handle a PLUS. */
1469 tem
abe32cce 1470 = force_operand (plus_constant (tem, crtl->args.pretend_args_size),
9d4b544c 1471 NULL_RTX);
1c7e61a7 1472#endif
1473 emit_move_insn (adjust_address (registers, Pmode, 0), tem);
0862b7e9 1474
53800dbe 1475 size = GET_MODE_SIZE (Pmode);
1476
1477 /* Save the structure value address unless this is passed as an
1478 "invisible" first argument. */
45550790 1479 if (struct_incoming_value)
53800dbe 1480 {
e513d163 1481 emit_move_insn (adjust_address (registers, Pmode, size),
45550790 1482 copy_to_reg (struct_incoming_value));
53800dbe 1483 size += GET_MODE_SIZE (Pmode);
1484 }
1485
1486 /* Return the address of the block. */
1487 return copy_addr_to_reg (XEXP (registers, 0));
1488}
1489
1490/* __builtin_apply_args returns block of memory allocated on
1491 the stack into which is stored the arg pointer, structure
1492 value address, static chain, and all the registers that might
1493 possibly be used in performing a function call. The code is
1494 moved to the start of the function so the incoming values are
1495 saved. */
27d0c333 1496
53800dbe 1497static rtx
aecda0d6 1498expand_builtin_apply_args (void)
53800dbe 1499{
1500 /* Don't do __builtin_apply_args more than once in a function.
1501 Save the result of the first call and reuse it. */
1502 if (apply_args_value != 0)
1503 return apply_args_value;
1504 {
1505 /* When this function is called, it means that registers must be
1506 saved on entry to this function. So we migrate the
1507 call to the first insn of this function. */
1508 rtx temp;
1509 rtx seq;
1510
1511 start_sequence ();
1512 temp = expand_builtin_apply_args_1 ();
1513 seq = get_insns ();
1514 end_sequence ();
1515
1516 apply_args_value = temp;
1517
31d3e01c 1518 /* Put the insns after the NOTE that starts the function.
1519 If this is inside a start_sequence, make the outer-level insn
53800dbe 1520 chain current, so the code is placed at the start of the
0ef1a651 1521 function. If internal_arg_pointer is a non-virtual pseudo,
1522 it needs to be placed after the function that initializes
1523 that pseudo. */
53800dbe 1524 push_topmost_sequence ();
0ef1a651 1525 if (REG_P (crtl->args.internal_arg_pointer)
1526 && REGNO (crtl->args.internal_arg_pointer) > LAST_VIRTUAL_REGISTER)
1527 emit_insn_before (seq, parm_birth_insn);
1528 else
1529 emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
53800dbe 1530 pop_topmost_sequence ();
1531 return temp;
1532 }
1533}
1534
1535/* Perform an untyped call and save the state required to perform an
1536 untyped return of whatever value was returned by the given function. */
1537
1538static rtx
aecda0d6 1539expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
53800dbe 1540{
1541 int size, align, regno;
1542 enum machine_mode mode;
2a631e19 1543 rtx incoming_args, result, reg, dest, src, call_insn;
53800dbe 1544 rtx old_stack_level = 0;
1545 rtx call_fusage = 0;
6812c89e 1546 rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
53800dbe 1547
85d654dd 1548 arguments = convert_memory_address (Pmode, arguments);
726ec87c 1549
53800dbe 1550 /* Create a block where the return registers can be saved. */
1551 result = assign_stack_local (BLKmode, apply_result_size (), -1);
1552
53800dbe 1553 /* Fetch the arg pointer from the ARGUMENTS block. */
1554 incoming_args = gen_reg_rtx (Pmode);
726ec87c 1555 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
53800dbe 1556#ifndef STACK_GROWS_DOWNWARD
ad99e708 1557 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1558 incoming_args, 0, OPTAB_LIB_WIDEN);
53800dbe 1559#endif
1560
04a46d40 1561 /* Push a new argument block and copy the arguments. Do not allow
1562 the (potential) memcpy call below to interfere with our stack
1563 manipulations. */
53800dbe 1564 do_pending_stack_adjust ();
04a46d40 1565 NO_DEFER_POP;
53800dbe 1566
2358393e 1567 /* Save the stack with nonlocal if available. */
53800dbe 1568#ifdef HAVE_save_stack_nonlocal
1569 if (HAVE_save_stack_nonlocal)
e9c97615 1570 emit_stack_save (SAVE_NONLOCAL, &old_stack_level);
53800dbe 1571 else
1572#endif
e9c97615 1573 emit_stack_save (SAVE_BLOCK, &old_stack_level);
53800dbe 1574
59647703 1575 /* Allocate a block of memory onto the stack and copy the memory
990495a7 1576 arguments to the outgoing arguments address. We can pass TRUE
1577 as the 4th argument because we just saved the stack pointer
1578 and will restore it right after the call. */
5be42b39 1579 allocate_dynamic_stack_space (argsize, 0, BIGGEST_ALIGNMENT, true);
27a7a23a 1580
1581 /* Set DRAP flag to true, even though allocate_dynamic_stack_space
1582 may have already set current_function_calls_alloca to true.
1583 current_function_calls_alloca won't be set if argsize is zero,
1584 so we have to guarantee need_drap is true here. */
1585 if (SUPPORTS_STACK_ALIGNMENT)
1586 crtl->need_drap = true;
1587
59647703 1588 dest = virtual_outgoing_args_rtx;
1589#ifndef STACK_GROWS_DOWNWARD
971ba038 1590 if (CONST_INT_P (argsize))
59647703 1591 dest = plus_constant (dest, -INTVAL (argsize));
1592 else
1593 dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1594#endif
2a631e19 1595 dest = gen_rtx_MEM (BLKmode, dest);
1596 set_mem_align (dest, PARM_BOUNDARY);
1597 src = gen_rtx_MEM (BLKmode, incoming_args);
1598 set_mem_align (src, PARM_BOUNDARY);
0378dbdc 1599 emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
53800dbe 1600
1601 /* Refer to the argument block. */
1602 apply_args_size ();
1603 arguments = gen_rtx_MEM (BLKmode, arguments);
2a631e19 1604 set_mem_align (arguments, PARM_BOUNDARY);
53800dbe 1605
1606 /* Walk past the arg-pointer and structure value address. */
1607 size = GET_MODE_SIZE (Pmode);
45550790 1608 if (struct_value)
53800dbe 1609 size += GET_MODE_SIZE (Pmode);
1610
1611 /* Restore each of the registers previously saved. Make USE insns
1612 for each of these registers for use in making the call. */
1613 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1614 if ((mode = apply_args_mode[regno]) != VOIDmode)
1615 {
1616 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1617 if (size % align != 0)
1618 size = CEIL (size, align) * align;
1619 reg = gen_rtx_REG (mode, regno);
e513d163 1620 emit_move_insn (reg, adjust_address (arguments, mode, size));
53800dbe 1621 use_reg (&call_fusage, reg);
1622 size += GET_MODE_SIZE (mode);
1623 }
1624
1625 /* Restore the structure value address unless this is passed as an
1626 "invisible" first argument. */
1627 size = GET_MODE_SIZE (Pmode);
45550790 1628 if (struct_value)
53800dbe 1629 {
1630 rtx value = gen_reg_rtx (Pmode);
e513d163 1631 emit_move_insn (value, adjust_address (arguments, Pmode, size));
45550790 1632 emit_move_insn (struct_value, value);
8ad4c111 1633 if (REG_P (struct_value))
45550790 1634 use_reg (&call_fusage, struct_value);
53800dbe 1635 size += GET_MODE_SIZE (Pmode);
1636 }
1637
1638 /* All arguments and registers used for the call are set up by now! */
82c7907c 1639 function = prepare_call_address (NULL, function, NULL, &call_fusage, 0, 0);
53800dbe 1640
1641 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1642 and we don't want to load it into a register as an optimization,
1643 because prepare_call_address already did it if it should be done. */
1644 if (GET_CODE (function) != SYMBOL_REF)
1645 function = memory_address (FUNCTION_MODE, function);
1646
1647 /* Generate the actual call instruction and save the return value. */
1648#ifdef HAVE_untyped_call
1649 if (HAVE_untyped_call)
1650 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1651 result, result_vector (1, result)));
1652 else
1653#endif
1654#ifdef HAVE_call_value
1655 if (HAVE_call_value)
1656 {
1657 rtx valreg = 0;
1658
1659 /* Locate the unique return register. It is not possible to
1660 express a call that sets more than one return register using
1661 call_value; use untyped_call for that. In fact, untyped_call
1662 only needs to save the return registers in the given block. */
1663 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1664 if ((mode = apply_result_mode[regno]) != VOIDmode)
1665 {
64db345d 1666 gcc_assert (!valreg); /* HAVE_untyped_call required. */
7d3f6cc7 1667
53800dbe 1668 valreg = gen_rtx_REG (mode, regno);
1669 }
1670
2ed6c343 1671 emit_call_insn (GEN_CALL_VALUE (valreg,
53800dbe 1672 gen_rtx_MEM (FUNCTION_MODE, function),
1673 const0_rtx, NULL_RTX, const0_rtx));
1674
e513d163 1675 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
53800dbe 1676 }
1677 else
1678#endif
64db345d 1679 gcc_unreachable ();
53800dbe 1680
d5f9786f 1681 /* Find the CALL insn we just emitted, and attach the register usage
1682 information. */
1683 call_insn = last_call_insn ();
1684 add_function_usage_to (call_insn, call_fusage);
53800dbe 1685
1686 /* Restore the stack. */
1687#ifdef HAVE_save_stack_nonlocal
1688 if (HAVE_save_stack_nonlocal)
e9c97615 1689 emit_stack_restore (SAVE_NONLOCAL, old_stack_level);
53800dbe 1690 else
1691#endif
e9c97615 1692 emit_stack_restore (SAVE_BLOCK, old_stack_level);
53800dbe 1693
04a46d40 1694 OK_DEFER_POP;
1695
53800dbe 1696 /* Return the address of the result block. */
85d654dd 1697 result = copy_addr_to_reg (XEXP (result, 0));
1698 return convert_memory_address (ptr_mode, result);
53800dbe 1699}
1700
1701/* Perform an untyped return. */
1702
1703static void
aecda0d6 1704expand_builtin_return (rtx result)
53800dbe 1705{
1706 int size, align, regno;
1707 enum machine_mode mode;
1708 rtx reg;
1709 rtx call_fusage = 0;
1710
85d654dd 1711 result = convert_memory_address (Pmode, result);
726ec87c 1712
53800dbe 1713 apply_result_size ();
1714 result = gen_rtx_MEM (BLKmode, result);
1715
1716#ifdef HAVE_untyped_return
1717 if (HAVE_untyped_return)
1718 {
1719 emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1720 emit_barrier ();
1721 return;
1722 }
1723#endif
1724
1725 /* Restore the return value and note that each value is used. */
1726 size = 0;
1727 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1728 if ((mode = apply_result_mode[regno]) != VOIDmode)
1729 {
1730 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1731 if (size % align != 0)
1732 size = CEIL (size, align) * align;
1733 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
e513d163 1734 emit_move_insn (reg, adjust_address (result, mode, size));
53800dbe 1735
1736 push_to_sequence (call_fusage);
18b42941 1737 emit_use (reg);
53800dbe 1738 call_fusage = get_insns ();
1739 end_sequence ();
1740 size += GET_MODE_SIZE (mode);
1741 }
1742
1743 /* Put the USE insns before the return. */
31d3e01c 1744 emit_insn (call_fusage);
53800dbe 1745
1746 /* Return whatever values was restored by jumping directly to the end
1747 of the function. */
62380d2d 1748 expand_naked_return ();
53800dbe 1749}
1750
539a3a92 1751/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
27d0c333 1752
539a3a92 1753static enum type_class
aecda0d6 1754type_to_class (tree type)
539a3a92 1755{
1756 switch (TREE_CODE (type))
1757 {
1758 case VOID_TYPE: return void_type_class;
1759 case INTEGER_TYPE: return integer_type_class;
539a3a92 1760 case ENUMERAL_TYPE: return enumeral_type_class;
1761 case BOOLEAN_TYPE: return boolean_type_class;
1762 case POINTER_TYPE: return pointer_type_class;
1763 case REFERENCE_TYPE: return reference_type_class;
1764 case OFFSET_TYPE: return offset_type_class;
1765 case REAL_TYPE: return real_type_class;
1766 case COMPLEX_TYPE: return complex_type_class;
1767 case FUNCTION_TYPE: return function_type_class;
1768 case METHOD_TYPE: return method_type_class;
1769 case RECORD_TYPE: return record_type_class;
1770 case UNION_TYPE:
1771 case QUAL_UNION_TYPE: return union_type_class;
1772 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1773 ? string_type_class : array_type_class);
539a3a92 1774 case LANG_TYPE: return lang_type_class;
1775 default: return no_type_class;
1776 }
1777}
bf8e3599 1778
c2f47e15 1779/* Expand a call EXP to __builtin_classify_type. */
27d0c333 1780
53800dbe 1781static rtx
c2f47e15 1782expand_builtin_classify_type (tree exp)
53800dbe 1783{
c2f47e15 1784 if (call_expr_nargs (exp))
1785 return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0))));
53800dbe 1786 return GEN_INT (no_type_class);
1787}
1788
07976da7 1789/* This helper macro, meant to be used in mathfn_built_in below,
1790 determines which among a set of three builtin math functions is
1791 appropriate for a given type mode. The `F' and `L' cases are
1792 automatically generated from the `double' case. */
1793#define CASE_MATHFN(BUILT_IN_MATHFN) \
1794 case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1795 fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1796 fcodel = BUILT_IN_MATHFN##L ; break;
cd2656b0 1797/* Similar to above, but appends _R after any F/L suffix. */
1798#define CASE_MATHFN_REENT(BUILT_IN_MATHFN) \
1799 case BUILT_IN_MATHFN##_R: case BUILT_IN_MATHFN##F_R: case BUILT_IN_MATHFN##L_R: \
1800 fcode = BUILT_IN_MATHFN##_R; fcodef = BUILT_IN_MATHFN##F_R ; \
1801 fcodel = BUILT_IN_MATHFN##L_R ; break;
07976da7 1802
1803/* Return mathematic function equivalent to FN but operating directly
c319d56a 1804 on TYPE, if available. If IMPLICIT is true find the function in
1805 implicit_built_in_decls[], otherwise use built_in_decls[]. If we
1806 can't do the conversion, return zero. */
1807
1808static tree
1809mathfn_built_in_1 (tree type, enum built_in_function fn, bool implicit)
0a68165a 1810{
c319d56a 1811 tree const *const fn_arr
1812 = implicit ? implicit_built_in_decls : built_in_decls;
07976da7 1813 enum built_in_function fcode, fcodef, fcodel;
1814
1815 switch (fn)
1816 {
746114e8 1817 CASE_MATHFN (BUILT_IN_ACOS)
1818 CASE_MATHFN (BUILT_IN_ACOSH)
1819 CASE_MATHFN (BUILT_IN_ASIN)
1820 CASE_MATHFN (BUILT_IN_ASINH)
07976da7 1821 CASE_MATHFN (BUILT_IN_ATAN)
746114e8 1822 CASE_MATHFN (BUILT_IN_ATAN2)
1823 CASE_MATHFN (BUILT_IN_ATANH)
1824 CASE_MATHFN (BUILT_IN_CBRT)
07976da7 1825 CASE_MATHFN (BUILT_IN_CEIL)
d735c391 1826 CASE_MATHFN (BUILT_IN_CEXPI)
746114e8 1827 CASE_MATHFN (BUILT_IN_COPYSIGN)
07976da7 1828 CASE_MATHFN (BUILT_IN_COS)
746114e8 1829 CASE_MATHFN (BUILT_IN_COSH)
1830 CASE_MATHFN (BUILT_IN_DREM)
1831 CASE_MATHFN (BUILT_IN_ERF)
1832 CASE_MATHFN (BUILT_IN_ERFC)
07976da7 1833 CASE_MATHFN (BUILT_IN_EXP)
746114e8 1834 CASE_MATHFN (BUILT_IN_EXP10)
1835 CASE_MATHFN (BUILT_IN_EXP2)
1836 CASE_MATHFN (BUILT_IN_EXPM1)
1837 CASE_MATHFN (BUILT_IN_FABS)
1838 CASE_MATHFN (BUILT_IN_FDIM)
07976da7 1839 CASE_MATHFN (BUILT_IN_FLOOR)
746114e8 1840 CASE_MATHFN (BUILT_IN_FMA)
1841 CASE_MATHFN (BUILT_IN_FMAX)
1842 CASE_MATHFN (BUILT_IN_FMIN)
1843 CASE_MATHFN (BUILT_IN_FMOD)
1844 CASE_MATHFN (BUILT_IN_FREXP)
1845 CASE_MATHFN (BUILT_IN_GAMMA)
cd2656b0 1846 CASE_MATHFN_REENT (BUILT_IN_GAMMA) /* GAMMA_R */
746114e8 1847 CASE_MATHFN (BUILT_IN_HUGE_VAL)
1848 CASE_MATHFN (BUILT_IN_HYPOT)
1849 CASE_MATHFN (BUILT_IN_ILOGB)
1850 CASE_MATHFN (BUILT_IN_INF)
69b779ea 1851 CASE_MATHFN (BUILT_IN_ISINF)
746114e8 1852 CASE_MATHFN (BUILT_IN_J0)
1853 CASE_MATHFN (BUILT_IN_J1)
1854 CASE_MATHFN (BUILT_IN_JN)
ac148751 1855 CASE_MATHFN (BUILT_IN_LCEIL)
746114e8 1856 CASE_MATHFN (BUILT_IN_LDEXP)
ad52b9b7 1857 CASE_MATHFN (BUILT_IN_LFLOOR)
746114e8 1858 CASE_MATHFN (BUILT_IN_LGAMMA)
cd2656b0 1859 CASE_MATHFN_REENT (BUILT_IN_LGAMMA) /* LGAMMA_R */
ac148751 1860 CASE_MATHFN (BUILT_IN_LLCEIL)
ad52b9b7 1861 CASE_MATHFN (BUILT_IN_LLFLOOR)
746114e8 1862 CASE_MATHFN (BUILT_IN_LLRINT)
1863 CASE_MATHFN (BUILT_IN_LLROUND)
07976da7 1864 CASE_MATHFN (BUILT_IN_LOG)
746114e8 1865 CASE_MATHFN (BUILT_IN_LOG10)
1866 CASE_MATHFN (BUILT_IN_LOG1P)
1867 CASE_MATHFN (BUILT_IN_LOG2)
1868 CASE_MATHFN (BUILT_IN_LOGB)
1869 CASE_MATHFN (BUILT_IN_LRINT)
1870 CASE_MATHFN (BUILT_IN_LROUND)
1871 CASE_MATHFN (BUILT_IN_MODF)
1872 CASE_MATHFN (BUILT_IN_NAN)
1873 CASE_MATHFN (BUILT_IN_NANS)
07976da7 1874 CASE_MATHFN (BUILT_IN_NEARBYINT)
746114e8 1875 CASE_MATHFN (BUILT_IN_NEXTAFTER)
1876 CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1877 CASE_MATHFN (BUILT_IN_POW)
757c219d 1878 CASE_MATHFN (BUILT_IN_POWI)
746114e8 1879 CASE_MATHFN (BUILT_IN_POW10)
1880 CASE_MATHFN (BUILT_IN_REMAINDER)
1881 CASE_MATHFN (BUILT_IN_REMQUO)
1882 CASE_MATHFN (BUILT_IN_RINT)
07976da7 1883 CASE_MATHFN (BUILT_IN_ROUND)
746114e8 1884 CASE_MATHFN (BUILT_IN_SCALB)
1885 CASE_MATHFN (BUILT_IN_SCALBLN)
1886 CASE_MATHFN (BUILT_IN_SCALBN)
c319d56a 1887 CASE_MATHFN (BUILT_IN_SIGNBIT)
746114e8 1888 CASE_MATHFN (BUILT_IN_SIGNIFICAND)
07976da7 1889 CASE_MATHFN (BUILT_IN_SIN)
746114e8 1890 CASE_MATHFN (BUILT_IN_SINCOS)
1891 CASE_MATHFN (BUILT_IN_SINH)
07976da7 1892 CASE_MATHFN (BUILT_IN_SQRT)
1893 CASE_MATHFN (BUILT_IN_TAN)
746114e8 1894 CASE_MATHFN (BUILT_IN_TANH)
1895 CASE_MATHFN (BUILT_IN_TGAMMA)
07976da7 1896 CASE_MATHFN (BUILT_IN_TRUNC)
746114e8 1897 CASE_MATHFN (BUILT_IN_Y0)
1898 CASE_MATHFN (BUILT_IN_Y1)
1899 CASE_MATHFN (BUILT_IN_YN)
07976da7 1900
0a68165a 1901 default:
c2f47e15 1902 return NULL_TREE;
0a68165a 1903 }
07976da7 1904
96b9f485 1905 if (TYPE_MAIN_VARIANT (type) == double_type_node)
c319d56a 1906 return fn_arr[fcode];
96b9f485 1907 else if (TYPE_MAIN_VARIANT (type) == float_type_node)
c319d56a 1908 return fn_arr[fcodef];
96b9f485 1909 else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
c319d56a 1910 return fn_arr[fcodel];
07976da7 1911 else
c2f47e15 1912 return NULL_TREE;
0a68165a 1913}
1914
c319d56a 1915/* Like mathfn_built_in_1(), but always use the implicit array. */
1916
1917tree
1918mathfn_built_in (tree type, enum built_in_function fn)
1919{
1920 return mathfn_built_in_1 (type, fn, /*implicit=*/ 1);
1921}
1922
0fd605a5 1923/* If errno must be maintained, expand the RTL to check if the result,
1924 TARGET, of a built-in function call, EXP, is NaN, and if so set
1925 errno to EDOM. */
1926
1927static void
aecda0d6 1928expand_errno_check (tree exp, rtx target)
0fd605a5 1929{
7f05340e 1930 rtx lab = gen_label_rtx ();
0fd605a5 1931
7f05340e 1932 /* Test the result; if it is NaN, set errno=EDOM because
1933 the argument was not in the domain. */
3fcf767f 1934 do_compare_rtx_and_jump (target, target, EQ, 0, GET_MODE (target),
79ab74cc 1935 NULL_RTX, NULL_RTX, lab,
1936 /* The jump is very likely. */
1937 REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1));
0fd605a5 1938
1939#ifdef TARGET_EDOM
7f05340e 1940 /* If this built-in doesn't throw an exception, set errno directly. */
c2f47e15 1941 if (TREE_NOTHROW (TREE_OPERAND (CALL_EXPR_FN (exp), 0)))
7f05340e 1942 {
0fd605a5 1943#ifdef GEN_ERRNO_RTX
7f05340e 1944 rtx errno_rtx = GEN_ERRNO_RTX;
0fd605a5 1945#else
7f05340e 1946 rtx errno_rtx
0fd605a5 1947 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1948#endif
7f05340e 1949 emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
0fd605a5 1950 emit_label (lab);
7f05340e 1951 return;
0fd605a5 1952 }
7f05340e 1953#endif
1954
08491912 1955 /* Make sure the library call isn't expanded as a tail call. */
1956 CALL_EXPR_TAILCALL (exp) = 0;
1957
7f05340e 1958 /* We can't set errno=EDOM directly; let the library call do it.
1959 Pop the arguments right away in case the call gets deleted. */
1960 NO_DEFER_POP;
1961 expand_call (exp, target, 0);
1962 OK_DEFER_POP;
1963 emit_label (lab);
0fd605a5 1964}
1965
6b43bae4 1966/* Expand a call to one of the builtin math functions (sqrt, exp, or log).
c2f47e15 1967 Return NULL_RTX if a normal call should be emitted rather than expanding
1968 the function in-line. EXP is the expression that is a call to the builtin
53800dbe 1969 function; if convenient, the result should be placed in TARGET.
1970 SUBTARGET may be used as the target for computing one of EXP's operands. */
27d0c333 1971
53800dbe 1972static rtx
aecda0d6 1973expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
53800dbe 1974{
bf8e3599 1975 optab builtin_optab;
1e4adcfc 1976 rtx op0, insns;
c6e6ecb1 1977 tree fndecl = get_callee_fndecl (exp);
7f05340e 1978 enum machine_mode mode;
528ee710 1979 bool errno_set = false;
abfea505 1980 tree arg;
53800dbe 1981
c2f47e15 1982 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
1983 return NULL_RTX;
53800dbe 1984
c2f47e15 1985 arg = CALL_EXPR_ARG (exp, 0);
53800dbe 1986
1987 switch (DECL_FUNCTION_CODE (fndecl))
1988 {
4f35b1fc 1989 CASE_FLT_FN (BUILT_IN_SQRT):
7f05340e 1990 errno_set = ! tree_expr_nonnegative_p (arg);
1991 builtin_optab = sqrt_optab;
1992 break;
4f35b1fc 1993 CASE_FLT_FN (BUILT_IN_EXP):
528ee710 1994 errno_set = true; builtin_optab = exp_optab; break;
4f35b1fc 1995 CASE_FLT_FN (BUILT_IN_EXP10):
1996 CASE_FLT_FN (BUILT_IN_POW10):
750ef9f5 1997 errno_set = true; builtin_optab = exp10_optab; break;
4f35b1fc 1998 CASE_FLT_FN (BUILT_IN_EXP2):
750ef9f5 1999 errno_set = true; builtin_optab = exp2_optab; break;
4f35b1fc 2000 CASE_FLT_FN (BUILT_IN_EXPM1):
a6b4eed2 2001 errno_set = true; builtin_optab = expm1_optab; break;
4f35b1fc 2002 CASE_FLT_FN (BUILT_IN_LOGB):
4efbc641 2003 errno_set = true; builtin_optab = logb_optab; break;
4f35b1fc 2004 CASE_FLT_FN (BUILT_IN_LOG):
528ee710 2005 errno_set = true; builtin_optab = log_optab; break;
4f35b1fc 2006 CASE_FLT_FN (BUILT_IN_LOG10):
d3cd9bde 2007 errno_set = true; builtin_optab = log10_optab; break;
4f35b1fc 2008 CASE_FLT_FN (BUILT_IN_LOG2):
d3cd9bde 2009 errno_set = true; builtin_optab = log2_optab; break;
4f35b1fc 2010 CASE_FLT_FN (BUILT_IN_LOG1P):
f474cd93 2011 errno_set = true; builtin_optab = log1p_optab; break;
4f35b1fc 2012 CASE_FLT_FN (BUILT_IN_ASIN):
8de2f465 2013 builtin_optab = asin_optab; break;
4f35b1fc 2014 CASE_FLT_FN (BUILT_IN_ACOS):
8de2f465 2015 builtin_optab = acos_optab; break;
4f35b1fc 2016 CASE_FLT_FN (BUILT_IN_TAN):
528ee710 2017 builtin_optab = tan_optab; break;
4f35b1fc 2018 CASE_FLT_FN (BUILT_IN_ATAN):
528ee710 2019 builtin_optab = atan_optab; break;
4f35b1fc 2020 CASE_FLT_FN (BUILT_IN_FLOOR):
528ee710 2021 builtin_optab = floor_optab; break;
4f35b1fc 2022 CASE_FLT_FN (BUILT_IN_CEIL):
528ee710 2023 builtin_optab = ceil_optab; break;
4f35b1fc 2024 CASE_FLT_FN (BUILT_IN_TRUNC):
a7cc195f 2025 builtin_optab = btrunc_optab; break;
4f35b1fc 2026 CASE_FLT_FN (BUILT_IN_ROUND):
528ee710 2027 builtin_optab = round_optab; break;
4f35b1fc 2028 CASE_FLT_FN (BUILT_IN_NEARBYINT):
0ddf4ad9 2029 builtin_optab = nearbyint_optab;
2030 if (flag_trapping_math)
2031 break;
2032 /* Else fallthrough and expand as rint. */
4f35b1fc 2033 CASE_FLT_FN (BUILT_IN_RINT):
aef94a0f 2034 builtin_optab = rint_optab; break;
b3154a1f 2035 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
2036 builtin_optab = significand_optab; break;
42721db0 2037 default:
64db345d 2038 gcc_unreachable ();
53800dbe 2039 }
2040
7f05340e 2041 /* Make a suitable register to place result in. */
2042 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2043
7f05340e 2044 if (! flag_errno_math || ! HONOR_NANS (mode))
2045 errno_set = false;
2046
bd421108 2047 /* Before working hard, check whether the instruction is available. */
f2aca212 2048 if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing
2049 && (!errno_set || !optimize_insn_for_size_p ()))
68e6cb9d 2050 {
bd421108 2051 target = gen_reg_rtx (mode);
7f05340e 2052
bd421108 2053 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2054 need to expand the argument again. This way, we will not perform
2055 side-effects more the once. */
abfea505 2056 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7f05340e 2057
1db6d067 2058 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
7f05340e 2059
bd421108 2060 start_sequence ();
53800dbe 2061
bd421108 2062 /* Compute into TARGET.
2063 Set TARGET to wherever the result comes back. */
2064 target = expand_unop (mode, builtin_optab, op0, target, 0);
2065
2066 if (target != 0)
2067 {
2068 if (errno_set)
2069 expand_errno_check (exp, target);
2070
2071 /* Output the entire sequence. */
2072 insns = get_insns ();
2073 end_sequence ();
2074 emit_insn (insns);
2075 return target;
2076 }
2077
2078 /* If we were unable to expand via the builtin, stop the sequence
2079 (without outputting the insns) and call to the library function
2080 with the stabilized argument list. */
53800dbe 2081 end_sequence ();
53800dbe 2082 }
2083
1e5b92fa 2084 return expand_call (exp, target, target == const0_rtx);
0fd605a5 2085}
2086
2087/* Expand a call to the builtin binary math functions (pow and atan2).
c2f47e15 2088 Return NULL_RTX if a normal call should be emitted rather than expanding the
0fd605a5 2089 function in-line. EXP is the expression that is a call to the builtin
2090 function; if convenient, the result should be placed in TARGET.
2091 SUBTARGET may be used as the target for computing one of EXP's
2092 operands. */
2093
2094static rtx
aecda0d6 2095expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
0fd605a5 2096{
2097 optab builtin_optab;
2098 rtx op0, op1, insns;
4737caf2 2099 int op1_type = REAL_TYPE;
c6e6ecb1 2100 tree fndecl = get_callee_fndecl (exp);
abfea505 2101 tree arg0, arg1;
7f05340e 2102 enum machine_mode mode;
0fd605a5 2103 bool errno_set = true;
0fd605a5 2104
73a954a1 2105 switch (DECL_FUNCTION_CODE (fndecl))
2106 {
2107 CASE_FLT_FN (BUILT_IN_SCALBN):
2108 CASE_FLT_FN (BUILT_IN_SCALBLN):
2109 CASE_FLT_FN (BUILT_IN_LDEXP):
2110 op1_type = INTEGER_TYPE;
2111 default:
2112 break;
2113 }
4737caf2 2114
c2f47e15 2115 if (!validate_arglist (exp, REAL_TYPE, op1_type, VOID_TYPE))
2116 return NULL_RTX;
0fd605a5 2117
c2f47e15 2118 arg0 = CALL_EXPR_ARG (exp, 0);
2119 arg1 = CALL_EXPR_ARG (exp, 1);
0fd605a5 2120
0fd605a5 2121 switch (DECL_FUNCTION_CODE (fndecl))
2122 {
4f35b1fc 2123 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 2124 builtin_optab = pow_optab; break;
4f35b1fc 2125 CASE_FLT_FN (BUILT_IN_ATAN2):
0fd605a5 2126 builtin_optab = atan2_optab; break;
73a954a1 2127 CASE_FLT_FN (BUILT_IN_SCALB):
2128 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2129 return 0;
2130 builtin_optab = scalb_optab; break;
2131 CASE_FLT_FN (BUILT_IN_SCALBN):
2132 CASE_FLT_FN (BUILT_IN_SCALBLN):
2133 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2134 return 0;
2135 /* Fall through... */
4f35b1fc 2136 CASE_FLT_FN (BUILT_IN_LDEXP):
4737caf2 2137 builtin_optab = ldexp_optab; break;
4f35b1fc 2138 CASE_FLT_FN (BUILT_IN_FMOD):
80ed5c06 2139 builtin_optab = fmod_optab; break;
ef722005 2140 CASE_FLT_FN (BUILT_IN_REMAINDER):
4f35b1fc 2141 CASE_FLT_FN (BUILT_IN_DREM):
ef722005 2142 builtin_optab = remainder_optab; break;
0fd605a5 2143 default:
64db345d 2144 gcc_unreachable ();
0fd605a5 2145 }
2146
7f05340e 2147 /* Make a suitable register to place result in. */
2148 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2149
2150 /* Before working hard, check whether the instruction is available. */
d6bf3b14 2151 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
c2f47e15 2152 return NULL_RTX;
fc4eef90 2153
7f05340e 2154 target = gen_reg_rtx (mode);
2155
2156 if (! flag_errno_math || ! HONOR_NANS (mode))
2157 errno_set = false;
2158
f2aca212 2159 if (errno_set && optimize_insn_for_size_p ())
2160 return 0;
2161
4ee9c684 2162 /* Always stabilize the argument list. */
abfea505 2163 CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
2164 CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
7f05340e 2165
8ec3c5c2 2166 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2167 op1 = expand_normal (arg1);
7f05340e 2168
7f05340e 2169 start_sequence ();
2170
0fd605a5 2171 /* Compute into TARGET.
2172 Set TARGET to wherever the result comes back. */
7f05340e 2173 target = expand_binop (mode, builtin_optab, op0, op1,
0fd605a5 2174 target, 0, OPTAB_DIRECT);
53800dbe 2175
68e6cb9d 2176 /* If we were unable to expand via the builtin, stop the sequence
2177 (without outputting the insns) and call to the library function
2178 with the stabilized argument list. */
0fd605a5 2179 if (target == 0)
2180 {
2181 end_sequence ();
68e6cb9d 2182 return expand_call (exp, target, target == const0_rtx);
53800dbe 2183 }
2184
a4356fb9 2185 if (errno_set)
2186 expand_errno_check (exp, target);
0fd605a5 2187
53800dbe 2188 /* Output the entire sequence. */
2189 insns = get_insns ();
2190 end_sequence ();
31d3e01c 2191 emit_insn (insns);
bf8e3599 2192
53800dbe 2193 return target;
2194}
2195
7e0713b1 2196/* Expand a call to the builtin trinary math functions (fma).
2197 Return NULL_RTX if a normal call should be emitted rather than expanding the
2198 function in-line. EXP is the expression that is a call to the builtin
2199 function; if convenient, the result should be placed in TARGET.
2200 SUBTARGET may be used as the target for computing one of EXP's
2201 operands. */
2202
2203static rtx
2204expand_builtin_mathfn_ternary (tree exp, rtx target, rtx subtarget)
2205{
2206 optab builtin_optab;
2207 rtx op0, op1, op2, insns;
2208 tree fndecl = get_callee_fndecl (exp);
2209 tree arg0, arg1, arg2;
2210 enum machine_mode mode;
2211
2212 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2213 return NULL_RTX;
2214
2215 arg0 = CALL_EXPR_ARG (exp, 0);
2216 arg1 = CALL_EXPR_ARG (exp, 1);
2217 arg2 = CALL_EXPR_ARG (exp, 2);
2218
2219 switch (DECL_FUNCTION_CODE (fndecl))
2220 {
2221 CASE_FLT_FN (BUILT_IN_FMA):
2222 builtin_optab = fma_optab; break;
2223 default:
2224 gcc_unreachable ();
2225 }
2226
2227 /* Make a suitable register to place result in. */
2228 mode = TYPE_MODE (TREE_TYPE (exp));
2229
2230 /* Before working hard, check whether the instruction is available. */
2231 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
2232 return NULL_RTX;
2233
2234 target = gen_reg_rtx (mode);
2235
2236 /* Always stabilize the argument list. */
2237 CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
2238 CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
2239 CALL_EXPR_ARG (exp, 2) = arg2 = builtin_save_expr (arg2);
2240
2241 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2242 op1 = expand_normal (arg1);
2243 op2 = expand_normal (arg2);
2244
2245 start_sequence ();
2246
2247 /* Compute into TARGET.
2248 Set TARGET to wherever the result comes back. */
2249 target = expand_ternary_op (mode, builtin_optab, op0, op1, op2,
2250 target, 0);
2251
2252 /* If we were unable to expand via the builtin, stop the sequence
2253 (without outputting the insns) and call to the library function
2254 with the stabilized argument list. */
2255 if (target == 0)
2256 {
2257 end_sequence ();
2258 return expand_call (exp, target, target == const0_rtx);
2259 }
2260
2261 /* Output the entire sequence. */
2262 insns = get_insns ();
2263 end_sequence ();
2264 emit_insn (insns);
2265
2266 return target;
2267}
2268
6b43bae4 2269/* Expand a call to the builtin sin and cos math functions.
c2f47e15 2270 Return NULL_RTX if a normal call should be emitted rather than expanding the
6b43bae4 2271 function in-line. EXP is the expression that is a call to the builtin
2272 function; if convenient, the result should be placed in TARGET.
2273 SUBTARGET may be used as the target for computing one of EXP's
2274 operands. */
2275
2276static rtx
2277expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
2278{
2279 optab builtin_optab;
7511b819 2280 rtx op0, insns;
6b43bae4 2281 tree fndecl = get_callee_fndecl (exp);
6b43bae4 2282 enum machine_mode mode;
abfea505 2283 tree arg;
6b43bae4 2284
c2f47e15 2285 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2286 return NULL_RTX;
6b43bae4 2287
c2f47e15 2288 arg = CALL_EXPR_ARG (exp, 0);
6b43bae4 2289
2290 switch (DECL_FUNCTION_CODE (fndecl))
2291 {
4f35b1fc 2292 CASE_FLT_FN (BUILT_IN_SIN):
2293 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2294 builtin_optab = sincos_optab; break;
2295 default:
64db345d 2296 gcc_unreachable ();
6b43bae4 2297 }
2298
2299 /* Make a suitable register to place result in. */
2300 mode = TYPE_MODE (TREE_TYPE (exp));
2301
6b43bae4 2302 /* Check if sincos insn is available, otherwise fallback
0bed3869 2303 to sin or cos insn. */
d6bf3b14 2304 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
6b43bae4 2305 switch (DECL_FUNCTION_CODE (fndecl))
2306 {
4f35b1fc 2307 CASE_FLT_FN (BUILT_IN_SIN):
6b43bae4 2308 builtin_optab = sin_optab; break;
4f35b1fc 2309 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2310 builtin_optab = cos_optab; break;
2311 default:
64db345d 2312 gcc_unreachable ();
6b43bae4 2313 }
6b43bae4 2314
2315 /* Before working hard, check whether the instruction is available. */
d6bf3b14 2316 if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing)
6b43bae4 2317 {
2318 target = gen_reg_rtx (mode);
2319
2320 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2321 need to expand the argument again. This way, we will not perform
2322 side-effects more the once. */
abfea505 2323 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
6b43bae4 2324
1db6d067 2325 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
6b43bae4 2326
6b43bae4 2327 start_sequence ();
2328
2329 /* Compute into TARGET.
2330 Set TARGET to wherever the result comes back. */
2331 if (builtin_optab == sincos_optab)
2332 {
64db345d 2333 int result;
7d3f6cc7 2334
6b43bae4 2335 switch (DECL_FUNCTION_CODE (fndecl))
2336 {
4f35b1fc 2337 CASE_FLT_FN (BUILT_IN_SIN):
64db345d 2338 result = expand_twoval_unop (builtin_optab, op0, 0, target, 0);
6b43bae4 2339 break;
4f35b1fc 2340 CASE_FLT_FN (BUILT_IN_COS):
64db345d 2341 result = expand_twoval_unop (builtin_optab, op0, target, 0, 0);
6b43bae4 2342 break;
2343 default:
64db345d 2344 gcc_unreachable ();
6b43bae4 2345 }
64db345d 2346 gcc_assert (result);
6b43bae4 2347 }
2348 else
2349 {
2350 target = expand_unop (mode, builtin_optab, op0, target, 0);
2351 }
2352
2353 if (target != 0)
2354 {
6b43bae4 2355 /* Output the entire sequence. */
2356 insns = get_insns ();
2357 end_sequence ();
2358 emit_insn (insns);
2359 return target;
2360 }
2361
2362 /* If we were unable to expand via the builtin, stop the sequence
2363 (without outputting the insns) and call to the library function
2364 with the stabilized argument list. */
2365 end_sequence ();
2366 }
2367
6b43bae4 2368 target = expand_call (exp, target, target == const0_rtx);
2369
2370 return target;
2371}
2372
a65c4d64 2373/* Given an interclass math builtin decl FNDECL and it's argument ARG
2374 return an RTL instruction code that implements the functionality.
2375 If that isn't possible or available return CODE_FOR_nothing. */
a67a90e5 2376
a65c4d64 2377static enum insn_code
2378interclass_mathfn_icode (tree arg, tree fndecl)
a67a90e5 2379{
a65c4d64 2380 bool errno_set = false;
cde061c1 2381 optab builtin_optab = 0;
a67a90e5 2382 enum machine_mode mode;
a67a90e5 2383
2384 switch (DECL_FUNCTION_CODE (fndecl))
2385 {
2386 CASE_FLT_FN (BUILT_IN_ILOGB):
2387 errno_set = true; builtin_optab = ilogb_optab; break;
69b779ea 2388 CASE_FLT_FN (BUILT_IN_ISINF):
2389 builtin_optab = isinf_optab; break;
8a1a9cb7 2390 case BUILT_IN_ISNORMAL:
cde061c1 2391 case BUILT_IN_ISFINITE:
2392 CASE_FLT_FN (BUILT_IN_FINITE):
a65c4d64 2393 case BUILT_IN_FINITED32:
2394 case BUILT_IN_FINITED64:
2395 case BUILT_IN_FINITED128:
2396 case BUILT_IN_ISINFD32:
2397 case BUILT_IN_ISINFD64:
2398 case BUILT_IN_ISINFD128:
cde061c1 2399 /* These builtins have no optabs (yet). */
2400 break;
a67a90e5 2401 default:
2402 gcc_unreachable ();
2403 }
2404
2405 /* There's no easy way to detect the case we need to set EDOM. */
2406 if (flag_errno_math && errno_set)
a65c4d64 2407 return CODE_FOR_nothing;
a67a90e5 2408
2409 /* Optab mode depends on the mode of the input argument. */
2410 mode = TYPE_MODE (TREE_TYPE (arg));
2411
cde061c1 2412 if (builtin_optab)
d6bf3b14 2413 return optab_handler (builtin_optab, mode);
a65c4d64 2414 return CODE_FOR_nothing;
2415}
2416
2417/* Expand a call to one of the builtin math functions that operate on
2418 floating point argument and output an integer result (ilogb, isinf,
2419 isnan, etc).
2420 Return 0 if a normal call should be emitted rather than expanding the
2421 function in-line. EXP is the expression that is a call to the builtin
f97eea22 2422 function; if convenient, the result should be placed in TARGET. */
a65c4d64 2423
2424static rtx
f97eea22 2425expand_builtin_interclass_mathfn (tree exp, rtx target)
a65c4d64 2426{
2427 enum insn_code icode = CODE_FOR_nothing;
2428 rtx op0;
2429 tree fndecl = get_callee_fndecl (exp);
2430 enum machine_mode mode;
2431 tree arg;
2432
2433 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2434 return NULL_RTX;
2435
2436 arg = CALL_EXPR_ARG (exp, 0);
2437 icode = interclass_mathfn_icode (arg, fndecl);
2438 mode = TYPE_MODE (TREE_TYPE (arg));
2439
a67a90e5 2440 if (icode != CODE_FOR_nothing)
2441 {
8786db1e 2442 struct expand_operand ops[1];
4e2a2fb4 2443 rtx last = get_last_insn ();
2444 tree orig_arg = arg;
a67a90e5 2445
2446 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2447 need to expand the argument again. This way, we will not perform
2448 side-effects more the once. */
abfea505 2449 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
a67a90e5 2450
f97eea22 2451 op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
a67a90e5 2452
2453 if (mode != GET_MODE (op0))
2454 op0 = convert_to_mode (mode, op0, 0);
2455
8786db1e 2456 create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
2457 if (maybe_legitimize_operands (icode, 0, 1, ops)
2458 && maybe_emit_unop_insn (icode, ops[0].value, op0, UNKNOWN))
2459 return ops[0].value;
2460
4e2a2fb4 2461 delete_insns_since (last);
2462 CALL_EXPR_ARG (exp, 0) = orig_arg;
a67a90e5 2463 }
2464
a65c4d64 2465 return NULL_RTX;
a67a90e5 2466}
2467
c3147c1a 2468/* Expand a call to the builtin sincos math function.
c2f47e15 2469 Return NULL_RTX if a normal call should be emitted rather than expanding the
c3147c1a 2470 function in-line. EXP is the expression that is a call to the builtin
2471 function. */
2472
2473static rtx
2474expand_builtin_sincos (tree exp)
2475{
2476 rtx op0, op1, op2, target1, target2;
c3147c1a 2477 enum machine_mode mode;
2478 tree arg, sinp, cosp;
2479 int result;
389dd41b 2480 location_t loc = EXPR_LOCATION (exp);
be5575b2 2481 tree alias_type, alias_off;
c3147c1a 2482
c2f47e15 2483 if (!validate_arglist (exp, REAL_TYPE,
2484 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2485 return NULL_RTX;
c3147c1a 2486
c2f47e15 2487 arg = CALL_EXPR_ARG (exp, 0);
2488 sinp = CALL_EXPR_ARG (exp, 1);
2489 cosp = CALL_EXPR_ARG (exp, 2);
c3147c1a 2490
2491 /* Make a suitable register to place result in. */
2492 mode = TYPE_MODE (TREE_TYPE (arg));
2493
2494 /* Check if sincos insn is available, otherwise emit the call. */
d6bf3b14 2495 if (optab_handler (sincos_optab, mode) == CODE_FOR_nothing)
c3147c1a 2496 return NULL_RTX;
2497
2498 target1 = gen_reg_rtx (mode);
2499 target2 = gen_reg_rtx (mode);
2500
8ec3c5c2 2501 op0 = expand_normal (arg);
be5575b2 2502 alias_type = build_pointer_type_for_mode (TREE_TYPE (arg), ptr_mode, true);
2503 alias_off = build_int_cst (alias_type, 0);
2504 op1 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
2505 sinp, alias_off));
2506 op2 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
2507 cosp, alias_off));
c3147c1a 2508
2509 /* Compute into target1 and target2.
2510 Set TARGET to wherever the result comes back. */
2511 result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
2512 gcc_assert (result);
2513
2514 /* Move target1 and target2 to the memory locations indicated
2515 by op1 and op2. */
2516 emit_move_insn (op1, target1);
2517 emit_move_insn (op2, target2);
2518
2519 return const0_rtx;
2520}
2521
d735c391 2522/* Expand a call to the internal cexpi builtin to the sincos math function.
2523 EXP is the expression that is a call to the builtin function; if convenient,
f97eea22 2524 the result should be placed in TARGET. */
d735c391 2525
2526static rtx
f97eea22 2527expand_builtin_cexpi (tree exp, rtx target)
d735c391 2528{
2529 tree fndecl = get_callee_fndecl (exp);
d735c391 2530 tree arg, type;
c2f47e15 2531 enum machine_mode mode;
d735c391 2532 rtx op0, op1, op2;
389dd41b 2533 location_t loc = EXPR_LOCATION (exp);
d735c391 2534
c2f47e15 2535 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2536 return NULL_RTX;
d735c391 2537
c2f47e15 2538 arg = CALL_EXPR_ARG (exp, 0);
d735c391 2539 type = TREE_TYPE (arg);
2540 mode = TYPE_MODE (TREE_TYPE (arg));
2541
2542 /* Try expanding via a sincos optab, fall back to emitting a libcall
18b8d8ae 2543 to sincos or cexp. We are sure we have sincos or cexp because cexpi
2544 is only generated from sincos, cexp or if we have either of them. */
d6bf3b14 2545 if (optab_handler (sincos_optab, mode) != CODE_FOR_nothing)
d735c391 2546 {
2547 op1 = gen_reg_rtx (mode);
2548 op2 = gen_reg_rtx (mode);
2549
f97eea22 2550 op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
d735c391 2551
2552 /* Compute into op1 and op2. */
2553 expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
2554 }
18b8d8ae 2555 else if (TARGET_HAS_SINCOS)
d735c391 2556 {
c2f47e15 2557 tree call, fn = NULL_TREE;
d735c391 2558 tree top1, top2;
2559 rtx op1a, op2a;
2560
2561 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2562 fn = built_in_decls[BUILT_IN_SINCOSF];
2563 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2564 fn = built_in_decls[BUILT_IN_SINCOS];
2565 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2566 fn = built_in_decls[BUILT_IN_SINCOSL];
c2f47e15 2567 else
2568 gcc_unreachable ();
48e1416a 2569
d735c391 2570 op1 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
2571 op2 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
2572 op1a = copy_to_mode_reg (Pmode, XEXP (op1, 0));
2573 op2a = copy_to_mode_reg (Pmode, XEXP (op2, 0));
2574 top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
2575 top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
2576
d735c391 2577 /* Make sure not to fold the sincos call again. */
2578 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
c2f47e15 2579 expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
2580 call, 3, arg, top1, top2));
d735c391 2581 }
18b8d8ae 2582 else
2583 {
0ecbc158 2584 tree call, fn = NULL_TREE, narg;
18b8d8ae 2585 tree ctype = build_complex_type (type);
2586
0ecbc158 2587 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2588 fn = built_in_decls[BUILT_IN_CEXPF];
2589 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2590 fn = built_in_decls[BUILT_IN_CEXP];
2591 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2592 fn = built_in_decls[BUILT_IN_CEXPL];
c2f47e15 2593 else
2594 gcc_unreachable ();
fc0dfa6e 2595
2596 /* If we don't have a decl for cexp create one. This is the
2597 friendliest fallback if the user calls __builtin_cexpi
2598 without full target C99 function support. */
2599 if (fn == NULL_TREE)
2600 {
2601 tree fntype;
2602 const char *name = NULL;
2603
2604 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2605 name = "cexpf";
2606 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2607 name = "cexp";
2608 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2609 name = "cexpl";
2610
2611 fntype = build_function_type_list (ctype, ctype, NULL_TREE);
2612 fn = build_fn_decl (name, fntype);
2613 }
2614
389dd41b 2615 narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype,
18b8d8ae 2616 build_real (type, dconst0), arg);
2617
2618 /* Make sure not to fold the cexp call again. */
2619 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
48e1416a 2620 return expand_expr (build_call_nary (ctype, call, 1, narg),
1db6d067 2621 target, VOIDmode, EXPAND_NORMAL);
18b8d8ae 2622 }
d735c391 2623
2624 /* Now build the proper return type. */
2625 return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
2626 make_tree (TREE_TYPE (arg), op2),
2627 make_tree (TREE_TYPE (arg), op1)),
1db6d067 2628 target, VOIDmode, EXPAND_NORMAL);
d735c391 2629}
2630
a65c4d64 2631/* Conveniently construct a function call expression. FNDECL names the
2632 function to be called, N is the number of arguments, and the "..."
2633 parameters are the argument expressions. Unlike build_call_exr
2634 this doesn't fold the call, hence it will always return a CALL_EXPR. */
2635
2636static tree
2637build_call_nofold_loc (location_t loc, tree fndecl, int n, ...)
2638{
2639 va_list ap;
2640 tree fntype = TREE_TYPE (fndecl);
2641 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
2642
2643 va_start (ap, n);
2644 fn = build_call_valist (TREE_TYPE (fntype), fn, n, ap);
2645 va_end (ap);
2646 SET_EXPR_LOCATION (fn, loc);
2647 return fn;
2648}
a65c4d64 2649
7d3afc77 2650/* Expand a call to one of the builtin rounding functions gcc defines
2651 as an extension (lfloor and lceil). As these are gcc extensions we
2652 do not need to worry about setting errno to EDOM.
ad52b9b7 2653 If expanding via optab fails, lower expression to (int)(floor(x)).
2654 EXP is the expression that is a call to the builtin function;
ff1b14e4 2655 if convenient, the result should be placed in TARGET. */
ad52b9b7 2656
2657static rtx
ff1b14e4 2658expand_builtin_int_roundingfn (tree exp, rtx target)
ad52b9b7 2659{
9c42dd28 2660 convert_optab builtin_optab;
ad52b9b7 2661 rtx op0, insns, tmp;
2662 tree fndecl = get_callee_fndecl (exp);
ad52b9b7 2663 enum built_in_function fallback_fn;
2664 tree fallback_fndecl;
2665 enum machine_mode mode;
4de0924f 2666 tree arg;
ad52b9b7 2667
c2f47e15 2668 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
ad52b9b7 2669 gcc_unreachable ();
2670
c2f47e15 2671 arg = CALL_EXPR_ARG (exp, 0);
ad52b9b7 2672
2673 switch (DECL_FUNCTION_CODE (fndecl))
2674 {
4f35b1fc 2675 CASE_FLT_FN (BUILT_IN_LCEIL):
2676 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 2677 builtin_optab = lceil_optab;
2678 fallback_fn = BUILT_IN_CEIL;
2679 break;
2680
4f35b1fc 2681 CASE_FLT_FN (BUILT_IN_LFLOOR):
2682 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 2683 builtin_optab = lfloor_optab;
2684 fallback_fn = BUILT_IN_FLOOR;
2685 break;
2686
2687 default:
2688 gcc_unreachable ();
2689 }
2690
2691 /* Make a suitable register to place result in. */
2692 mode = TYPE_MODE (TREE_TYPE (exp));
2693
9c42dd28 2694 target = gen_reg_rtx (mode);
ad52b9b7 2695
9c42dd28 2696 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2697 need to expand the argument again. This way, we will not perform
2698 side-effects more the once. */
abfea505 2699 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
ad52b9b7 2700
ff1b14e4 2701 op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
ad52b9b7 2702
9c42dd28 2703 start_sequence ();
ad52b9b7 2704
9c42dd28 2705 /* Compute into TARGET. */
2706 if (expand_sfix_optab (target, op0, builtin_optab))
2707 {
2708 /* Output the entire sequence. */
2709 insns = get_insns ();
ad52b9b7 2710 end_sequence ();
9c42dd28 2711 emit_insn (insns);
2712 return target;
ad52b9b7 2713 }
2714
9c42dd28 2715 /* If we were unable to expand via the builtin, stop the sequence
2716 (without outputting the insns). */
2717 end_sequence ();
2718
ad52b9b7 2719 /* Fall back to floating point rounding optab. */
2720 fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
fc0dfa6e 2721
2722 /* For non-C99 targets we may end up without a fallback fndecl here
2723 if the user called __builtin_lfloor directly. In this case emit
2724 a call to the floor/ceil variants nevertheless. This should result
2725 in the best user experience for not full C99 targets. */
2726 if (fallback_fndecl == NULL_TREE)
2727 {
2728 tree fntype;
2729 const char *name = NULL;
2730
2731 switch (DECL_FUNCTION_CODE (fndecl))
2732 {
2733 case BUILT_IN_LCEIL:
2734 case BUILT_IN_LLCEIL:
2735 name = "ceil";
2736 break;
2737 case BUILT_IN_LCEILF:
2738 case BUILT_IN_LLCEILF:
2739 name = "ceilf";
2740 break;
2741 case BUILT_IN_LCEILL:
2742 case BUILT_IN_LLCEILL:
2743 name = "ceill";
2744 break;
2745 case BUILT_IN_LFLOOR:
2746 case BUILT_IN_LLFLOOR:
2747 name = "floor";
2748 break;
2749 case BUILT_IN_LFLOORF:
2750 case BUILT_IN_LLFLOORF:
2751 name = "floorf";
2752 break;
2753 case BUILT_IN_LFLOORL:
2754 case BUILT_IN_LLFLOORL:
2755 name = "floorl";
2756 break;
2757 default:
2758 gcc_unreachable ();
2759 }
2760
2761 fntype = build_function_type_list (TREE_TYPE (arg),
2762 TREE_TYPE (arg), NULL_TREE);
2763 fallback_fndecl = build_fn_decl (name, fntype);
2764 }
2765
0568e9c1 2766 exp = build_call_nofold_loc (EXPR_LOCATION (exp), fallback_fndecl, 1, arg);
ad52b9b7 2767
d4c690af 2768 tmp = expand_normal (exp);
ad52b9b7 2769
2770 /* Truncate the result of floating point optab to integer
2771 via expand_fix (). */
2772 target = gen_reg_rtx (mode);
2773 expand_fix (target, tmp, 0);
2774
2775 return target;
2776}
2777
7d3afc77 2778/* Expand a call to one of the builtin math functions doing integer
2779 conversion (lrint).
2780 Return 0 if a normal call should be emitted rather than expanding the
2781 function in-line. EXP is the expression that is a call to the builtin
ff1b14e4 2782 function; if convenient, the result should be placed in TARGET. */
7d3afc77 2783
2784static rtx
ff1b14e4 2785expand_builtin_int_roundingfn_2 (tree exp, rtx target)
7d3afc77 2786{
5f51ee59 2787 convert_optab builtin_optab;
7d3afc77 2788 rtx op0, insns;
2789 tree fndecl = get_callee_fndecl (exp);
4de0924f 2790 tree arg;
c2f47e15 2791 enum machine_mode mode;
7d3afc77 2792
2793 /* There's no easy way to detect the case we need to set EDOM. */
2794 if (flag_errno_math)
2795 return NULL_RTX;
2796
c2f47e15 2797 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2798 gcc_unreachable ();
48e1416a 2799
c2f47e15 2800 arg = CALL_EXPR_ARG (exp, 0);
7d3afc77 2801
2802 switch (DECL_FUNCTION_CODE (fndecl))
2803 {
2804 CASE_FLT_FN (BUILT_IN_LRINT):
2805 CASE_FLT_FN (BUILT_IN_LLRINT):
2806 builtin_optab = lrint_optab; break;
ef2f1a10 2807 CASE_FLT_FN (BUILT_IN_LROUND):
2808 CASE_FLT_FN (BUILT_IN_LLROUND):
2809 builtin_optab = lround_optab; break;
7d3afc77 2810 default:
2811 gcc_unreachable ();
2812 }
2813
2814 /* Make a suitable register to place result in. */
2815 mode = TYPE_MODE (TREE_TYPE (exp));
2816
5f51ee59 2817 target = gen_reg_rtx (mode);
7d3afc77 2818
5f51ee59 2819 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2820 need to expand the argument again. This way, we will not perform
2821 side-effects more the once. */
abfea505 2822 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7d3afc77 2823
ff1b14e4 2824 op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
7d3afc77 2825
5f51ee59 2826 start_sequence ();
7d3afc77 2827
5f51ee59 2828 if (expand_sfix_optab (target, op0, builtin_optab))
2829 {
2830 /* Output the entire sequence. */
2831 insns = get_insns ();
7d3afc77 2832 end_sequence ();
5f51ee59 2833 emit_insn (insns);
2834 return target;
7d3afc77 2835 }
2836
5f51ee59 2837 /* If we were unable to expand via the builtin, stop the sequence
2838 (without outputting the insns) and call to the library function
2839 with the stabilized argument list. */
2840 end_sequence ();
2841
7d3afc77 2842 target = expand_call (exp, target, target == const0_rtx);
2843
2844 return target;
2845}
2846
c2f47e15 2847/* Expand a call to the powi built-in mathematical function. Return NULL_RTX if
757c219d 2848 a normal call should be emitted rather than expanding the function
2849 in-line. EXP is the expression that is a call to the builtin
2850 function; if convenient, the result should be placed in TARGET. */
2851
2852static rtx
f97eea22 2853expand_builtin_powi (tree exp, rtx target)
757c219d 2854{
757c219d 2855 tree arg0, arg1;
2856 rtx op0, op1;
2857 enum machine_mode mode;
d0405f40 2858 enum machine_mode mode2;
757c219d 2859
c2f47e15 2860 if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
2861 return NULL_RTX;
757c219d 2862
c2f47e15 2863 arg0 = CALL_EXPR_ARG (exp, 0);
2864 arg1 = CALL_EXPR_ARG (exp, 1);
757c219d 2865 mode = TYPE_MODE (TREE_TYPE (exp));
2866
757c219d 2867 /* Emit a libcall to libgcc. */
2868
c2f47e15 2869 /* Mode of the 2nd argument must match that of an int. */
d0405f40 2870 mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
2871
757c219d 2872 if (target == NULL_RTX)
2873 target = gen_reg_rtx (mode);
2874
f97eea22 2875 op0 = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
757c219d 2876 if (GET_MODE (op0) != mode)
2877 op0 = convert_to_mode (mode, op0, 0);
1db6d067 2878 op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
d0405f40 2879 if (GET_MODE (op1) != mode2)
2880 op1 = convert_to_mode (mode2, op1, 0);
757c219d 2881
f36b9f69 2882 target = emit_library_call_value (optab_libfunc (powi_optab, mode),
2dd6f9ed 2883 target, LCT_CONST, mode, 2,
d0405f40 2884 op0, mode, op1, mode2);
757c219d 2885
2886 return target;
2887}
2888
48e1416a 2889/* Expand expression EXP which is a call to the strlen builtin. Return
c2f47e15 2890 NULL_RTX if we failed the caller should emit a normal call, otherwise
aed0bd19 2891 try to get the result in TARGET, if convenient. */
f7c44134 2892
53800dbe 2893static rtx
c2f47e15 2894expand_builtin_strlen (tree exp, rtx target,
aecda0d6 2895 enum machine_mode target_mode)
53800dbe 2896{
c2f47e15 2897 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2898 return NULL_RTX;
53800dbe 2899 else
2900 {
8786db1e 2901 struct expand_operand ops[4];
911c0150 2902 rtx pat;
c2f47e15 2903 tree len;
2904 tree src = CALL_EXPR_ARG (exp, 0);
8786db1e 2905 rtx src_reg, before_strlen;
2906 enum machine_mode insn_mode = target_mode;
ef2c4a29 2907 enum insn_code icode = CODE_FOR_nothing;
153c3b50 2908 unsigned int align;
6248e345 2909
2910 /* If the length can be computed at compile-time, return it. */
681fab1e 2911 len = c_strlen (src, 0);
6248e345 2912 if (len)
80cd7a5e 2913 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
6248e345 2914
681fab1e 2915 /* If the length can be computed at compile-time and is constant
2916 integer, but there are side-effects in src, evaluate
2917 src for side-effects, then return len.
2918 E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
2919 can be optimized into: i++; x = 3; */
2920 len = c_strlen (src, 1);
2921 if (len && TREE_CODE (len) == INTEGER_CST)
2922 {
2923 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2924 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
2925 }
2926
6248e345 2927 align = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
53800dbe 2928
53800dbe 2929 /* If SRC is not a pointer type, don't do this operation inline. */
2930 if (align == 0)
c2f47e15 2931 return NULL_RTX;
53800dbe 2932
911c0150 2933 /* Bail out if we can't compute strlen in the right mode. */
53800dbe 2934 while (insn_mode != VOIDmode)
2935 {
d6bf3b14 2936 icode = optab_handler (strlen_optab, insn_mode);
53800dbe 2937 if (icode != CODE_FOR_nothing)
c28ae87f 2938 break;
53800dbe 2939
2940 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
2941 }
2942 if (insn_mode == VOIDmode)
c2f47e15 2943 return NULL_RTX;
53800dbe 2944
911c0150 2945 /* Make a place to hold the source address. We will not expand
2946 the actual source until we are sure that the expansion will
2947 not fail -- there are trees that cannot be expanded twice. */
2948 src_reg = gen_reg_rtx (Pmode);
53800dbe 2949
911c0150 2950 /* Mark the beginning of the strlen sequence so we can emit the
2951 source operand later. */
f0ce3b1f 2952 before_strlen = get_last_insn ();
53800dbe 2953
8786db1e 2954 create_output_operand (&ops[0], target, insn_mode);
2955 create_fixed_operand (&ops[1], gen_rtx_MEM (BLKmode, src_reg));
2956 create_integer_operand (&ops[2], 0);
2957 create_integer_operand (&ops[3], align);
2958 if (!maybe_expand_insn (icode, 4, ops))
c2f47e15 2959 return NULL_RTX;
911c0150 2960
2961 /* Now that we are assured of success, expand the source. */
2962 start_sequence ();
499eee58 2963 pat = expand_expr (src, src_reg, Pmode, EXPAND_NORMAL);
911c0150 2964 if (pat != src_reg)
499eee58 2965 {
2966#ifdef POINTERS_EXTEND_UNSIGNED
2967 if (GET_MODE (pat) != Pmode)
2968 pat = convert_to_mode (Pmode, pat,
2969 POINTERS_EXTEND_UNSIGNED);
2970#endif
2971 emit_move_insn (src_reg, pat);
2972 }
31d3e01c 2973 pat = get_insns ();
911c0150 2974 end_sequence ();
bceb0d1f 2975
2976 if (before_strlen)
2977 emit_insn_after (pat, before_strlen);
2978 else
2979 emit_insn_before (pat, get_insns ());
53800dbe 2980
2981 /* Return the value in the proper mode for this function. */
8786db1e 2982 if (GET_MODE (ops[0].value) == target_mode)
2983 target = ops[0].value;
53800dbe 2984 else if (target != 0)
8786db1e 2985 convert_move (target, ops[0].value, 0);
53800dbe 2986 else
8786db1e 2987 target = convert_to_mode (target_mode, ops[0].value, 0);
911c0150 2988
2989 return target;
53800dbe 2990 }
2991}
2992
6840589f 2993/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
2994 bytes from constant string DATA + OFFSET and return it as target
2995 constant. */
2996
2997static rtx
aecda0d6 2998builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
2999 enum machine_mode mode)
6840589f 3000{
3001 const char *str = (const char *) data;
3002
64db345d 3003 gcc_assert (offset >= 0
3004 && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
3005 <= strlen (str) + 1));
6840589f 3006
3007 return c_readstr (str + offset, mode);
3008}
3009
c2f47e15 3010/* Expand a call EXP to the memcpy builtin.
3011 Return NULL_RTX if we failed, the caller should emit a normal call,
3b824fa6 3012 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3013 mode MODE if that's convenient). */
c2f47e15 3014
53800dbe 3015static rtx
a65c4d64 3016expand_builtin_memcpy (tree exp, rtx target)
53800dbe 3017{
c2f47e15 3018 if (!validate_arglist (exp,
3019 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3020 return NULL_RTX;
53800dbe 3021 else
3022 {
c2f47e15 3023 tree dest = CALL_EXPR_ARG (exp, 0);
3024 tree src = CALL_EXPR_ARG (exp, 1);
3025 tree len = CALL_EXPR_ARG (exp, 2);
6840589f 3026 const char *src_str;
27d0c333 3027 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3028 unsigned int dest_align
3029 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
53800dbe 3030 rtx dest_mem, src_mem, dest_addr, len_rtx;
162719b3 3031 HOST_WIDE_INT expected_size = -1;
3032 unsigned int expected_align = 0;
5a0de151 3033
6f428e8b 3034 /* If DEST is not a pointer type, call the normal function. */
3035 if (dest_align == 0)
c2f47e15 3036 return NULL_RTX;
6f428e8b 3037
6f428e8b 3038 /* If either SRC is not a pointer type, don't do this
a0c938f0 3039 operation in-line. */
6f428e8b 3040 if (src_align == 0)
c2f47e15 3041 return NULL_RTX;
48e1416a 3042
8cee8dc0 3043 if (currently_expanding_gimple_stmt)
3044 stringop_block_profile (currently_expanding_gimple_stmt,
3045 &expected_align, &expected_size);
75a70cf9 3046
162719b3 3047 if (expected_align < dest_align)
3048 expected_align = dest_align;
d8ae1baa 3049 dest_mem = get_memory_rtx (dest, len);
2a631e19 3050 set_mem_align (dest_mem, dest_align);
8ec3c5c2 3051 len_rtx = expand_normal (len);
6840589f 3052 src_str = c_getstr (src);
3053
3054 /* If SRC is a string constant and block move would be done
3055 by pieces, we can avoid loading the string from memory
3056 and only stored the computed constants. */
3057 if (src_str
971ba038 3058 && CONST_INT_P (len_rtx)
6840589f 3059 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3060 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3061 CONST_CAST (char *, src_str),
3062 dest_align, false))
6840589f 3063 {
9fe0e1b8 3064 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3065 builtin_memcpy_read_str,
364c0c59 3066 CONST_CAST (char *, src_str),
3067 dest_align, false, 0);
a65c4d64 3068 dest_mem = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3069 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3070 return dest_mem;
6840589f 3071 }
3072
d8ae1baa 3073 src_mem = get_memory_rtx (src, len);
2a631e19 3074 set_mem_align (src_mem, src_align);
53800dbe 3075
53800dbe 3076 /* Copy word part most expediently. */
162719b3 3077 dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
3078 CALL_EXPR_TAILCALL (exp)
3079 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3080 expected_align, expected_size);
53800dbe 3081
3082 if (dest_addr == 0)
e5716f7e 3083 {
a65c4d64 3084 dest_addr = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3085 dest_addr = convert_memory_address (ptr_mode, dest_addr);
e5716f7e 3086 }
9fe0e1b8 3087 return dest_addr;
53800dbe 3088 }
3089}
3090
c2f47e15 3091/* Expand a call EXP to the mempcpy builtin.
3092 Return NULL_RTX if we failed; the caller should emit a normal call,
647661c6 3093 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3094 mode MODE if that's convenient). If ENDP is 0 return the
3095 destination pointer, if ENDP is 1 return the end pointer ala
3096 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3097 stpcpy. */
647661c6 3098
3099static rtx
c8b17b2e 3100expand_builtin_mempcpy (tree exp, rtx target, enum machine_mode mode)
647661c6 3101{
c2f47e15 3102 if (!validate_arglist (exp,
3103 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3104 return NULL_RTX;
3105 else
3106 {
3107 tree dest = CALL_EXPR_ARG (exp, 0);
3108 tree src = CALL_EXPR_ARG (exp, 1);
3109 tree len = CALL_EXPR_ARG (exp, 2);
3110 return expand_builtin_mempcpy_args (dest, src, len,
c2f47e15 3111 target, mode, /*endp=*/ 1);
3112 }
3113}
3114
3115/* Helper function to do the actual work for expand_builtin_mempcpy. The
3116 arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out
3117 so that this can also be called without constructing an actual CALL_EXPR.
a65c4d64 3118 The other arguments and return value are the same as for
3119 expand_builtin_mempcpy. */
c2f47e15 3120
3121static rtx
a65c4d64 3122expand_builtin_mempcpy_args (tree dest, tree src, tree len,
c2f47e15 3123 rtx target, enum machine_mode mode, int endp)
3124{
3125 /* If return value is ignored, transform mempcpy into memcpy. */
c8b17b2e 3126 if (target == const0_rtx && implicit_built_in_decls[BUILT_IN_MEMCPY])
9fe0e1b8 3127 {
3128 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
0568e9c1 3129 tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3,
3130 dest, src, len);
c8b17b2e 3131 return expand_expr (result, target, mode, EXPAND_NORMAL);
9fe0e1b8 3132 }
647661c6 3133 else
3134 {
9fe0e1b8 3135 const char *src_str;
3136 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3137 unsigned int dest_align
3138 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3139 rtx dest_mem, src_mem, len_rtx;
a0c938f0 3140
7da1412b 3141 /* If either SRC or DEST is not a pointer type, don't do this
a0c938f0 3142 operation in-line. */
7da1412b 3143 if (dest_align == 0 || src_align == 0)
c2f47e15 3144 return NULL_RTX;
9fe0e1b8 3145
6217c238 3146 /* If LEN is not constant, call the normal function. */
3147 if (! host_integerp (len, 1))
c2f47e15 3148 return NULL_RTX;
0862b7e9 3149
8ec3c5c2 3150 len_rtx = expand_normal (len);
9fe0e1b8 3151 src_str = c_getstr (src);
647661c6 3152
9fe0e1b8 3153 /* If SRC is a string constant and block move would be done
3154 by pieces, we can avoid loading the string from memory
3155 and only stored the computed constants. */
3156 if (src_str
971ba038 3157 && CONST_INT_P (len_rtx)
9fe0e1b8 3158 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3159 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3160 CONST_CAST (char *, src_str),
3161 dest_align, false))
9fe0e1b8 3162 {
d8ae1baa 3163 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3164 set_mem_align (dest_mem, dest_align);
3165 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3166 builtin_memcpy_read_str,
364c0c59 3167 CONST_CAST (char *, src_str),
3168 dest_align, false, endp);
9fe0e1b8 3169 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3170 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3171 return dest_mem;
647661c6 3172 }
3173
971ba038 3174 if (CONST_INT_P (len_rtx)
9fe0e1b8 3175 && can_move_by_pieces (INTVAL (len_rtx),
3176 MIN (dest_align, src_align)))
3177 {
d8ae1baa 3178 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3179 set_mem_align (dest_mem, dest_align);
d8ae1baa 3180 src_mem = get_memory_rtx (src, len);
9fe0e1b8 3181 set_mem_align (src_mem, src_align);
3182 dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
3183 MIN (dest_align, src_align), endp);
3184 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3185 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3186 return dest_mem;
3187 }
3188
c2f47e15 3189 return NULL_RTX;
647661c6 3190 }
3191}
3192
727c62dd 3193#ifndef HAVE_movstr
3194# define HAVE_movstr 0
3195# define CODE_FOR_movstr CODE_FOR_nothing
3196#endif
3197
c2f47e15 3198/* Expand into a movstr instruction, if one is available. Return NULL_RTX if
727c62dd 3199 we failed, the caller should emit a normal call, otherwise try to
3200 get the result in TARGET, if convenient. If ENDP is 0 return the
3201 destination pointer, if ENDP is 1 return the end pointer ala
3202 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3203 stpcpy. */
3204
3205static rtx
3206expand_movstr (tree dest, tree src, rtx target, int endp)
3207{
8786db1e 3208 struct expand_operand ops[3];
727c62dd 3209 rtx dest_mem;
3210 rtx src_mem;
727c62dd 3211
3212 if (!HAVE_movstr)
c2f47e15 3213 return NULL_RTX;
727c62dd 3214
d8ae1baa 3215 dest_mem = get_memory_rtx (dest, NULL);
3216 src_mem = get_memory_rtx (src, NULL);
727c62dd 3217 if (!endp)
3218 {
3219 target = force_reg (Pmode, XEXP (dest_mem, 0));
3220 dest_mem = replace_equiv_address (dest_mem, target);
727c62dd 3221 }
3222
8786db1e 3223 create_output_operand (&ops[0], endp ? target : NULL_RTX, Pmode);
3224 create_fixed_operand (&ops[1], dest_mem);
3225 create_fixed_operand (&ops[2], src_mem);
3226 expand_insn (CODE_FOR_movstr, 3, ops);
727c62dd 3227
8786db1e 3228 if (endp && target != const0_rtx)
c5aba89c 3229 {
8786db1e 3230 target = ops[0].value;
3231 /* movstr is supposed to set end to the address of the NUL
3232 terminator. If the caller requested a mempcpy-like return value,
3233 adjust it. */
3234 if (endp == 1)
3235 {
45c0b118 3236 rtx tem = plus_constant (gen_lowpart (GET_MODE (target), target), 1);
8786db1e 3237 emit_move_insn (target, force_operand (tem, NULL_RTX));
3238 }
c5aba89c 3239 }
727c62dd 3240 return target;
3241}
3242
48e1416a 3243/* Expand expression EXP, which is a call to the strcpy builtin. Return
3244 NULL_RTX if we failed the caller should emit a normal call, otherwise
c2f47e15 3245 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3246 convenient). */
902de8ed 3247
53800dbe 3248static rtx
a65c4d64 3249expand_builtin_strcpy (tree exp, rtx target)
53800dbe 3250{
c2f47e15 3251 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3252 {
3253 tree dest = CALL_EXPR_ARG (exp, 0);
3254 tree src = CALL_EXPR_ARG (exp, 1);
a65c4d64 3255 return expand_builtin_strcpy_args (dest, src, target);
c2f47e15 3256 }
3257 return NULL_RTX;
3258}
3259
3260/* Helper function to do the actual work for expand_builtin_strcpy. The
3261 arguments to the builtin_strcpy call DEST and SRC are broken out
3262 so that this can also be called without constructing an actual CALL_EXPR.
3263 The other arguments and return value are the same as for
3264 expand_builtin_strcpy. */
3265
3266static rtx
a65c4d64 3267expand_builtin_strcpy_args (tree dest, tree src, rtx target)
c2f47e15 3268{
c2f47e15 3269 return expand_movstr (dest, src, target, /*endp=*/0);
53800dbe 3270}
3271
c2f47e15 3272/* Expand a call EXP to the stpcpy builtin.
3273 Return NULL_RTX if we failed the caller should emit a normal call,
3b824fa6 3274 otherwise try to get the result in TARGET, if convenient (and in
3275 mode MODE if that's convenient). */
3276
3277static rtx
dc369150 3278expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
3b824fa6 3279{
c2f47e15 3280 tree dst, src;
389dd41b 3281 location_t loc = EXPR_LOCATION (exp);
c2f47e15 3282
3283 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3284 return NULL_RTX;
3285
3286 dst = CALL_EXPR_ARG (exp, 0);
3287 src = CALL_EXPR_ARG (exp, 1);
3288
727c62dd 3289 /* If return value is ignored, transform stpcpy into strcpy. */
c8b17b2e 3290 if (target == const0_rtx && implicit_built_in_decls[BUILT_IN_STRCPY])
978836e5 3291 {
3292 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
0568e9c1 3293 tree result = build_call_nofold_loc (loc, fn, 2, dst, src);
c8b17b2e 3294 return expand_expr (result, target, mode, EXPAND_NORMAL);
978836e5 3295 }
3b824fa6 3296 else
3297 {
c2f47e15 3298 tree len, lenp1;
727c62dd 3299 rtx ret;
647661c6 3300
9fe0e1b8 3301 /* Ensure we get an actual string whose length can be evaluated at
a0c938f0 3302 compile-time, not an expression containing a string. This is
3303 because the latter will potentially produce pessimized code
3304 when used to produce the return value. */
681fab1e 3305 if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
c2f47e15 3306 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3307
389dd41b 3308 lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
a65c4d64 3309 ret = expand_builtin_mempcpy_args (dst, src, lenp1,
c2f47e15 3310 target, mode, /*endp=*/2);
727c62dd 3311
3312 if (ret)
3313 return ret;
3314
3315 if (TREE_CODE (len) == INTEGER_CST)
3316 {
8ec3c5c2 3317 rtx len_rtx = expand_normal (len);
727c62dd 3318
971ba038 3319 if (CONST_INT_P (len_rtx))
727c62dd 3320 {
a65c4d64 3321 ret = expand_builtin_strcpy_args (dst, src, target);
727c62dd 3322
3323 if (ret)
3324 {
3325 if (! target)
7ac87324 3326 {
3327 if (mode != VOIDmode)
3328 target = gen_reg_rtx (mode);
3329 else
3330 target = gen_reg_rtx (GET_MODE (ret));
3331 }
727c62dd 3332 if (GET_MODE (target) != GET_MODE (ret))
3333 ret = gen_lowpart (GET_MODE (target), ret);
3334
c5aba89c 3335 ret = plus_constant (ret, INTVAL (len_rtx));
3336 ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
64db345d 3337 gcc_assert (ret);
727c62dd 3338
3339 return target;
3340 }
3341 }
3342 }
3343
c2f47e15 3344 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3345 }
3346}
3347
6840589f 3348/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3349 bytes from constant string DATA + OFFSET and return it as target
3350 constant. */
3351
09879952 3352rtx
aecda0d6 3353builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
3354 enum machine_mode mode)
6840589f 3355{
3356 const char *str = (const char *) data;
3357
3358 if ((unsigned HOST_WIDE_INT) offset > strlen (str))
3359 return const0_rtx;
3360
3361 return c_readstr (str + offset, mode);
3362}
3363
48e1416a 3364/* Expand expression EXP, which is a call to the strncpy builtin. Return
c2f47e15 3365 NULL_RTX if we failed the caller should emit a normal call. */
ed09096d 3366
3367static rtx
a65c4d64 3368expand_builtin_strncpy (tree exp, rtx target)
ed09096d 3369{
389dd41b 3370 location_t loc = EXPR_LOCATION (exp);
c2f47e15 3371
3372 if (validate_arglist (exp,
3373 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
ed09096d 3374 {
c2f47e15 3375 tree dest = CALL_EXPR_ARG (exp, 0);
3376 tree src = CALL_EXPR_ARG (exp, 1);
3377 tree len = CALL_EXPR_ARG (exp, 2);
3378 tree slen = c_strlen (src, 1);
6840589f 3379
8ff6a5cd 3380 /* We must be passed a constant len and src parameter. */
3381 if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
c2f47e15 3382 return NULL_RTX;
ed09096d 3383
389dd41b 3384 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
ed09096d 3385
3386 /* We're required to pad with trailing zeros if the requested
a0c938f0 3387 len is greater than strlen(s2)+1. In that case try to
6840589f 3388 use store_by_pieces, if it fails, punt. */
ed09096d 3389 if (tree_int_cst_lt (slen, len))
6840589f 3390 {
27d0c333 3391 unsigned int dest_align
3392 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
c2f47e15 3393 const char *p = c_getstr (src);
6840589f 3394 rtx dest_mem;
3395
27d0c333 3396 if (!p || dest_align == 0 || !host_integerp (len, 1)
3397 || !can_store_by_pieces (tree_low_cst (len, 1),
6840589f 3398 builtin_strncpy_read_str,
364c0c59 3399 CONST_CAST (char *, p),
3400 dest_align, false))
c2f47e15 3401 return NULL_RTX;
6840589f 3402
d8ae1baa 3403 dest_mem = get_memory_rtx (dest, len);
27d0c333 3404 store_by_pieces (dest_mem, tree_low_cst (len, 1),
6840589f 3405 builtin_strncpy_read_str,
364c0c59 3406 CONST_CAST (char *, p), dest_align, false, 0);
a65c4d64 3407 dest_mem = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3408 dest_mem = convert_memory_address (ptr_mode, dest_mem);
e5716f7e 3409 return dest_mem;
6840589f 3410 }
ed09096d 3411 }
c2f47e15 3412 return NULL_RTX;
ed09096d 3413}
3414
ecc318ff 3415/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3416 bytes from constant string DATA + OFFSET and return it as target
3417 constant. */
3418
f656b751 3419rtx
aecda0d6 3420builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3421 enum machine_mode mode)
ecc318ff 3422{
3423 const char *c = (const char *) data;
364c0c59 3424 char *p = XALLOCAVEC (char, GET_MODE_SIZE (mode));
ecc318ff 3425
3426 memset (p, *c, GET_MODE_SIZE (mode));
3427
3428 return c_readstr (p, mode);
3429}
3430
a7ec6974 3431/* Callback routine for store_by_pieces. Return the RTL of a register
3432 containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
3433 char value given in the RTL register data. For example, if mode is
3434 4 bytes wide, return the RTL for 0x01010101*data. */
3435
3436static rtx
aecda0d6 3437builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3438 enum machine_mode mode)
a7ec6974 3439{
3440 rtx target, coeff;
3441 size_t size;
3442 char *p;
3443
3444 size = GET_MODE_SIZE (mode);
f0ce3b1f 3445 if (size == 1)
3446 return (rtx) data;
a7ec6974 3447
364c0c59 3448 p = XALLOCAVEC (char, size);
a7ec6974 3449 memset (p, 1, size);
3450 coeff = c_readstr (p, mode);
3451
f0ce3b1f 3452 target = convert_to_mode (mode, (rtx) data, 1);
a7ec6974 3453 target = expand_mult (mode, target, coeff, NULL_RTX, 1);
3454 return force_reg (mode, target);
3455}
3456
48e1416a 3457/* Expand expression EXP, which is a call to the memset builtin. Return
3458 NULL_RTX if we failed the caller should emit a normal call, otherwise
c2f47e15 3459 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3460 convenient). */
902de8ed 3461
53800dbe 3462static rtx
c2f47e15 3463expand_builtin_memset (tree exp, rtx target, enum machine_mode mode)
53800dbe 3464{
c2f47e15 3465 if (!validate_arglist (exp,
3466 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
3467 return NULL_RTX;
53800dbe 3468 else
3469 {
c2f47e15 3470 tree dest = CALL_EXPR_ARG (exp, 0);
3471 tree val = CALL_EXPR_ARG (exp, 1);
3472 tree len = CALL_EXPR_ARG (exp, 2);
3473 return expand_builtin_memset_args (dest, val, len, target, mode, exp);
3474 }
3475}
53800dbe 3476
c2f47e15 3477/* Helper function to do the actual work for expand_builtin_memset. The
3478 arguments to the builtin_memset call DEST, VAL, and LEN are broken out
3479 so that this can also be called without constructing an actual CALL_EXPR.
3480 The other arguments and return value are the same as for
3481 expand_builtin_memset. */
6b961939 3482
c2f47e15 3483static rtx
3484expand_builtin_memset_args (tree dest, tree val, tree len,
3485 rtx target, enum machine_mode mode, tree orig_exp)
3486{
3487 tree fndecl, fn;
3488 enum built_in_function fcode;
03a5dda9 3489 enum machine_mode val_mode;
c2f47e15 3490 char c;
3491 unsigned int dest_align;
3492 rtx dest_mem, dest_addr, len_rtx;
3493 HOST_WIDE_INT expected_size = -1;
3494 unsigned int expected_align = 0;
53800dbe 3495
c2f47e15 3496 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
162719b3 3497
c2f47e15 3498 /* If DEST is not a pointer type, don't do this operation in-line. */
3499 if (dest_align == 0)
3500 return NULL_RTX;
6f428e8b 3501
8cee8dc0 3502 if (currently_expanding_gimple_stmt)
3503 stringop_block_profile (currently_expanding_gimple_stmt,
3504 &expected_align, &expected_size);
75a70cf9 3505
c2f47e15 3506 if (expected_align < dest_align)
3507 expected_align = dest_align;
6b961939 3508
c2f47e15 3509 /* If the LEN parameter is zero, return DEST. */
3510 if (integer_zerop (len))
3511 {
3512 /* Evaluate and ignore VAL in case it has side-effects. */
3513 expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
3514 return expand_expr (dest, target, mode, EXPAND_NORMAL);
3515 }
7a3e5564 3516
c2f47e15 3517 /* Stabilize the arguments in case we fail. */
3518 dest = builtin_save_expr (dest);
3519 val = builtin_save_expr (val);
3520 len = builtin_save_expr (len);
a7ec6974 3521
c2f47e15 3522 len_rtx = expand_normal (len);
3523 dest_mem = get_memory_rtx (dest, len);
03a5dda9 3524 val_mode = TYPE_MODE (unsigned_char_type_node);
a7ec6974 3525
c2f47e15 3526 if (TREE_CODE (val) != INTEGER_CST)
3527 {
3528 rtx val_rtx;
a7ec6974 3529
c2f47e15 3530 val_rtx = expand_normal (val);
03a5dda9 3531 val_rtx = convert_to_mode (val_mode, val_rtx, 0);
53800dbe 3532
c2f47e15 3533 /* Assume that we can memset by pieces if we can store
3534 * the coefficients by pieces (in the required modes).
3535 * We can't pass builtin_memset_gen_str as that emits RTL. */
3536 c = 1;
3537 if (host_integerp (len, 1)
c2f47e15 3538 && can_store_by_pieces (tree_low_cst (len, 1),
4b297e2e 3539 builtin_memset_read_str, &c, dest_align,
3540 true))
c2f47e15 3541 {
03a5dda9 3542 val_rtx = force_reg (val_mode, val_rtx);
c2f47e15 3543 store_by_pieces (dest_mem, tree_low_cst (len, 1),
4b297e2e 3544 builtin_memset_gen_str, val_rtx, dest_align,
3545 true, 0);
c2f47e15 3546 }
3547 else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
3548 dest_align, expected_align,
3549 expected_size))
6b961939 3550 goto do_libcall;
48e1416a 3551
c2f47e15 3552 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3553 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3554 return dest_mem;
3555 }
53800dbe 3556
c2f47e15 3557 if (target_char_cast (val, &c))
3558 goto do_libcall;
ecc318ff 3559
c2f47e15 3560 if (c)
3561 {
3562 if (host_integerp (len, 1)
c2f47e15 3563 && can_store_by_pieces (tree_low_cst (len, 1),
4b297e2e 3564 builtin_memset_read_str, &c, dest_align,
3565 true))
c2f47e15 3566 store_by_pieces (dest_mem, tree_low_cst (len, 1),
4b297e2e 3567 builtin_memset_read_str, &c, dest_align, true, 0);
03a5dda9 3568 else if (!set_storage_via_setmem (dest_mem, len_rtx,
3569 gen_int_mode (c, val_mode),
c2f47e15 3570 dest_align, expected_align,
3571 expected_size))
3572 goto do_libcall;
48e1416a 3573
c2f47e15 3574 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3575 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3576 return dest_mem;
3577 }
ecc318ff 3578
c2f47e15 3579 set_mem_align (dest_mem, dest_align);
3580 dest_addr = clear_storage_hints (dest_mem, len_rtx,
3581 CALL_EXPR_TAILCALL (orig_exp)
3582 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3583 expected_align, expected_size);
53800dbe 3584
c2f47e15 3585 if (dest_addr == 0)
3586 {
3587 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3588 dest_addr = convert_memory_address (ptr_mode, dest_addr);
3589 }
53800dbe 3590
c2f47e15 3591 return dest_addr;
6b961939 3592
c2f47e15 3593 do_libcall:
3594 fndecl = get_callee_fndecl (orig_exp);
3595 fcode = DECL_FUNCTION_CODE (fndecl);
3596 if (fcode == BUILT_IN_MEMSET)
0568e9c1 3597 fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 3,
3598 dest, val, len);
c2f47e15 3599 else if (fcode == BUILT_IN_BZERO)
0568e9c1 3600 fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 2,
3601 dest, len);
c2f47e15 3602 else
3603 gcc_unreachable ();
a65c4d64 3604 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
3605 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
c2f47e15 3606 return expand_call (fn, target, target == const0_rtx);
53800dbe 3607}
3608
48e1416a 3609/* Expand expression EXP, which is a call to the bzero builtin. Return
c2f47e15 3610 NULL_RTX if we failed the caller should emit a normal call. */
27d0c333 3611
ffc83088 3612static rtx
0b25db21 3613expand_builtin_bzero (tree exp)
ffc83088 3614{
c2f47e15 3615 tree dest, size;
389dd41b 3616 location_t loc = EXPR_LOCATION (exp);
ffc83088 3617
c2f47e15 3618 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
7369e7ba 3619 return NULL_RTX;
ffc83088 3620
c2f47e15 3621 dest = CALL_EXPR_ARG (exp, 0);
3622 size = CALL_EXPR_ARG (exp, 1);
bf8e3599 3623
7369e7ba 3624 /* New argument list transforming bzero(ptr x, int y) to
6f428e8b 3625 memset(ptr x, int 0, size_t y). This is done this way
3626 so that if it isn't expanded inline, we fallback to
3627 calling bzero instead of memset. */
bf8e3599 3628
c2f47e15 3629 return expand_builtin_memset_args (dest, integer_zero_node,
389dd41b 3630 fold_convert_loc (loc, sizetype, size),
c2f47e15 3631 const0_rtx, VOIDmode, exp);
ffc83088 3632}
3633
7a3f89b5 3634/* Expand expression EXP, which is a call to the memcmp built-in function.
c2f47e15 3635 Return NULL_RTX if we failed and the
53800dbe 3636 caller should emit a normal call, otherwise try to get the result in
6f428e8b 3637 TARGET, if convenient (and in mode MODE, if that's convenient). */
27d0c333 3638
53800dbe 3639static rtx
a65c4d64 3640expand_builtin_memcmp (tree exp, ATTRIBUTE_UNUSED rtx target,
3641 ATTRIBUTE_UNUSED enum machine_mode mode)
53800dbe 3642{
a65c4d64 3643 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
389dd41b 3644
c2f47e15 3645 if (!validate_arglist (exp,
3646 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3647 return NULL_RTX;
6f428e8b 3648
6ac5504b 3649#if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi
53800dbe 3650 {
0cd832f0 3651 rtx arg1_rtx, arg2_rtx, arg3_rtx;
53800dbe 3652 rtx result;
0cd832f0 3653 rtx insn;
c2f47e15 3654 tree arg1 = CALL_EXPR_ARG (exp, 0);
3655 tree arg2 = CALL_EXPR_ARG (exp, 1);
3656 tree len = CALL_EXPR_ARG (exp, 2);
53800dbe 3657
153c3b50 3658 unsigned int arg1_align
53800dbe 3659 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
153c3b50 3660 unsigned int arg2_align
53800dbe 3661 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
b428c0a5 3662 enum machine_mode insn_mode;
3663
3664#ifdef HAVE_cmpmemsi
3665 if (HAVE_cmpmemsi)
3666 insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
3667 else
3668#endif
6ac5504b 3669#ifdef HAVE_cmpstrnsi
3670 if (HAVE_cmpstrnsi)
3671 insn_mode = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
b428c0a5 3672 else
3673#endif
c2f47e15 3674 return NULL_RTX;
53800dbe 3675
3676 /* If we don't have POINTER_TYPE, call the function. */
3677 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 3678 return NULL_RTX;
53800dbe 3679
3680 /* Make a place to write the result of the instruction. */
3681 result = target;
3682 if (! (result != 0
8ad4c111 3683 && REG_P (result) && GET_MODE (result) == insn_mode
53800dbe 3684 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3685 result = gen_reg_rtx (insn_mode);
3686
d8ae1baa 3687 arg1_rtx = get_memory_rtx (arg1, len);
3688 arg2_rtx = get_memory_rtx (arg2, len);
389dd41b 3689 arg3_rtx = expand_normal (fold_convert_loc (loc, sizetype, len));
83f88f8e 3690
3691 /* Set MEM_SIZE as appropriate. */
971ba038 3692 if (CONST_INT_P (arg3_rtx))
83f88f8e 3693 {
3694 set_mem_size (arg1_rtx, arg3_rtx);
3695 set_mem_size (arg2_rtx, arg3_rtx);
3696 }
3697
b428c0a5 3698#ifdef HAVE_cmpmemsi
3699 if (HAVE_cmpmemsi)
3700 insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3701 GEN_INT (MIN (arg1_align, arg2_align)));
0cd832f0 3702 else
b428c0a5 3703#endif
6ac5504b 3704#ifdef HAVE_cmpstrnsi
3705 if (HAVE_cmpstrnsi)
3706 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3707 GEN_INT (MIN (arg1_align, arg2_align)));
b428c0a5 3708 else
3709#endif
64db345d 3710 gcc_unreachable ();
0cd832f0 3711
3712 if (insn)
3713 emit_insn (insn);
3714 else
2dd6f9ed 3715 emit_library_call_value (memcmp_libfunc, result, LCT_PURE,
0cd832f0 3716 TYPE_MODE (integer_type_node), 3,
3717 XEXP (arg1_rtx, 0), Pmode,
3718 XEXP (arg2_rtx, 0), Pmode,
3719 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
78a8ed03 3720 TYPE_UNSIGNED (sizetype)),
0cd832f0 3721 TYPE_MODE (sizetype));
53800dbe 3722
3723 /* Return the value in the proper mode for this function. */
3724 mode = TYPE_MODE (TREE_TYPE (exp));
3725 if (GET_MODE (result) == mode)
3726 return result;
3727 else if (target != 0)
3728 {
3729 convert_move (target, result, 0);
3730 return target;
3731 }
3732 else
3733 return convert_to_mode (mode, result, 0);
3734 }
83d79705 3735#endif
53800dbe 3736
c2f47e15 3737 return NULL_RTX;
6f428e8b 3738}
3739
c2f47e15 3740/* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX
53800dbe 3741 if we failed the caller should emit a normal call, otherwise try to get
3742 the result in TARGET, if convenient. */
902de8ed 3743
53800dbe 3744static rtx
a65c4d64 3745expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
53800dbe 3746{
c2f47e15 3747 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3748 return NULL_RTX;
bf8e3599 3749
6ac5504b 3750#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
6b531606 3751 if (direct_optab_handler (cmpstr_optab, SImode) != CODE_FOR_nothing
3752 || direct_optab_handler (cmpstrn_optab, SImode) != CODE_FOR_nothing)
6ac5504b 3753 {
3754 rtx arg1_rtx, arg2_rtx;
3755 rtx result, insn = NULL_RTX;
3756 tree fndecl, fn;
c2f47e15 3757 tree arg1 = CALL_EXPR_ARG (exp, 0);
3758 tree arg2 = CALL_EXPR_ARG (exp, 1);
a0c938f0 3759
153c3b50 3760 unsigned int arg1_align
6ac5504b 3761 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
153c3b50 3762 unsigned int arg2_align
6ac5504b 3763 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3764
3765 /* If we don't have POINTER_TYPE, call the function. */
3766 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 3767 return NULL_RTX;
7a3f89b5 3768
6ac5504b 3769 /* Stabilize the arguments in case gen_cmpstr(n)si fail. */
3770 arg1 = builtin_save_expr (arg1);
3771 arg2 = builtin_save_expr (arg2);
7a3f89b5 3772
d8ae1baa 3773 arg1_rtx = get_memory_rtx (arg1, NULL);
3774 arg2_rtx = get_memory_rtx (arg2, NULL);
53800dbe 3775
6ac5504b 3776#ifdef HAVE_cmpstrsi
3777 /* Try to call cmpstrsi. */
3778 if (HAVE_cmpstrsi)
3779 {
a0c938f0 3780 enum machine_mode insn_mode
6ac5504b 3781 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3782
3783 /* Make a place to write the result of the instruction. */
3784 result = target;
3785 if (! (result != 0
3786 && REG_P (result) && GET_MODE (result) == insn_mode
3787 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3788 result = gen_reg_rtx (insn_mode);
3789
3790 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
3791 GEN_INT (MIN (arg1_align, arg2_align)));
3792 }
3793#endif
03fd9d2c 3794#ifdef HAVE_cmpstrnsi
6ac5504b 3795 /* Try to determine at least one length and call cmpstrnsi. */
a0c938f0 3796 if (!insn && HAVE_cmpstrnsi)
6ac5504b 3797 {
3798 tree len;
3799 rtx arg3_rtx;
3800
a0c938f0 3801 enum machine_mode insn_mode
6ac5504b 3802 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
3803 tree len1 = c_strlen (arg1, 1);
3804 tree len2 = c_strlen (arg2, 1);
3805
3806 if (len1)
3807 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3808 if (len2)
3809 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3810
3811 /* If we don't have a constant length for the first, use the length
3812 of the second, if we know it. We don't require a constant for
3813 this case; some cost analysis could be done if both are available
3814 but neither is constant. For now, assume they're equally cheap,
3815 unless one has side effects. If both strings have constant lengths,
3816 use the smaller. */
3817
3818 if (!len1)
3819 len = len2;
3820 else if (!len2)
3821 len = len1;
3822 else if (TREE_SIDE_EFFECTS (len1))
3823 len = len2;
3824 else if (TREE_SIDE_EFFECTS (len2))
3825 len = len1;
3826 else if (TREE_CODE (len1) != INTEGER_CST)
3827 len = len2;
3828 else if (TREE_CODE (len2) != INTEGER_CST)
3829 len = len1;
3830 else if (tree_int_cst_lt (len1, len2))
3831 len = len1;
3832 else
3833 len = len2;
3834
3835 /* If both arguments have side effects, we cannot optimize. */
3836 if (!len || TREE_SIDE_EFFECTS (len))
6b961939 3837 goto do_libcall;
53800dbe 3838
8ec3c5c2 3839 arg3_rtx = expand_normal (len);
902de8ed 3840
6ac5504b 3841 /* Make a place to write the result of the instruction. */
3842 result = target;
3843 if (! (result != 0
3844 && REG_P (result) && GET_MODE (result) == insn_mode
3845 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3846 result = gen_reg_rtx (insn_mode);
53800dbe 3847
6ac5504b 3848 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3849 GEN_INT (MIN (arg1_align, arg2_align)));
3850 }
3851#endif
3f8aefe2 3852
6ac5504b 3853 if (insn)
3854 {
a65c4d64 3855 enum machine_mode mode;
6ac5504b 3856 emit_insn (insn);
3f8aefe2 3857
6ac5504b 3858 /* Return the value in the proper mode for this function. */
3859 mode = TYPE_MODE (TREE_TYPE (exp));
3860 if (GET_MODE (result) == mode)
3861 return result;
3862 if (target == 0)
3863 return convert_to_mode (mode, result, 0);
3864 convert_move (target, result, 0);
3865 return target;
3866 }
902de8ed 3867
6ac5504b 3868 /* Expand the library call ourselves using a stabilized argument
3869 list to avoid re-evaluating the function's arguments twice. */
2694880e 3870#ifdef HAVE_cmpstrnsi
6b961939 3871 do_libcall:
2694880e 3872#endif
6ac5504b 3873 fndecl = get_callee_fndecl (exp);
0568e9c1 3874 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2);
a65c4d64 3875 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
3876 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
6ac5504b 3877 return expand_call (fn, target, target == const0_rtx);
3878 }
7a3f89b5 3879#endif
c2f47e15 3880 return NULL_RTX;
83d79705 3881}
53800dbe 3882
48e1416a 3883/* Expand expression EXP, which is a call to the strncmp builtin. Return
c2f47e15 3884 NULL_RTX if we failed the caller should emit a normal call, otherwise try to get
ed09096d 3885 the result in TARGET, if convenient. */
27d0c333 3886
ed09096d 3887static rtx
a65c4d64 3888expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
3889 ATTRIBUTE_UNUSED enum machine_mode mode)
ed09096d 3890{
a65c4d64 3891 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
389dd41b 3892
c2f47e15 3893 if (!validate_arglist (exp,
3894 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3895 return NULL_RTX;
ed09096d 3896
6e34e617 3897 /* If c_strlen can determine an expression for one of the string
6ac5504b 3898 lengths, and it doesn't have side effects, then emit cmpstrnsi
7a3f89b5 3899 using length MIN(strlen(string)+1, arg3). */
6ac5504b 3900#ifdef HAVE_cmpstrnsi
3901 if (HAVE_cmpstrnsi)
7a3f89b5 3902 {
3903 tree len, len1, len2;
3904 rtx arg1_rtx, arg2_rtx, arg3_rtx;
3905 rtx result, insn;
0b25db21 3906 tree fndecl, fn;
c2f47e15 3907 tree arg1 = CALL_EXPR_ARG (exp, 0);
3908 tree arg2 = CALL_EXPR_ARG (exp, 1);
3909 tree arg3 = CALL_EXPR_ARG (exp, 2);
6f428e8b 3910
153c3b50 3911 unsigned int arg1_align
7a3f89b5 3912 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
153c3b50 3913 unsigned int arg2_align
7a3f89b5 3914 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3915 enum machine_mode insn_mode
6ac5504b 3916 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
bf8e3599 3917
681fab1e 3918 len1 = c_strlen (arg1, 1);
3919 len2 = c_strlen (arg2, 1);
7a3f89b5 3920
3921 if (len1)
389dd41b 3922 len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1);
7a3f89b5 3923 if (len2)
389dd41b 3924 len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2);
7a3f89b5 3925
3926 /* If we don't have a constant length for the first, use the length
3927 of the second, if we know it. We don't require a constant for
3928 this case; some cost analysis could be done if both are available
3929 but neither is constant. For now, assume they're equally cheap,
3930 unless one has side effects. If both strings have constant lengths,
3931 use the smaller. */
3932
3933 if (!len1)
3934 len = len2;
3935 else if (!len2)
3936 len = len1;
3937 else if (TREE_SIDE_EFFECTS (len1))
3938 len = len2;
3939 else if (TREE_SIDE_EFFECTS (len2))
3940 len = len1;
3941 else if (TREE_CODE (len1) != INTEGER_CST)
3942 len = len2;
3943 else if (TREE_CODE (len2) != INTEGER_CST)
3944 len = len1;
3945 else if (tree_int_cst_lt (len1, len2))
3946 len = len1;
3947 else
3948 len = len2;
6e34e617 3949
7a3f89b5 3950 /* If both arguments have side effects, we cannot optimize. */
3951 if (!len || TREE_SIDE_EFFECTS (len))
c2f47e15 3952 return NULL_RTX;
bf8e3599 3953
7a3f89b5 3954 /* The actual new length parameter is MIN(len,arg3). */
389dd41b 3955 len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len,
3956 fold_convert_loc (loc, TREE_TYPE (len), arg3));
7a3f89b5 3957
3958 /* If we don't have POINTER_TYPE, call the function. */
3959 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 3960 return NULL_RTX;
7a3f89b5 3961
3962 /* Make a place to write the result of the instruction. */
3963 result = target;
3964 if (! (result != 0
8ad4c111 3965 && REG_P (result) && GET_MODE (result) == insn_mode
7a3f89b5 3966 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3967 result = gen_reg_rtx (insn_mode);
3968
a65c4d64 3969 /* Stabilize the arguments in case gen_cmpstrnsi fails. */
3970 arg1 = builtin_save_expr (arg1);
3971 arg2 = builtin_save_expr (arg2);
3972 len = builtin_save_expr (len);
27d0c333 3973
a65c4d64 3974 arg1_rtx = get_memory_rtx (arg1, len);
3975 arg2_rtx = get_memory_rtx (arg2, len);
3976 arg3_rtx = expand_normal (len);
3977 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3978 GEN_INT (MIN (arg1_align, arg2_align)));
3979 if (insn)
3980 {
3981 emit_insn (insn);
49f0327b 3982
a65c4d64 3983 /* Return the value in the proper mode for this function. */
3984 mode = TYPE_MODE (TREE_TYPE (exp));
3985 if (GET_MODE (result) == mode)
3986 return result;
3987 if (target == 0)
3988 return convert_to_mode (mode, result, 0);
3989 convert_move (target, result, 0);
3990 return target;
3991 }
27d0c333 3992
a65c4d64 3993 /* Expand the library call ourselves using a stabilized argument
3994 list to avoid re-evaluating the function's arguments twice. */
3995 fndecl = get_callee_fndecl (exp);
0568e9c1 3996 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 3,
3997 arg1, arg2, len);
a65c4d64 3998 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
3999 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4000 return expand_call (fn, target, target == const0_rtx);
4001 }
4002#endif
c2f47e15 4003 return NULL_RTX;
49f0327b 4004}
4005
a66c9326 4006/* Expand a call to __builtin_saveregs, generating the result in TARGET,
4007 if that's convenient. */
902de8ed 4008
a66c9326 4009rtx
aecda0d6 4010expand_builtin_saveregs (void)
53800dbe 4011{
a66c9326 4012 rtx val, seq;
53800dbe 4013
4014 /* Don't do __builtin_saveregs more than once in a function.
4015 Save the result of the first call and reuse it. */
4016 if (saveregs_value != 0)
4017 return saveregs_value;
53800dbe 4018
a66c9326 4019 /* When this function is called, it means that registers must be
4020 saved on entry to this function. So we migrate the call to the
4021 first insn of this function. */
4022
4023 start_sequence ();
53800dbe 4024
a66c9326 4025 /* Do whatever the machine needs done in this case. */
45550790 4026 val = targetm.calls.expand_builtin_saveregs ();
53800dbe 4027
a66c9326 4028 seq = get_insns ();
4029 end_sequence ();
53800dbe 4030
a66c9326 4031 saveregs_value = val;
53800dbe 4032
31d3e01c 4033 /* Put the insns after the NOTE that starts the function. If this
4034 is inside a start_sequence, make the outer-level insn chain current, so
a66c9326 4035 the code is placed at the start of the function. */
4036 push_topmost_sequence ();
0ec80471 4037 emit_insn_after (seq, entry_of_function ());
a66c9326 4038 pop_topmost_sequence ();
4039
4040 return val;
53800dbe 4041}
4042
79012a9d 4043/* Expand a call to __builtin_next_arg. */
27d0c333 4044
53800dbe 4045static rtx
79012a9d 4046expand_builtin_next_arg (void)
53800dbe 4047{
79012a9d 4048 /* Checking arguments is already done in fold_builtin_next_arg
4049 that must be called before this function. */
940ddc5c 4050 return expand_binop (ptr_mode, add_optab,
abe32cce 4051 crtl->args.internal_arg_pointer,
4052 crtl->args.arg_offset_rtx,
53800dbe 4053 NULL_RTX, 0, OPTAB_LIB_WIDEN);
4054}
4055
a66c9326 4056/* Make it easier for the backends by protecting the valist argument
4057 from multiple evaluations. */
4058
4059static tree
389dd41b 4060stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
a66c9326 4061{
5f57a8b1 4062 tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
4063
182cf5a9 4064 /* The current way of determining the type of valist is completely
4065 bogus. We should have the information on the va builtin instead. */
4066 if (!vatype)
4067 vatype = targetm.fn_abi_va_list (cfun->decl);
5f57a8b1 4068
4069 if (TREE_CODE (vatype) == ARRAY_TYPE)
a66c9326 4070 {
2d47cc32 4071 if (TREE_SIDE_EFFECTS (valist))
4072 valist = save_expr (valist);
11a61dea 4073
2d47cc32 4074 /* For this case, the backends will be expecting a pointer to
5f57a8b1 4075 vatype, but it's possible we've actually been given an array
4076 (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)).
2d47cc32 4077 So fix it. */
4078 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
8a15c04a 4079 {
5f57a8b1 4080 tree p1 = build_pointer_type (TREE_TYPE (vatype));
389dd41b 4081 valist = build_fold_addr_expr_with_type_loc (loc, valist, p1);
8a15c04a 4082 }
a66c9326 4083 }
11a61dea 4084 else
a66c9326 4085 {
182cf5a9 4086 tree pt = build_pointer_type (vatype);
11a61dea 4087
2d47cc32 4088 if (! needs_lvalue)
4089 {
11a61dea 4090 if (! TREE_SIDE_EFFECTS (valist))
4091 return valist;
bf8e3599 4092
389dd41b 4093 valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist);
a66c9326 4094 TREE_SIDE_EFFECTS (valist) = 1;
a66c9326 4095 }
2d47cc32 4096
11a61dea 4097 if (TREE_SIDE_EFFECTS (valist))
2d47cc32 4098 valist = save_expr (valist);
182cf5a9 4099 valist = fold_build2_loc (loc, MEM_REF,
4100 vatype, valist, build_int_cst (pt, 0));
a66c9326 4101 }
4102
4103 return valist;
4104}
4105
2e15d750 4106/* The "standard" definition of va_list is void*. */
4107
4108tree
4109std_build_builtin_va_list (void)
4110{
4111 return ptr_type_node;
4112}
4113
5f57a8b1 4114/* The "standard" abi va_list is va_list_type_node. */
4115
4116tree
4117std_fn_abi_va_list (tree fndecl ATTRIBUTE_UNUSED)
4118{
4119 return va_list_type_node;
4120}
4121
4122/* The "standard" type of va_list is va_list_type_node. */
4123
4124tree
4125std_canonical_va_list_type (tree type)
4126{
4127 tree wtype, htype;
4128
4129 if (INDIRECT_REF_P (type))
4130 type = TREE_TYPE (type);
4131 else if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE(type)))
4132 type = TREE_TYPE (type);
5f57a8b1 4133 wtype = va_list_type_node;
4134 htype = type;
7b36f9ab 4135 /* Treat structure va_list types. */
4136 if (TREE_CODE (wtype) == RECORD_TYPE && POINTER_TYPE_P (htype))
4137 htype = TREE_TYPE (htype);
4138 else if (TREE_CODE (wtype) == ARRAY_TYPE)
5f57a8b1 4139 {
4140 /* If va_list is an array type, the argument may have decayed
4141 to a pointer type, e.g. by being passed to another function.
4142 In that case, unwrap both types so that we can compare the
4143 underlying records. */
4144 if (TREE_CODE (htype) == ARRAY_TYPE
4145 || POINTER_TYPE_P (htype))
4146 {
4147 wtype = TREE_TYPE (wtype);
4148 htype = TREE_TYPE (htype);
4149 }
4150 }
4151 if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype))
4152 return va_list_type_node;
4153
4154 return NULL_TREE;
4155}
4156
a66c9326 4157/* The "standard" implementation of va_start: just assign `nextarg' to
4158 the variable. */
27d0c333 4159
a66c9326 4160void
aecda0d6 4161std_expand_builtin_va_start (tree valist, rtx nextarg)
a66c9326 4162{
f03c17bc 4163 rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
4164 convert_move (va_r, nextarg, 0);
a66c9326 4165}
4166
c2f47e15 4167/* Expand EXP, a call to __builtin_va_start. */
27d0c333 4168
a66c9326 4169static rtx
c2f47e15 4170expand_builtin_va_start (tree exp)
a66c9326 4171{
4172 rtx nextarg;
c2f47e15 4173 tree valist;
389dd41b 4174 location_t loc = EXPR_LOCATION (exp);
a66c9326 4175
c2f47e15 4176 if (call_expr_nargs (exp) < 2)
cb166087 4177 {
389dd41b 4178 error_at (loc, "too few arguments to function %<va_start%>");
cb166087 4179 return const0_rtx;
4180 }
a66c9326 4181
c2f47e15 4182 if (fold_builtin_next_arg (exp, true))
79012a9d 4183 return const0_rtx;
7c2f0500 4184
79012a9d 4185 nextarg = expand_builtin_next_arg ();
389dd41b 4186 valist = stabilize_va_list_loc (loc, CALL_EXPR_ARG (exp, 0), 1);
a66c9326 4187
8a58ed0a 4188 if (targetm.expand_builtin_va_start)
4189 targetm.expand_builtin_va_start (valist, nextarg);
4190 else
4191 std_expand_builtin_va_start (valist, nextarg);
a66c9326 4192
4193 return const0_rtx;
4194}
4195
a66c9326 4196/* The "standard" implementation of va_arg: read the value from the
4197 current (padded) address and increment by the (padded) size. */
f7c44134 4198
e0eca1fa 4199tree
75a70cf9 4200std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
4201 gimple_seq *post_p)
fcdd3ab3 4202{
52cc2eeb 4203 tree addr, t, type_size, rounded_size, valist_tmp;
b8e8e485 4204 unsigned HOST_WIDE_INT align, boundary;
bef380a4 4205 bool indirect;
52cc2eeb 4206
4207#ifdef ARGS_GROW_DOWNWARD
4208 /* All of the alignment and movement below is for args-grow-up machines.
4209 As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
4210 implement their own specialized gimplify_va_arg_expr routines. */
64db345d 4211 gcc_unreachable ();
52cc2eeb 4212#endif
fcdd3ab3 4213
bef380a4 4214 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
4215 if (indirect)
4216 type = build_pointer_type (type);
4217
52cc2eeb 4218 align = PARM_BOUNDARY / BITS_PER_UNIT;
bd99ba64 4219 boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
c8b779eb 4220
4221 /* When we align parameter on stack for caller, if the parameter
befa808c 4222 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
4223 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
c8b779eb 4224 here with caller. */
befa808c 4225 if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
4226 boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
c8b779eb 4227
4228 boundary /= BITS_PER_UNIT;
fcdd3ab3 4229
52cc2eeb 4230 /* Hoist the valist value into a temporary for the moment. */
ecdeeb37 4231 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
4232
fcdd3ab3 4233 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
4234 requires greater alignment, we must perform dynamic alignment. */
85c1f587 4235 if (boundary > align
4236 && !integer_zerop (TYPE_SIZE (type)))
fcdd3ab3 4237 {
41076ef6 4238 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
2cc66f2a 4239 fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
52cc2eeb 4240 gimplify_and_add (t, pre_p);
4241
0de36bdb 4242 t = fold_convert (sizetype, valist_tmp);
41076ef6 4243 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
0de36bdb 4244 fold_convert (TREE_TYPE (valist),
4245 fold_build2 (BIT_AND_EXPR, sizetype, t,
4246 size_int (-boundary))));
ecdeeb37 4247 gimplify_and_add (t, pre_p);
fcdd3ab3 4248 }
c5dc0c32 4249 else
4250 boundary = align;
4251
4252 /* If the actual alignment is less than the alignment of the type,
4253 adjust the type accordingly so that we don't assume strict alignment
f0b5f617 4254 when dereferencing the pointer. */
c5dc0c32 4255 boundary *= BITS_PER_UNIT;
4256 if (boundary < TYPE_ALIGN (type))
4257 {
4258 type = build_variant_type_copy (type);
4259 TYPE_ALIGN (type) = boundary;
4260 }
fcdd3ab3 4261
bcff3604 4262 /* Compute the rounded size of the type. */
52cc2eeb 4263 type_size = size_in_bytes (type);
4264 rounded_size = round_up (type_size, align);
4265
fcdd3ab3 4266 /* Reduce rounded_size so it's sharable with the postqueue. */
4267 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
4268
4269 /* Get AP. */
ecdeeb37 4270 addr = valist_tmp;
52cc2eeb 4271 if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
fcdd3ab3 4272 {
4273 /* Small args are padded downward. */
389dd41b 4274 t = fold_build2_loc (input_location, GT_EXPR, sizetype,
4275 rounded_size, size_int (align));
49d00087 4276 t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
4277 size_binop (MINUS_EXPR, rounded_size, type_size));
2cc66f2a 4278 addr = fold_build_pointer_plus (addr, t);
fcdd3ab3 4279 }
4280
fcdd3ab3 4281 /* Compute new value for AP. */
2cc66f2a 4282 t = fold_build_pointer_plus (valist_tmp, rounded_size);
41076ef6 4283 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
ecdeeb37 4284 gimplify_and_add (t, pre_p);
e0eca1fa 4285
4286 addr = fold_convert (build_pointer_type (type), addr);
fcdd3ab3 4287
bef380a4 4288 if (indirect)
f2462d6c 4289 addr = build_va_arg_indirect_ref (addr);
4290
4291 return build_va_arg_indirect_ref (addr);
4292}
a0930a69 4293
f2462d6c 4294/* Build an indirect-ref expression over the given TREE, which represents a
4295 piece of a va_arg() expansion. */
4296tree
4297build_va_arg_indirect_ref (tree addr)
4298{
5c9d7b33 4299 addr = build_simple_mem_ref_loc (EXPR_LOCATION (addr), addr);
f2462d6c 4300
a0930a69 4301 if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */
4302 mf_mark (addr);
bef380a4 4303
a0930a69 4304 return addr;
433006a9 4305}
4306
fcdd3ab3 4307/* Return a dummy expression of type TYPE in order to keep going after an
4308 error. */
4309
4310static tree
4311dummy_object (tree type)
4312{
535664e3 4313 tree t = build_int_cst (build_pointer_type (type), 0);
377bc54c 4314 return build2 (MEM_REF, type, t, t);
fcdd3ab3 4315}
4316
2799a2b7 4317/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
4318 builtin function, but a very special sort of operator. */
fcdd3ab3 4319
4320enum gimplify_status
75a70cf9 4321gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
fcdd3ab3 4322{
5f57a8b1 4323 tree promoted_type, have_va_type;
fcdd3ab3 4324 tree valist = TREE_OPERAND (*expr_p, 0);
4325 tree type = TREE_TYPE (*expr_p);
4326 tree t;
389dd41b 4327 location_t loc = EXPR_LOCATION (*expr_p);
fcdd3ab3 4328
4329 /* Verify that valist is of the proper type. */
fcdd3ab3 4330 have_va_type = TREE_TYPE (valist);
f43dda35 4331 if (have_va_type == error_mark_node)
4332 return GS_ERROR;
5f57a8b1 4333 have_va_type = targetm.canonical_va_list_type (have_va_type);
f43dda35 4334
5f57a8b1 4335 if (have_va_type == NULL_TREE)
fcdd3ab3 4336 {
e60a6f7b 4337 error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>");
e0eca1fa 4338 return GS_ERROR;
fcdd3ab3 4339 }
4340
4341 /* Generate a diagnostic for requesting data of a type that cannot
4342 be passed through `...' due to type promotion at the call site. */
5f57a8b1 4343 if ((promoted_type = lang_hooks.types.type_promotes_to (type))
fcdd3ab3 4344 != type)
4345 {
4346 static bool gave_help;
a52d5726 4347 bool warned;
fcdd3ab3 4348
4349 /* Unfortunately, this is merely undefined, rather than a constraint
4350 violation, so we cannot make this an error. If this call is never
4351 executed, the program is still strictly conforming. */
e60a6f7b 4352 warned = warning_at (loc, 0,
4353 "%qT is promoted to %qT when passed through %<...%>",
4354 type, promoted_type);
a52d5726 4355 if (!gave_help && warned)
fcdd3ab3 4356 {
4357 gave_help = true;
e60a6f7b 4358 inform (loc, "(so you should pass %qT not %qT to %<va_arg%>)",
4359 promoted_type, type);
fcdd3ab3 4360 }
4361
4362 /* We can, however, treat "undefined" any way we please.
4363 Call abort to encourage the user to fix the program. */
a52d5726 4364 if (warned)
e60a6f7b 4365 inform (loc, "if this code is reached, the program will abort");
ad0e7a06 4366 /* Before the abort, allow the evaluation of the va_list
4367 expression to exit or longjmp. */
4368 gimplify_and_add (valist, pre_p);
389dd41b 4369 t = build_call_expr_loc (loc,
4370 implicit_built_in_decls[BUILT_IN_TRAP], 0);
75a70cf9 4371 gimplify_and_add (t, pre_p);
fcdd3ab3 4372
4373 /* This is dead code, but go ahead and finish so that the
4374 mode of the result comes out right. */
4375 *expr_p = dummy_object (type);
4376 return GS_ALL_DONE;
4377 }
4378 else
4379 {
4380 /* Make it easier for the backends by protecting the valist argument
a0c938f0 4381 from multiple evaluations. */
5f57a8b1 4382 if (TREE_CODE (have_va_type) == ARRAY_TYPE)
e0eca1fa 4383 {
4384 /* For this case, the backends will be expecting a pointer to
5f57a8b1 4385 TREE_TYPE (abi), but it's possible we've
4386 actually been given an array (an actual TARGET_FN_ABI_VA_LIST).
e0eca1fa 4387 So fix it. */
4388 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
4389 {
5f57a8b1 4390 tree p1 = build_pointer_type (TREE_TYPE (have_va_type));
389dd41b 4391 valist = fold_convert_loc (loc, p1,
4392 build_fold_addr_expr_loc (loc, valist));
e0eca1fa 4393 }
75a70cf9 4394
e0eca1fa 4395 gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
4396 }
4397 else
4398 gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
fcdd3ab3 4399
17a6380d 4400 if (!targetm.gimplify_va_arg_expr)
75a70cf9 4401 /* FIXME: Once most targets are converted we should merely
89f18f73 4402 assert this is non-null. */
fcdd3ab3 4403 return GS_ALL_DONE;
4404
17a6380d 4405 *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
fcdd3ab3 4406 return GS_OK;
4407 }
4408}
4409
c2f47e15 4410/* Expand EXP, a call to __builtin_va_end. */
f7c44134 4411
a66c9326 4412static rtx
c2f47e15 4413expand_builtin_va_end (tree exp)
a66c9326 4414{
c2f47e15 4415 tree valist = CALL_EXPR_ARG (exp, 0);
8a15c04a 4416
8a15c04a 4417 /* Evaluate for side effects, if needed. I hate macros that don't
4418 do that. */
4419 if (TREE_SIDE_EFFECTS (valist))
4420 expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
a66c9326 4421
4422 return const0_rtx;
4423}
4424
c2f47e15 4425/* Expand EXP, a call to __builtin_va_copy. We do this as a
a66c9326 4426 builtin rather than just as an assignment in stdarg.h because of the
4427 nastiness of array-type va_list types. */
f7c44134 4428
a66c9326 4429static rtx
c2f47e15 4430expand_builtin_va_copy (tree exp)
a66c9326 4431{
4432 tree dst, src, t;
389dd41b 4433 location_t loc = EXPR_LOCATION (exp);
a66c9326 4434
c2f47e15 4435 dst = CALL_EXPR_ARG (exp, 0);
4436 src = CALL_EXPR_ARG (exp, 1);
a66c9326 4437
389dd41b 4438 dst = stabilize_va_list_loc (loc, dst, 1);
4439 src = stabilize_va_list_loc (loc, src, 0);
a66c9326 4440
5f57a8b1 4441 gcc_assert (cfun != NULL && cfun->decl != NULL_TREE);
4442
4443 if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE)
a66c9326 4444 {
5f57a8b1 4445 t = build2 (MODIFY_EXPR, targetm.fn_abi_va_list (cfun->decl), dst, src);
a66c9326 4446 TREE_SIDE_EFFECTS (t) = 1;
4447 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4448 }
4449 else
4450 {
11a61dea 4451 rtx dstb, srcb, size;
4452
4453 /* Evaluate to pointers. */
4454 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
4455 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
5f57a8b1 4456 size = expand_expr (TYPE_SIZE_UNIT (targetm.fn_abi_va_list (cfun->decl)),
4457 NULL_RTX, VOIDmode, EXPAND_NORMAL);
11a61dea 4458
85d654dd 4459 dstb = convert_memory_address (Pmode, dstb);
4460 srcb = convert_memory_address (Pmode, srcb);
726ec87c 4461
11a61dea 4462 /* "Dereference" to BLKmode memories. */
4463 dstb = gen_rtx_MEM (BLKmode, dstb);
ab6ab77e 4464 set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
5f57a8b1 4465 set_mem_align (dstb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 4466 srcb = gen_rtx_MEM (BLKmode, srcb);
ab6ab77e 4467 set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
5f57a8b1 4468 set_mem_align (srcb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 4469
4470 /* Copy. */
0378dbdc 4471 emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
a66c9326 4472 }
4473
4474 return const0_rtx;
4475}
4476
53800dbe 4477/* Expand a call to one of the builtin functions __builtin_frame_address or
4478 __builtin_return_address. */
27d0c333 4479
53800dbe 4480static rtx
c2f47e15 4481expand_builtin_frame_address (tree fndecl, tree exp)
53800dbe 4482{
53800dbe 4483 /* The argument must be a nonnegative integer constant.
4484 It counts the number of frames to scan up the stack.
4485 The value is the return address saved in that frame. */
c2f47e15 4486 if (call_expr_nargs (exp) == 0)
53800dbe 4487 /* Warning about missing arg was already issued. */
4488 return const0_rtx;
c2f47e15 4489 else if (! host_integerp (CALL_EXPR_ARG (exp, 0), 1))
53800dbe 4490 {
4491 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
07e3a3d2 4492 error ("invalid argument to %<__builtin_frame_address%>");
53800dbe 4493 else
07e3a3d2 4494 error ("invalid argument to %<__builtin_return_address%>");
53800dbe 4495 return const0_rtx;
4496 }
4497 else
4498 {
27d0c333 4499 rtx tem
4500 = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
c2f47e15 4501 tree_low_cst (CALL_EXPR_ARG (exp, 0), 1));
53800dbe 4502
4503 /* Some ports cannot access arbitrary stack frames. */
4504 if (tem == NULL)
4505 {
4506 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
c3ceba8e 4507 warning (0, "unsupported argument to %<__builtin_frame_address%>");
53800dbe 4508 else
c3ceba8e 4509 warning (0, "unsupported argument to %<__builtin_return_address%>");
53800dbe 4510 return const0_rtx;
4511 }
4512
4513 /* For __builtin_frame_address, return what we've got. */
4514 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4515 return tem;
4516
8ad4c111 4517 if (!REG_P (tem)
53800dbe 4518 && ! CONSTANT_P (tem))
4519 tem = copy_to_mode_reg (Pmode, tem);
4520 return tem;
4521 }
4522}
4523
990495a7 4524/* Expand EXP, a call to the alloca builtin. Return NULL_RTX if we
5be42b39 4525 failed and the caller should emit a normal call. CANNOT_ACCUMULATE
4526 is the same as for allocate_dynamic_stack_space. */
15c6cf6b 4527
53800dbe 4528static rtx
5be42b39 4529expand_builtin_alloca (tree exp, bool cannot_accumulate)
53800dbe 4530{
4531 rtx op0;
15c6cf6b 4532 rtx result;
53800dbe 4533
f9fa0459 4534 /* Emit normal call if marked not-inlineable. */
48e1416a 4535 if (CALL_CANNOT_INLINE_P (exp))
c2f47e15 4536 return NULL_RTX;
4ee9c684 4537
c2f47e15 4538 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4539 return NULL_RTX;
53800dbe 4540
4541 /* Compute the argument. */
c2f47e15 4542 op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
53800dbe 4543
4544 /* Allocate the desired space. */
5be42b39 4545 result = allocate_dynamic_stack_space (op0, 0, BIGGEST_ALIGNMENT,
990495a7 4546 cannot_accumulate);
85d654dd 4547 result = convert_memory_address (ptr_mode, result);
15c6cf6b 4548
4549 return result;
53800dbe 4550}
4551
c2f47e15 4552/* Expand a call to a bswap builtin with argument ARG0. MODE
42791117 4553 is the mode to expand with. */
4554
4555static rtx
c2f47e15 4556expand_builtin_bswap (tree exp, rtx target, rtx subtarget)
42791117 4557{
4558 enum machine_mode mode;
4559 tree arg;
4560 rtx op0;
4561
c2f47e15 4562 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4563 return NULL_RTX;
42791117 4564
c2f47e15 4565 arg = CALL_EXPR_ARG (exp, 0);
42791117 4566 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 4567 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
42791117 4568
4569 target = expand_unop (mode, bswap_optab, op0, target, 1);
4570
4571 gcc_assert (target);
4572
4573 return convert_to_mode (mode, target, 0);
4574}
4575
c2f47e15 4576/* Expand a call to a unary builtin in EXP.
4577 Return NULL_RTX if a normal call should be emitted rather than expanding the
53800dbe 4578 function in-line. If convenient, the result should be placed in TARGET.
4579 SUBTARGET may be used as the target for computing one of EXP's operands. */
15c6cf6b 4580
53800dbe 4581static rtx
c2f47e15 4582expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target,
aecda0d6 4583 rtx subtarget, optab op_optab)
53800dbe 4584{
4585 rtx op0;
c2f47e15 4586
4587 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4588 return NULL_RTX;
53800dbe 4589
4590 /* Compute the argument. */
f97eea22 4591 op0 = expand_expr (CALL_EXPR_ARG (exp, 0),
4592 (subtarget
4593 && (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0)))
4594 == GET_MODE (subtarget))) ? subtarget : NULL_RTX,
1db6d067 4595 VOIDmode, EXPAND_NORMAL);
6a08d0ab 4596 /* Compute op, into TARGET if possible.
53800dbe 4597 Set TARGET to wherever the result comes back. */
c2f47e15 4598 target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
6aaa1f9e 4599 op_optab, op0, target, op_optab != clrsb_optab);
64db345d 4600 gcc_assert (target);
7d3f6cc7 4601
efb070c8 4602 return convert_to_mode (target_mode, target, 0);
53800dbe 4603}
89cfe6e5 4604
48e1416a 4605/* Expand a call to __builtin_expect. We just return our argument
5a74f77e 4606 as the builtin_expect semantic should've been already executed by
4607 tree branch prediction pass. */
89cfe6e5 4608
4609static rtx
c2f47e15 4610expand_builtin_expect (tree exp, rtx target)
89cfe6e5 4611{
1e4adcfc 4612 tree arg;
89cfe6e5 4613
c2f47e15 4614 if (call_expr_nargs (exp) < 2)
89cfe6e5 4615 return const0_rtx;
c2f47e15 4616 arg = CALL_EXPR_ARG (exp, 0);
89cfe6e5 4617
c2f47e15 4618 target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5a74f77e 4619 /* When guessing was done, the hints should be already stripped away. */
07311427 4620 gcc_assert (!flag_guess_branch_prob
852f689e 4621 || optimize == 0 || seen_error ());
89cfe6e5 4622 return target;
4623}
689df48e 4624
fca0886c 4625/* Expand a call to __builtin_assume_aligned. We just return our first
4626 argument as the builtin_assume_aligned semantic should've been already
4627 executed by CCP. */
4628
4629static rtx
4630expand_builtin_assume_aligned (tree exp, rtx target)
4631{
4632 if (call_expr_nargs (exp) < 2)
4633 return const0_rtx;
4634 target = expand_expr (CALL_EXPR_ARG (exp, 0), target, VOIDmode,
4635 EXPAND_NORMAL);
4636 gcc_assert (!TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 1))
4637 && (call_expr_nargs (exp) < 3
4638 || !TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 2))));
4639 return target;
4640}
4641
c22de3f0 4642void
aecda0d6 4643expand_builtin_trap (void)
a0ef1725 4644{
4645#ifdef HAVE_trap
4646 if (HAVE_trap)
4647 emit_insn (gen_trap ());
4648 else
4649#endif
4650 emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
4651 emit_barrier ();
4652}
78a74442 4653
d2b48f0c 4654/* Expand a call to __builtin_unreachable. We do nothing except emit
4655 a barrier saying that control flow will not pass here.
4656
4657 It is the responsibility of the program being compiled to ensure
4658 that control flow does never reach __builtin_unreachable. */
4659static void
4660expand_builtin_unreachable (void)
4661{
4662 emit_barrier ();
4663}
4664
c2f47e15 4665/* Expand EXP, a call to fabs, fabsf or fabsl.
4666 Return NULL_RTX if a normal call should be emitted rather than expanding
78a74442 4667 the function inline. If convenient, the result should be placed
4668 in TARGET. SUBTARGET may be used as the target for computing
4669 the operand. */
4670
4671static rtx
c2f47e15 4672expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
78a74442 4673{
4674 enum machine_mode mode;
4675 tree arg;
4676 rtx op0;
4677
c2f47e15 4678 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
4679 return NULL_RTX;
78a74442 4680
c2f47e15 4681 arg = CALL_EXPR_ARG (exp, 0);
c7f617c2 4682 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
78a74442 4683 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 4684 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
78a74442 4685 return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
4686}
4687
c2f47e15 4688/* Expand EXP, a call to copysign, copysignf, or copysignl.
270436f3 4689 Return NULL is a normal call should be emitted rather than expanding the
4690 function inline. If convenient, the result should be placed in TARGET.
4691 SUBTARGET may be used as the target for computing the operand. */
4692
4693static rtx
c2f47e15 4694expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
270436f3 4695{
4696 rtx op0, op1;
4697 tree arg;
4698
c2f47e15 4699 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
4700 return NULL_RTX;
270436f3 4701
c2f47e15 4702 arg = CALL_EXPR_ARG (exp, 0);
8ec3c5c2 4703 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
270436f3 4704
c2f47e15 4705 arg = CALL_EXPR_ARG (exp, 1);
8ec3c5c2 4706 op1 = expand_normal (arg);
270436f3 4707
4708 return expand_copysign (op0, op1, target);
4709}
4710
19bf118a 4711/* Create a new constant string literal and return a char* pointer to it.
4712 The STRING_CST value is the LEN characters at STR. */
1e8e9920 4713tree
19bf118a 4714build_string_literal (int len, const char *str)
4715{
4716 tree t, elem, index, type;
4717
4718 t = build_string (len, str);
4719 elem = build_type_variant (char_type_node, 1, 0);
40238f64 4720 index = build_index_type (size_int (len - 1));
19bf118a 4721 type = build_array_type (elem, index);
4722 TREE_TYPE (t) = type;
4723 TREE_CONSTANT (t) = 1;
4724 TREE_READONLY (t) = 1;
4725 TREE_STATIC (t) = 1;
4726
19bf118a 4727 type = build_pointer_type (elem);
40238f64 4728 t = build1 (ADDR_EXPR, type,
4729 build4 (ARRAY_REF, elem,
4730 t, integer_zero_node, NULL_TREE, NULL_TREE));
19bf118a 4731 return t;
4732}
4733
ac8fb6db 4734/* Expand a call to __builtin___clear_cache. */
4735
4736static rtx
4737expand_builtin___clear_cache (tree exp ATTRIBUTE_UNUSED)
4738{
4739#ifndef HAVE_clear_cache
4740#ifdef CLEAR_INSN_CACHE
4741 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
4742 does something. Just do the default expansion to a call to
4743 __clear_cache(). */
4744 return NULL_RTX;
4745#else
4746 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
4747 does nothing. There is no need to call it. Do nothing. */
4748 return const0_rtx;
4749#endif /* CLEAR_INSN_CACHE */
4750#else
4751 /* We have a "clear_cache" insn, and it will handle everything. */
4752 tree begin, end;
4753 rtx begin_rtx, end_rtx;
ac8fb6db 4754
4755 /* We must not expand to a library call. If we did, any
4756 fallback library function in libgcc that might contain a call to
4757 __builtin___clear_cache() would recurse infinitely. */
4758 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4759 {
4760 error ("both arguments to %<__builtin___clear_cache%> must be pointers");
4761 return const0_rtx;
4762 }
4763
4764 if (HAVE_clear_cache)
4765 {
8786db1e 4766 struct expand_operand ops[2];
ac8fb6db 4767
4768 begin = CALL_EXPR_ARG (exp, 0);
4769 begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
ac8fb6db 4770
4771 end = CALL_EXPR_ARG (exp, 1);
4772 end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
ac8fb6db 4773
8786db1e 4774 create_address_operand (&ops[0], begin_rtx);
4775 create_address_operand (&ops[1], end_rtx);
4776 if (maybe_expand_insn (CODE_FOR_clear_cache, 2, ops))
4777 return const0_rtx;
ac8fb6db 4778 }
4779 return const0_rtx;
4780#endif /* HAVE_clear_cache */
4781}
4782
4ee9c684 4783/* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
4784
4785static rtx
4786round_trampoline_addr (rtx tramp)
4787{
4788 rtx temp, addend, mask;
4789
4790 /* If we don't need too much alignment, we'll have been guaranteed
4791 proper alignment by get_trampoline_type. */
4792 if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
4793 return tramp;
4794
4795 /* Round address up to desired boundary. */
4796 temp = gen_reg_rtx (Pmode);
4797 addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
4798 mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
4799
4800 temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
4801 temp, 0, OPTAB_LIB_WIDEN);
4802 tramp = expand_simple_binop (Pmode, AND, temp, mask,
4803 temp, 0, OPTAB_LIB_WIDEN);
4804
4805 return tramp;
4806}
4807
4808static rtx
c2f47e15 4809expand_builtin_init_trampoline (tree exp)
4ee9c684 4810{
4811 tree t_tramp, t_func, t_chain;
82c7907c 4812 rtx m_tramp, r_tramp, r_chain, tmp;
4ee9c684 4813
c2f47e15 4814 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
4ee9c684 4815 POINTER_TYPE, VOID_TYPE))
4816 return NULL_RTX;
4817
c2f47e15 4818 t_tramp = CALL_EXPR_ARG (exp, 0);
4819 t_func = CALL_EXPR_ARG (exp, 1);
4820 t_chain = CALL_EXPR_ARG (exp, 2);
4ee9c684 4821
8ec3c5c2 4822 r_tramp = expand_normal (t_tramp);
82c7907c 4823 m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
4824 MEM_NOTRAP_P (m_tramp) = 1;
4825
4826 /* The TRAMP argument should be the address of a field within the
4827 local function's FRAME decl. Let's see if we can fill in the
4828 to fill in the MEM_ATTRs for this memory. */
4829 if (TREE_CODE (t_tramp) == ADDR_EXPR)
4830 set_mem_attributes_minus_bitpos (m_tramp, TREE_OPERAND (t_tramp, 0),
4831 true, 0);
4832
4833 tmp = round_trampoline_addr (r_tramp);
4834 if (tmp != r_tramp)
4835 {
4836 m_tramp = change_address (m_tramp, BLKmode, tmp);
4837 set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
4838 set_mem_size (m_tramp, GEN_INT (TRAMPOLINE_SIZE));
4839 }
4840
4841 /* The FUNC argument should be the address of the nested function.
4842 Extract the actual function decl to pass to the hook. */
4843 gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
4844 t_func = TREE_OPERAND (t_func, 0);
4845 gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
4846
8ec3c5c2 4847 r_chain = expand_normal (t_chain);
4ee9c684 4848
4849 /* Generate insns to initialize the trampoline. */
82c7907c 4850 targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
4ee9c684 4851
82c7907c 4852 trampolines_created = 1;
8bc8a8f4 4853
4854 warning_at (DECL_SOURCE_LOCATION (t_func), OPT_Wtrampolines,
4855 "trampoline generated for nested function %qD", t_func);
4856
4ee9c684 4857 return const0_rtx;
4858}
4859
4860static rtx
c2f47e15 4861expand_builtin_adjust_trampoline (tree exp)
4ee9c684 4862{
4863 rtx tramp;
4864
c2f47e15 4865 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
4ee9c684 4866 return NULL_RTX;
4867
c2f47e15 4868 tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
4ee9c684 4869 tramp = round_trampoline_addr (tramp);
82c7907c 4870 if (targetm.calls.trampoline_adjust_address)
4871 tramp = targetm.calls.trampoline_adjust_address (tramp);
4ee9c684 4872
4873 return tramp;
4874}
4875
93f564d6 4876/* Expand the call EXP to the built-in signbit, signbitf or signbitl
4877 function. The function first checks whether the back end provides
4878 an insn to implement signbit for the respective mode. If not, it
4879 checks whether the floating point format of the value is such that
4880 the sign bit can be extracted. If that is not the case, the
4881 function returns NULL_RTX to indicate that a normal call should be
4882 emitted rather than expanding the function in-line. EXP is the
4883 expression that is a call to the builtin function; if convenient,
4884 the result should be placed in TARGET. */
27f261ef 4885static rtx
4886expand_builtin_signbit (tree exp, rtx target)
4887{
4888 const struct real_format *fmt;
4889 enum machine_mode fmode, imode, rmode;
c2f47e15 4890 tree arg;
ca4f1f5b 4891 int word, bitpos;
27eda240 4892 enum insn_code icode;
27f261ef 4893 rtx temp;
389dd41b 4894 location_t loc = EXPR_LOCATION (exp);
27f261ef 4895
c2f47e15 4896 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
4897 return NULL_RTX;
27f261ef 4898
c2f47e15 4899 arg = CALL_EXPR_ARG (exp, 0);
27f261ef 4900 fmode = TYPE_MODE (TREE_TYPE (arg));
4901 rmode = TYPE_MODE (TREE_TYPE (exp));
4902 fmt = REAL_MODE_FORMAT (fmode);
4903
93f564d6 4904 arg = builtin_save_expr (arg);
4905
4906 /* Expand the argument yielding a RTX expression. */
4907 temp = expand_normal (arg);
4908
4909 /* Check if the back end provides an insn that handles signbit for the
4910 argument's mode. */
d6bf3b14 4911 icode = optab_handler (signbit_optab, fmode);
27eda240 4912 if (icode != CODE_FOR_nothing)
93f564d6 4913 {
4e2a2fb4 4914 rtx last = get_last_insn ();
93f564d6 4915 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
4e2a2fb4 4916 if (maybe_emit_unop_insn (icode, target, temp, UNKNOWN))
4917 return target;
4918 delete_insns_since (last);
93f564d6 4919 }
4920
27f261ef 4921 /* For floating point formats without a sign bit, implement signbit
4922 as "ARG < 0.0". */
8d564692 4923 bitpos = fmt->signbit_ro;
ca4f1f5b 4924 if (bitpos < 0)
27f261ef 4925 {
4926 /* But we can't do this if the format supports signed zero. */
4927 if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
c2f47e15 4928 return NULL_RTX;
27f261ef 4929
389dd41b 4930 arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
49d00087 4931 build_real (TREE_TYPE (arg), dconst0));
27f261ef 4932 return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
4933 }
4934
ca4f1f5b 4935 if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
27f261ef 4936 {
ca4f1f5b 4937 imode = int_mode_for_mode (fmode);
4938 if (imode == BLKmode)
c2f47e15 4939 return NULL_RTX;
ca4f1f5b 4940 temp = gen_lowpart (imode, temp);
24fd4260 4941 }
4942 else
4943 {
ca4f1f5b 4944 imode = word_mode;
4945 /* Handle targets with different FP word orders. */
4946 if (FLOAT_WORDS_BIG_ENDIAN)
a0c938f0 4947 word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
ca4f1f5b 4948 else
a0c938f0 4949 word = bitpos / BITS_PER_WORD;
ca4f1f5b 4950 temp = operand_subword_force (temp, word, fmode);
4951 bitpos = bitpos % BITS_PER_WORD;
4952 }
4953
44b0f1d0 4954 /* Force the intermediate word_mode (or narrower) result into a
4955 register. This avoids attempting to create paradoxical SUBREGs
4956 of floating point modes below. */
4957 temp = force_reg (imode, temp);
4958
ca4f1f5b 4959 /* If the bitpos is within the "result mode" lowpart, the operation
4960 can be implement with a single bitwise AND. Otherwise, we need
4961 a right shift and an AND. */
4962
4963 if (bitpos < GET_MODE_BITSIZE (rmode))
4964 {
3e052aec 4965 double_int mask = double_int_setbit (double_int_zero, bitpos);
27f261ef 4966
4a46f016 4967 if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
ca4f1f5b 4968 temp = gen_lowpart (rmode, temp);
24fd4260 4969 temp = expand_binop (rmode, and_optab, temp,
3e052aec 4970 immed_double_int_const (mask, rmode),
ca4f1f5b 4971 NULL_RTX, 1, OPTAB_LIB_WIDEN);
27f261ef 4972 }
ca4f1f5b 4973 else
4974 {
4975 /* Perform a logical right shift to place the signbit in the least
a0c938f0 4976 significant bit, then truncate the result to the desired mode
ca4f1f5b 4977 and mask just this bit. */
f5ff0b21 4978 temp = expand_shift (RSHIFT_EXPR, imode, temp, bitpos, NULL_RTX, 1);
ca4f1f5b 4979 temp = gen_lowpart (rmode, temp);
4980 temp = expand_binop (rmode, and_optab, temp, const1_rtx,
4981 NULL_RTX, 1, OPTAB_LIB_WIDEN);
4982 }
4983
27f261ef 4984 return temp;
4985}
73673831 4986
4987/* Expand fork or exec calls. TARGET is the desired target of the
c2f47e15 4988 call. EXP is the call. FN is the
73673831 4989 identificator of the actual function. IGNORE is nonzero if the
4990 value is to be ignored. */
4991
4992static rtx
c2f47e15 4993expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
73673831 4994{
4995 tree id, decl;
4996 tree call;
4997
4998 /* If we are not profiling, just call the function. */
4999 if (!profile_arc_flag)
5000 return NULL_RTX;
5001
5002 /* Otherwise call the wrapper. This should be equivalent for the rest of
5003 compiler, so the code does not diverge, and the wrapper may run the
9c9bad97 5004 code necessary for keeping the profiling sane. */
73673831 5005
5006 switch (DECL_FUNCTION_CODE (fn))
5007 {
5008 case BUILT_IN_FORK:
5009 id = get_identifier ("__gcov_fork");
5010 break;
5011
5012 case BUILT_IN_EXECL:
5013 id = get_identifier ("__gcov_execl");
5014 break;
5015
5016 case BUILT_IN_EXECV:
5017 id = get_identifier ("__gcov_execv");
5018 break;
5019
5020 case BUILT_IN_EXECLP:
5021 id = get_identifier ("__gcov_execlp");
5022 break;
5023
5024 case BUILT_IN_EXECLE:
5025 id = get_identifier ("__gcov_execle");
5026 break;
5027
5028 case BUILT_IN_EXECVP:
5029 id = get_identifier ("__gcov_execvp");
5030 break;
5031
5032 case BUILT_IN_EXECVE:
5033 id = get_identifier ("__gcov_execve");
5034 break;
5035
5036 default:
64db345d 5037 gcc_unreachable ();
73673831 5038 }
5039
e60a6f7b 5040 decl = build_decl (DECL_SOURCE_LOCATION (fn),
5041 FUNCTION_DECL, id, TREE_TYPE (fn));
73673831 5042 DECL_EXTERNAL (decl) = 1;
5043 TREE_PUBLIC (decl) = 1;
5044 DECL_ARTIFICIAL (decl) = 1;
5045 TREE_NOTHROW (decl) = 1;
e82d310b 5046 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
5047 DECL_VISIBILITY_SPECIFIED (decl) = 1;
389dd41b 5048 call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0);
73673831 5049 return expand_call (call, target, ignore);
c2f47e15 5050 }
48e1416a 5051
b6a5fc45 5052
5053\f
3e272de8 5054/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
5055 the pointer in these functions is void*, the tree optimizers may remove
5056 casts. The mode computed in expand_builtin isn't reliable either, due
5057 to __sync_bool_compare_and_swap.
5058
5059 FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
5060 group of builtins. This gives us log2 of the mode size. */
5061
5062static inline enum machine_mode
5063get_builtin_sync_mode (int fcode_diff)
5064{
ad3a13b5 5065 /* The size is not negotiable, so ask not to get BLKmode in return
5066 if the target indicates that a smaller size would be better. */
5067 return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
3e272de8 5068}
5069
041e0215 5070/* Expand the memory expression LOC and return the appropriate memory operand
5071 for the builtin_sync operations. */
5072
5073static rtx
5074get_builtin_sync_mem (tree loc, enum machine_mode mode)
5075{
5076 rtx addr, mem;
5077
7f4d56ad 5078 addr = expand_expr (loc, NULL_RTX, ptr_mode, EXPAND_SUM);
5079 addr = convert_memory_address (Pmode, addr);
041e0215 5080
5081 /* Note that we explicitly do not want any alias information for this
5082 memory, so that we kill all other live memories. Otherwise we don't
5083 satisfy the full barrier semantics of the intrinsic. */
5084 mem = validize_mem (gen_rtx_MEM (mode, addr));
5085
153c3b50 5086 /* The alignment needs to be at least according to that of the mode. */
5087 set_mem_align (mem, MAX (GET_MODE_ALIGNMENT (mode),
5088 get_pointer_alignment (loc, BIGGEST_ALIGNMENT)));
c94cfd1c 5089 set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
041e0215 5090 MEM_VOLATILE_P (mem) = 1;
5091
5092 return mem;
5093}
5094
b6a5fc45 5095/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
c2f47e15 5096 EXP is the CALL_EXPR. CODE is the rtx code
b6a5fc45 5097 that corresponds to the arithmetic or logical operation from the name;
5098 an exception here is that NOT actually means NAND. TARGET is an optional
5099 place for us to store the results; AFTER is true if this is the
5100 fetch_and_xxx form. IGNORE is true if we don't actually care about
5101 the result of the operation at all. */
5102
5103static rtx
c2f47e15 5104expand_builtin_sync_operation (enum machine_mode mode, tree exp,
3e272de8 5105 enum rtx_code code, bool after,
b6a5fc45 5106 rtx target, bool ignore)
5107{
041e0215 5108 rtx val, mem;
a8bb7059 5109 enum machine_mode old_mode;
e60a6f7b 5110 location_t loc = EXPR_LOCATION (exp);
b6a5fc45 5111
cf73e559 5112 if (code == NOT && warn_sync_nand)
5113 {
5114 tree fndecl = get_callee_fndecl (exp);
5115 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
5116
5117 static bool warned_f_a_n, warned_n_a_f;
5118
5119 switch (fcode)
5120 {
2797f13a 5121 case BUILT_IN_SYNC_FETCH_AND_NAND_1:
5122 case BUILT_IN_SYNC_FETCH_AND_NAND_2:
5123 case BUILT_IN_SYNC_FETCH_AND_NAND_4:
5124 case BUILT_IN_SYNC_FETCH_AND_NAND_8:
5125 case BUILT_IN_SYNC_FETCH_AND_NAND_16:
cf73e559 5126
5127 if (warned_f_a_n)
5128 break;
5129
2797f13a 5130 fndecl = implicit_built_in_decls[BUILT_IN_SYNC_FETCH_AND_NAND_N];
e60a6f7b 5131 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
cf73e559 5132 warned_f_a_n = true;
5133 break;
5134
2797f13a 5135 case BUILT_IN_SYNC_NAND_AND_FETCH_1:
5136 case BUILT_IN_SYNC_NAND_AND_FETCH_2:
5137 case BUILT_IN_SYNC_NAND_AND_FETCH_4:
5138 case BUILT_IN_SYNC_NAND_AND_FETCH_8:
5139 case BUILT_IN_SYNC_NAND_AND_FETCH_16:
cf73e559 5140
5141 if (warned_n_a_f)
5142 break;
5143
2797f13a 5144 fndecl = implicit_built_in_decls[BUILT_IN_SYNC_NAND_AND_FETCH_N];
e60a6f7b 5145 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
cf73e559 5146 warned_n_a_f = true;
5147 break;
5148
5149 default:
5150 gcc_unreachable ();
5151 }
5152 }
5153
b6a5fc45 5154 /* Expand the operands. */
c2f47e15 5155 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5156
1db6d067 5157 val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
a8bb7059 5158 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5159 of CONST_INTs, where we know the old_mode only from the call argument. */
5160 old_mode = GET_MODE (val);
5161 if (old_mode == VOIDmode)
5162 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5163 val = convert_modes (mode, old_mode, val, 1);
b6a5fc45 5164
b6a5fc45 5165 if (ignore)
5166 return expand_sync_operation (mem, val, code);
5167 else
5168 return expand_sync_fetch_operation (mem, val, code, after, target);
5169}
5170
5171/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
c2f47e15 5172 intrinsics. EXP is the CALL_EXPR. IS_BOOL is
b6a5fc45 5173 true if this is the boolean form. TARGET is a place for us to store the
5174 results; this is NOT optional if IS_BOOL is true. */
5175
5176static rtx
c2f47e15 5177expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
3e272de8 5178 bool is_bool, rtx target)
b6a5fc45 5179{
041e0215 5180 rtx old_val, new_val, mem;
a8bb7059 5181 enum machine_mode old_mode;
b6a5fc45 5182
5183 /* Expand the operands. */
c2f47e15 5184 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5185
c2f47e15 5186
1db6d067 5187 old_val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX,
5188 mode, EXPAND_NORMAL);
a8bb7059 5189 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5190 of CONST_INTs, where we know the old_mode only from the call argument. */
5191 old_mode = GET_MODE (old_val);
5192 if (old_mode == VOIDmode)
5193 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5194 old_val = convert_modes (mode, old_mode, old_val, 1);
b6a5fc45 5195
1db6d067 5196 new_val = expand_expr (CALL_EXPR_ARG (exp, 2), NULL_RTX,
5197 mode, EXPAND_NORMAL);
a8bb7059 5198 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5199 of CONST_INTs, where we know the old_mode only from the call argument. */
5200 old_mode = GET_MODE (new_val);
5201 if (old_mode == VOIDmode)
5202 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2)));
5203 new_val = convert_modes (mode, old_mode, new_val, 1);
b6a5fc45 5204
b6a5fc45 5205 if (is_bool)
5206 return expand_bool_compare_and_swap (mem, old_val, new_val, target);
5207 else
5208 return expand_val_compare_and_swap (mem, old_val, new_val, target);
5209}
5210
5211/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
5212 general form is actually an atomic exchange, and some targets only
5213 support a reduced form with the second argument being a constant 1.
48e1416a 5214 EXP is the CALL_EXPR; TARGET is an optional place for us to store
c2f47e15 5215 the results. */
b6a5fc45 5216
5217static rtx
2797f13a 5218expand_builtin_sync_lock_test_and_set (enum machine_mode mode, tree exp,
3e272de8 5219 rtx target)
b6a5fc45 5220{
041e0215 5221 rtx val, mem;
a8bb7059 5222 enum machine_mode old_mode;
b6a5fc45 5223
5224 /* Expand the operands. */
c2f47e15 5225 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1db6d067 5226 val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
a8bb7059 5227 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5228 of CONST_INTs, where we know the old_mode only from the call argument. */
5229 old_mode = GET_MODE (val);
5230 if (old_mode == VOIDmode)
5231 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5232 val = convert_modes (mode, old_mode, val, 1);
b6a5fc45 5233
b6a5fc45 5234 return expand_sync_lock_test_and_set (mem, val, target);
5235}
5236
5237/* Expand the __sync_synchronize intrinsic. */
5238
5239static void
2797f13a 5240expand_builtin_sync_synchronize (void)
b6a5fc45 5241{
16c9337c 5242 gimple x;
78f55ca8 5243 VEC (tree, gc) *v_clobbers;
b6a5fc45 5244
5245#ifdef HAVE_memory_barrier
5246 if (HAVE_memory_barrier)
5247 {
5248 emit_insn (gen_memory_barrier ());
5249 return;
5250 }
5251#endif
5252
047a7e40 5253 if (synchronize_libfunc != NULL_RTX)
5254 {
5255 emit_library_call (synchronize_libfunc, LCT_NORMAL, VOIDmode, 0);
5256 return;
5257 }
5258
82e58396 5259 /* If no explicit memory barrier instruction is available, create an
5260 empty asm stmt with a memory clobber. */
78f55ca8 5261 v_clobbers = VEC_alloc (tree, gc, 1);
5262 VEC_quick_push (tree, v_clobbers,
5263 tree_cons (NULL, build_string (6, "memory"), NULL));
5264 x = gimple_build_asm_vec ("", NULL, NULL, v_clobbers, NULL);
16c9337c 5265 gimple_asm_set_volatile (x, true);
5266 expand_asm_stmt (x);
b6a5fc45 5267}
5268
c2f47e15 5269/* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */
b6a5fc45 5270
5271static void
2797f13a 5272expand_builtin_sync_lock_release (enum machine_mode mode, tree exp)
b6a5fc45 5273{
8786db1e 5274 struct expand_operand ops[2];
b6a5fc45 5275 enum insn_code icode;
8786db1e 5276 rtx mem;
b6a5fc45 5277
5278 /* Expand the operands. */
c2f47e15 5279 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5280
5281 /* If there is an explicit operation in the md file, use it. */
6b531606 5282 icode = direct_optab_handler (sync_lock_release_optab, mode);
b6a5fc45 5283 if (icode != CODE_FOR_nothing)
5284 {
8786db1e 5285 create_fixed_operand (&ops[0], mem);
5286 create_input_operand (&ops[1], const0_rtx, mode);
5287 if (maybe_expand_insn (icode, 2, ops))
5288 return;
b6a5fc45 5289 }
5290
5291 /* Otherwise we can implement this operation by emitting a barrier
5292 followed by a store of zero. */
2797f13a 5293 expand_builtin_sync_synchronize ();
8786db1e 5294 emit_move_insn (mem, const0_rtx);
b6a5fc45 5295}
53800dbe 5296\f
5297/* Expand an expression EXP that calls a built-in function,
5298 with result going to TARGET if that's convenient
5299 (and in mode MODE if that's convenient).
5300 SUBTARGET may be used as the target for computing one of EXP's operands.
5301 IGNORE is nonzero if the value is to be ignored. */
5302
5303rtx
aecda0d6 5304expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
5305 int ignore)
53800dbe 5306{
c6e6ecb1 5307 tree fndecl = get_callee_fndecl (exp);
53800dbe 5308 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
efb070c8 5309 enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
67fa4078 5310 int flags;
53800dbe 5311
8305149e 5312 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
883b2e73 5313 return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
bf8e3599 5314
53800dbe 5315 /* When not optimizing, generate calls to library functions for a certain
5316 set of builtins. */
cd9ff771 5317 if (!optimize
b6a5fc45 5318 && !called_as_built_in (fndecl)
cd9ff771 5319 && DECL_ASSEMBLER_NAME_SET_P (fndecl)
2c281b15 5320 && fcode != BUILT_IN_ALLOCA
5321 && fcode != BUILT_IN_FREE)
cd9ff771 5322 return expand_call (exp, target, ignore);
53800dbe 5323
8d6d7930 5324 /* The built-in function expanders test for target == const0_rtx
5325 to determine whether the function's result will be ignored. */
5326 if (ignore)
5327 target = const0_rtx;
5328
5329 /* If the result of a pure or const built-in function is ignored, and
5330 none of its arguments are volatile, we can avoid expanding the
5331 built-in call and just evaluate the arguments for side-effects. */
5332 if (target == const0_rtx
67fa4078 5333 && ((flags = flags_from_decl_or_type (fndecl)) & (ECF_CONST | ECF_PURE))
5334 && !(flags & ECF_LOOPING_CONST_OR_PURE))
8d6d7930 5335 {
5336 bool volatilep = false;
5337 tree arg;
c2f47e15 5338 call_expr_arg_iterator iter;
8d6d7930 5339
c2f47e15 5340 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5341 if (TREE_THIS_VOLATILE (arg))
8d6d7930 5342 {
5343 volatilep = true;
5344 break;
5345 }
5346
5347 if (! volatilep)
5348 {
c2f47e15 5349 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5350 expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
8d6d7930 5351 return const0_rtx;
5352 }
5353 }
5354
53800dbe 5355 switch (fcode)
5356 {
4f35b1fc 5357 CASE_FLT_FN (BUILT_IN_FABS):
c2f47e15 5358 target = expand_builtin_fabs (exp, target, subtarget);
78a74442 5359 if (target)
a0c938f0 5360 return target;
78a74442 5361 break;
5362
4f35b1fc 5363 CASE_FLT_FN (BUILT_IN_COPYSIGN):
c2f47e15 5364 target = expand_builtin_copysign (exp, target, subtarget);
270436f3 5365 if (target)
5366 return target;
5367 break;
5368
7d3f6cc7 5369 /* Just do a normal library call if we were unable to fold
5370 the values. */
4f35b1fc 5371 CASE_FLT_FN (BUILT_IN_CABS):
78a74442 5372 break;
53800dbe 5373
4f35b1fc 5374 CASE_FLT_FN (BUILT_IN_EXP):
5375 CASE_FLT_FN (BUILT_IN_EXP10):
5376 CASE_FLT_FN (BUILT_IN_POW10):
5377 CASE_FLT_FN (BUILT_IN_EXP2):
5378 CASE_FLT_FN (BUILT_IN_EXPM1):
5379 CASE_FLT_FN (BUILT_IN_LOGB):
4f35b1fc 5380 CASE_FLT_FN (BUILT_IN_LOG):
5381 CASE_FLT_FN (BUILT_IN_LOG10):
5382 CASE_FLT_FN (BUILT_IN_LOG2):
5383 CASE_FLT_FN (BUILT_IN_LOG1P):
5384 CASE_FLT_FN (BUILT_IN_TAN):
5385 CASE_FLT_FN (BUILT_IN_ASIN):
5386 CASE_FLT_FN (BUILT_IN_ACOS):
5387 CASE_FLT_FN (BUILT_IN_ATAN):
b3154a1f 5388 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
7f3be425 5389 /* Treat these like sqrt only if unsafe math optimizations are allowed,
5390 because of possible accuracy problems. */
5391 if (! flag_unsafe_math_optimizations)
53800dbe 5392 break;
4f35b1fc 5393 CASE_FLT_FN (BUILT_IN_SQRT):
5394 CASE_FLT_FN (BUILT_IN_FLOOR):
5395 CASE_FLT_FN (BUILT_IN_CEIL):
5396 CASE_FLT_FN (BUILT_IN_TRUNC):
5397 CASE_FLT_FN (BUILT_IN_ROUND):
5398 CASE_FLT_FN (BUILT_IN_NEARBYINT):
5399 CASE_FLT_FN (BUILT_IN_RINT):
53800dbe 5400 target = expand_builtin_mathfn (exp, target, subtarget);
5401 if (target)
5402 return target;
5403 break;
5404
7e0713b1 5405 CASE_FLT_FN (BUILT_IN_FMA):
5406 target = expand_builtin_mathfn_ternary (exp, target, subtarget);
5407 if (target)
5408 return target;
5409 break;
5410
a67a90e5 5411 CASE_FLT_FN (BUILT_IN_ILOGB):
5412 if (! flag_unsafe_math_optimizations)
5413 break;
69b779ea 5414 CASE_FLT_FN (BUILT_IN_ISINF):
cde061c1 5415 CASE_FLT_FN (BUILT_IN_FINITE):
5416 case BUILT_IN_ISFINITE:
8a1a9cb7 5417 case BUILT_IN_ISNORMAL:
f97eea22 5418 target = expand_builtin_interclass_mathfn (exp, target);
a67a90e5 5419 if (target)
5420 return target;
5421 break;
5422
4f35b1fc 5423 CASE_FLT_FN (BUILT_IN_LCEIL):
5424 CASE_FLT_FN (BUILT_IN_LLCEIL):
5425 CASE_FLT_FN (BUILT_IN_LFLOOR):
5426 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ff1b14e4 5427 target = expand_builtin_int_roundingfn (exp, target);
ad52b9b7 5428 if (target)
5429 return target;
5430 break;
5431
7d3afc77 5432 CASE_FLT_FN (BUILT_IN_LRINT):
5433 CASE_FLT_FN (BUILT_IN_LLRINT):
ef2f1a10 5434 CASE_FLT_FN (BUILT_IN_LROUND):
5435 CASE_FLT_FN (BUILT_IN_LLROUND):
ff1b14e4 5436 target = expand_builtin_int_roundingfn_2 (exp, target);
7d3afc77 5437 if (target)
5438 return target;
5439 break;
5440
4f35b1fc 5441 CASE_FLT_FN (BUILT_IN_POWI):
f97eea22 5442 target = expand_builtin_powi (exp, target);
757c219d 5443 if (target)
5444 return target;
5445 break;
5446
4f35b1fc 5447 CASE_FLT_FN (BUILT_IN_ATAN2):
5448 CASE_FLT_FN (BUILT_IN_LDEXP):
73a954a1 5449 CASE_FLT_FN (BUILT_IN_SCALB):
5450 CASE_FLT_FN (BUILT_IN_SCALBN):
5451 CASE_FLT_FN (BUILT_IN_SCALBLN):
0fd605a5 5452 if (! flag_unsafe_math_optimizations)
5453 break;
ef722005 5454
5455 CASE_FLT_FN (BUILT_IN_FMOD):
5456 CASE_FLT_FN (BUILT_IN_REMAINDER):
5457 CASE_FLT_FN (BUILT_IN_DREM):
0810ff17 5458 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 5459 target = expand_builtin_mathfn_2 (exp, target, subtarget);
5460 if (target)
5461 return target;
5462 break;
5463
d735c391 5464 CASE_FLT_FN (BUILT_IN_CEXPI):
f97eea22 5465 target = expand_builtin_cexpi (exp, target);
d735c391 5466 gcc_assert (target);
5467 return target;
5468
4f35b1fc 5469 CASE_FLT_FN (BUILT_IN_SIN):
5470 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 5471 if (! flag_unsafe_math_optimizations)
5472 break;
5473 target = expand_builtin_mathfn_3 (exp, target, subtarget);
5474 if (target)
5475 return target;
5476 break;
5477
c3147c1a 5478 CASE_FLT_FN (BUILT_IN_SINCOS):
5479 if (! flag_unsafe_math_optimizations)
5480 break;
5481 target = expand_builtin_sincos (exp);
5482 if (target)
5483 return target;
5484 break;
5485
53800dbe 5486 case BUILT_IN_APPLY_ARGS:
5487 return expand_builtin_apply_args ();
5488
5489 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
5490 FUNCTION with a copy of the parameters described by
5491 ARGUMENTS, and ARGSIZE. It returns a block of memory
5492 allocated on the stack into which is stored all the registers
5493 that might possibly be used for returning the result of a
5494 function. ARGUMENTS is the value returned by
5495 __builtin_apply_args. ARGSIZE is the number of bytes of
5496 arguments that must be copied. ??? How should this value be
5497 computed? We'll also need a safe worst case value for varargs
5498 functions. */
5499 case BUILT_IN_APPLY:
c2f47e15 5500 if (!validate_arglist (exp, POINTER_TYPE,
0eb671f7 5501 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
c2f47e15 5502 && !validate_arglist (exp, REFERENCE_TYPE,
0eb671f7 5503 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 5504 return const0_rtx;
5505 else
5506 {
53800dbe 5507 rtx ops[3];
5508
c2f47e15 5509 ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
5510 ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
5511 ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
53800dbe 5512
5513 return expand_builtin_apply (ops[0], ops[1], ops[2]);
5514 }
5515
5516 /* __builtin_return (RESULT) causes the function to return the
5517 value described by RESULT. RESULT is address of the block of
5518 memory returned by __builtin_apply. */
5519 case BUILT_IN_RETURN:
c2f47e15 5520 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
5521 expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
53800dbe 5522 return const0_rtx;
5523
5524 case BUILT_IN_SAVEREGS:
a66c9326 5525 return expand_builtin_saveregs ();
53800dbe 5526
48dc2227 5527 case BUILT_IN_VA_ARG_PACK:
5528 /* All valid uses of __builtin_va_arg_pack () are removed during
5529 inlining. */
b8c23db3 5530 error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
48dc2227 5531 return const0_rtx;
5532
4e1d7ea4 5533 case BUILT_IN_VA_ARG_PACK_LEN:
5534 /* All valid uses of __builtin_va_arg_pack_len () are removed during
5535 inlining. */
b8c23db3 5536 error ("%Kinvalid use of %<__builtin_va_arg_pack_len ()%>", exp);
4e1d7ea4 5537 return const0_rtx;
5538
53800dbe 5539 /* Return the address of the first anonymous stack arg. */
5540 case BUILT_IN_NEXT_ARG:
c2f47e15 5541 if (fold_builtin_next_arg (exp, false))
a0c938f0 5542 return const0_rtx;
79012a9d 5543 return expand_builtin_next_arg ();
53800dbe 5544
ac8fb6db 5545 case BUILT_IN_CLEAR_CACHE:
5546 target = expand_builtin___clear_cache (exp);
5547 if (target)
5548 return target;
5549 break;
5550
53800dbe 5551 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 5552 return expand_builtin_classify_type (exp);
53800dbe 5553
5554 case BUILT_IN_CONSTANT_P:
4ee9c684 5555 return const0_rtx;
53800dbe 5556
5557 case BUILT_IN_FRAME_ADDRESS:
5558 case BUILT_IN_RETURN_ADDRESS:
c2f47e15 5559 return expand_builtin_frame_address (fndecl, exp);
53800dbe 5560
5561 /* Returns the address of the area where the structure is returned.
5562 0 otherwise. */
5563 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
c2f47e15 5564 if (call_expr_nargs (exp) != 0
9342ee68 5565 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
e16ceb8e 5566 || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
9342ee68 5567 return const0_rtx;
53800dbe 5568 else
9342ee68 5569 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
53800dbe 5570
5571 case BUILT_IN_ALLOCA:
990495a7 5572 /* If the allocation stems from the declaration of a variable-sized
5573 object, it cannot accumulate. */
a882d754 5574 target = expand_builtin_alloca (exp, CALL_ALLOCA_FOR_VAR_P (exp));
53800dbe 5575 if (target)
5576 return target;
5577 break;
5578
4ee9c684 5579 case BUILT_IN_STACK_SAVE:
5580 return expand_stack_save ();
5581
5582 case BUILT_IN_STACK_RESTORE:
c2f47e15 5583 expand_stack_restore (CALL_EXPR_ARG (exp, 0));
4ee9c684 5584 return const0_rtx;
5585
42791117 5586 case BUILT_IN_BSWAP32:
5587 case BUILT_IN_BSWAP64:
c2f47e15 5588 target = expand_builtin_bswap (exp, target, subtarget);
42791117 5589
5590 if (target)
5591 return target;
5592 break;
5593
4f35b1fc 5594 CASE_INT_FN (BUILT_IN_FFS):
5053259b 5595 case BUILT_IN_FFSIMAX:
c2f47e15 5596 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 5597 subtarget, ffs_optab);
6a08d0ab 5598 if (target)
5599 return target;
5600 break;
5601
4f35b1fc 5602 CASE_INT_FN (BUILT_IN_CLZ):
5053259b 5603 case BUILT_IN_CLZIMAX:
c2f47e15 5604 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 5605 subtarget, clz_optab);
6a08d0ab 5606 if (target)
5607 return target;
5608 break;
5609
4f35b1fc 5610 CASE_INT_FN (BUILT_IN_CTZ):
5053259b 5611 case BUILT_IN_CTZIMAX:
c2f47e15 5612 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 5613 subtarget, ctz_optab);
6a08d0ab 5614 if (target)
5615 return target;
5616 break;
5617
d8492bd3 5618 CASE_INT_FN (BUILT_IN_CLRSB):
5619 case BUILT_IN_CLRSBIMAX:
5620 target = expand_builtin_unop (target_mode, exp, target,
5621 subtarget, clrsb_optab);
5622 if (target)
5623 return target;
5624 break;
5625
4f35b1fc 5626 CASE_INT_FN (BUILT_IN_POPCOUNT):
5053259b 5627 case BUILT_IN_POPCOUNTIMAX:
c2f47e15 5628 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 5629 subtarget, popcount_optab);
6a08d0ab 5630 if (target)
5631 return target;
5632 break;
5633
4f35b1fc 5634 CASE_INT_FN (BUILT_IN_PARITY):
5053259b 5635 case BUILT_IN_PARITYIMAX:
c2f47e15 5636 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 5637 subtarget, parity_optab);
53800dbe 5638 if (target)
5639 return target;
5640 break;
5641
5642 case BUILT_IN_STRLEN:
c2f47e15 5643 target = expand_builtin_strlen (exp, target, target_mode);
53800dbe 5644 if (target)
5645 return target;
5646 break;
5647
5648 case BUILT_IN_STRCPY:
a65c4d64 5649 target = expand_builtin_strcpy (exp, target);
53800dbe 5650 if (target)
5651 return target;
5652 break;
bf8e3599 5653
ed09096d 5654 case BUILT_IN_STRNCPY:
a65c4d64 5655 target = expand_builtin_strncpy (exp, target);
ed09096d 5656 if (target)
5657 return target;
5658 break;
bf8e3599 5659
3b824fa6 5660 case BUILT_IN_STPCPY:
dc369150 5661 target = expand_builtin_stpcpy (exp, target, mode);
3b824fa6 5662 if (target)
5663 return target;
5664 break;
5665
53800dbe 5666 case BUILT_IN_MEMCPY:
a65c4d64 5667 target = expand_builtin_memcpy (exp, target);
3b824fa6 5668 if (target)
5669 return target;
5670 break;
5671
5672 case BUILT_IN_MEMPCPY:
c2f47e15 5673 target = expand_builtin_mempcpy (exp, target, mode);
53800dbe 5674 if (target)
5675 return target;
5676 break;
5677
5678 case BUILT_IN_MEMSET:
c2f47e15 5679 target = expand_builtin_memset (exp, target, mode);
53800dbe 5680 if (target)
5681 return target;
5682 break;
5683
ffc83088 5684 case BUILT_IN_BZERO:
0b25db21 5685 target = expand_builtin_bzero (exp);
ffc83088 5686 if (target)
5687 return target;
5688 break;
5689
53800dbe 5690 case BUILT_IN_STRCMP:
a65c4d64 5691 target = expand_builtin_strcmp (exp, target);
53800dbe 5692 if (target)
5693 return target;
5694 break;
5695
ed09096d 5696 case BUILT_IN_STRNCMP:
5697 target = expand_builtin_strncmp (exp, target, mode);
5698 if (target)
5699 return target;
5700 break;
5701
071f1696 5702 case BUILT_IN_BCMP:
53800dbe 5703 case BUILT_IN_MEMCMP:
c2f47e15 5704 target = expand_builtin_memcmp (exp, target, mode);
53800dbe 5705 if (target)
5706 return target;
5707 break;
53800dbe 5708
5709 case BUILT_IN_SETJMP:
2c8a1497 5710 /* This should have been lowered to the builtins below. */
5711 gcc_unreachable ();
5712
5713 case BUILT_IN_SETJMP_SETUP:
5714 /* __builtin_setjmp_setup is passed a pointer to an array of five words
5715 and the receiver label. */
c2f47e15 5716 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2c8a1497 5717 {
c2f47e15 5718 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
2c8a1497 5719 VOIDmode, EXPAND_NORMAL);
c2f47e15 5720 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
2c8a1497 5721 rtx label_r = label_rtx (label);
5722
5723 /* This is copied from the handling of non-local gotos. */
5724 expand_builtin_setjmp_setup (buf_addr, label_r);
5725 nonlocal_goto_handler_labels
5726 = gen_rtx_EXPR_LIST (VOIDmode, label_r,
5727 nonlocal_goto_handler_labels);
5728 /* ??? Do not let expand_label treat us as such since we would
5729 not want to be both on the list of non-local labels and on
5730 the list of forced labels. */
5731 FORCED_LABEL (label) = 0;
5732 return const0_rtx;
5733 }
5734 break;
5735
5736 case BUILT_IN_SETJMP_DISPATCHER:
5737 /* __builtin_setjmp_dispatcher is passed the dispatcher label. */
c2f47e15 5738 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 5739 {
c2f47e15 5740 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 5741 rtx label_r = label_rtx (label);
5742
5743 /* Remove the dispatcher label from the list of non-local labels
5744 since the receiver labels have been added to it above. */
5745 remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels);
5746 return const0_rtx;
5747 }
5748 break;
5749
5750 case BUILT_IN_SETJMP_RECEIVER:
5751 /* __builtin_setjmp_receiver is passed the receiver label. */
c2f47e15 5752 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 5753 {
c2f47e15 5754 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 5755 rtx label_r = label_rtx (label);
5756
5757 expand_builtin_setjmp_receiver (label_r);
5758 return const0_rtx;
5759 }
6b7f6858 5760 break;
53800dbe 5761
5762 /* __builtin_longjmp is passed a pointer to an array of five words.
5763 It's similar to the C library longjmp function but works with
5764 __builtin_setjmp above. */
5765 case BUILT_IN_LONGJMP:
c2f47e15 5766 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 5767 {
c2f47e15 5768 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
8ec3c5c2 5769 VOIDmode, EXPAND_NORMAL);
c2f47e15 5770 rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
53800dbe 5771
5772 if (value != const1_rtx)
5773 {
1e5fcbe2 5774 error ("%<__builtin_longjmp%> second argument must be 1");
53800dbe 5775 return const0_rtx;
5776 }
5777
5778 expand_builtin_longjmp (buf_addr, value);
5779 return const0_rtx;
5780 }
2c8a1497 5781 break;
53800dbe 5782
4ee9c684 5783 case BUILT_IN_NONLOCAL_GOTO:
c2f47e15 5784 target = expand_builtin_nonlocal_goto (exp);
4ee9c684 5785 if (target)
5786 return target;
5787 break;
5788
843d08a9 5789 /* This updates the setjmp buffer that is its argument with the value
5790 of the current stack pointer. */
5791 case BUILT_IN_UPDATE_SETJMP_BUF:
c2f47e15 5792 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
843d08a9 5793 {
5794 rtx buf_addr
c2f47e15 5795 = expand_normal (CALL_EXPR_ARG (exp, 0));
843d08a9 5796
5797 expand_builtin_update_setjmp_buf (buf_addr);
5798 return const0_rtx;
5799 }
5800 break;
5801
53800dbe 5802 case BUILT_IN_TRAP:
a0ef1725 5803 expand_builtin_trap ();
53800dbe 5804 return const0_rtx;
5805
d2b48f0c 5806 case BUILT_IN_UNREACHABLE:
5807 expand_builtin_unreachable ();
5808 return const0_rtx;
5809
4f35b1fc 5810 CASE_FLT_FN (BUILT_IN_SIGNBIT):
004e23c4 5811 case BUILT_IN_SIGNBITD32:
5812 case BUILT_IN_SIGNBITD64:
5813 case BUILT_IN_SIGNBITD128:
27f261ef 5814 target = expand_builtin_signbit (exp, target);
5815 if (target)
5816 return target;
5817 break;
5818
53800dbe 5819 /* Various hooks for the DWARF 2 __throw routine. */
5820 case BUILT_IN_UNWIND_INIT:
5821 expand_builtin_unwind_init ();
5822 return const0_rtx;
5823 case BUILT_IN_DWARF_CFA:
5824 return virtual_cfa_rtx;
5825#ifdef DWARF2_UNWIND_INFO
f8f023a5 5826 case BUILT_IN_DWARF_SP_COLUMN:
5827 return expand_builtin_dwarf_sp_column ();
695e919b 5828 case BUILT_IN_INIT_DWARF_REG_SIZES:
c2f47e15 5829 expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
695e919b 5830 return const0_rtx;
53800dbe 5831#endif
5832 case BUILT_IN_FROB_RETURN_ADDR:
c2f47e15 5833 return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 5834 case BUILT_IN_EXTRACT_RETURN_ADDR:
c2f47e15 5835 return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 5836 case BUILT_IN_EH_RETURN:
c2f47e15 5837 expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
5838 CALL_EXPR_ARG (exp, 1));
53800dbe 5839 return const0_rtx;
df4b504c 5840#ifdef EH_RETURN_DATA_REGNO
5841 case BUILT_IN_EH_RETURN_DATA_REGNO:
c2f47e15 5842 return expand_builtin_eh_return_data_regno (exp);
df4b504c 5843#endif
26093bf4 5844 case BUILT_IN_EXTEND_POINTER:
c2f47e15 5845 return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
e38def9c 5846 case BUILT_IN_EH_POINTER:
5847 return expand_builtin_eh_pointer (exp);
5848 case BUILT_IN_EH_FILTER:
5849 return expand_builtin_eh_filter (exp);
5850 case BUILT_IN_EH_COPY_VALUES:
5851 return expand_builtin_eh_copy_values (exp);
26093bf4 5852
7ccc713a 5853 case BUILT_IN_VA_START:
c2f47e15 5854 return expand_builtin_va_start (exp);
a66c9326 5855 case BUILT_IN_VA_END:
c2f47e15 5856 return expand_builtin_va_end (exp);
a66c9326 5857 case BUILT_IN_VA_COPY:
c2f47e15 5858 return expand_builtin_va_copy (exp);
89cfe6e5 5859 case BUILT_IN_EXPECT:
c2f47e15 5860 return expand_builtin_expect (exp, target);
fca0886c 5861 case BUILT_IN_ASSUME_ALIGNED:
5862 return expand_builtin_assume_aligned (exp, target);
5e3608d8 5863 case BUILT_IN_PREFETCH:
c2f47e15 5864 expand_builtin_prefetch (exp);
5e3608d8 5865 return const0_rtx;
5866
4ee9c684 5867 case BUILT_IN_INIT_TRAMPOLINE:
c2f47e15 5868 return expand_builtin_init_trampoline (exp);
4ee9c684 5869 case BUILT_IN_ADJUST_TRAMPOLINE:
c2f47e15 5870 return expand_builtin_adjust_trampoline (exp);
4ee9c684 5871
73673831 5872 case BUILT_IN_FORK:
5873 case BUILT_IN_EXECL:
5874 case BUILT_IN_EXECV:
5875 case BUILT_IN_EXECLP:
5876 case BUILT_IN_EXECLE:
5877 case BUILT_IN_EXECVP:
5878 case BUILT_IN_EXECVE:
c2f47e15 5879 target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
73673831 5880 if (target)
5881 return target;
5882 break;
53800dbe 5883
2797f13a 5884 case BUILT_IN_SYNC_FETCH_AND_ADD_1:
5885 case BUILT_IN_SYNC_FETCH_AND_ADD_2:
5886 case BUILT_IN_SYNC_FETCH_AND_ADD_4:
5887 case BUILT_IN_SYNC_FETCH_AND_ADD_8:
5888 case BUILT_IN_SYNC_FETCH_AND_ADD_16:
5889 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_ADD_1);
c2f47e15 5890 target = expand_builtin_sync_operation (mode, exp, PLUS,
b6a5fc45 5891 false, target, ignore);
5892 if (target)
5893 return target;
5894 break;
5895
2797f13a 5896 case BUILT_IN_SYNC_FETCH_AND_SUB_1:
5897 case BUILT_IN_SYNC_FETCH_AND_SUB_2:
5898 case BUILT_IN_SYNC_FETCH_AND_SUB_4:
5899 case BUILT_IN_SYNC_FETCH_AND_SUB_8:
5900 case BUILT_IN_SYNC_FETCH_AND_SUB_16:
5901 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_SUB_1);
c2f47e15 5902 target = expand_builtin_sync_operation (mode, exp, MINUS,
b6a5fc45 5903 false, target, ignore);
5904 if (target)
5905 return target;
5906 break;
5907
2797f13a 5908 case BUILT_IN_SYNC_FETCH_AND_OR_1:
5909 case BUILT_IN_SYNC_FETCH_AND_OR_2:
5910 case BUILT_IN_SYNC_FETCH_AND_OR_4:
5911 case BUILT_IN_SYNC_FETCH_AND_OR_8:
5912 case BUILT_IN_SYNC_FETCH_AND_OR_16:
5913 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_OR_1);
c2f47e15 5914 target = expand_builtin_sync_operation (mode, exp, IOR,
b6a5fc45 5915 false, target, ignore);
5916 if (target)
5917 return target;
5918 break;
5919
2797f13a 5920 case BUILT_IN_SYNC_FETCH_AND_AND_1:
5921 case BUILT_IN_SYNC_FETCH_AND_AND_2:
5922 case BUILT_IN_SYNC_FETCH_AND_AND_4:
5923 case BUILT_IN_SYNC_FETCH_AND_AND_8:
5924 case BUILT_IN_SYNC_FETCH_AND_AND_16:
5925 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_AND_1);
c2f47e15 5926 target = expand_builtin_sync_operation (mode, exp, AND,
b6a5fc45 5927 false, target, ignore);
5928 if (target)
5929 return target;
5930 break;
5931
2797f13a 5932 case BUILT_IN_SYNC_FETCH_AND_XOR_1:
5933 case BUILT_IN_SYNC_FETCH_AND_XOR_2:
5934 case BUILT_IN_SYNC_FETCH_AND_XOR_4:
5935 case BUILT_IN_SYNC_FETCH_AND_XOR_8:
5936 case BUILT_IN_SYNC_FETCH_AND_XOR_16:
5937 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_XOR_1);
c2f47e15 5938 target = expand_builtin_sync_operation (mode, exp, XOR,
b6a5fc45 5939 false, target, ignore);
5940 if (target)
5941 return target;
5942 break;
5943
2797f13a 5944 case BUILT_IN_SYNC_FETCH_AND_NAND_1:
5945 case BUILT_IN_SYNC_FETCH_AND_NAND_2:
5946 case BUILT_IN_SYNC_FETCH_AND_NAND_4:
5947 case BUILT_IN_SYNC_FETCH_AND_NAND_8:
5948 case BUILT_IN_SYNC_FETCH_AND_NAND_16:
5949 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_NAND_1);
c2f47e15 5950 target = expand_builtin_sync_operation (mode, exp, NOT,
b6a5fc45 5951 false, target, ignore);
5952 if (target)
5953 return target;
5954 break;
5955
2797f13a 5956 case BUILT_IN_SYNC_ADD_AND_FETCH_1:
5957 case BUILT_IN_SYNC_ADD_AND_FETCH_2:
5958 case BUILT_IN_SYNC_ADD_AND_FETCH_4:
5959 case BUILT_IN_SYNC_ADD_AND_FETCH_8:
5960 case BUILT_IN_SYNC_ADD_AND_FETCH_16:
5961 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_ADD_AND_FETCH_1);
c2f47e15 5962 target = expand_builtin_sync_operation (mode, exp, PLUS,
b6a5fc45 5963 true, target, ignore);
5964 if (target)
5965 return target;
5966 break;
5967
2797f13a 5968 case BUILT_IN_SYNC_SUB_AND_FETCH_1:
5969 case BUILT_IN_SYNC_SUB_AND_FETCH_2:
5970 case BUILT_IN_SYNC_SUB_AND_FETCH_4:
5971 case BUILT_IN_SYNC_SUB_AND_FETCH_8:
5972 case BUILT_IN_SYNC_SUB_AND_FETCH_16:
5973 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_SUB_AND_FETCH_1);
c2f47e15 5974 target = expand_builtin_sync_operation (mode, exp, MINUS,
b6a5fc45 5975 true, target, ignore);
5976 if (target)
5977 return target;
5978 break;
5979
2797f13a 5980 case BUILT_IN_SYNC_OR_AND_FETCH_1:
5981 case BUILT_IN_SYNC_OR_AND_FETCH_2:
5982 case BUILT_IN_SYNC_OR_AND_FETCH_4:
5983 case BUILT_IN_SYNC_OR_AND_FETCH_8:
5984 case BUILT_IN_SYNC_OR_AND_FETCH_16:
5985 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_OR_AND_FETCH_1);
c2f47e15 5986 target = expand_builtin_sync_operation (mode, exp, IOR,
b6a5fc45 5987 true, target, ignore);
5988 if (target)
5989 return target;
5990 break;
5991
2797f13a 5992 case BUILT_IN_SYNC_AND_AND_FETCH_1:
5993 case BUILT_IN_SYNC_AND_AND_FETCH_2:
5994 case BUILT_IN_SYNC_AND_AND_FETCH_4:
5995 case BUILT_IN_SYNC_AND_AND_FETCH_8:
5996 case BUILT_IN_SYNC_AND_AND_FETCH_16:
5997 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_AND_AND_FETCH_1);
c2f47e15 5998 target = expand_builtin_sync_operation (mode, exp, AND,
b6a5fc45 5999 true, target, ignore);
6000 if (target)
6001 return target;
6002 break;
6003
2797f13a 6004 case BUILT_IN_SYNC_XOR_AND_FETCH_1:
6005 case BUILT_IN_SYNC_XOR_AND_FETCH_2:
6006 case BUILT_IN_SYNC_XOR_AND_FETCH_4:
6007 case BUILT_IN_SYNC_XOR_AND_FETCH_8:
6008 case BUILT_IN_SYNC_XOR_AND_FETCH_16:
6009 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_XOR_AND_FETCH_1);
c2f47e15 6010 target = expand_builtin_sync_operation (mode, exp, XOR,
b6a5fc45 6011 true, target, ignore);
6012 if (target)
6013 return target;
6014 break;
6015
2797f13a 6016 case BUILT_IN_SYNC_NAND_AND_FETCH_1:
6017 case BUILT_IN_SYNC_NAND_AND_FETCH_2:
6018 case BUILT_IN_SYNC_NAND_AND_FETCH_4:
6019 case BUILT_IN_SYNC_NAND_AND_FETCH_8:
6020 case BUILT_IN_SYNC_NAND_AND_FETCH_16:
6021 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_NAND_AND_FETCH_1);
c2f47e15 6022 target = expand_builtin_sync_operation (mode, exp, NOT,
b6a5fc45 6023 true, target, ignore);
6024 if (target)
6025 return target;
6026 break;
6027
2797f13a 6028 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
6029 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
6030 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
6031 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
6032 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16:
a601d32a 6033 if (mode == VOIDmode)
6034 mode = TYPE_MODE (boolean_type_node);
b6a5fc45 6035 if (!target || !register_operand (target, mode))
6036 target = gen_reg_rtx (mode);
3e272de8 6037
2797f13a 6038 mode = get_builtin_sync_mode
6039 (fcode - BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1);
c2f47e15 6040 target = expand_builtin_compare_and_swap (mode, exp, true, target);
b6a5fc45 6041 if (target)
6042 return target;
6043 break;
6044
2797f13a 6045 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
6046 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
6047 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
6048 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
6049 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
6050 mode = get_builtin_sync_mode
6051 (fcode - BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1);
c2f47e15 6052 target = expand_builtin_compare_and_swap (mode, exp, false, target);
b6a5fc45 6053 if (target)
6054 return target;
6055 break;
6056
2797f13a 6057 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
6058 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
6059 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
6060 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
6061 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16:
6062 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_TEST_AND_SET_1);
6063 target = expand_builtin_sync_lock_test_and_set (mode, exp, target);
b6a5fc45 6064 if (target)
6065 return target;
6066 break;
6067
2797f13a 6068 case BUILT_IN_SYNC_LOCK_RELEASE_1:
6069 case BUILT_IN_SYNC_LOCK_RELEASE_2:
6070 case BUILT_IN_SYNC_LOCK_RELEASE_4:
6071 case BUILT_IN_SYNC_LOCK_RELEASE_8:
6072 case BUILT_IN_SYNC_LOCK_RELEASE_16:
6073 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_RELEASE_1);
6074 expand_builtin_sync_lock_release (mode, exp);
b6a5fc45 6075 return const0_rtx;
6076
2797f13a 6077 case BUILT_IN_SYNC_SYNCHRONIZE:
6078 expand_builtin_sync_synchronize ();
b6a5fc45 6079 return const0_rtx;
6080
0a39fd54 6081 case BUILT_IN_OBJECT_SIZE:
6082 return expand_builtin_object_size (exp);
6083
6084 case BUILT_IN_MEMCPY_CHK:
6085 case BUILT_IN_MEMPCPY_CHK:
6086 case BUILT_IN_MEMMOVE_CHK:
6087 case BUILT_IN_MEMSET_CHK:
6088 target = expand_builtin_memory_chk (exp, target, mode, fcode);
6089 if (target)
6090 return target;
6091 break;
6092
6093 case BUILT_IN_STRCPY_CHK:
6094 case BUILT_IN_STPCPY_CHK:
6095 case BUILT_IN_STRNCPY_CHK:
6096 case BUILT_IN_STRCAT_CHK:
b356dfef 6097 case BUILT_IN_STRNCAT_CHK:
0a39fd54 6098 case BUILT_IN_SNPRINTF_CHK:
6099 case BUILT_IN_VSNPRINTF_CHK:
6100 maybe_emit_chk_warning (exp, fcode);
6101 break;
6102
6103 case BUILT_IN_SPRINTF_CHK:
6104 case BUILT_IN_VSPRINTF_CHK:
6105 maybe_emit_sprintf_chk_warning (exp, fcode);
6106 break;
6107
2c281b15 6108 case BUILT_IN_FREE:
6109 maybe_emit_free_warning (exp);
6110 break;
6111
92482ee0 6112 default: /* just do library call, if unknown builtin */
146c1b4f 6113 break;
53800dbe 6114 }
6115
6116 /* The switch statement above can drop through to cause the function
6117 to be called normally. */
6118 return expand_call (exp, target, ignore);
6119}
650e4c94 6120
805e22b2 6121/* Determine whether a tree node represents a call to a built-in
52203a9d 6122 function. If the tree T is a call to a built-in function with
6123 the right number of arguments of the appropriate types, return
6124 the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
6125 Otherwise the return value is END_BUILTINS. */
aecda0d6 6126
805e22b2 6127enum built_in_function
b7bf20db 6128builtin_mathfn_code (const_tree t)
805e22b2 6129{
b7bf20db 6130 const_tree fndecl, arg, parmlist;
6131 const_tree argtype, parmtype;
6132 const_call_expr_arg_iterator iter;
805e22b2 6133
6134 if (TREE_CODE (t) != CALL_EXPR
c2f47e15 6135 || TREE_CODE (CALL_EXPR_FN (t)) != ADDR_EXPR)
805e22b2 6136 return END_BUILTINS;
6137
c6e6ecb1 6138 fndecl = get_callee_fndecl (t);
6139 if (fndecl == NULL_TREE
52203a9d 6140 || TREE_CODE (fndecl) != FUNCTION_DECL
805e22b2 6141 || ! DECL_BUILT_IN (fndecl)
6142 || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
6143 return END_BUILTINS;
6144
52203a9d 6145 parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
b7bf20db 6146 init_const_call_expr_arg_iterator (t, &iter);
52203a9d 6147 for (; parmlist; parmlist = TREE_CHAIN (parmlist))
e9f80ff5 6148 {
52203a9d 6149 /* If a function doesn't take a variable number of arguments,
6150 the last element in the list will have type `void'. */
6151 parmtype = TREE_VALUE (parmlist);
6152 if (VOID_TYPE_P (parmtype))
6153 {
b7bf20db 6154 if (more_const_call_expr_args_p (&iter))
52203a9d 6155 return END_BUILTINS;
6156 return DECL_FUNCTION_CODE (fndecl);
6157 }
6158
b7bf20db 6159 if (! more_const_call_expr_args_p (&iter))
e9f80ff5 6160 return END_BUILTINS;
48e1416a 6161
b7bf20db 6162 arg = next_const_call_expr_arg (&iter);
c2f47e15 6163 argtype = TREE_TYPE (arg);
52203a9d 6164
6165 if (SCALAR_FLOAT_TYPE_P (parmtype))
6166 {
6167 if (! SCALAR_FLOAT_TYPE_P (argtype))
6168 return END_BUILTINS;
6169 }
6170 else if (COMPLEX_FLOAT_TYPE_P (parmtype))
6171 {
6172 if (! COMPLEX_FLOAT_TYPE_P (argtype))
6173 return END_BUILTINS;
6174 }
6175 else if (POINTER_TYPE_P (parmtype))
6176 {
6177 if (! POINTER_TYPE_P (argtype))
6178 return END_BUILTINS;
6179 }
6180 else if (INTEGRAL_TYPE_P (parmtype))
6181 {
6182 if (! INTEGRAL_TYPE_P (argtype))
6183 return END_BUILTINS;
6184 }
6185 else
e9f80ff5 6186 return END_BUILTINS;
e9f80ff5 6187 }
6188
52203a9d 6189 /* Variable-length argument list. */
805e22b2 6190 return DECL_FUNCTION_CODE (fndecl);
6191}
6192
c2f47e15 6193/* Fold a call to __builtin_constant_p, if we know its argument ARG will
6194 evaluate to a constant. */
650e4c94 6195
6196static tree
c2f47e15 6197fold_builtin_constant_p (tree arg)
650e4c94 6198{
650e4c94 6199 /* We return 1 for a numeric type that's known to be a constant
6200 value at compile-time or for an aggregate type that's a
6201 literal constant. */
c2f47e15 6202 STRIP_NOPS (arg);
650e4c94 6203
6204 /* If we know this is a constant, emit the constant of one. */
c2f47e15 6205 if (CONSTANT_CLASS_P (arg)
6206 || (TREE_CODE (arg) == CONSTRUCTOR
6207 && TREE_CONSTANT (arg)))
650e4c94 6208 return integer_one_node;
c2f47e15 6209 if (TREE_CODE (arg) == ADDR_EXPR)
adcfa3a3 6210 {
c2f47e15 6211 tree op = TREE_OPERAND (arg, 0);
adcfa3a3 6212 if (TREE_CODE (op) == STRING_CST
6213 || (TREE_CODE (op) == ARRAY_REF
6214 && integer_zerop (TREE_OPERAND (op, 1))
6215 && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
6216 return integer_one_node;
6217 }
650e4c94 6218
1fb4300c 6219 /* If this expression has side effects, show we don't know it to be a
6220 constant. Likewise if it's a pointer or aggregate type since in
6221 those case we only want literals, since those are only optimized
f97c71a1 6222 when generating RTL, not later.
6223 And finally, if we are compiling an initializer, not code, we
6224 need to return a definite result now; there's not going to be any
6225 more optimization done. */
c2f47e15 6226 if (TREE_SIDE_EFFECTS (arg)
6227 || AGGREGATE_TYPE_P (TREE_TYPE (arg))
6228 || POINTER_TYPE_P (TREE_TYPE (arg))
47be647d 6229 || cfun == 0
6230 || folding_initializer)
650e4c94 6231 return integer_zero_node;
6232
c2f47e15 6233 return NULL_TREE;
650e4c94 6234}
6235
76f5a783 6236/* Create builtin_expect with PRED and EXPECTED as its arguments and
6237 return it as a truthvalue. */
4ee9c684 6238
6239static tree
389dd41b 6240build_builtin_expect_predicate (location_t loc, tree pred, tree expected)
4ee9c684 6241{
76f5a783 6242 tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
4ee9c684 6243
76f5a783 6244 fn = built_in_decls[BUILT_IN_EXPECT];
6245 arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
6246 ret_type = TREE_TYPE (TREE_TYPE (fn));
6247 pred_type = TREE_VALUE (arg_types);
6248 expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
6249
389dd41b 6250 pred = fold_convert_loc (loc, pred_type, pred);
6251 expected = fold_convert_loc (loc, expected_type, expected);
6252 call_expr = build_call_expr_loc (loc, fn, 2, pred, expected);
76f5a783 6253
6254 return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
6255 build_int_cst (ret_type, 0));
6256}
6257
6258/* Fold a call to builtin_expect with arguments ARG0 and ARG1. Return
6259 NULL_TREE if no simplification is possible. */
6260
6261static tree
389dd41b 6262fold_builtin_expect (location_t loc, tree arg0, tree arg1)
76f5a783 6263{
6264 tree inner, fndecl;
6265 enum tree_code code;
6266
6267 /* If this is a builtin_expect within a builtin_expect keep the
6268 inner one. See through a comparison against a constant. It
6269 might have been added to create a thruthvalue. */
6270 inner = arg0;
6271 if (COMPARISON_CLASS_P (inner)
6272 && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST)
6273 inner = TREE_OPERAND (inner, 0);
6274
6275 if (TREE_CODE (inner) == CALL_EXPR
6276 && (fndecl = get_callee_fndecl (inner))
6277 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
6278 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT)
6279 return arg0;
6280
6281 /* Distribute the expected value over short-circuiting operators.
6282 See through the cast from truthvalue_type_node to long. */
6283 inner = arg0;
6284 while (TREE_CODE (inner) == NOP_EXPR
6285 && INTEGRAL_TYPE_P (TREE_TYPE (inner))
6286 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner, 0))))
6287 inner = TREE_OPERAND (inner, 0);
6288
6289 code = TREE_CODE (inner);
6290 if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
6291 {
6292 tree op0 = TREE_OPERAND (inner, 0);
6293 tree op1 = TREE_OPERAND (inner, 1);
6294
389dd41b 6295 op0 = build_builtin_expect_predicate (loc, op0, arg1);
6296 op1 = build_builtin_expect_predicate (loc, op1, arg1);
76f5a783 6297 inner = build2 (code, TREE_TYPE (inner), op0, op1);
6298
389dd41b 6299 return fold_convert_loc (loc, TREE_TYPE (arg0), inner);
76f5a783 6300 }
6301
6302 /* If the argument isn't invariant then there's nothing else we can do. */
c7d4e749 6303 if (!TREE_CONSTANT (arg0))
c2f47e15 6304 return NULL_TREE;
4ee9c684 6305
76f5a783 6306 /* If we expect that a comparison against the argument will fold to
6307 a constant return the constant. In practice, this means a true
6308 constant or the address of a non-weak symbol. */
6309 inner = arg0;
4ee9c684 6310 STRIP_NOPS (inner);
6311 if (TREE_CODE (inner) == ADDR_EXPR)
6312 {
6313 do
6314 {
6315 inner = TREE_OPERAND (inner, 0);
6316 }
6317 while (TREE_CODE (inner) == COMPONENT_REF
6318 || TREE_CODE (inner) == ARRAY_REF);
062b4460 6319 if ((TREE_CODE (inner) == VAR_DECL
6320 || TREE_CODE (inner) == FUNCTION_DECL)
6321 && DECL_WEAK (inner))
c2f47e15 6322 return NULL_TREE;
4ee9c684 6323 }
6324
76f5a783 6325 /* Otherwise, ARG0 already has the proper type for the return value. */
6326 return arg0;
4ee9c684 6327}
6328
c2f47e15 6329/* Fold a call to __builtin_classify_type with argument ARG. */
27d0c333 6330
539a3a92 6331static tree
c2f47e15 6332fold_builtin_classify_type (tree arg)
539a3a92 6333{
c2f47e15 6334 if (arg == 0)
7002a1c8 6335 return build_int_cst (integer_type_node, no_type_class);
539a3a92 6336
7002a1c8 6337 return build_int_cst (integer_type_node, type_to_class (TREE_TYPE (arg)));
539a3a92 6338}
6339
c2f47e15 6340/* Fold a call to __builtin_strlen with argument ARG. */
e6e27594 6341
6342static tree
c7cbde74 6343fold_builtin_strlen (location_t loc, tree type, tree arg)
e6e27594 6344{
c2f47e15 6345 if (!validate_arg (arg, POINTER_TYPE))
e6e27594 6346 return NULL_TREE;
6347 else
6348 {
c2f47e15 6349 tree len = c_strlen (arg, 0);
e6e27594 6350
6351 if (len)
c7cbde74 6352 return fold_convert_loc (loc, type, len);
e6e27594 6353
6354 return NULL_TREE;
6355 }
6356}
6357
92c43e3c 6358/* Fold a call to __builtin_inf or __builtin_huge_val. */
6359
6360static tree
389dd41b 6361fold_builtin_inf (location_t loc, tree type, int warn)
92c43e3c 6362{
aa870c1b 6363 REAL_VALUE_TYPE real;
6364
40f4dbd5 6365 /* __builtin_inff is intended to be usable to define INFINITY on all
6366 targets. If an infinity is not available, INFINITY expands "to a
6367 positive constant of type float that overflows at translation
6368 time", footnote "In this case, using INFINITY will violate the
6369 constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
6370 Thus we pedwarn to ensure this constraint violation is
6371 diagnosed. */
92c43e3c 6372 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
389dd41b 6373 pedwarn (loc, 0, "target format does not support infinity");
92c43e3c 6374
aa870c1b 6375 real_inf (&real);
6376 return build_real (type, real);
92c43e3c 6377}
6378
c2f47e15 6379/* Fold a call to __builtin_nan or __builtin_nans with argument ARG. */
b0db7939 6380
6381static tree
c2f47e15 6382fold_builtin_nan (tree arg, tree type, int quiet)
b0db7939 6383{
6384 REAL_VALUE_TYPE real;
6385 const char *str;
6386
c2f47e15 6387 if (!validate_arg (arg, POINTER_TYPE))
6388 return NULL_TREE;
6389 str = c_getstr (arg);
b0db7939 6390 if (!str)
c2f47e15 6391 return NULL_TREE;
b0db7939 6392
6393 if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
c2f47e15 6394 return NULL_TREE;
b0db7939 6395
6396 return build_real (type, real);
6397}
6398
277f8dd2 6399/* Return true if the floating point expression T has an integer value.
6400 We also allow +Inf, -Inf and NaN to be considered integer values. */
6401
6402static bool
6403integer_valued_real_p (tree t)
6404{
6405 switch (TREE_CODE (t))
6406 {
6407 case FLOAT_EXPR:
6408 return true;
6409
6410 case ABS_EXPR:
6411 case SAVE_EXPR:
277f8dd2 6412 return integer_valued_real_p (TREE_OPERAND (t, 0));
6413
6414 case COMPOUND_EXPR:
41076ef6 6415 case MODIFY_EXPR:
277f8dd2 6416 case BIND_EXPR:
75a70cf9 6417 return integer_valued_real_p (TREE_OPERAND (t, 1));
277f8dd2 6418
6419 case PLUS_EXPR:
6420 case MINUS_EXPR:
6421 case MULT_EXPR:
6422 case MIN_EXPR:
6423 case MAX_EXPR:
6424 return integer_valued_real_p (TREE_OPERAND (t, 0))
6425 && integer_valued_real_p (TREE_OPERAND (t, 1));
6426
6427 case COND_EXPR:
6428 return integer_valued_real_p (TREE_OPERAND (t, 1))
6429 && integer_valued_real_p (TREE_OPERAND (t, 2));
6430
6431 case REAL_CST:
0570334c 6432 return real_isinteger (TREE_REAL_CST_PTR (t), TYPE_MODE (TREE_TYPE (t)));
277f8dd2 6433
6434 case NOP_EXPR:
6435 {
6436 tree type = TREE_TYPE (TREE_OPERAND (t, 0));
6437 if (TREE_CODE (type) == INTEGER_TYPE)
6438 return true;
6439 if (TREE_CODE (type) == REAL_TYPE)
6440 return integer_valued_real_p (TREE_OPERAND (t, 0));
6441 break;
6442 }
6443
6444 case CALL_EXPR:
6445 switch (builtin_mathfn_code (t))
6446 {
4f35b1fc 6447 CASE_FLT_FN (BUILT_IN_CEIL):
6448 CASE_FLT_FN (BUILT_IN_FLOOR):
6449 CASE_FLT_FN (BUILT_IN_NEARBYINT):
6450 CASE_FLT_FN (BUILT_IN_RINT):
6451 CASE_FLT_FN (BUILT_IN_ROUND):
6452 CASE_FLT_FN (BUILT_IN_TRUNC):
277f8dd2 6453 return true;
6454
d4a43a03 6455 CASE_FLT_FN (BUILT_IN_FMIN):
6456 CASE_FLT_FN (BUILT_IN_FMAX):
c2f47e15 6457 return integer_valued_real_p (CALL_EXPR_ARG (t, 0))
6458 && integer_valued_real_p (CALL_EXPR_ARG (t, 1));
d4a43a03 6459
277f8dd2 6460 default:
6461 break;
6462 }
6463 break;
6464
6465 default:
6466 break;
6467 }
6468 return false;
6469}
6470
c2f47e15 6471/* FNDECL is assumed to be a builtin where truncation can be propagated
6528f4f4 6472 across (for instance floor((double)f) == (double)floorf (f).
c2f47e15 6473 Do the transformation for a call with argument ARG. */
277f8dd2 6474
6528f4f4 6475static tree
389dd41b 6476fold_trunc_transparent_mathfn (location_t loc, tree fndecl, tree arg)
6528f4f4 6477{
6528f4f4 6478 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
277f8dd2 6479
c2f47e15 6480 if (!validate_arg (arg, REAL_TYPE))
6481 return NULL_TREE;
6528f4f4 6482
277f8dd2 6483 /* Integer rounding functions are idempotent. */
6484 if (fcode == builtin_mathfn_code (arg))
6485 return arg;
6486
6487 /* If argument is already integer valued, and we don't need to worry
6488 about setting errno, there's no need to perform rounding. */
6489 if (! flag_errno_math && integer_valued_real_p (arg))
6490 return arg;
6491
6492 if (optimize)
6528f4f4 6493 {
277f8dd2 6494 tree arg0 = strip_float_extensions (arg);
2426241c 6495 tree ftype = TREE_TYPE (TREE_TYPE (fndecl));
6528f4f4 6496 tree newtype = TREE_TYPE (arg0);
6497 tree decl;
6498
6499 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
6500 && (decl = mathfn_built_in (newtype, fcode)))
389dd41b 6501 return fold_convert_loc (loc, ftype,
6502 build_call_expr_loc (loc, decl, 1,
6503 fold_convert_loc (loc,
6504 newtype,
6505 arg0)));
6528f4f4 6506 }
c2f47e15 6507 return NULL_TREE;
6528f4f4 6508}
6509
c2f47e15 6510/* FNDECL is assumed to be builtin which can narrow the FP type of
6511 the argument, for instance lround((double)f) -> lroundf (f).
6512 Do the transformation for a call with argument ARG. */
9ed65c7f 6513
6514static tree
389dd41b 6515fold_fixed_mathfn (location_t loc, tree fndecl, tree arg)
9ed65c7f 6516{
9ed65c7f 6517 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9ed65c7f 6518
c2f47e15 6519 if (!validate_arg (arg, REAL_TYPE))
6520 return NULL_TREE;
9ed65c7f 6521
6522 /* If argument is already integer valued, and we don't need to worry
6523 about setting errno, there's no need to perform rounding. */
6524 if (! flag_errno_math && integer_valued_real_p (arg))
389dd41b 6525 return fold_build1_loc (loc, FIX_TRUNC_EXPR,
6526 TREE_TYPE (TREE_TYPE (fndecl)), arg);
9ed65c7f 6527
6528 if (optimize)
6529 {
6530 tree ftype = TREE_TYPE (arg);
6531 tree arg0 = strip_float_extensions (arg);
6532 tree newtype = TREE_TYPE (arg0);
6533 tree decl;
6534
6535 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
6536 && (decl = mathfn_built_in (newtype, fcode)))
389dd41b 6537 return build_call_expr_loc (loc, decl, 1,
6538 fold_convert_loc (loc, newtype, arg0));
9ed65c7f 6539 }
73a0da56 6540
6541 /* Canonicalize llround (x) to lround (x) on LP64 targets where
6542 sizeof (long long) == sizeof (long). */
6543 if (TYPE_PRECISION (long_long_integer_type_node)
6544 == TYPE_PRECISION (long_integer_type_node))
6545 {
6546 tree newfn = NULL_TREE;
6547 switch (fcode)
6548 {
6549 CASE_FLT_FN (BUILT_IN_LLCEIL):
6550 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
6551 break;
6552
6553 CASE_FLT_FN (BUILT_IN_LLFLOOR):
6554 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
6555 break;
6556
6557 CASE_FLT_FN (BUILT_IN_LLROUND):
6558 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
6559 break;
6560
6561 CASE_FLT_FN (BUILT_IN_LLRINT):
6562 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
6563 break;
6564
6565 default:
6566 break;
6567 }
6568
6569 if (newfn)
6570 {
389dd41b 6571 tree newcall = build_call_expr_loc (loc, newfn, 1, arg);
6572 return fold_convert_loc (loc,
6573 TREE_TYPE (TREE_TYPE (fndecl)), newcall);
73a0da56 6574 }
6575 }
6576
c2f47e15 6577 return NULL_TREE;
9ed65c7f 6578}
6579
c2f47e15 6580/* Fold call to builtin cabs, cabsf or cabsl with argument ARG. TYPE is the
6581 return type. Return NULL_TREE if no simplification can be made. */
c63f4ad3 6582
6583static tree
389dd41b 6584fold_builtin_cabs (location_t loc, tree arg, tree type, tree fndecl)
c63f4ad3 6585{
c2f47e15 6586 tree res;
c63f4ad3 6587
b0ce8887 6588 if (!validate_arg (arg, COMPLEX_TYPE)
c63f4ad3 6589 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
6590 return NULL_TREE;
6591
b4725390 6592 /* Calculate the result when the argument is a constant. */
6593 if (TREE_CODE (arg) == COMPLEX_CST
6594 && (res = do_mpfr_arg2 (TREE_REALPART (arg), TREE_IMAGPART (arg),
6595 type, mpfr_hypot)))
6596 return res;
48e1416a 6597
1af0d139 6598 if (TREE_CODE (arg) == COMPLEX_EXPR)
6599 {
6600 tree real = TREE_OPERAND (arg, 0);
6601 tree imag = TREE_OPERAND (arg, 1);
48e1416a 6602
1af0d139 6603 /* If either part is zero, cabs is fabs of the other. */
6604 if (real_zerop (real))
389dd41b 6605 return fold_build1_loc (loc, ABS_EXPR, type, imag);
1af0d139 6606 if (real_zerop (imag))
389dd41b 6607 return fold_build1_loc (loc, ABS_EXPR, type, real);
1af0d139 6608
6609 /* cabs(x+xi) -> fabs(x)*sqrt(2). */
6610 if (flag_unsafe_math_optimizations
6611 && operand_equal_p (real, imag, OEP_PURE_SAME))
6612 {
2e7ca27b 6613 const REAL_VALUE_TYPE sqrt2_trunc
7910b2fb 6614 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
1af0d139 6615 STRIP_NOPS (real);
389dd41b 6616 return fold_build2_loc (loc, MULT_EXPR, type,
6617 fold_build1_loc (loc, ABS_EXPR, type, real),
2e7ca27b 6618 build_real (type, sqrt2_trunc));
1af0d139 6619 }
6620 }
c63f4ad3 6621
749891b2 6622 /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */
6623 if (TREE_CODE (arg) == NEGATE_EXPR
6624 || TREE_CODE (arg) == CONJ_EXPR)
389dd41b 6625 return build_call_expr_loc (loc, fndecl, 1, TREE_OPERAND (arg, 0));
749891b2 6626
7d3f6cc7 6627 /* Don't do this when optimizing for size. */
6628 if (flag_unsafe_math_optimizations
0bfd8d5c 6629 && optimize && optimize_function_for_speed_p (cfun))
c63f4ad3 6630 {
0da0dbfa 6631 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
c63f4ad3 6632
6633 if (sqrtfn != NULL_TREE)
6634 {
c2f47e15 6635 tree rpart, ipart, result;
c63f4ad3 6636
4ee9c684 6637 arg = builtin_save_expr (arg);
29a6518e 6638
389dd41b 6639 rpart = fold_build1_loc (loc, REALPART_EXPR, type, arg);
6640 ipart = fold_build1_loc (loc, IMAGPART_EXPR, type, arg);
c63f4ad3 6641
4ee9c684 6642 rpart = builtin_save_expr (rpart);
6643 ipart = builtin_save_expr (ipart);
c63f4ad3 6644
389dd41b 6645 result = fold_build2_loc (loc, PLUS_EXPR, type,
6646 fold_build2_loc (loc, MULT_EXPR, type,
49d00087 6647 rpart, rpart),
389dd41b 6648 fold_build2_loc (loc, MULT_EXPR, type,
49d00087 6649 ipart, ipart));
c63f4ad3 6650
389dd41b 6651 return build_call_expr_loc (loc, sqrtfn, 1, result);
c63f4ad3 6652 }
6653 }
6654
6655 return NULL_TREE;
6656}
6657
c2373fdb 6658/* Build a complex (inf +- 0i) for the result of cproj. TYPE is the
6659 complex tree type of the result. If NEG is true, the imaginary
6660 zero is negative. */
6661
6662static tree
6663build_complex_cproj (tree type, bool neg)
6664{
6665 REAL_VALUE_TYPE rinf, rzero = dconst0;
6666
6667 real_inf (&rinf);
6668 rzero.sign = neg;
6669 return build_complex (type, build_real (TREE_TYPE (type), rinf),
6670 build_real (TREE_TYPE (type), rzero));
6671}
6672
6673/* Fold call to builtin cproj, cprojf or cprojl with argument ARG. TYPE is the
6674 return type. Return NULL_TREE if no simplification can be made. */
6675
6676static tree
6677fold_builtin_cproj (location_t loc, tree arg, tree type)
6678{
6679 if (!validate_arg (arg, COMPLEX_TYPE)
6680 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
6681 return NULL_TREE;
6682
6683 /* If there are no infinities, return arg. */
6684 if (! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (type))))
6685 return non_lvalue_loc (loc, arg);
6686
6687 /* Calculate the result when the argument is a constant. */
6688 if (TREE_CODE (arg) == COMPLEX_CST)
6689 {
6690 const REAL_VALUE_TYPE *real = TREE_REAL_CST_PTR (TREE_REALPART (arg));
6691 const REAL_VALUE_TYPE *imag = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
6692
6693 if (real_isinf (real) || real_isinf (imag))
6694 return build_complex_cproj (type, imag->sign);
6695 else
6696 return arg;
6697 }
b4c7e601 6698 else if (TREE_CODE (arg) == COMPLEX_EXPR)
6699 {
6700 tree real = TREE_OPERAND (arg, 0);
6701 tree imag = TREE_OPERAND (arg, 1);
6702
6703 STRIP_NOPS (real);
6704 STRIP_NOPS (imag);
6705
6706 /* If the real part is inf and the imag part is known to be
6707 nonnegative, return (inf + 0i). Remember side-effects are
6708 possible in the imag part. */
6709 if (TREE_CODE (real) == REAL_CST
6710 && real_isinf (TREE_REAL_CST_PTR (real))
6711 && tree_expr_nonnegative_p (imag))
6712 return omit_one_operand_loc (loc, type,
6713 build_complex_cproj (type, false),
6714 arg);
6715
6716 /* If the imag part is inf, return (inf+I*copysign(0,imag)).
6717 Remember side-effects are possible in the real part. */
6718 if (TREE_CODE (imag) == REAL_CST
6719 && real_isinf (TREE_REAL_CST_PTR (imag)))
6720 return
6721 omit_one_operand_loc (loc, type,
6722 build_complex_cproj (type, TREE_REAL_CST_PTR
6723 (imag)->sign), arg);
6724 }
c2373fdb 6725
6726 return NULL_TREE;
6727}
6728
c2f47e15 6729/* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG.
6730 Return NULL_TREE if no simplification can be made. */
e6e27594 6731
6732static tree
389dd41b 6733fold_builtin_sqrt (location_t loc, tree arg, tree type)
e6e27594 6734{
6735
6736 enum built_in_function fcode;
b4e8ab0c 6737 tree res;
c2f47e15 6738
6739 if (!validate_arg (arg, REAL_TYPE))
e6e27594 6740 return NULL_TREE;
6741
b4e8ab0c 6742 /* Calculate the result when the argument is a constant. */
6743 if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
6744 return res;
48e1416a 6745
e6e27594 6746 /* Optimize sqrt(expN(x)) = expN(x*0.5). */
6747 fcode = builtin_mathfn_code (arg);
6748 if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
6749 {
c2f47e15 6750 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
389dd41b 6751 arg = fold_build2_loc (loc, MULT_EXPR, type,
c2f47e15 6752 CALL_EXPR_ARG (arg, 0),
49d00087 6753 build_real (type, dconsthalf));
389dd41b 6754 return build_call_expr_loc (loc, expfn, 1, arg);
e6e27594 6755 }
6756
6757 /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */
6758 if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
6759 {
6760 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
6761
6762 if (powfn)
6763 {
c2f47e15 6764 tree arg0 = CALL_EXPR_ARG (arg, 0);
e6e27594 6765 tree tree_root;
6766 /* The inner root was either sqrt or cbrt. */
57510da6 6767 /* This was a conditional expression but it triggered a bug
18381619 6768 in Sun C 5.5. */
ce6cd837 6769 REAL_VALUE_TYPE dconstroot;
6770 if (BUILTIN_SQRT_P (fcode))
6771 dconstroot = dconsthalf;
6772 else
6773 dconstroot = dconst_third ();
e6e27594 6774
6775 /* Adjust for the outer root. */
6776 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
6777 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
6778 tree_root = build_real (type, dconstroot);
389dd41b 6779 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
e6e27594 6780 }
6781 }
6782
bc33117f 6783 /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
e6e27594 6784 if (flag_unsafe_math_optimizations
6785 && (fcode == BUILT_IN_POW
6786 || fcode == BUILT_IN_POWF
6787 || fcode == BUILT_IN_POWL))
6788 {
c2f47e15 6789 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
6790 tree arg0 = CALL_EXPR_ARG (arg, 0);
6791 tree arg1 = CALL_EXPR_ARG (arg, 1);
bc33117f 6792 tree narg1;
6793 if (!tree_expr_nonnegative_p (arg0))
6794 arg0 = build1 (ABS_EXPR, type, arg0);
389dd41b 6795 narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 6796 build_real (type, dconsthalf));
389dd41b 6797 return build_call_expr_loc (loc, powfn, 2, arg0, narg1);
e6e27594 6798 }
6799
6800 return NULL_TREE;
6801}
6802
c2f47e15 6803/* Fold a builtin function call to cbrt, cbrtf, or cbrtl with argument ARG.
6804 Return NULL_TREE if no simplification can be made. */
6805
e6e27594 6806static tree
389dd41b 6807fold_builtin_cbrt (location_t loc, tree arg, tree type)
e6e27594 6808{
e6e27594 6809 const enum built_in_function fcode = builtin_mathfn_code (arg);
29f4cd78 6810 tree res;
e6e27594 6811
c2f47e15 6812 if (!validate_arg (arg, REAL_TYPE))
e6e27594 6813 return NULL_TREE;
6814
29f4cd78 6815 /* Calculate the result when the argument is a constant. */
6816 if ((res = do_mpfr_arg1 (arg, type, mpfr_cbrt, NULL, NULL, 0)))
6817 return res;
e6e27594 6818
cdfeb715 6819 if (flag_unsafe_math_optimizations)
e6e27594 6820 {
cdfeb715 6821 /* Optimize cbrt(expN(x)) -> expN(x/3). */
6822 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 6823 {
c2f47e15 6824 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 6825 const REAL_VALUE_TYPE third_trunc =
7910b2fb 6826 real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 6827 arg = fold_build2_loc (loc, MULT_EXPR, type,
c2f47e15 6828 CALL_EXPR_ARG (arg, 0),
49d00087 6829 build_real (type, third_trunc));
389dd41b 6830 return build_call_expr_loc (loc, expfn, 1, arg);
cdfeb715 6831 }
e6e27594 6832
cdfeb715 6833 /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */
6834 if (BUILTIN_SQRT_P (fcode))
a0c938f0 6835 {
cdfeb715 6836 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
e6e27594 6837
cdfeb715 6838 if (powfn)
6839 {
c2f47e15 6840 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 6841 tree tree_root;
7910b2fb 6842 REAL_VALUE_TYPE dconstroot = dconst_third ();
cdfeb715 6843
6844 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
6845 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
6846 tree_root = build_real (type, dconstroot);
389dd41b 6847 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
cdfeb715 6848 }
e6e27594 6849 }
6850
cdfeb715 6851 /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */
6852 if (BUILTIN_CBRT_P (fcode))
a0c938f0 6853 {
c2f47e15 6854 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 6855 if (tree_expr_nonnegative_p (arg0))
6856 {
6857 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
6858
6859 if (powfn)
a0c938f0 6860 {
cdfeb715 6861 tree tree_root;
6862 REAL_VALUE_TYPE dconstroot;
a0c938f0 6863
3fa759a9 6864 real_arithmetic (&dconstroot, MULT_EXPR,
7910b2fb 6865 dconst_third_ptr (), dconst_third_ptr ());
cdfeb715 6866 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
6867 tree_root = build_real (type, dconstroot);
389dd41b 6868 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
cdfeb715 6869 }
6870 }
6871 }
a0c938f0 6872
cdfeb715 6873 /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */
48e1416a 6874 if (fcode == BUILT_IN_POW
c2f47e15 6875 || fcode == BUILT_IN_POWF
cdfeb715 6876 || fcode == BUILT_IN_POWL)
a0c938f0 6877 {
c2f47e15 6878 tree arg00 = CALL_EXPR_ARG (arg, 0);
6879 tree arg01 = CALL_EXPR_ARG (arg, 1);
cdfeb715 6880 if (tree_expr_nonnegative_p (arg00))
6881 {
c2f47e15 6882 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 6883 const REAL_VALUE_TYPE dconstroot
7910b2fb 6884 = real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 6885 tree narg01 = fold_build2_loc (loc, MULT_EXPR, type, arg01,
49d00087 6886 build_real (type, dconstroot));
389dd41b 6887 return build_call_expr_loc (loc, powfn, 2, arg00, narg01);
cdfeb715 6888 }
6889 }
e6e27594 6890 }
6891 return NULL_TREE;
6892}
6893
c2f47e15 6894/* Fold function call to builtin cos, cosf, or cosl with argument ARG.
6895 TYPE is the type of the return value. Return NULL_TREE if no
6896 simplification can be made. */
6897
e6e27594 6898static tree
389dd41b 6899fold_builtin_cos (location_t loc,
6900 tree arg, tree type, tree fndecl)
e6e27594 6901{
e6ab33d8 6902 tree res, narg;
e6e27594 6903
c2f47e15 6904 if (!validate_arg (arg, REAL_TYPE))
e6e27594 6905 return NULL_TREE;
6906
bffb7645 6907 /* Calculate the result when the argument is a constant. */
728bac60 6908 if ((res = do_mpfr_arg1 (arg, type, mpfr_cos, NULL, NULL, 0)))
bffb7645 6909 return res;
48e1416a 6910
e6e27594 6911 /* Optimize cos(-x) into cos (x). */
e6ab33d8 6912 if ((narg = fold_strip_sign_ops (arg)))
389dd41b 6913 return build_call_expr_loc (loc, fndecl, 1, narg);
e6e27594 6914
6915 return NULL_TREE;
6916}
6917
c2f47e15 6918/* Fold function call to builtin cosh, coshf, or coshl with argument ARG.
6919 Return NULL_TREE if no simplification can be made. */
6920
cacdc1af 6921static tree
389dd41b 6922fold_builtin_cosh (location_t loc, tree arg, tree type, tree fndecl)
cacdc1af 6923{
c2f47e15 6924 if (validate_arg (arg, REAL_TYPE))
cacdc1af 6925 {
cacdc1af 6926 tree res, narg;
6927
6928 /* Calculate the result when the argument is a constant. */
6929 if ((res = do_mpfr_arg1 (arg, type, mpfr_cosh, NULL, NULL, 0)))
6930 return res;
48e1416a 6931
cacdc1af 6932 /* Optimize cosh(-x) into cosh (x). */
6933 if ((narg = fold_strip_sign_ops (arg)))
389dd41b 6934 return build_call_expr_loc (loc, fndecl, 1, narg);
cacdc1af 6935 }
48e1416a 6936
cacdc1af 6937 return NULL_TREE;
6938}
6939
239d491a 6940/* Fold function call to builtin ccos (or ccosh if HYPER is TRUE) with
6941 argument ARG. TYPE is the type of the return value. Return
6942 NULL_TREE if no simplification can be made. */
6943
6944static tree
965d0f29 6945fold_builtin_ccos (location_t loc, tree arg, tree type, tree fndecl,
6946 bool hyper)
239d491a 6947{
6948 if (validate_arg (arg, COMPLEX_TYPE)
6949 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
6950 {
6951 tree tmp;
6952
239d491a 6953 /* Calculate the result when the argument is a constant. */
6954 if ((tmp = do_mpc_arg1 (arg, type, (hyper ? mpc_cosh : mpc_cos))))
6955 return tmp;
48e1416a 6956
239d491a 6957 /* Optimize fn(-x) into fn(x). */
6958 if ((tmp = fold_strip_sign_ops (arg)))
389dd41b 6959 return build_call_expr_loc (loc, fndecl, 1, tmp);
239d491a 6960 }
6961
6962 return NULL_TREE;
6963}
6964
c2f47e15 6965/* Fold function call to builtin tan, tanf, or tanl with argument ARG.
6966 Return NULL_TREE if no simplification can be made. */
6967
e6e27594 6968static tree
c2f47e15 6969fold_builtin_tan (tree arg, tree type)
e6e27594 6970{
6971 enum built_in_function fcode;
29f4cd78 6972 tree res;
e6e27594 6973
c2f47e15 6974 if (!validate_arg (arg, REAL_TYPE))
e6e27594 6975 return NULL_TREE;
6976
bffb7645 6977 /* Calculate the result when the argument is a constant. */
728bac60 6978 if ((res = do_mpfr_arg1 (arg, type, mpfr_tan, NULL, NULL, 0)))
bffb7645 6979 return res;
48e1416a 6980
e6e27594 6981 /* Optimize tan(atan(x)) = x. */
6982 fcode = builtin_mathfn_code (arg);
6983 if (flag_unsafe_math_optimizations
6984 && (fcode == BUILT_IN_ATAN
6985 || fcode == BUILT_IN_ATANF
6986 || fcode == BUILT_IN_ATANL))
c2f47e15 6987 return CALL_EXPR_ARG (arg, 0);
e6e27594 6988
6989 return NULL_TREE;
6990}
6991
d735c391 6992/* Fold function call to builtin sincos, sincosf, or sincosl. Return
6993 NULL_TREE if no simplification can be made. */
6994
6995static tree
389dd41b 6996fold_builtin_sincos (location_t loc,
6997 tree arg0, tree arg1, tree arg2)
d735c391 6998{
c2f47e15 6999 tree type;
d735c391 7000 tree res, fn, call;
7001
c2f47e15 7002 if (!validate_arg (arg0, REAL_TYPE)
7003 || !validate_arg (arg1, POINTER_TYPE)
7004 || !validate_arg (arg2, POINTER_TYPE))
d735c391 7005 return NULL_TREE;
7006
d735c391 7007 type = TREE_TYPE (arg0);
d735c391 7008
7009 /* Calculate the result when the argument is a constant. */
7010 if ((res = do_mpfr_sincos (arg0, arg1, arg2)))
7011 return res;
7012
7013 /* Canonicalize sincos to cexpi. */
2a6b4c77 7014 if (!TARGET_C99_FUNCTIONS)
7015 return NULL_TREE;
d735c391 7016 fn = mathfn_built_in (type, BUILT_IN_CEXPI);
7017 if (!fn)
7018 return NULL_TREE;
7019
389dd41b 7020 call = build_call_expr_loc (loc, fn, 1, arg0);
d735c391 7021 call = builtin_save_expr (call);
7022
a75b1c71 7023 return build2 (COMPOUND_EXPR, void_type_node,
d735c391 7024 build2 (MODIFY_EXPR, void_type_node,
389dd41b 7025 build_fold_indirect_ref_loc (loc, arg1),
d735c391 7026 build1 (IMAGPART_EXPR, type, call)),
7027 build2 (MODIFY_EXPR, void_type_node,
389dd41b 7028 build_fold_indirect_ref_loc (loc, arg2),
d735c391 7029 build1 (REALPART_EXPR, type, call)));
7030}
7031
c5bb2c4b 7032/* Fold function call to builtin cexp, cexpf, or cexpl. Return
7033 NULL_TREE if no simplification can be made. */
7034
7035static tree
389dd41b 7036fold_builtin_cexp (location_t loc, tree arg0, tree type)
c5bb2c4b 7037{
c2f47e15 7038 tree rtype;
c5bb2c4b 7039 tree realp, imagp, ifn;
239d491a 7040 tree res;
c5bb2c4b 7041
239d491a 7042 if (!validate_arg (arg0, COMPLEX_TYPE)
b0ce8887 7043 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) != REAL_TYPE)
c5bb2c4b 7044 return NULL_TREE;
7045
239d491a 7046 /* Calculate the result when the argument is a constant. */
7047 if ((res = do_mpc_arg1 (arg0, type, mpc_exp)))
7048 return res;
48e1416a 7049
c5bb2c4b 7050 rtype = TREE_TYPE (TREE_TYPE (arg0));
7051
7052 /* In case we can figure out the real part of arg0 and it is constant zero
7053 fold to cexpi. */
2a6b4c77 7054 if (!TARGET_C99_FUNCTIONS)
7055 return NULL_TREE;
c5bb2c4b 7056 ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI);
7057 if (!ifn)
7058 return NULL_TREE;
7059
389dd41b 7060 if ((realp = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0))
c5bb2c4b 7061 && real_zerop (realp))
7062 {
389dd41b 7063 tree narg = fold_build1_loc (loc, IMAGPART_EXPR, rtype, arg0);
7064 return build_call_expr_loc (loc, ifn, 1, narg);
c5bb2c4b 7065 }
7066
7067 /* In case we can easily decompose real and imaginary parts split cexp
7068 to exp (r) * cexpi (i). */
7069 if (flag_unsafe_math_optimizations
7070 && realp)
7071 {
7072 tree rfn, rcall, icall;
7073
7074 rfn = mathfn_built_in (rtype, BUILT_IN_EXP);
7075 if (!rfn)
7076 return NULL_TREE;
7077
389dd41b 7078 imagp = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
c5bb2c4b 7079 if (!imagp)
7080 return NULL_TREE;
7081
389dd41b 7082 icall = build_call_expr_loc (loc, ifn, 1, imagp);
c5bb2c4b 7083 icall = builtin_save_expr (icall);
389dd41b 7084 rcall = build_call_expr_loc (loc, rfn, 1, realp);
c5bb2c4b 7085 rcall = builtin_save_expr (rcall);
389dd41b 7086 return fold_build2_loc (loc, COMPLEX_EXPR, type,
7087 fold_build2_loc (loc, MULT_EXPR, rtype,
71bf42bb 7088 rcall,
389dd41b 7089 fold_build1_loc (loc, REALPART_EXPR,
7090 rtype, icall)),
7091 fold_build2_loc (loc, MULT_EXPR, rtype,
71bf42bb 7092 rcall,
389dd41b 7093 fold_build1_loc (loc, IMAGPART_EXPR,
7094 rtype, icall)));
c5bb2c4b 7095 }
7096
7097 return NULL_TREE;
7098}
7099
c2f47e15 7100/* Fold function call to builtin trunc, truncf or truncl with argument ARG.
7101 Return NULL_TREE if no simplification can be made. */
277f8dd2 7102
7103static tree
389dd41b 7104fold_builtin_trunc (location_t loc, tree fndecl, tree arg)
277f8dd2 7105{
c2f47e15 7106 if (!validate_arg (arg, REAL_TYPE))
7107 return NULL_TREE;
277f8dd2 7108
7109 /* Optimize trunc of constant value. */
f96bd2bf 7110 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7111 {
7112 REAL_VALUE_TYPE r, x;
2426241c 7113 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7114
7115 x = TREE_REAL_CST (arg);
7116 real_trunc (&r, TYPE_MODE (type), &x);
7117 return build_real (type, r);
7118 }
7119
389dd41b 7120 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7121}
7122
c2f47e15 7123/* Fold function call to builtin floor, floorf or floorl with argument ARG.
7124 Return NULL_TREE if no simplification can be made. */
277f8dd2 7125
7126static tree
389dd41b 7127fold_builtin_floor (location_t loc, tree fndecl, tree arg)
277f8dd2 7128{
c2f47e15 7129 if (!validate_arg (arg, REAL_TYPE))
7130 return NULL_TREE;
277f8dd2 7131
7132 /* Optimize floor of constant value. */
f96bd2bf 7133 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7134 {
7135 REAL_VALUE_TYPE x;
7136
7137 x = TREE_REAL_CST (arg);
7138 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7139 {
2426241c 7140 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7141 REAL_VALUE_TYPE r;
7142
7143 real_floor (&r, TYPE_MODE (type), &x);
7144 return build_real (type, r);
7145 }
7146 }
7147
acc2b92e 7148 /* Fold floor (x) where x is nonnegative to trunc (x). */
7149 if (tree_expr_nonnegative_p (arg))
30fe8286 7150 {
7151 tree truncfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_TRUNC);
7152 if (truncfn)
389dd41b 7153 return build_call_expr_loc (loc, truncfn, 1, arg);
30fe8286 7154 }
acc2b92e 7155
389dd41b 7156 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7157}
7158
c2f47e15 7159/* Fold function call to builtin ceil, ceilf or ceill with argument ARG.
7160 Return NULL_TREE if no simplification can be made. */
277f8dd2 7161
7162static tree
389dd41b 7163fold_builtin_ceil (location_t loc, tree fndecl, tree arg)
277f8dd2 7164{
c2f47e15 7165 if (!validate_arg (arg, REAL_TYPE))
7166 return NULL_TREE;
277f8dd2 7167
7168 /* Optimize ceil of constant value. */
f96bd2bf 7169 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7170 {
7171 REAL_VALUE_TYPE x;
7172
7173 x = TREE_REAL_CST (arg);
7174 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7175 {
2426241c 7176 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7177 REAL_VALUE_TYPE r;
7178
7179 real_ceil (&r, TYPE_MODE (type), &x);
7180 return build_real (type, r);
7181 }
7182 }
7183
389dd41b 7184 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7185}
7186
c2f47e15 7187/* Fold function call to builtin round, roundf or roundl with argument ARG.
7188 Return NULL_TREE if no simplification can be made. */
89ab3887 7189
7190static tree
389dd41b 7191fold_builtin_round (location_t loc, tree fndecl, tree arg)
89ab3887 7192{
c2f47e15 7193 if (!validate_arg (arg, REAL_TYPE))
7194 return NULL_TREE;
89ab3887 7195
34f17811 7196 /* Optimize round of constant value. */
f96bd2bf 7197 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
89ab3887 7198 {
7199 REAL_VALUE_TYPE x;
7200
7201 x = TREE_REAL_CST (arg);
7202 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7203 {
2426241c 7204 tree type = TREE_TYPE (TREE_TYPE (fndecl));
89ab3887 7205 REAL_VALUE_TYPE r;
7206
7207 real_round (&r, TYPE_MODE (type), &x);
7208 return build_real (type, r);
7209 }
7210 }
7211
389dd41b 7212 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
89ab3887 7213}
7214
34f17811 7215/* Fold function call to builtin lround, lroundf or lroundl (or the
c2f47e15 7216 corresponding long long versions) and other rounding functions. ARG
7217 is the argument to the call. Return NULL_TREE if no simplification
7218 can be made. */
34f17811 7219
7220static tree
389dd41b 7221fold_builtin_int_roundingfn (location_t loc, tree fndecl, tree arg)
34f17811 7222{
c2f47e15 7223 if (!validate_arg (arg, REAL_TYPE))
7224 return NULL_TREE;
34f17811 7225
7226 /* Optimize lround of constant value. */
f96bd2bf 7227 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
34f17811 7228 {
7229 const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
7230
776a7bab 7231 if (real_isfinite (&x))
34f17811 7232 {
2426241c 7233 tree itype = TREE_TYPE (TREE_TYPE (fndecl));
ca9b061d 7234 tree ftype = TREE_TYPE (arg);
a6caa15f 7235 double_int val;
34f17811 7236 REAL_VALUE_TYPE r;
7237
ad52b9b7 7238 switch (DECL_FUNCTION_CODE (fndecl))
7239 {
4f35b1fc 7240 CASE_FLT_FN (BUILT_IN_LFLOOR):
7241 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 7242 real_floor (&r, TYPE_MODE (ftype), &x);
7243 break;
7244
4f35b1fc 7245 CASE_FLT_FN (BUILT_IN_LCEIL):
7246 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 7247 real_ceil (&r, TYPE_MODE (ftype), &x);
7248 break;
7249
4f35b1fc 7250 CASE_FLT_FN (BUILT_IN_LROUND):
7251 CASE_FLT_FN (BUILT_IN_LLROUND):
ad52b9b7 7252 real_round (&r, TYPE_MODE (ftype), &x);
7253 break;
7254
7255 default:
7256 gcc_unreachable ();
7257 }
7258
a6caa15f 7259 real_to_integer2 ((HOST_WIDE_INT *)&val.low, &val.high, &r);
7260 if (double_int_fits_to_tree_p (itype, val))
7261 return double_int_to_tree (itype, val);
34f17811 7262 }
7263 }
7264
acc2b92e 7265 switch (DECL_FUNCTION_CODE (fndecl))
7266 {
7267 CASE_FLT_FN (BUILT_IN_LFLOOR):
7268 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7269 /* Fold lfloor (x) where x is nonnegative to FIX_TRUNC (x). */
7270 if (tree_expr_nonnegative_p (arg))
389dd41b 7271 return fold_build1_loc (loc, FIX_TRUNC_EXPR,
7272 TREE_TYPE (TREE_TYPE (fndecl)), arg);
acc2b92e 7273 break;
7274 default:;
7275 }
7276
389dd41b 7277 return fold_fixed_mathfn (loc, fndecl, arg);
34f17811 7278}
7279
70fb4c07 7280/* Fold function call to builtin ffs, clz, ctz, popcount and parity
c2f47e15 7281 and their long and long long variants (i.e. ffsl and ffsll). ARG is
7282 the argument to the call. Return NULL_TREE if no simplification can
7283 be made. */
70fb4c07 7284
7285static tree
c2f47e15 7286fold_builtin_bitop (tree fndecl, tree arg)
70fb4c07 7287{
c2f47e15 7288 if (!validate_arg (arg, INTEGER_TYPE))
70fb4c07 7289 return NULL_TREE;
7290
7291 /* Optimize for constant argument. */
f96bd2bf 7292 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
70fb4c07 7293 {
7294 HOST_WIDE_INT hi, width, result;
7295 unsigned HOST_WIDE_INT lo;
7c446c95 7296 tree type;
70fb4c07 7297
7298 type = TREE_TYPE (arg);
7299 width = TYPE_PRECISION (type);
7300 lo = TREE_INT_CST_LOW (arg);
7301
7302 /* Clear all the bits that are beyond the type's precision. */
7303 if (width > HOST_BITS_PER_WIDE_INT)
7304 {
7305 hi = TREE_INT_CST_HIGH (arg);
7306 if (width < 2 * HOST_BITS_PER_WIDE_INT)
6aaa1f9e 7307 hi &= ~((unsigned HOST_WIDE_INT) (-1)
7308 << (width - HOST_BITS_PER_WIDE_INT));
70fb4c07 7309 }
7310 else
7311 {
7312 hi = 0;
7313 if (width < HOST_BITS_PER_WIDE_INT)
7314 lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
7315 }
7316
7317 switch (DECL_FUNCTION_CODE (fndecl))
7318 {
4f35b1fc 7319 CASE_INT_FN (BUILT_IN_FFS):
70fb4c07 7320 if (lo != 0)
7e8d812e 7321 result = ffs_hwi (lo);
70fb4c07 7322 else if (hi != 0)
7e8d812e 7323 result = HOST_BITS_PER_WIDE_INT + ffs_hwi (hi);
70fb4c07 7324 else
7325 result = 0;
7326 break;
7327
4f35b1fc 7328 CASE_INT_FN (BUILT_IN_CLZ):
70fb4c07 7329 if (hi != 0)
7330 result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
7331 else if (lo != 0)
7332 result = width - floor_log2 (lo) - 1;
7333 else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
7334 result = width;
7335 break;
7336
4f35b1fc 7337 CASE_INT_FN (BUILT_IN_CTZ):
70fb4c07 7338 if (lo != 0)
7e8d812e 7339 result = ctz_hwi (lo);
70fb4c07 7340 else if (hi != 0)
7e8d812e 7341 result = HOST_BITS_PER_WIDE_INT + ctz_hwi (hi);
70fb4c07 7342 else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
7343 result = width;
7344 break;
7345
6aaa1f9e 7346 CASE_INT_FN (BUILT_IN_CLRSB):
7347 if (width > HOST_BITS_PER_WIDE_INT
7348 && (hi & ((unsigned HOST_WIDE_INT) 1
7349 << (width - HOST_BITS_PER_WIDE_INT - 1))) != 0)
7350 {
7351 hi = ~hi & ~((unsigned HOST_WIDE_INT) (-1)
7352 << (width - HOST_BITS_PER_WIDE_INT - 1));
7353 lo = ~lo;
7354 }
7355 else if (width <= HOST_BITS_PER_WIDE_INT
7356 && (lo & ((unsigned HOST_WIDE_INT) 1 << (width - 1))) != 0)
7357 lo = ~lo & ~((unsigned HOST_WIDE_INT) (-1) << (width - 1));
7358 if (hi != 0)
7359 result = width - floor_log2 (hi) - 2 - HOST_BITS_PER_WIDE_INT;
7360 else if (lo != 0)
7361 result = width - floor_log2 (lo) - 2;
7362 else
7363 result = width - 1;
7364 break;
7365
4f35b1fc 7366 CASE_INT_FN (BUILT_IN_POPCOUNT):
70fb4c07 7367 result = 0;
7368 while (lo)
7369 result++, lo &= lo - 1;
7370 while (hi)
7e8d812e 7371 result++, hi &= (unsigned HOST_WIDE_INT) hi - 1;
70fb4c07 7372 break;
7373
4f35b1fc 7374 CASE_INT_FN (BUILT_IN_PARITY):
70fb4c07 7375 result = 0;
7376 while (lo)
7377 result++, lo &= lo - 1;
7378 while (hi)
7e8d812e 7379 result++, hi &= (unsigned HOST_WIDE_INT) hi - 1;
70fb4c07 7380 result &= 1;
7381 break;
7382
7383 default:
64db345d 7384 gcc_unreachable ();
70fb4c07 7385 }
7386
2426241c 7387 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
70fb4c07 7388 }
7389
7390 return NULL_TREE;
7391}
7392
42791117 7393/* Fold function call to builtin_bswap and the long and long long
7394 variants. Return NULL_TREE if no simplification can be made. */
7395static tree
c2f47e15 7396fold_builtin_bswap (tree fndecl, tree arg)
42791117 7397{
c2f47e15 7398 if (! validate_arg (arg, INTEGER_TYPE))
7399 return NULL_TREE;
42791117 7400
7401 /* Optimize constant value. */
f96bd2bf 7402 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
42791117 7403 {
7404 HOST_WIDE_INT hi, width, r_hi = 0;
7405 unsigned HOST_WIDE_INT lo, r_lo = 0;
7406 tree type;
7407
7408 type = TREE_TYPE (arg);
7409 width = TYPE_PRECISION (type);
7410 lo = TREE_INT_CST_LOW (arg);
7411 hi = TREE_INT_CST_HIGH (arg);
7412
7413 switch (DECL_FUNCTION_CODE (fndecl))
7414 {
7415 case BUILT_IN_BSWAP32:
7416 case BUILT_IN_BSWAP64:
7417 {
7418 int s;
7419
7420 for (s = 0; s < width; s += 8)
7421 {
7422 int d = width - s - 8;
7423 unsigned HOST_WIDE_INT byte;
7424
7425 if (s < HOST_BITS_PER_WIDE_INT)
7426 byte = (lo >> s) & 0xff;
7427 else
7428 byte = (hi >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff;
7429
7430 if (d < HOST_BITS_PER_WIDE_INT)
7431 r_lo |= byte << d;
7432 else
7433 r_hi |= byte << (d - HOST_BITS_PER_WIDE_INT);
7434 }
7435 }
7436
7437 break;
7438
7439 default:
7440 gcc_unreachable ();
7441 }
7442
7443 if (width < HOST_BITS_PER_WIDE_INT)
7444 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), r_lo);
7445 else
7446 return build_int_cst_wide (TREE_TYPE (TREE_TYPE (fndecl)), r_lo, r_hi);
7447 }
7448
7449 return NULL_TREE;
7450}
c2f47e15 7451
8918c507 7452/* A subroutine of fold_builtin to fold the various logarithmic
29f4cd78 7453 functions. Return NULL_TREE if no simplification can me made.
7454 FUNC is the corresponding MPFR logarithm function. */
8918c507 7455
7456static tree
389dd41b 7457fold_builtin_logarithm (location_t loc, tree fndecl, tree arg,
29f4cd78 7458 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 7459{
c2f47e15 7460 if (validate_arg (arg, REAL_TYPE))
8918c507 7461 {
8918c507 7462 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 7463 tree res;
8918c507 7464 const enum built_in_function fcode = builtin_mathfn_code (arg);
0862b7e9 7465
29f4cd78 7466 /* Calculate the result when the argument is a constant. */
7467 if ((res = do_mpfr_arg1 (arg, type, func, &dconst0, NULL, false)))
7468 return res;
7469
8918c507 7470 /* Special case, optimize logN(expN(x)) = x. */
7471 if (flag_unsafe_math_optimizations
29f4cd78 7472 && ((func == mpfr_log
8918c507 7473 && (fcode == BUILT_IN_EXP
7474 || fcode == BUILT_IN_EXPF
7475 || fcode == BUILT_IN_EXPL))
29f4cd78 7476 || (func == mpfr_log2
8918c507 7477 && (fcode == BUILT_IN_EXP2
7478 || fcode == BUILT_IN_EXP2F
7479 || fcode == BUILT_IN_EXP2L))
29f4cd78 7480 || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode)))))
389dd41b 7481 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
8918c507 7482
ca273d4a 7483 /* Optimize logN(func()) for various exponential functions. We
a0c938f0 7484 want to determine the value "x" and the power "exponent" in
7485 order to transform logN(x**exponent) into exponent*logN(x). */
8918c507 7486 if (flag_unsafe_math_optimizations)
a0c938f0 7487 {
8918c507 7488 tree exponent = 0, x = 0;
0862b7e9 7489
8918c507 7490 switch (fcode)
7491 {
4f35b1fc 7492 CASE_FLT_FN (BUILT_IN_EXP):
8918c507 7493 /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
48e1416a 7494 x = build_real (type, real_value_truncate (TYPE_MODE (type),
7910b2fb 7495 dconst_e ()));
c2f47e15 7496 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 7497 break;
4f35b1fc 7498 CASE_FLT_FN (BUILT_IN_EXP2):
8918c507 7499 /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */
7500 x = build_real (type, dconst2);
c2f47e15 7501 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 7502 break;
4f35b1fc 7503 CASE_FLT_FN (BUILT_IN_EXP10):
7504 CASE_FLT_FN (BUILT_IN_POW10):
8918c507 7505 /* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */
3fa759a9 7506 {
7507 REAL_VALUE_TYPE dconst10;
7508 real_from_integer (&dconst10, VOIDmode, 10, 0, 0);
7509 x = build_real (type, dconst10);
7510 }
c2f47e15 7511 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 7512 break;
4f35b1fc 7513 CASE_FLT_FN (BUILT_IN_SQRT):
8918c507 7514 /* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */
c2f47e15 7515 x = CALL_EXPR_ARG (arg, 0);
8918c507 7516 exponent = build_real (type, dconsthalf);
7517 break;
4f35b1fc 7518 CASE_FLT_FN (BUILT_IN_CBRT):
8918c507 7519 /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */
c2f47e15 7520 x = CALL_EXPR_ARG (arg, 0);
8918c507 7521 exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
7910b2fb 7522 dconst_third ()));
8918c507 7523 break;
4f35b1fc 7524 CASE_FLT_FN (BUILT_IN_POW):
8918c507 7525 /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x). */
c2f47e15 7526 x = CALL_EXPR_ARG (arg, 0);
7527 exponent = CALL_EXPR_ARG (arg, 1);
8918c507 7528 break;
7529 default:
7530 break;
7531 }
7532
7533 /* Now perform the optimization. */
7534 if (x && exponent)
7535 {
389dd41b 7536 tree logfn = build_call_expr_loc (loc, fndecl, 1, x);
7537 return fold_build2_loc (loc, MULT_EXPR, type, exponent, logfn);
8918c507 7538 }
7539 }
7540 }
7541
c2f47e15 7542 return NULL_TREE;
8918c507 7543}
0862b7e9 7544
f0c477f2 7545/* Fold a builtin function call to hypot, hypotf, or hypotl. Return
7546 NULL_TREE if no simplification can be made. */
7547
7548static tree
389dd41b 7549fold_builtin_hypot (location_t loc, tree fndecl,
7550 tree arg0, tree arg1, tree type)
f0c477f2 7551{
e6ab33d8 7552 tree res, narg0, narg1;
f0c477f2 7553
c2f47e15 7554 if (!validate_arg (arg0, REAL_TYPE)
7555 || !validate_arg (arg1, REAL_TYPE))
f0c477f2 7556 return NULL_TREE;
7557
7558 /* Calculate the result when the argument is a constant. */
7559 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot)))
7560 return res;
48e1416a 7561
6c95f21c 7562 /* If either argument to hypot has a negate or abs, strip that off.
7563 E.g. hypot(-x,fabs(y)) -> hypot(x,y). */
e6ab33d8 7564 narg0 = fold_strip_sign_ops (arg0);
7565 narg1 = fold_strip_sign_ops (arg1);
7566 if (narg0 || narg1)
7567 {
48e1416a 7568 return build_call_expr_loc (loc, fndecl, 2, narg0 ? narg0 : arg0,
c2f47e15 7569 narg1 ? narg1 : arg1);
6c95f21c 7570 }
48e1416a 7571
f0c477f2 7572 /* If either argument is zero, hypot is fabs of the other. */
7573 if (real_zerop (arg0))
389dd41b 7574 return fold_build1_loc (loc, ABS_EXPR, type, arg1);
f0c477f2 7575 else if (real_zerop (arg1))
389dd41b 7576 return fold_build1_loc (loc, ABS_EXPR, type, arg0);
48e1416a 7577
6c95f21c 7578 /* hypot(x,x) -> fabs(x)*sqrt(2). */
7579 if (flag_unsafe_math_optimizations
7580 && operand_equal_p (arg0, arg1, OEP_PURE_SAME))
f0c477f2 7581 {
2e7ca27b 7582 const REAL_VALUE_TYPE sqrt2_trunc
7910b2fb 7583 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
389dd41b 7584 return fold_build2_loc (loc, MULT_EXPR, type,
7585 fold_build1_loc (loc, ABS_EXPR, type, arg0),
2e7ca27b 7586 build_real (type, sqrt2_trunc));
f0c477f2 7587 }
7588
f0c477f2 7589 return NULL_TREE;
7590}
7591
7592
e6e27594 7593/* Fold a builtin function call to pow, powf, or powl. Return
7594 NULL_TREE if no simplification can be made. */
7595static tree
389dd41b 7596fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
e6e27594 7597{
f0c477f2 7598 tree res;
e6e27594 7599
c2f47e15 7600 if (!validate_arg (arg0, REAL_TYPE)
7601 || !validate_arg (arg1, REAL_TYPE))
e6e27594 7602 return NULL_TREE;
7603
f0c477f2 7604 /* Calculate the result when the argument is a constant. */
7605 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_pow)))
7606 return res;
7607
e6e27594 7608 /* Optimize pow(1.0,y) = 1.0. */
7609 if (real_onep (arg0))
389dd41b 7610 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
e6e27594 7611
7612 if (TREE_CODE (arg1) == REAL_CST
f96bd2bf 7613 && !TREE_OVERFLOW (arg1))
e6e27594 7614 {
198d9bbe 7615 REAL_VALUE_TYPE cint;
e6e27594 7616 REAL_VALUE_TYPE c;
198d9bbe 7617 HOST_WIDE_INT n;
7618
e6e27594 7619 c = TREE_REAL_CST (arg1);
7620
7621 /* Optimize pow(x,0.0) = 1.0. */
7622 if (REAL_VALUES_EQUAL (c, dconst0))
389dd41b 7623 return omit_one_operand_loc (loc, type, build_real (type, dconst1),
e6e27594 7624 arg0);
7625
7626 /* Optimize pow(x,1.0) = x. */
7627 if (REAL_VALUES_EQUAL (c, dconst1))
7628 return arg0;
7629
7630 /* Optimize pow(x,-1.0) = 1.0/x. */
7631 if (REAL_VALUES_EQUAL (c, dconstm1))
389dd41b 7632 return fold_build2_loc (loc, RDIV_EXPR, type,
49d00087 7633 build_real (type, dconst1), arg0);
e6e27594 7634
7635 /* Optimize pow(x,0.5) = sqrt(x). */
7636 if (flag_unsafe_math_optimizations
7637 && REAL_VALUES_EQUAL (c, dconsthalf))
7638 {
7639 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
7640
7641 if (sqrtfn != NULL_TREE)
389dd41b 7642 return build_call_expr_loc (loc, sqrtfn, 1, arg0);
e6e27594 7643 }
7644
feb5b3eb 7645 /* Optimize pow(x,1.0/3.0) = cbrt(x). */
7646 if (flag_unsafe_math_optimizations)
7647 {
7648 const REAL_VALUE_TYPE dconstroot
7910b2fb 7649 = real_value_truncate (TYPE_MODE (type), dconst_third ());
feb5b3eb 7650
7651 if (REAL_VALUES_EQUAL (c, dconstroot))
7652 {
7653 tree cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT);
7654 if (cbrtfn != NULL_TREE)
389dd41b 7655 return build_call_expr_loc (loc, cbrtfn, 1, arg0);
feb5b3eb 7656 }
7657 }
7658
198d9bbe 7659 /* Check for an integer exponent. */
7660 n = real_to_integer (&c);
7661 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
7662 if (real_identical (&c, &cint))
e6e27594 7663 {
a2b30b48 7664 /* Attempt to evaluate pow at compile-time, unless this should
7665 raise an exception. */
198d9bbe 7666 if (TREE_CODE (arg0) == REAL_CST
a2b30b48 7667 && !TREE_OVERFLOW (arg0)
7668 && (n > 0
7669 || (!flag_trapping_math && !flag_errno_math)
7670 || !REAL_VALUES_EQUAL (TREE_REAL_CST (arg0), dconst0)))
e6e27594 7671 {
7672 REAL_VALUE_TYPE x;
7673 bool inexact;
7674
7675 x = TREE_REAL_CST (arg0);
7676 inexact = real_powi (&x, TYPE_MODE (type), &x, n);
7677 if (flag_unsafe_math_optimizations || !inexact)
7678 return build_real (type, x);
7679 }
198d9bbe 7680
7681 /* Strip sign ops from even integer powers. */
7682 if ((n & 1) == 0 && flag_unsafe_math_optimizations)
7683 {
7684 tree narg0 = fold_strip_sign_ops (arg0);
7685 if (narg0)
389dd41b 7686 return build_call_expr_loc (loc, fndecl, 2, narg0, arg1);
198d9bbe 7687 }
e6e27594 7688 }
7689 }
7690
cdfeb715 7691 if (flag_unsafe_math_optimizations)
e6e27594 7692 {
cdfeb715 7693 const enum built_in_function fcode = builtin_mathfn_code (arg0);
e6e27594 7694
cdfeb715 7695 /* Optimize pow(expN(x),y) = expN(x*y). */
7696 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 7697 {
c2f47e15 7698 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
7699 tree arg = CALL_EXPR_ARG (arg0, 0);
389dd41b 7700 arg = fold_build2_loc (loc, MULT_EXPR, type, arg, arg1);
7701 return build_call_expr_loc (loc, expfn, 1, arg);
cdfeb715 7702 }
e6e27594 7703
cdfeb715 7704 /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
7705 if (BUILTIN_SQRT_P (fcode))
a0c938f0 7706 {
c2f47e15 7707 tree narg0 = CALL_EXPR_ARG (arg0, 0);
389dd41b 7708 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 7709 build_real (type, dconsthalf));
389dd41b 7710 return build_call_expr_loc (loc, fndecl, 2, narg0, narg1);
cdfeb715 7711 }
7712
7713 /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */
7714 if (BUILTIN_CBRT_P (fcode))
a0c938f0 7715 {
c2f47e15 7716 tree arg = CALL_EXPR_ARG (arg0, 0);
cdfeb715 7717 if (tree_expr_nonnegative_p (arg))
7718 {
7719 const REAL_VALUE_TYPE dconstroot
7910b2fb 7720 = real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 7721 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 7722 build_real (type, dconstroot));
389dd41b 7723 return build_call_expr_loc (loc, fndecl, 2, arg, narg1);
cdfeb715 7724 }
7725 }
a0c938f0 7726
49e436b5 7727 /* Optimize pow(pow(x,y),z) = pow(x,y*z) iff x is nonnegative. */
c2f47e15 7728 if (fcode == BUILT_IN_POW
7729 || fcode == BUILT_IN_POWF
7730 || fcode == BUILT_IN_POWL)
a0c938f0 7731 {
c2f47e15 7732 tree arg00 = CALL_EXPR_ARG (arg0, 0);
49e436b5 7733 if (tree_expr_nonnegative_p (arg00))
7734 {
7735 tree arg01 = CALL_EXPR_ARG (arg0, 1);
7736 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg01, arg1);
7737 return build_call_expr_loc (loc, fndecl, 2, arg00, narg1);
7738 }
cdfeb715 7739 }
e6e27594 7740 }
cdfeb715 7741
e6e27594 7742 return NULL_TREE;
7743}
7744
c2f47e15 7745/* Fold a builtin function call to powi, powif, or powil with argument ARG.
7746 Return NULL_TREE if no simplification can be made. */
b4d0c20c 7747static tree
389dd41b 7748fold_builtin_powi (location_t loc, tree fndecl ATTRIBUTE_UNUSED,
c2f47e15 7749 tree arg0, tree arg1, tree type)
b4d0c20c 7750{
c2f47e15 7751 if (!validate_arg (arg0, REAL_TYPE)
7752 || !validate_arg (arg1, INTEGER_TYPE))
b4d0c20c 7753 return NULL_TREE;
7754
7755 /* Optimize pow(1.0,y) = 1.0. */
7756 if (real_onep (arg0))
389dd41b 7757 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
b4d0c20c 7758
7759 if (host_integerp (arg1, 0))
7760 {
7761 HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
7762
7763 /* Evaluate powi at compile-time. */
7764 if (TREE_CODE (arg0) == REAL_CST
f96bd2bf 7765 && !TREE_OVERFLOW (arg0))
b4d0c20c 7766 {
7767 REAL_VALUE_TYPE x;
7768 x = TREE_REAL_CST (arg0);
7769 real_powi (&x, TYPE_MODE (type), &x, c);
7770 return build_real (type, x);
7771 }
7772
7773 /* Optimize pow(x,0) = 1.0. */
7774 if (c == 0)
389dd41b 7775 return omit_one_operand_loc (loc, type, build_real (type, dconst1),
b4d0c20c 7776 arg0);
7777
7778 /* Optimize pow(x,1) = x. */
7779 if (c == 1)
7780 return arg0;
7781
7782 /* Optimize pow(x,-1) = 1.0/x. */
7783 if (c == -1)
389dd41b 7784 return fold_build2_loc (loc, RDIV_EXPR, type,
49d00087 7785 build_real (type, dconst1), arg0);
b4d0c20c 7786 }
7787
7788 return NULL_TREE;
7789}
7790
8918c507 7791/* A subroutine of fold_builtin to fold the various exponent
c2f47e15 7792 functions. Return NULL_TREE if no simplification can be made.
debf9994 7793 FUNC is the corresponding MPFR exponent function. */
8918c507 7794
7795static tree
389dd41b 7796fold_builtin_exponent (location_t loc, tree fndecl, tree arg,
debf9994 7797 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 7798{
c2f47e15 7799 if (validate_arg (arg, REAL_TYPE))
8918c507 7800 {
8918c507 7801 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 7802 tree res;
48e1416a 7803
debf9994 7804 /* Calculate the result when the argument is a constant. */
728bac60 7805 if ((res = do_mpfr_arg1 (arg, type, func, NULL, NULL, 0)))
debf9994 7806 return res;
8918c507 7807
7808 /* Optimize expN(logN(x)) = x. */
7809 if (flag_unsafe_math_optimizations)
a0c938f0 7810 {
8918c507 7811 const enum built_in_function fcode = builtin_mathfn_code (arg);
7812
debf9994 7813 if ((func == mpfr_exp
8918c507 7814 && (fcode == BUILT_IN_LOG
7815 || fcode == BUILT_IN_LOGF
7816 || fcode == BUILT_IN_LOGL))
debf9994 7817 || (func == mpfr_exp2
8918c507 7818 && (fcode == BUILT_IN_LOG2
7819 || fcode == BUILT_IN_LOG2F
7820 || fcode == BUILT_IN_LOG2L))
debf9994 7821 || (func == mpfr_exp10
8918c507 7822 && (fcode == BUILT_IN_LOG10
7823 || fcode == BUILT_IN_LOG10F
7824 || fcode == BUILT_IN_LOG10L)))
389dd41b 7825 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
8918c507 7826 }
7827 }
7828
c2f47e15 7829 return NULL_TREE;
8918c507 7830}
7831
e973ffcc 7832/* Return true if VAR is a VAR_DECL or a component thereof. */
7833
7834static bool
7835var_decl_component_p (tree var)
7836{
7837 tree inner = var;
7838 while (handled_component_p (inner))
7839 inner = TREE_OPERAND (inner, 0);
7840 return SSA_VAR_P (inner);
7841}
7842
4f46f2b9 7843/* Fold function call to builtin memset. Return
9c8a1629 7844 NULL_TREE if no simplification can be made. */
7845
7846static tree
389dd41b 7847fold_builtin_memset (location_t loc, tree dest, tree c, tree len,
7848 tree type, bool ignore)
9c8a1629 7849{
45bb3afb 7850 tree var, ret, etype;
4f46f2b9 7851 unsigned HOST_WIDE_INT length, cval;
9c8a1629 7852
c2f47e15 7853 if (! validate_arg (dest, POINTER_TYPE)
7854 || ! validate_arg (c, INTEGER_TYPE)
7855 || ! validate_arg (len, INTEGER_TYPE))
7856 return NULL_TREE;
9c8a1629 7857
4f46f2b9 7858 if (! host_integerp (len, 1))
c2f47e15 7859 return NULL_TREE;
4f46f2b9 7860
9c8a1629 7861 /* If the LEN parameter is zero, return DEST. */
7862 if (integer_zerop (len))
389dd41b 7863 return omit_one_operand_loc (loc, type, dest, c);
9c8a1629 7864
d5d2f74a 7865 if (TREE_CODE (c) != INTEGER_CST || TREE_SIDE_EFFECTS (dest))
c2f47e15 7866 return NULL_TREE;
9c8a1629 7867
4f46f2b9 7868 var = dest;
7869 STRIP_NOPS (var);
7870 if (TREE_CODE (var) != ADDR_EXPR)
c2f47e15 7871 return NULL_TREE;
4f46f2b9 7872
7873 var = TREE_OPERAND (var, 0);
7874 if (TREE_THIS_VOLATILE (var))
c2f47e15 7875 return NULL_TREE;
4f46f2b9 7876
45bb3afb 7877 etype = TREE_TYPE (var);
7878 if (TREE_CODE (etype) == ARRAY_TYPE)
7879 etype = TREE_TYPE (etype);
7880
7881 if (!INTEGRAL_TYPE_P (etype)
7882 && !POINTER_TYPE_P (etype))
c2f47e15 7883 return NULL_TREE;
4f46f2b9 7884
e973ffcc 7885 if (! var_decl_component_p (var))
c2f47e15 7886 return NULL_TREE;
e973ffcc 7887
4f46f2b9 7888 length = tree_low_cst (len, 1);
45bb3afb 7889 if (GET_MODE_SIZE (TYPE_MODE (etype)) != length
4f46f2b9 7890 || get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
153c3b50 7891 < length)
c2f47e15 7892 return NULL_TREE;
4f46f2b9 7893
7894 if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT)
c2f47e15 7895 return NULL_TREE;
4f46f2b9 7896
7897 if (integer_zerop (c))
7898 cval = 0;
7899 else
7900 {
7901 if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64)
c2f47e15 7902 return NULL_TREE;
4f46f2b9 7903
d5d2f74a 7904 cval = TREE_INT_CST_LOW (c);
4f46f2b9 7905 cval &= 0xff;
7906 cval |= cval << 8;
7907 cval |= cval << 16;
7908 cval |= (cval << 31) << 1;
7909 }
7910
45bb3afb 7911 ret = build_int_cst_type (etype, cval);
389dd41b 7912 var = build_fold_indirect_ref_loc (loc,
7913 fold_convert_loc (loc,
7914 build_pointer_type (etype),
7915 dest));
45bb3afb 7916 ret = build2 (MODIFY_EXPR, etype, var, ret);
4f46f2b9 7917 if (ignore)
7918 return ret;
7919
389dd41b 7920 return omit_one_operand_loc (loc, type, dest, ret);
9c8a1629 7921}
7922
4f46f2b9 7923/* Fold function call to builtin memset. Return
9c8a1629 7924 NULL_TREE if no simplification can be made. */
7925
7926static tree
389dd41b 7927fold_builtin_bzero (location_t loc, tree dest, tree size, bool ignore)
9c8a1629 7928{
c2f47e15 7929 if (! validate_arg (dest, POINTER_TYPE)
7930 || ! validate_arg (size, INTEGER_TYPE))
7931 return NULL_TREE;
9c8a1629 7932
4f46f2b9 7933 if (!ignore)
c2f47e15 7934 return NULL_TREE;
a0c938f0 7935
4f46f2b9 7936 /* New argument list transforming bzero(ptr x, int y) to
7937 memset(ptr x, int 0, size_t y). This is done this way
7938 so that if it isn't expanded inline, we fallback to
7939 calling bzero instead of memset. */
7940
389dd41b 7941 return fold_builtin_memset (loc, dest, integer_zero_node,
7942 fold_convert_loc (loc, sizetype, size),
c2f47e15 7943 void_type_node, ignore);
9c8a1629 7944}
7945
4f46f2b9 7946/* Fold function call to builtin mem{{,p}cpy,move}. Return
7947 NULL_TREE if no simplification can be made.
7948 If ENDP is 0, return DEST (like memcpy).
7949 If ENDP is 1, return DEST+LEN (like mempcpy).
7950 If ENDP is 2, return DEST+LEN-1 (like stpcpy).
7951 If ENDP is 3, return DEST, additionally *SRC and *DEST may overlap
7952 (memmove). */
9c8a1629 7953
7954static tree
389dd41b 7955fold_builtin_memory_op (location_t loc, tree dest, tree src,
7956 tree len, tree type, bool ignore, int endp)
9c8a1629 7957{
c2f47e15 7958 tree destvar, srcvar, expr;
9c8a1629 7959
c2f47e15 7960 if (! validate_arg (dest, POINTER_TYPE)
7961 || ! validate_arg (src, POINTER_TYPE)
7962 || ! validate_arg (len, INTEGER_TYPE))
7963 return NULL_TREE;
9c8a1629 7964
7965 /* If the LEN parameter is zero, return DEST. */
7966 if (integer_zerop (len))
389dd41b 7967 return omit_one_operand_loc (loc, type, dest, src);
9c8a1629 7968
4f46f2b9 7969 /* If SRC and DEST are the same (and not volatile), return
7970 DEST{,+LEN,+LEN-1}. */
9c8a1629 7971 if (operand_equal_p (src, dest, 0))
4f46f2b9 7972 expr = len;
7973 else
7974 {
5a84fdd6 7975 tree srctype, desttype;
153c3b50 7976 unsigned int src_align, dest_align;
182cf5a9 7977 tree off0;
5383fb56 7978
3b1757a2 7979 if (endp == 3)
7980 {
5383fb56 7981 src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
7982 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
5a84fdd6 7983
48e1416a 7984 /* Both DEST and SRC must be pointer types.
3b1757a2 7985 ??? This is what old code did. Is the testing for pointer types
7986 really mandatory?
7987
7988 If either SRC is readonly or length is 1, we can use memcpy. */
3f95c690 7989 if (!dest_align || !src_align)
7990 return NULL_TREE;
7991 if (readonly_data_expr (src)
7992 || (host_integerp (len, 1)
7993 && (MIN (src_align, dest_align) / BITS_PER_UNIT
12c655b1 7994 >= (unsigned HOST_WIDE_INT) tree_low_cst (len, 1))))
3b1757a2 7995 {
7996 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
7997 if (!fn)
c2f47e15 7998 return NULL_TREE;
389dd41b 7999 return build_call_expr_loc (loc, fn, 3, dest, src, len);
3b1757a2 8000 }
3f95c690 8001
8002 /* If *src and *dest can't overlap, optimize into memcpy as well. */
182cf5a9 8003 if (TREE_CODE (src) == ADDR_EXPR
8004 && TREE_CODE (dest) == ADDR_EXPR)
3f95c690 8005 {
f85fb819 8006 tree src_base, dest_base, fn;
8007 HOST_WIDE_INT src_offset = 0, dest_offset = 0;
8008 HOST_WIDE_INT size = -1;
8009 HOST_WIDE_INT maxsize = -1;
8010
182cf5a9 8011 srcvar = TREE_OPERAND (src, 0);
8012 src_base = get_ref_base_and_extent (srcvar, &src_offset,
8013 &size, &maxsize);
8014 destvar = TREE_OPERAND (dest, 0);
8015 dest_base = get_ref_base_and_extent (destvar, &dest_offset,
8016 &size, &maxsize);
f85fb819 8017 if (host_integerp (len, 1))
182cf5a9 8018 maxsize = tree_low_cst (len, 1);
f85fb819 8019 else
8020 maxsize = -1;
182cf5a9 8021 src_offset /= BITS_PER_UNIT;
8022 dest_offset /= BITS_PER_UNIT;
f85fb819 8023 if (SSA_VAR_P (src_base)
8024 && SSA_VAR_P (dest_base))
8025 {
8026 if (operand_equal_p (src_base, dest_base, 0)
8027 && ranges_overlap_p (src_offset, maxsize,
8028 dest_offset, maxsize))
8029 return NULL_TREE;
8030 }
182cf5a9 8031 else if (TREE_CODE (src_base) == MEM_REF
8032 && TREE_CODE (dest_base) == MEM_REF)
f85fb819 8033 {
182cf5a9 8034 double_int off;
f85fb819 8035 if (! operand_equal_p (TREE_OPERAND (src_base, 0),
182cf5a9 8036 TREE_OPERAND (dest_base, 0), 0))
8037 return NULL_TREE;
8038 off = double_int_add (mem_ref_offset (src_base),
8039 shwi_to_double_int (src_offset));
8040 if (!double_int_fits_in_shwi_p (off))
8041 return NULL_TREE;
8042 src_offset = off.low;
8043 off = double_int_add (mem_ref_offset (dest_base),
8044 shwi_to_double_int (dest_offset));
8045 if (!double_int_fits_in_shwi_p (off))
8046 return NULL_TREE;
8047 dest_offset = off.low;
8048 if (ranges_overlap_p (src_offset, maxsize,
8049 dest_offset, maxsize))
f85fb819 8050 return NULL_TREE;
8051 }
8052 else
8053 return NULL_TREE;
8054
8055 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
3f95c690 8056 if (!fn)
8057 return NULL_TREE;
389dd41b 8058 return build_call_expr_loc (loc, fn, 3, dest, src, len);
3f95c690 8059 }
c4222b63 8060
8061 /* If the destination and source do not alias optimize into
8062 memcpy as well. */
8063 if ((is_gimple_min_invariant (dest)
8064 || TREE_CODE (dest) == SSA_NAME)
8065 && (is_gimple_min_invariant (src)
8066 || TREE_CODE (src) == SSA_NAME))
8067 {
8068 ao_ref destr, srcr;
8069 ao_ref_init_from_ptr_and_size (&destr, dest, len);
8070 ao_ref_init_from_ptr_and_size (&srcr, src, len);
8071 if (!refs_may_alias_p_1 (&destr, &srcr, false))
8072 {
8073 tree fn;
8074 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8075 if (!fn)
8076 return NULL_TREE;
8077 return build_call_expr_loc (loc, fn, 3, dest, src, len);
8078 }
8079 }
8080
c2f47e15 8081 return NULL_TREE;
3b1757a2 8082 }
4f46f2b9 8083
5a84fdd6 8084 if (!host_integerp (len, 0))
c2f47e15 8085 return NULL_TREE;
5a84fdd6 8086 /* FIXME:
8087 This logic lose for arguments like (type *)malloc (sizeof (type)),
8088 since we strip the casts of up to VOID return value from malloc.
8089 Perhaps we ought to inherit type from non-VOID argument here? */
8090 STRIP_NOPS (src);
8091 STRIP_NOPS (dest);
e07c7898 8092 if (!POINTER_TYPE_P (TREE_TYPE (src))
8093 || !POINTER_TYPE_P (TREE_TYPE (dest)))
8094 return NULL_TREE;
45bb3afb 8095 /* As we fold (void *)(p + CST) to (void *)p + CST undo this here. */
8096 if (TREE_CODE (src) == POINTER_PLUS_EXPR)
8097 {
8098 tree tem = TREE_OPERAND (src, 0);
8099 STRIP_NOPS (tem);
8100 if (tem != TREE_OPERAND (src, 0))
8101 src = build1 (NOP_EXPR, TREE_TYPE (tem), src);
8102 }
8103 if (TREE_CODE (dest) == POINTER_PLUS_EXPR)
8104 {
8105 tree tem = TREE_OPERAND (dest, 0);
8106 STRIP_NOPS (tem);
8107 if (tem != TREE_OPERAND (dest, 0))
8108 dest = build1 (NOP_EXPR, TREE_TYPE (tem), dest);
8109 }
5a84fdd6 8110 srctype = TREE_TYPE (TREE_TYPE (src));
e07c7898 8111 if (TREE_CODE (srctype) == ARRAY_TYPE
97d4c6a6 8112 && !tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
45bb3afb 8113 {
8114 srctype = TREE_TYPE (srctype);
8115 STRIP_NOPS (src);
8116 src = build1 (NOP_EXPR, build_pointer_type (srctype), src);
8117 }
5a84fdd6 8118 desttype = TREE_TYPE (TREE_TYPE (dest));
e07c7898 8119 if (TREE_CODE (desttype) == ARRAY_TYPE
97d4c6a6 8120 && !tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
45bb3afb 8121 {
8122 desttype = TREE_TYPE (desttype);
8123 STRIP_NOPS (dest);
8124 dest = build1 (NOP_EXPR, build_pointer_type (desttype), dest);
8125 }
e07c7898 8126 if (TREE_ADDRESSABLE (srctype)
8127 || TREE_ADDRESSABLE (desttype))
c2f47e15 8128 return NULL_TREE;
4f46f2b9 8129
5383fb56 8130 src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
8131 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
153c3b50 8132 if (dest_align < TYPE_ALIGN (desttype)
8133 || src_align < TYPE_ALIGN (srctype))
c2f47e15 8134 return NULL_TREE;
e973ffcc 8135
5a84fdd6 8136 if (!ignore)
8137 dest = builtin_save_expr (dest);
4f46f2b9 8138
182cf5a9 8139 /* Build accesses at offset zero with a ref-all character type. */
8140 off0 = build_int_cst (build_pointer_type_for_mode (char_type_node,
8141 ptr_mode, true), 0);
4f46f2b9 8142
182cf5a9 8143 destvar = dest;
8144 STRIP_NOPS (destvar);
8145 if (TREE_CODE (destvar) == ADDR_EXPR
8146 && var_decl_component_p (TREE_OPERAND (destvar, 0))
8147 && tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
8148 destvar = fold_build2 (MEM_REF, desttype, destvar, off0);
8149 else
8150 destvar = NULL_TREE;
8151
8152 srcvar = src;
8153 STRIP_NOPS (srcvar);
8154 if (TREE_CODE (srcvar) == ADDR_EXPR
8155 && var_decl_component_p (TREE_OPERAND (srcvar, 0))
5b99ff01 8156 && tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
8157 {
8158 if (!destvar
8159 || src_align >= TYPE_ALIGN (desttype))
8160 srcvar = fold_build2 (MEM_REF, destvar ? desttype : srctype,
8161 srcvar, off0);
8162 else if (!STRICT_ALIGNMENT)
8163 {
8164 srctype = build_aligned_type (TYPE_MAIN_VARIANT (desttype),
8165 src_align);
8166 srcvar = fold_build2 (MEM_REF, srctype, srcvar, off0);
8167 }
8168 else
8169 srcvar = NULL_TREE;
8170 }
182cf5a9 8171 else
8172 srcvar = NULL_TREE;
5383fb56 8173
8174 if (srcvar == NULL_TREE && destvar == NULL_TREE)
c2f47e15 8175 return NULL_TREE;
4f46f2b9 8176
5383fb56 8177 if (srcvar == NULL_TREE)
8178 {
182cf5a9 8179 STRIP_NOPS (src);
5b99ff01 8180 if (src_align >= TYPE_ALIGN (desttype))
8181 srcvar = fold_build2 (MEM_REF, desttype, src, off0);
8182 else
8183 {
8184 if (STRICT_ALIGNMENT)
8185 return NULL_TREE;
8186 srctype = build_aligned_type (TYPE_MAIN_VARIANT (desttype),
8187 src_align);
8188 srcvar = fold_build2 (MEM_REF, srctype, src, off0);
8189 }
5383fb56 8190 }
8191 else if (destvar == NULL_TREE)
8192 {
182cf5a9 8193 STRIP_NOPS (dest);
5b99ff01 8194 if (dest_align >= TYPE_ALIGN (srctype))
8195 destvar = fold_build2 (MEM_REF, srctype, dest, off0);
8196 else
8197 {
8198 if (STRICT_ALIGNMENT)
8199 return NULL_TREE;
8200 desttype = build_aligned_type (TYPE_MAIN_VARIANT (srctype),
8201 dest_align);
8202 destvar = fold_build2 (MEM_REF, desttype, dest, off0);
8203 }
5383fb56 8204 }
8205
182cf5a9 8206 expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, srcvar);
4f46f2b9 8207 }
8208
8209 if (ignore)
8210 return expr;
8211
8212 if (endp == 0 || endp == 3)
389dd41b 8213 return omit_one_operand_loc (loc, type, dest, expr);
4f46f2b9 8214
8215 if (expr == len)
c2f47e15 8216 expr = NULL_TREE;
4f46f2b9 8217
8218 if (endp == 2)
389dd41b 8219 len = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (len), len,
4f46f2b9 8220 ssize_int (1));
8221
2cc66f2a 8222 dest = fold_build_pointer_plus_loc (loc, dest, len);
389dd41b 8223 dest = fold_convert_loc (loc, type, dest);
4f46f2b9 8224 if (expr)
389dd41b 8225 dest = omit_one_operand_loc (loc, type, dest, expr);
4f46f2b9 8226 return dest;
8227}
8228
c2f47e15 8229/* Fold function call to builtin strcpy with arguments DEST and SRC.
8230 If LEN is not NULL, it represents the length of the string to be
8231 copied. Return NULL_TREE if no simplification can be made. */
9c8a1629 8232
f0613857 8233tree
389dd41b 8234fold_builtin_strcpy (location_t loc, tree fndecl, tree dest, tree src, tree len)
9c8a1629 8235{
c2f47e15 8236 tree fn;
9c8a1629 8237
c2f47e15 8238 if (!validate_arg (dest, POINTER_TYPE)
8239 || !validate_arg (src, POINTER_TYPE))
8240 return NULL_TREE;
9c8a1629 8241
8242 /* If SRC and DEST are the same (and not volatile), return DEST. */
8243 if (operand_equal_p (src, dest, 0))
389dd41b 8244 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
9c8a1629 8245
0bfd8d5c 8246 if (optimize_function_for_size_p (cfun))
c2f47e15 8247 return NULL_TREE;
f0613857 8248
8249 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8250 if (!fn)
c2f47e15 8251 return NULL_TREE;
f0613857 8252
8253 if (!len)
8254 {
8255 len = c_strlen (src, 1);
8256 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 8257 return NULL_TREE;
f0613857 8258 }
8259
389dd41b 8260 len = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
8261 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
8262 build_call_expr_loc (loc, fn, 3, dest, src, len));
9c8a1629 8263}
8264
a65c4d64 8265/* Fold function call to builtin stpcpy with arguments DEST and SRC.
8266 Return NULL_TREE if no simplification can be made. */
8267
8268static tree
8269fold_builtin_stpcpy (location_t loc, tree fndecl, tree dest, tree src)
8270{
8271 tree fn, len, lenp1, call, type;
8272
8273 if (!validate_arg (dest, POINTER_TYPE)
8274 || !validate_arg (src, POINTER_TYPE))
8275 return NULL_TREE;
8276
8277 len = c_strlen (src, 1);
8278 if (!len
8279 || TREE_CODE (len) != INTEGER_CST)
8280 return NULL_TREE;
8281
8282 if (optimize_function_for_size_p (cfun)
8283 /* If length is zero it's small enough. */
8284 && !integer_zerop (len))
8285 return NULL_TREE;
8286
8287 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8288 if (!fn)
8289 return NULL_TREE;
8290
8291 lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
8292 /* We use dest twice in building our expression. Save it from
8293 multiple expansions. */
8294 dest = builtin_save_expr (dest);
8295 call = build_call_expr_loc (loc, fn, 3, dest, src, lenp1);
8296
8297 type = TREE_TYPE (TREE_TYPE (fndecl));
2cc66f2a 8298 dest = fold_build_pointer_plus_loc (loc, dest, len);
a65c4d64 8299 dest = fold_convert_loc (loc, type, dest);
8300 dest = omit_one_operand_loc (loc, type, dest, call);
8301 return dest;
8302}
8303
c2f47e15 8304/* Fold function call to builtin strncpy with arguments DEST, SRC, and LEN.
8305 If SLEN is not NULL, it represents the length of the source string.
8306 Return NULL_TREE if no simplification can be made. */
9c8a1629 8307
f0613857 8308tree
389dd41b 8309fold_builtin_strncpy (location_t loc, tree fndecl, tree dest,
8310 tree src, tree len, tree slen)
9c8a1629 8311{
c2f47e15 8312 tree fn;
9c8a1629 8313
c2f47e15 8314 if (!validate_arg (dest, POINTER_TYPE)
8315 || !validate_arg (src, POINTER_TYPE)
8316 || !validate_arg (len, INTEGER_TYPE))
8317 return NULL_TREE;
9c8a1629 8318
8319 /* If the LEN parameter is zero, return DEST. */
8320 if (integer_zerop (len))
389dd41b 8321 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
9c8a1629 8322
19226313 8323 /* We can't compare slen with len as constants below if len is not a
8324 constant. */
8325 if (len == 0 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 8326 return NULL_TREE;
19226313 8327
f0613857 8328 if (!slen)
8329 slen = c_strlen (src, 1);
8330
8331 /* Now, we must be passed a constant src ptr parameter. */
8332 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
c2f47e15 8333 return NULL_TREE;
f0613857 8334
389dd41b 8335 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
f0613857 8336
8337 /* We do not support simplification of this case, though we do
8338 support it when expanding trees into RTL. */
8339 /* FIXME: generate a call to __builtin_memset. */
8340 if (tree_int_cst_lt (slen, len))
c2f47e15 8341 return NULL_TREE;
f0613857 8342
8343 /* OK transform into builtin memcpy. */
8344 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8345 if (!fn)
c2f47e15 8346 return NULL_TREE;
389dd41b 8347 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
8348 build_call_expr_loc (loc, fn, 3, dest, src, len));
9c8a1629 8349}
8350
7959b13b 8351/* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the
8352 arguments to the call, and TYPE is its return type.
8353 Return NULL_TREE if no simplification can be made. */
8354
8355static tree
389dd41b 8356fold_builtin_memchr (location_t loc, tree arg1, tree arg2, tree len, tree type)
7959b13b 8357{
8358 if (!validate_arg (arg1, POINTER_TYPE)
8359 || !validate_arg (arg2, INTEGER_TYPE)
8360 || !validate_arg (len, INTEGER_TYPE))
8361 return NULL_TREE;
8362 else
8363 {
8364 const char *p1;
8365
8366 if (TREE_CODE (arg2) != INTEGER_CST
8367 || !host_integerp (len, 1))
8368 return NULL_TREE;
8369
8370 p1 = c_getstr (arg1);
8371 if (p1 && compare_tree_int (len, strlen (p1) + 1) <= 0)
8372 {
8373 char c;
8374 const char *r;
8375 tree tem;
8376
8377 if (target_char_cast (arg2, &c))
8378 return NULL_TREE;
8379
364c0c59 8380 r = (char *) memchr (p1, c, tree_low_cst (len, 1));
7959b13b 8381
8382 if (r == NULL)
8383 return build_int_cst (TREE_TYPE (arg1), 0);
8384
2cc66f2a 8385 tem = fold_build_pointer_plus_hwi_loc (loc, arg1, r - p1);
389dd41b 8386 return fold_convert_loc (loc, type, tem);
7959b13b 8387 }
8388 return NULL_TREE;
8389 }
8390}
8391
c2f47e15 8392/* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
8393 Return NULL_TREE if no simplification can be made. */
9c8a1629 8394
8395static tree
389dd41b 8396fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
9c8a1629 8397{
c4fef134 8398 const char *p1, *p2;
9c8a1629 8399
c2f47e15 8400 if (!validate_arg (arg1, POINTER_TYPE)
8401 || !validate_arg (arg2, POINTER_TYPE)
8402 || !validate_arg (len, INTEGER_TYPE))
8403 return NULL_TREE;
9c8a1629 8404
8405 /* If the LEN parameter is zero, return zero. */
8406 if (integer_zerop (len))
389dd41b 8407 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
c4fef134 8408 arg1, arg2);
9c8a1629 8409
8410 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8411 if (operand_equal_p (arg1, arg2, 0))
389dd41b 8412 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
c4fef134 8413
8414 p1 = c_getstr (arg1);
8415 p2 = c_getstr (arg2);
8416
8417 /* If all arguments are constant, and the value of len is not greater
8418 than the lengths of arg1 and arg2, evaluate at compile-time. */
8419 if (host_integerp (len, 1) && p1 && p2
8420 && compare_tree_int (len, strlen (p1) + 1) <= 0
8421 && compare_tree_int (len, strlen (p2) + 1) <= 0)
8422 {
8423 const int r = memcmp (p1, p2, tree_low_cst (len, 1));
8424
8425 if (r > 0)
8426 return integer_one_node;
8427 else if (r < 0)
8428 return integer_minus_one_node;
8429 else
8430 return integer_zero_node;
8431 }
8432
8433 /* If len parameter is one, return an expression corresponding to
8434 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
8435 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
8436 {
8437 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8438 tree cst_uchar_ptr_node
8439 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8440
389dd41b 8441 tree ind1
8442 = fold_convert_loc (loc, integer_type_node,
8443 build1 (INDIRECT_REF, cst_uchar_node,
8444 fold_convert_loc (loc,
8445 cst_uchar_ptr_node,
c4fef134 8446 arg1)));
389dd41b 8447 tree ind2
8448 = fold_convert_loc (loc, integer_type_node,
8449 build1 (INDIRECT_REF, cst_uchar_node,
8450 fold_convert_loc (loc,
8451 cst_uchar_ptr_node,
c4fef134 8452 arg2)));
389dd41b 8453 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
c4fef134 8454 }
9c8a1629 8455
c2f47e15 8456 return NULL_TREE;
9c8a1629 8457}
8458
c2f47e15 8459/* Fold function call to builtin strcmp with arguments ARG1 and ARG2.
8460 Return NULL_TREE if no simplification can be made. */
9c8a1629 8461
8462static tree
389dd41b 8463fold_builtin_strcmp (location_t loc, tree arg1, tree arg2)
9c8a1629 8464{
9c8a1629 8465 const char *p1, *p2;
8466
c2f47e15 8467 if (!validate_arg (arg1, POINTER_TYPE)
8468 || !validate_arg (arg2, POINTER_TYPE))
8469 return NULL_TREE;
9c8a1629 8470
8471 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8472 if (operand_equal_p (arg1, arg2, 0))
c4fef134 8473 return integer_zero_node;
9c8a1629 8474
8475 p1 = c_getstr (arg1);
8476 p2 = c_getstr (arg2);
8477
8478 if (p1 && p2)
8479 {
9c8a1629 8480 const int i = strcmp (p1, p2);
8481 if (i < 0)
c4fef134 8482 return integer_minus_one_node;
9c8a1629 8483 else if (i > 0)
c4fef134 8484 return integer_one_node;
9c8a1629 8485 else
c4fef134 8486 return integer_zero_node;
8487 }
8488
8489 /* If the second arg is "", return *(const unsigned char*)arg1. */
8490 if (p2 && *p2 == '\0')
8491 {
8492 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8493 tree cst_uchar_ptr_node
8494 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8495
389dd41b 8496 return fold_convert_loc (loc, integer_type_node,
8497 build1 (INDIRECT_REF, cst_uchar_node,
8498 fold_convert_loc (loc,
8499 cst_uchar_ptr_node,
8500 arg1)));
c4fef134 8501 }
8502
8503 /* If the first arg is "", return -*(const unsigned char*)arg2. */
8504 if (p1 && *p1 == '\0')
8505 {
8506 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8507 tree cst_uchar_ptr_node
8508 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8509
389dd41b 8510 tree temp
8511 = fold_convert_loc (loc, integer_type_node,
8512 build1 (INDIRECT_REF, cst_uchar_node,
8513 fold_convert_loc (loc,
8514 cst_uchar_ptr_node,
c4fef134 8515 arg2)));
389dd41b 8516 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp);
9c8a1629 8517 }
8518
c2f47e15 8519 return NULL_TREE;
9c8a1629 8520}
8521
c2f47e15 8522/* Fold function call to builtin strncmp with arguments ARG1, ARG2, and LEN.
8523 Return NULL_TREE if no simplification can be made. */
9c8a1629 8524
8525static tree
389dd41b 8526fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len)
9c8a1629 8527{
9c8a1629 8528 const char *p1, *p2;
8529
c2f47e15 8530 if (!validate_arg (arg1, POINTER_TYPE)
8531 || !validate_arg (arg2, POINTER_TYPE)
8532 || !validate_arg (len, INTEGER_TYPE))
8533 return NULL_TREE;
9c8a1629 8534
8535 /* If the LEN parameter is zero, return zero. */
8536 if (integer_zerop (len))
389dd41b 8537 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
c4fef134 8538 arg1, arg2);
9c8a1629 8539
8540 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8541 if (operand_equal_p (arg1, arg2, 0))
389dd41b 8542 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
9c8a1629 8543
8544 p1 = c_getstr (arg1);
8545 p2 = c_getstr (arg2);
8546
8547 if (host_integerp (len, 1) && p1 && p2)
8548 {
9c8a1629 8549 const int i = strncmp (p1, p2, tree_low_cst (len, 1));
c4fef134 8550 if (i > 0)
8551 return integer_one_node;
8552 else if (i < 0)
8553 return integer_minus_one_node;
9c8a1629 8554 else
c4fef134 8555 return integer_zero_node;
8556 }
8557
8558 /* If the second arg is "", and the length is greater than zero,
8559 return *(const unsigned char*)arg1. */
8560 if (p2 && *p2 == '\0'
8561 && TREE_CODE (len) == INTEGER_CST
8562 && tree_int_cst_sgn (len) == 1)
8563 {
8564 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8565 tree cst_uchar_ptr_node
8566 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8567
389dd41b 8568 return fold_convert_loc (loc, integer_type_node,
8569 build1 (INDIRECT_REF, cst_uchar_node,
8570 fold_convert_loc (loc,
8571 cst_uchar_ptr_node,
8572 arg1)));
c4fef134 8573 }
8574
8575 /* If the first arg is "", and the length is greater than zero,
8576 return -*(const unsigned char*)arg2. */
8577 if (p1 && *p1 == '\0'
8578 && TREE_CODE (len) == INTEGER_CST
8579 && tree_int_cst_sgn (len) == 1)
8580 {
8581 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8582 tree cst_uchar_ptr_node
8583 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8584
389dd41b 8585 tree temp = fold_convert_loc (loc, integer_type_node,
8586 build1 (INDIRECT_REF, cst_uchar_node,
8587 fold_convert_loc (loc,
8588 cst_uchar_ptr_node,
8589 arg2)));
8590 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp);
c4fef134 8591 }
8592
8593 /* If len parameter is one, return an expression corresponding to
8594 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
8595 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
8596 {
8597 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8598 tree cst_uchar_ptr_node
8599 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8600
389dd41b 8601 tree ind1 = fold_convert_loc (loc, integer_type_node,
8602 build1 (INDIRECT_REF, cst_uchar_node,
8603 fold_convert_loc (loc,
8604 cst_uchar_ptr_node,
8605 arg1)));
8606 tree ind2 = fold_convert_loc (loc, integer_type_node,
8607 build1 (INDIRECT_REF, cst_uchar_node,
8608 fold_convert_loc (loc,
8609 cst_uchar_ptr_node,
8610 arg2)));
8611 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
9c8a1629 8612 }
8613
c2f47e15 8614 return NULL_TREE;
9c8a1629 8615}
8616
c2f47e15 8617/* Fold function call to builtin signbit, signbitf or signbitl with argument
8618 ARG. Return NULL_TREE if no simplification can be made. */
27f261ef 8619
8620static tree
389dd41b 8621fold_builtin_signbit (location_t loc, tree arg, tree type)
27f261ef 8622{
c2f47e15 8623 if (!validate_arg (arg, REAL_TYPE))
27f261ef 8624 return NULL_TREE;
8625
27f261ef 8626 /* If ARG is a compile-time constant, determine the result. */
8627 if (TREE_CODE (arg) == REAL_CST
f96bd2bf 8628 && !TREE_OVERFLOW (arg))
27f261ef 8629 {
8630 REAL_VALUE_TYPE c;
8631
8632 c = TREE_REAL_CST (arg);
385f3f36 8633 return (REAL_VALUE_NEGATIVE (c)
8634 ? build_one_cst (type)
8635 : build_zero_cst (type));
27f261ef 8636 }
8637
8638 /* If ARG is non-negative, the result is always zero. */
8639 if (tree_expr_nonnegative_p (arg))
389dd41b 8640 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
27f261ef 8641
8642 /* If ARG's format doesn't have signed zeros, return "arg < 0.0". */
8643 if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 8644 return fold_build2_loc (loc, LT_EXPR, type, arg,
49d00087 8645 build_real (TREE_TYPE (arg), dconst0));
27f261ef 8646
8647 return NULL_TREE;
8648}
8649
c2f47e15 8650/* Fold function call to builtin copysign, copysignf or copysignl with
8651 arguments ARG1 and ARG2. Return NULL_TREE if no simplification can
8652 be made. */
467214fd 8653
8654static tree
389dd41b 8655fold_builtin_copysign (location_t loc, tree fndecl,
8656 tree arg1, tree arg2, tree type)
467214fd 8657{
c2f47e15 8658 tree tem;
467214fd 8659
c2f47e15 8660 if (!validate_arg (arg1, REAL_TYPE)
8661 || !validate_arg (arg2, REAL_TYPE))
467214fd 8662 return NULL_TREE;
8663
467214fd 8664 /* copysign(X,X) is X. */
8665 if (operand_equal_p (arg1, arg2, 0))
389dd41b 8666 return fold_convert_loc (loc, type, arg1);
467214fd 8667
8668 /* If ARG1 and ARG2 are compile-time constants, determine the result. */
8669 if (TREE_CODE (arg1) == REAL_CST
8670 && TREE_CODE (arg2) == REAL_CST
f96bd2bf 8671 && !TREE_OVERFLOW (arg1)
8672 && !TREE_OVERFLOW (arg2))
467214fd 8673 {
8674 REAL_VALUE_TYPE c1, c2;
8675
8676 c1 = TREE_REAL_CST (arg1);
8677 c2 = TREE_REAL_CST (arg2);
749680e2 8678 /* c1.sign := c2.sign. */
467214fd 8679 real_copysign (&c1, &c2);
8680 return build_real (type, c1);
467214fd 8681 }
8682
8683 /* copysign(X, Y) is fabs(X) when Y is always non-negative.
8684 Remember to evaluate Y for side-effects. */
8685 if (tree_expr_nonnegative_p (arg2))
389dd41b 8686 return omit_one_operand_loc (loc, type,
8687 fold_build1_loc (loc, ABS_EXPR, type, arg1),
467214fd 8688 arg2);
8689
198d9bbe 8690 /* Strip sign changing operations for the first argument. */
8691 tem = fold_strip_sign_ops (arg1);
8692 if (tem)
389dd41b 8693 return build_call_expr_loc (loc, fndecl, 2, tem, arg2);
198d9bbe 8694
467214fd 8695 return NULL_TREE;
8696}
8697
c2f47e15 8698/* Fold a call to builtin isascii with argument ARG. */
d49367d4 8699
8700static tree
389dd41b 8701fold_builtin_isascii (location_t loc, tree arg)
d49367d4 8702{
c2f47e15 8703 if (!validate_arg (arg, INTEGER_TYPE))
8704 return NULL_TREE;
d49367d4 8705 else
8706 {
8707 /* Transform isascii(c) -> ((c & ~0x7f) == 0). */
c90b5d40 8708 arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
7002a1c8 8709 build_int_cst (integer_type_node,
c90b5d40 8710 ~ (unsigned HOST_WIDE_INT) 0x7f));
389dd41b 8711 return fold_build2_loc (loc, EQ_EXPR, integer_type_node,
7002a1c8 8712 arg, integer_zero_node);
d49367d4 8713 }
8714}
8715
c2f47e15 8716/* Fold a call to builtin toascii with argument ARG. */
d49367d4 8717
8718static tree
389dd41b 8719fold_builtin_toascii (location_t loc, tree arg)
d49367d4 8720{
c2f47e15 8721 if (!validate_arg (arg, INTEGER_TYPE))
8722 return NULL_TREE;
48e1416a 8723
c2f47e15 8724 /* Transform toascii(c) -> (c & 0x7f). */
389dd41b 8725 return fold_build2_loc (loc, BIT_AND_EXPR, integer_type_node, arg,
7002a1c8 8726 build_int_cst (integer_type_node, 0x7f));
d49367d4 8727}
8728
c2f47e15 8729/* Fold a call to builtin isdigit with argument ARG. */
df1cf42e 8730
8731static tree
389dd41b 8732fold_builtin_isdigit (location_t loc, tree arg)
df1cf42e 8733{
c2f47e15 8734 if (!validate_arg (arg, INTEGER_TYPE))
8735 return NULL_TREE;
df1cf42e 8736 else
8737 {
8738 /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */
624d37a6 8739 /* According to the C standard, isdigit is unaffected by locale.
8740 However, it definitely is affected by the target character set. */
624d37a6 8741 unsigned HOST_WIDE_INT target_digit0
8742 = lang_hooks.to_target_charset ('0');
8743
8744 if (target_digit0 == 0)
8745 return NULL_TREE;
8746
389dd41b 8747 arg = fold_convert_loc (loc, unsigned_type_node, arg);
c90b5d40 8748 arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg,
8749 build_int_cst (unsigned_type_node, target_digit0));
389dd41b 8750 return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg,
f2532264 8751 build_int_cst (unsigned_type_node, 9));
df1cf42e 8752 }
8753}
27f261ef 8754
c2f47e15 8755/* Fold a call to fabs, fabsf or fabsl with argument ARG. */
d1aade50 8756
8757static tree
389dd41b 8758fold_builtin_fabs (location_t loc, tree arg, tree type)
d1aade50 8759{
c2f47e15 8760 if (!validate_arg (arg, REAL_TYPE))
8761 return NULL_TREE;
d1aade50 8762
389dd41b 8763 arg = fold_convert_loc (loc, type, arg);
d1aade50 8764 if (TREE_CODE (arg) == REAL_CST)
8765 return fold_abs_const (arg, type);
389dd41b 8766 return fold_build1_loc (loc, ABS_EXPR, type, arg);
d1aade50 8767}
8768
c2f47e15 8769/* Fold a call to abs, labs, llabs or imaxabs with argument ARG. */
d1aade50 8770
8771static tree
389dd41b 8772fold_builtin_abs (location_t loc, tree arg, tree type)
d1aade50 8773{
c2f47e15 8774 if (!validate_arg (arg, INTEGER_TYPE))
8775 return NULL_TREE;
d1aade50 8776
389dd41b 8777 arg = fold_convert_loc (loc, type, arg);
d1aade50 8778 if (TREE_CODE (arg) == INTEGER_CST)
8779 return fold_abs_const (arg, type);
389dd41b 8780 return fold_build1_loc (loc, ABS_EXPR, type, arg);
d1aade50 8781}
8782
b9be572e 8783/* Fold a fma operation with arguments ARG[012]. */
8784
8785tree
8786fold_fma (location_t loc ATTRIBUTE_UNUSED,
8787 tree type, tree arg0, tree arg1, tree arg2)
8788{
8789 if (TREE_CODE (arg0) == REAL_CST
8790 && TREE_CODE (arg1) == REAL_CST
8791 && TREE_CODE (arg2) == REAL_CST)
8792 return do_mpfr_arg3 (arg0, arg1, arg2, type, mpfr_fma);
8793
8794 return NULL_TREE;
8795}
8796
8797/* Fold a call to fma, fmaf, or fmal with arguments ARG[012]. */
8798
8799static tree
8800fold_builtin_fma (location_t loc, tree arg0, tree arg1, tree arg2, tree type)
8801{
8802 if (validate_arg (arg0, REAL_TYPE)
8803 && validate_arg(arg1, REAL_TYPE)
8804 && validate_arg(arg2, REAL_TYPE))
8805 {
8806 tree tem = fold_fma (loc, type, arg0, arg1, arg2);
8807 if (tem)
8808 return tem;
8809
8810 /* ??? Only expand to FMA_EXPR if it's directly supported. */
8811 if (optab_handler (fma_optab, TYPE_MODE (type)) != CODE_FOR_nothing)
8812 return fold_build3_loc (loc, FMA_EXPR, type, arg0, arg1, arg2);
8813 }
8814 return NULL_TREE;
8815}
8816
d4a43a03 8817/* Fold a call to builtin fmin or fmax. */
8818
8819static tree
389dd41b 8820fold_builtin_fmin_fmax (location_t loc, tree arg0, tree arg1,
8821 tree type, bool max)
d4a43a03 8822{
c2f47e15 8823 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, REAL_TYPE))
d4a43a03 8824 {
d4a43a03 8825 /* Calculate the result when the argument is a constant. */
8826 tree res = do_mpfr_arg2 (arg0, arg1, type, (max ? mpfr_max : mpfr_min));
8827
8828 if (res)
8829 return res;
8830
61fe3555 8831 /* If either argument is NaN, return the other one. Avoid the
8832 transformation if we get (and honor) a signalling NaN. Using
8833 omit_one_operand() ensures we create a non-lvalue. */
8834 if (TREE_CODE (arg0) == REAL_CST
8835 && real_isnan (&TREE_REAL_CST (arg0))
8836 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
8837 || ! TREE_REAL_CST (arg0).signalling))
389dd41b 8838 return omit_one_operand_loc (loc, type, arg1, arg0);
61fe3555 8839 if (TREE_CODE (arg1) == REAL_CST
8840 && real_isnan (&TREE_REAL_CST (arg1))
8841 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
8842 || ! TREE_REAL_CST (arg1).signalling))
389dd41b 8843 return omit_one_operand_loc (loc, type, arg0, arg1);
61fe3555 8844
d4a43a03 8845 /* Transform fmin/fmax(x,x) -> x. */
8846 if (operand_equal_p (arg0, arg1, OEP_PURE_SAME))
389dd41b 8847 return omit_one_operand_loc (loc, type, arg0, arg1);
48e1416a 8848
d4a43a03 8849 /* Convert fmin/fmax to MIN_EXPR/MAX_EXPR. C99 requires these
8850 functions to return the numeric arg if the other one is NaN.
8851 These tree codes don't honor that, so only transform if
8852 -ffinite-math-only is set. C99 doesn't require -0.0 to be
8853 handled, so we don't have to worry about it either. */
8854 if (flag_finite_math_only)
389dd41b 8855 return fold_build2_loc (loc, (max ? MAX_EXPR : MIN_EXPR), type,
8856 fold_convert_loc (loc, type, arg0),
8857 fold_convert_loc (loc, type, arg1));
d4a43a03 8858 }
8859 return NULL_TREE;
8860}
8861
abe4dcf6 8862/* Fold a call to builtin carg(a+bi) -> atan2(b,a). */
8863
8864static tree
389dd41b 8865fold_builtin_carg (location_t loc, tree arg, tree type)
abe4dcf6 8866{
239d491a 8867 if (validate_arg (arg, COMPLEX_TYPE)
8868 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
abe4dcf6 8869 {
8870 tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
48e1416a 8871
abe4dcf6 8872 if (atan2_fn)
8873 {
c2f47e15 8874 tree new_arg = builtin_save_expr (arg);
389dd41b 8875 tree r_arg = fold_build1_loc (loc, REALPART_EXPR, type, new_arg);
8876 tree i_arg = fold_build1_loc (loc, IMAGPART_EXPR, type, new_arg);
8877 return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg);
abe4dcf6 8878 }
8879 }
48e1416a 8880
abe4dcf6 8881 return NULL_TREE;
8882}
8883
cb2b9385 8884/* Fold a call to builtin logb/ilogb. */
8885
8886static tree
389dd41b 8887fold_builtin_logb (location_t loc, tree arg, tree rettype)
cb2b9385 8888{
8889 if (! validate_arg (arg, REAL_TYPE))
8890 return NULL_TREE;
48e1416a 8891
cb2b9385 8892 STRIP_NOPS (arg);
48e1416a 8893
cb2b9385 8894 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
8895 {
8896 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
48e1416a 8897
cb2b9385 8898 switch (value->cl)
8899 {
8900 case rvc_nan:
8901 case rvc_inf:
8902 /* If arg is Inf or NaN and we're logb, return it. */
8903 if (TREE_CODE (rettype) == REAL_TYPE)
389dd41b 8904 return fold_convert_loc (loc, rettype, arg);
cb2b9385 8905 /* Fall through... */
8906 case rvc_zero:
8907 /* Zero may set errno and/or raise an exception for logb, also
8908 for ilogb we don't know FP_ILOGB0. */
8909 return NULL_TREE;
8910 case rvc_normal:
8911 /* For normal numbers, proceed iff radix == 2. In GCC,
8912 normalized significands are in the range [0.5, 1.0). We
8913 want the exponent as if they were [1.0, 2.0) so get the
8914 exponent and subtract 1. */
8915 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
389dd41b 8916 return fold_convert_loc (loc, rettype,
7002a1c8 8917 build_int_cst (integer_type_node,
389dd41b 8918 REAL_EXP (value)-1));
cb2b9385 8919 break;
8920 }
8921 }
48e1416a 8922
cb2b9385 8923 return NULL_TREE;
8924}
8925
8926/* Fold a call to builtin significand, if radix == 2. */
8927
8928static tree
389dd41b 8929fold_builtin_significand (location_t loc, tree arg, tree rettype)
cb2b9385 8930{
8931 if (! validate_arg (arg, REAL_TYPE))
8932 return NULL_TREE;
48e1416a 8933
cb2b9385 8934 STRIP_NOPS (arg);
48e1416a 8935
cb2b9385 8936 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
8937 {
8938 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
48e1416a 8939
cb2b9385 8940 switch (value->cl)
8941 {
8942 case rvc_zero:
8943 case rvc_nan:
8944 case rvc_inf:
8945 /* If arg is +-0, +-Inf or +-NaN, then return it. */
389dd41b 8946 return fold_convert_loc (loc, rettype, arg);
cb2b9385 8947 case rvc_normal:
8948 /* For normal numbers, proceed iff radix == 2. */
8949 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
8950 {
8951 REAL_VALUE_TYPE result = *value;
8952 /* In GCC, normalized significands are in the range [0.5,
8953 1.0). We want them to be [1.0, 2.0) so set the
8954 exponent to 1. */
8955 SET_REAL_EXP (&result, 1);
8956 return build_real (rettype, result);
8957 }
8958 break;
8959 }
8960 }
48e1416a 8961
cb2b9385 8962 return NULL_TREE;
8963}
8964
3838b9ae 8965/* Fold a call to builtin frexp, we can assume the base is 2. */
8966
8967static tree
389dd41b 8968fold_builtin_frexp (location_t loc, tree arg0, tree arg1, tree rettype)
3838b9ae 8969{
8970 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
8971 return NULL_TREE;
48e1416a 8972
3838b9ae 8973 STRIP_NOPS (arg0);
48e1416a 8974
3838b9ae 8975 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
8976 return NULL_TREE;
48e1416a 8977
389dd41b 8978 arg1 = build_fold_indirect_ref_loc (loc, arg1);
3838b9ae 8979
8980 /* Proceed if a valid pointer type was passed in. */
8981 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
8982 {
8983 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
8984 tree frac, exp;
48e1416a 8985
3838b9ae 8986 switch (value->cl)
8987 {
8988 case rvc_zero:
8989 /* For +-0, return (*exp = 0, +-0). */
8990 exp = integer_zero_node;
8991 frac = arg0;
8992 break;
8993 case rvc_nan:
8994 case rvc_inf:
8995 /* For +-NaN or +-Inf, *exp is unspecified, return arg0. */
389dd41b 8996 return omit_one_operand_loc (loc, rettype, arg0, arg1);
3838b9ae 8997 case rvc_normal:
8998 {
8999 /* Since the frexp function always expects base 2, and in
9000 GCC normalized significands are already in the range
9001 [0.5, 1.0), we have exactly what frexp wants. */
9002 REAL_VALUE_TYPE frac_rvt = *value;
9003 SET_REAL_EXP (&frac_rvt, 0);
9004 frac = build_real (rettype, frac_rvt);
7002a1c8 9005 exp = build_int_cst (integer_type_node, REAL_EXP (value));
3838b9ae 9006 }
9007 break;
9008 default:
9009 gcc_unreachable ();
9010 }
48e1416a 9011
3838b9ae 9012 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
389dd41b 9013 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, exp);
3838b9ae 9014 TREE_SIDE_EFFECTS (arg1) = 1;
389dd41b 9015 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1, frac);
3838b9ae 9016 }
9017
9018 return NULL_TREE;
9019}
9020
7587301b 9021/* Fold a call to builtin ldexp or scalbn/scalbln. If LDEXP is true
9022 then we can assume the base is two. If it's false, then we have to
9023 check the mode of the TYPE parameter in certain cases. */
9024
9025static tree
389dd41b 9026fold_builtin_load_exponent (location_t loc, tree arg0, tree arg1,
9027 tree type, bool ldexp)
7587301b 9028{
9029 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, INTEGER_TYPE))
9030 {
9031 STRIP_NOPS (arg0);
9032 STRIP_NOPS (arg1);
9033
9034 /* If arg0 is 0, Inf or NaN, or if arg1 is 0, then return arg0. */
9035 if (real_zerop (arg0) || integer_zerop (arg1)
9036 || (TREE_CODE (arg0) == REAL_CST
776a7bab 9037 && !real_isfinite (&TREE_REAL_CST (arg0))))
389dd41b 9038 return omit_one_operand_loc (loc, type, arg0, arg1);
48e1416a 9039
7587301b 9040 /* If both arguments are constant, then try to evaluate it. */
9041 if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2)
9042 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
9043 && host_integerp (arg1, 0))
9044 {
9045 /* Bound the maximum adjustment to twice the range of the
9046 mode's valid exponents. Use abs to ensure the range is
9047 positive as a sanity check. */
48e1416a 9048 const long max_exp_adj = 2 *
7587301b 9049 labs (REAL_MODE_FORMAT (TYPE_MODE (type))->emax
9050 - REAL_MODE_FORMAT (TYPE_MODE (type))->emin);
9051
9052 /* Get the user-requested adjustment. */
9053 const HOST_WIDE_INT req_exp_adj = tree_low_cst (arg1, 0);
48e1416a 9054
7587301b 9055 /* The requested adjustment must be inside this range. This
9056 is a preliminary cap to avoid things like overflow, we
9057 may still fail to compute the result for other reasons. */
9058 if (-max_exp_adj < req_exp_adj && req_exp_adj < max_exp_adj)
9059 {
9060 REAL_VALUE_TYPE initial_result;
48e1416a 9061
7587301b 9062 real_ldexp (&initial_result, &TREE_REAL_CST (arg0), req_exp_adj);
9063
9064 /* Ensure we didn't overflow. */
9065 if (! real_isinf (&initial_result))
9066 {
9067 const REAL_VALUE_TYPE trunc_result
9068 = real_value_truncate (TYPE_MODE (type), initial_result);
48e1416a 9069
7587301b 9070 /* Only proceed if the target mode can hold the
9071 resulting value. */
9072 if (REAL_VALUES_EQUAL (initial_result, trunc_result))
9073 return build_real (type, trunc_result);
9074 }
9075 }
9076 }
9077 }
9078
9079 return NULL_TREE;
9080}
9081
ebf8b4f5 9082/* Fold a call to builtin modf. */
9083
9084static tree
389dd41b 9085fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
ebf8b4f5 9086{
9087 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9088 return NULL_TREE;
48e1416a 9089
ebf8b4f5 9090 STRIP_NOPS (arg0);
48e1416a 9091
ebf8b4f5 9092 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9093 return NULL_TREE;
48e1416a 9094
389dd41b 9095 arg1 = build_fold_indirect_ref_loc (loc, arg1);
ebf8b4f5 9096
9097 /* Proceed if a valid pointer type was passed in. */
9098 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
9099 {
9100 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9101 REAL_VALUE_TYPE trunc, frac;
9102
9103 switch (value->cl)
9104 {
9105 case rvc_nan:
9106 case rvc_zero:
9107 /* For +-NaN or +-0, return (*arg1 = arg0, arg0). */
9108 trunc = frac = *value;
9109 break;
9110 case rvc_inf:
9111 /* For +-Inf, return (*arg1 = arg0, +-0). */
9112 frac = dconst0;
9113 frac.sign = value->sign;
9114 trunc = *value;
9115 break;
9116 case rvc_normal:
9117 /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)). */
9118 real_trunc (&trunc, VOIDmode, value);
9119 real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
9120 /* If the original number was negative and already
9121 integral, then the fractional part is -0.0. */
9122 if (value->sign && frac.cl == rvc_zero)
9123 frac.sign = value->sign;
9124 break;
9125 }
48e1416a 9126
ebf8b4f5 9127 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
389dd41b 9128 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1,
ebf8b4f5 9129 build_real (rettype, trunc));
9130 TREE_SIDE_EFFECTS (arg1) = 1;
389dd41b 9131 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1,
ebf8b4f5 9132 build_real (rettype, frac));
9133 }
48e1416a 9134
ebf8b4f5 9135 return NULL_TREE;
9136}
9137
a65c4d64 9138/* Given a location LOC, an interclass builtin function decl FNDECL
9139 and its single argument ARG, return an folded expression computing
9140 the same, or NULL_TREE if we either couldn't or didn't want to fold
9141 (the latter happen if there's an RTL instruction available). */
9142
9143static tree
9144fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
9145{
9146 enum machine_mode mode;
9147
9148 if (!validate_arg (arg, REAL_TYPE))
9149 return NULL_TREE;
9150
9151 if (interclass_mathfn_icode (arg, fndecl) != CODE_FOR_nothing)
9152 return NULL_TREE;
9153
9154 mode = TYPE_MODE (TREE_TYPE (arg));
9155
9156 /* If there is no optab, try generic code. */
9157 switch (DECL_FUNCTION_CODE (fndecl))
9158 {
9159 tree result;
9160
9161 CASE_FLT_FN (BUILT_IN_ISINF):
9162 {
9163 /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
9164 tree const isgr_fn = built_in_decls[BUILT_IN_ISGREATER];
9165 tree const type = TREE_TYPE (arg);
9166 REAL_VALUE_TYPE r;
9167 char buf[128];
9168
9169 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9170 real_from_string (&r, buf);
9171 result = build_call_expr (isgr_fn, 2,
9172 fold_build1_loc (loc, ABS_EXPR, type, arg),
9173 build_real (type, r));
9174 return result;
9175 }
9176 CASE_FLT_FN (BUILT_IN_FINITE):
9177 case BUILT_IN_ISFINITE:
9178 {
9179 /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
9180 tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
9181 tree const type = TREE_TYPE (arg);
9182 REAL_VALUE_TYPE r;
9183 char buf[128];
9184
9185 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9186 real_from_string (&r, buf);
9187 result = build_call_expr (isle_fn, 2,
9188 fold_build1_loc (loc, ABS_EXPR, type, arg),
9189 build_real (type, r));
9190 /*result = fold_build2_loc (loc, UNGT_EXPR,
9191 TREE_TYPE (TREE_TYPE (fndecl)),
9192 fold_build1_loc (loc, ABS_EXPR, type, arg),
9193 build_real (type, r));
9194 result = fold_build1_loc (loc, TRUTH_NOT_EXPR,
9195 TREE_TYPE (TREE_TYPE (fndecl)),
9196 result);*/
9197 return result;
9198 }
9199 case BUILT_IN_ISNORMAL:
9200 {
9201 /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
9202 islessequal(fabs(x),DBL_MAX). */
9203 tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
9204 tree const isge_fn = built_in_decls[BUILT_IN_ISGREATEREQUAL];
9205 tree const type = TREE_TYPE (arg);
9206 REAL_VALUE_TYPE rmax, rmin;
9207 char buf[128];
9208
9209 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9210 real_from_string (&rmax, buf);
9211 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
9212 real_from_string (&rmin, buf);
9213 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
9214 result = build_call_expr (isle_fn, 2, arg,
9215 build_real (type, rmax));
9216 result = fold_build2 (BIT_AND_EXPR, integer_type_node, result,
9217 build_call_expr (isge_fn, 2, arg,
9218 build_real (type, rmin)));
9219 return result;
9220 }
9221 default:
9222 break;
9223 }
9224
9225 return NULL_TREE;
9226}
9227
726069ba 9228/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
c2f47e15 9229 ARG is the argument for the call. */
726069ba 9230
9231static tree
389dd41b 9232fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
726069ba 9233{
726069ba 9234 tree type = TREE_TYPE (TREE_TYPE (fndecl));
726069ba 9235 REAL_VALUE_TYPE r;
9236
c2f47e15 9237 if (!validate_arg (arg, REAL_TYPE))
d43cee80 9238 return NULL_TREE;
726069ba 9239
726069ba 9240 switch (builtin_index)
9241 {
9242 case BUILT_IN_ISINF:
b70bfd00 9243 if (!HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 9244 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
726069ba 9245
9246 if (TREE_CODE (arg) == REAL_CST)
9247 {
9248 r = TREE_REAL_CST (arg);
9249 if (real_isinf (&r))
9250 return real_compare (GT_EXPR, &r, &dconst0)
9251 ? integer_one_node : integer_minus_one_node;
9252 else
9253 return integer_zero_node;
9254 }
9255
9256 return NULL_TREE;
9257
c319d56a 9258 case BUILT_IN_ISINF_SIGN:
9259 {
9260 /* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */
9261 /* In a boolean context, GCC will fold the inner COND_EXPR to
9262 1. So e.g. "if (isinf_sign(x))" would be folded to just
9263 "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
9264 tree signbit_fn = mathfn_built_in_1 (TREE_TYPE (arg), BUILT_IN_SIGNBIT, 0);
9265 tree isinf_fn = built_in_decls[BUILT_IN_ISINF];
9266 tree tmp = NULL_TREE;
9267
9268 arg = builtin_save_expr (arg);
9269
9270 if (signbit_fn && isinf_fn)
9271 {
389dd41b 9272 tree signbit_call = build_call_expr_loc (loc, signbit_fn, 1, arg);
9273 tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg);
c319d56a 9274
389dd41b 9275 signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
c319d56a 9276 signbit_call, integer_zero_node);
389dd41b 9277 isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
c319d56a 9278 isinf_call, integer_zero_node);
48e1416a 9279
389dd41b 9280 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call,
c319d56a 9281 integer_minus_one_node, integer_one_node);
389dd41b 9282 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
9283 isinf_call, tmp,
c319d56a 9284 integer_zero_node);
9285 }
9286
9287 return tmp;
9288 }
9289
cde061c1 9290 case BUILT_IN_ISFINITE:
b70bfd00 9291 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
9292 && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 9293 return omit_one_operand_loc (loc, type, integer_one_node, arg);
726069ba 9294
9295 if (TREE_CODE (arg) == REAL_CST)
9296 {
9297 r = TREE_REAL_CST (arg);
776a7bab 9298 return real_isfinite (&r) ? integer_one_node : integer_zero_node;
726069ba 9299 }
9300
9301 return NULL_TREE;
9302
9303 case BUILT_IN_ISNAN:
b70bfd00 9304 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 9305 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
726069ba 9306
9307 if (TREE_CODE (arg) == REAL_CST)
9308 {
9309 r = TREE_REAL_CST (arg);
9310 return real_isnan (&r) ? integer_one_node : integer_zero_node;
9311 }
9312
9313 arg = builtin_save_expr (arg);
389dd41b 9314 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
726069ba 9315
9316 default:
64db345d 9317 gcc_unreachable ();
726069ba 9318 }
9319}
9320
19fbe3a4 9321/* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...).
9322 This builtin will generate code to return the appropriate floating
9323 point classification depending on the value of the floating point
9324 number passed in. The possible return values must be supplied as
921b27c0 9325 int arguments to the call in the following order: FP_NAN, FP_INFINITE,
19fbe3a4 9326 FP_NORMAL, FP_SUBNORMAL and FP_ZERO. The ellipses is for exactly
9327 one floating point argument which is "type generic". */
9328
9329static tree
389dd41b 9330fold_builtin_fpclassify (location_t loc, tree exp)
19fbe3a4 9331{
921b27c0 9332 tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
9333 arg, type, res, tmp;
19fbe3a4 9334 enum machine_mode mode;
9335 REAL_VALUE_TYPE r;
9336 char buf[128];
48e1416a 9337
19fbe3a4 9338 /* Verify the required arguments in the original call. */
9339 if (!validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE,
9340 INTEGER_TYPE, INTEGER_TYPE,
9341 INTEGER_TYPE, REAL_TYPE, VOID_TYPE))
9342 return NULL_TREE;
48e1416a 9343
19fbe3a4 9344 fp_nan = CALL_EXPR_ARG (exp, 0);
921b27c0 9345 fp_infinite = CALL_EXPR_ARG (exp, 1);
19fbe3a4 9346 fp_normal = CALL_EXPR_ARG (exp, 2);
9347 fp_subnormal = CALL_EXPR_ARG (exp, 3);
9348 fp_zero = CALL_EXPR_ARG (exp, 4);
9349 arg = CALL_EXPR_ARG (exp, 5);
9350 type = TREE_TYPE (arg);
9351 mode = TYPE_MODE (type);
389dd41b 9352 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
19fbe3a4 9353
48e1416a 9354 /* fpclassify(x) ->
19fbe3a4 9355 isnan(x) ? FP_NAN :
921b27c0 9356 (fabs(x) == Inf ? FP_INFINITE :
19fbe3a4 9357 (fabs(x) >= DBL_MIN ? FP_NORMAL :
9358 (x == 0 ? FP_ZERO : FP_SUBNORMAL))). */
48e1416a 9359
389dd41b 9360 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
19fbe3a4 9361 build_real (type, dconst0));
389dd41b 9362 res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
9363 tmp, fp_zero, fp_subnormal);
19fbe3a4 9364
9365 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
9366 real_from_string (&r, buf);
389dd41b 9367 tmp = fold_build2_loc (loc, GE_EXPR, integer_type_node,
9368 arg, build_real (type, r));
9369 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, fp_normal, res);
48e1416a 9370
19fbe3a4 9371 if (HONOR_INFINITIES (mode))
9372 {
9373 real_inf (&r);
389dd41b 9374 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
19fbe3a4 9375 build_real (type, r));
389dd41b 9376 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
9377 fp_infinite, res);
19fbe3a4 9378 }
9379
9380 if (HONOR_NANS (mode))
9381 {
389dd41b 9382 tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
9383 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, res, fp_nan);
19fbe3a4 9384 }
48e1416a 9385
19fbe3a4 9386 return res;
9387}
9388
9bc9f15f 9389/* Fold a call to an unordered comparison function such as
d5019fe8 9390 __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function
c2f47e15 9391 being called and ARG0 and ARG1 are the arguments for the call.
726069ba 9392 UNORDERED_CODE and ORDERED_CODE are comparison codes that give
9393 the opposite of the desired result. UNORDERED_CODE is used
9394 for modes that can hold NaNs and ORDERED_CODE is used for
9395 the rest. */
9bc9f15f 9396
9397static tree
389dd41b 9398fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
9bc9f15f 9399 enum tree_code unordered_code,
9400 enum tree_code ordered_code)
9401{
859f903a 9402 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9bc9f15f 9403 enum tree_code code;
6978db0d 9404 tree type0, type1;
9405 enum tree_code code0, code1;
9406 tree cmp_type = NULL_TREE;
9bc9f15f 9407
6978db0d 9408 type0 = TREE_TYPE (arg0);
9409 type1 = TREE_TYPE (arg1);
a0c938f0 9410
6978db0d 9411 code0 = TREE_CODE (type0);
9412 code1 = TREE_CODE (type1);
a0c938f0 9413
6978db0d 9414 if (code0 == REAL_TYPE && code1 == REAL_TYPE)
9415 /* Choose the wider of two real types. */
9416 cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
9417 ? type0 : type1;
9418 else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
9419 cmp_type = type0;
9420 else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
9421 cmp_type = type1;
a0c938f0 9422
389dd41b 9423 arg0 = fold_convert_loc (loc, cmp_type, arg0);
9424 arg1 = fold_convert_loc (loc, cmp_type, arg1);
859f903a 9425
9426 if (unordered_code == UNORDERED_EXPR)
9427 {
b70bfd00 9428 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
389dd41b 9429 return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
9430 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
859f903a 9431 }
9bc9f15f 9432
b70bfd00 9433 code = HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
9434 : ordered_code;
389dd41b 9435 return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
9436 fold_build2_loc (loc, code, type, arg0, arg1));
9bc9f15f 9437}
9438
c2f47e15 9439/* Fold a call to built-in function FNDECL with 0 arguments.
9440 IGNORE is true if the result of the function call is ignored. This
9441 function returns NULL_TREE if no simplification was possible. */
650e4c94 9442
4ee9c684 9443static tree
389dd41b 9444fold_builtin_0 (location_t loc, tree fndecl, bool ignore ATTRIBUTE_UNUSED)
650e4c94 9445{
e9f80ff5 9446 tree type = TREE_TYPE (TREE_TYPE (fndecl));
c2f47e15 9447 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
189b3398 9448 switch (fcode)
650e4c94 9449 {
c2f47e15 9450 CASE_FLT_FN (BUILT_IN_INF):
9451 case BUILT_IN_INFD32:
9452 case BUILT_IN_INFD64:
9453 case BUILT_IN_INFD128:
389dd41b 9454 return fold_builtin_inf (loc, type, true);
7c2f0500 9455
c2f47e15 9456 CASE_FLT_FN (BUILT_IN_HUGE_VAL):
389dd41b 9457 return fold_builtin_inf (loc, type, false);
7c2f0500 9458
c2f47e15 9459 case BUILT_IN_CLASSIFY_TYPE:
9460 return fold_builtin_classify_type (NULL_TREE);
7c2f0500 9461
c2f47e15 9462 default:
9463 break;
9464 }
9465 return NULL_TREE;
9466}
7c2f0500 9467
c2f47e15 9468/* Fold a call to built-in function FNDECL with 1 argument, ARG0.
9469 IGNORE is true if the result of the function call is ignored. This
9470 function returns NULL_TREE if no simplification was possible. */
7c2f0500 9471
c2f47e15 9472static tree
389dd41b 9473fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
c2f47e15 9474{
9475 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9476 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9477 switch (fcode)
9478 {
650e4c94 9479 case BUILT_IN_CONSTANT_P:
7c2f0500 9480 {
c2f47e15 9481 tree val = fold_builtin_constant_p (arg0);
7c2f0500 9482
7c2f0500 9483 /* Gimplification will pull the CALL_EXPR for the builtin out of
9484 an if condition. When not optimizing, we'll not CSE it back.
9485 To avoid link error types of regressions, return false now. */
9486 if (!val && !optimize)
9487 val = integer_zero_node;
9488
9489 return val;
9490 }
650e4c94 9491
539a3a92 9492 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 9493 return fold_builtin_classify_type (arg0);
539a3a92 9494
650e4c94 9495 case BUILT_IN_STRLEN:
c7cbde74 9496 return fold_builtin_strlen (loc, type, arg0);
650e4c94 9497
4f35b1fc 9498 CASE_FLT_FN (BUILT_IN_FABS):
389dd41b 9499 return fold_builtin_fabs (loc, arg0, type);
d1aade50 9500
9501 case BUILT_IN_ABS:
9502 case BUILT_IN_LABS:
9503 case BUILT_IN_LLABS:
9504 case BUILT_IN_IMAXABS:
389dd41b 9505 return fold_builtin_abs (loc, arg0, type);
c63f4ad3 9506
4f35b1fc 9507 CASE_FLT_FN (BUILT_IN_CONJ):
239d491a 9508 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9509 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 9510 return fold_build1_loc (loc, CONJ_EXPR, type, arg0);
c2f47e15 9511 break;
36d3581d 9512
4f35b1fc 9513 CASE_FLT_FN (BUILT_IN_CREAL):
239d491a 9514 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9515 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 9516 return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));;
c2f47e15 9517 break;
36d3581d 9518
4f35b1fc 9519 CASE_FLT_FN (BUILT_IN_CIMAG):
b0ce8887 9520 if (validate_arg (arg0, COMPLEX_TYPE)
9521 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 9522 return non_lvalue_loc (loc, fold_build1_loc (loc, IMAGPART_EXPR, type, arg0));
c2f47e15 9523 break;
36d3581d 9524
503733d5 9525 CASE_FLT_FN (BUILT_IN_CCOS):
389dd41b 9526 return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ false);
48e1416a 9527
503733d5 9528 CASE_FLT_FN (BUILT_IN_CCOSH):
389dd41b 9529 return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ true);
48e1416a 9530
c2373fdb 9531 CASE_FLT_FN (BUILT_IN_CPROJ):
9532 return fold_builtin_cproj(loc, arg0, type);
9533
239d491a 9534 CASE_FLT_FN (BUILT_IN_CSIN):
9535 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9536 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 9537 return do_mpc_arg1 (arg0, type, mpc_sin);
c2f47e15 9538 break;
48e1416a 9539
239d491a 9540 CASE_FLT_FN (BUILT_IN_CSINH):
9541 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9542 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 9543 return do_mpc_arg1 (arg0, type, mpc_sinh);
9544 break;
48e1416a 9545
239d491a 9546 CASE_FLT_FN (BUILT_IN_CTAN):
9547 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9548 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 9549 return do_mpc_arg1 (arg0, type, mpc_tan);
9550 break;
48e1416a 9551
239d491a 9552 CASE_FLT_FN (BUILT_IN_CTANH):
9553 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9554 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 9555 return do_mpc_arg1 (arg0, type, mpc_tanh);
9556 break;
48e1416a 9557
239d491a 9558 CASE_FLT_FN (BUILT_IN_CLOG):
9559 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9560 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 9561 return do_mpc_arg1 (arg0, type, mpc_log);
9562 break;
48e1416a 9563
239d491a 9564 CASE_FLT_FN (BUILT_IN_CSQRT):
9565 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9566 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 9567 return do_mpc_arg1 (arg0, type, mpc_sqrt);
9568 break;
48e1416a 9569
0e7e6e7f 9570 CASE_FLT_FN (BUILT_IN_CASIN):
9571 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9572 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 9573 return do_mpc_arg1 (arg0, type, mpc_asin);
9574 break;
48e1416a 9575
0e7e6e7f 9576 CASE_FLT_FN (BUILT_IN_CACOS):
9577 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9578 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 9579 return do_mpc_arg1 (arg0, type, mpc_acos);
9580 break;
48e1416a 9581
0e7e6e7f 9582 CASE_FLT_FN (BUILT_IN_CATAN):
9583 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9584 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 9585 return do_mpc_arg1 (arg0, type, mpc_atan);
9586 break;
48e1416a 9587
0e7e6e7f 9588 CASE_FLT_FN (BUILT_IN_CASINH):
9589 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9590 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 9591 return do_mpc_arg1 (arg0, type, mpc_asinh);
9592 break;
48e1416a 9593
0e7e6e7f 9594 CASE_FLT_FN (BUILT_IN_CACOSH):
9595 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9596 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 9597 return do_mpc_arg1 (arg0, type, mpc_acosh);
9598 break;
48e1416a 9599
0e7e6e7f 9600 CASE_FLT_FN (BUILT_IN_CATANH):
9601 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9602 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 9603 return do_mpc_arg1 (arg0, type, mpc_atanh);
9604 break;
48e1416a 9605
4f35b1fc 9606 CASE_FLT_FN (BUILT_IN_CABS):
389dd41b 9607 return fold_builtin_cabs (loc, arg0, type, fndecl);
c63f4ad3 9608
abe4dcf6 9609 CASE_FLT_FN (BUILT_IN_CARG):
389dd41b 9610 return fold_builtin_carg (loc, arg0, type);
abe4dcf6 9611
4f35b1fc 9612 CASE_FLT_FN (BUILT_IN_SQRT):
389dd41b 9613 return fold_builtin_sqrt (loc, arg0, type);
805e22b2 9614
4f35b1fc 9615 CASE_FLT_FN (BUILT_IN_CBRT):
389dd41b 9616 return fold_builtin_cbrt (loc, arg0, type);
3bc5c41b 9617
728bac60 9618 CASE_FLT_FN (BUILT_IN_ASIN):
c2f47e15 9619 if (validate_arg (arg0, REAL_TYPE))
9620 return do_mpfr_arg1 (arg0, type, mpfr_asin,
728bac60 9621 &dconstm1, &dconst1, true);
9622 break;
9623
9624 CASE_FLT_FN (BUILT_IN_ACOS):
c2f47e15 9625 if (validate_arg (arg0, REAL_TYPE))
9626 return do_mpfr_arg1 (arg0, type, mpfr_acos,
728bac60 9627 &dconstm1, &dconst1, true);
9628 break;
9629
9630 CASE_FLT_FN (BUILT_IN_ATAN):
c2f47e15 9631 if (validate_arg (arg0, REAL_TYPE))
9632 return do_mpfr_arg1 (arg0, type, mpfr_atan, NULL, NULL, 0);
728bac60 9633 break;
9634
9635 CASE_FLT_FN (BUILT_IN_ASINH):
c2f47e15 9636 if (validate_arg (arg0, REAL_TYPE))
9637 return do_mpfr_arg1 (arg0, type, mpfr_asinh, NULL, NULL, 0);
728bac60 9638 break;
9639
9640 CASE_FLT_FN (BUILT_IN_ACOSH):
c2f47e15 9641 if (validate_arg (arg0, REAL_TYPE))
9642 return do_mpfr_arg1 (arg0, type, mpfr_acosh,
728bac60 9643 &dconst1, NULL, true);
9644 break;
9645
9646 CASE_FLT_FN (BUILT_IN_ATANH):
c2f47e15 9647 if (validate_arg (arg0, REAL_TYPE))
9648 return do_mpfr_arg1 (arg0, type, mpfr_atanh,
728bac60 9649 &dconstm1, &dconst1, false);
9650 break;
9651
4f35b1fc 9652 CASE_FLT_FN (BUILT_IN_SIN):
c2f47e15 9653 if (validate_arg (arg0, REAL_TYPE))
9654 return do_mpfr_arg1 (arg0, type, mpfr_sin, NULL, NULL, 0);
728bac60 9655 break;
77e89269 9656
4f35b1fc 9657 CASE_FLT_FN (BUILT_IN_COS):
389dd41b 9658 return fold_builtin_cos (loc, arg0, type, fndecl);
77e89269 9659
728bac60 9660 CASE_FLT_FN (BUILT_IN_TAN):
c2f47e15 9661 return fold_builtin_tan (arg0, type);
d735c391 9662
c5bb2c4b 9663 CASE_FLT_FN (BUILT_IN_CEXP):
389dd41b 9664 return fold_builtin_cexp (loc, arg0, type);
c5bb2c4b 9665
d735c391 9666 CASE_FLT_FN (BUILT_IN_CEXPI):
c2f47e15 9667 if (validate_arg (arg0, REAL_TYPE))
9668 return do_mpfr_sincos (arg0, NULL_TREE, NULL_TREE);
9669 break;
d92f994c 9670
728bac60 9671 CASE_FLT_FN (BUILT_IN_SINH):
c2f47e15 9672 if (validate_arg (arg0, REAL_TYPE))
9673 return do_mpfr_arg1 (arg0, type, mpfr_sinh, NULL, NULL, 0);
728bac60 9674 break;
9675
9676 CASE_FLT_FN (BUILT_IN_COSH):
389dd41b 9677 return fold_builtin_cosh (loc, arg0, type, fndecl);
728bac60 9678
9679 CASE_FLT_FN (BUILT_IN_TANH):
c2f47e15 9680 if (validate_arg (arg0, REAL_TYPE))
9681 return do_mpfr_arg1 (arg0, type, mpfr_tanh, NULL, NULL, 0);
728bac60 9682 break;
9683
29f4cd78 9684 CASE_FLT_FN (BUILT_IN_ERF):
c2f47e15 9685 if (validate_arg (arg0, REAL_TYPE))
9686 return do_mpfr_arg1 (arg0, type, mpfr_erf, NULL, NULL, 0);
29f4cd78 9687 break;
9688
9689 CASE_FLT_FN (BUILT_IN_ERFC):
c2f47e15 9690 if (validate_arg (arg0, REAL_TYPE))
9691 return do_mpfr_arg1 (arg0, type, mpfr_erfc, NULL, NULL, 0);
29f4cd78 9692 break;
9693
32dba52b 9694 CASE_FLT_FN (BUILT_IN_TGAMMA):
c2f47e15 9695 if (validate_arg (arg0, REAL_TYPE))
9696 return do_mpfr_arg1 (arg0, type, mpfr_gamma, NULL, NULL, 0);
32dba52b 9697 break;
48e1416a 9698
4f35b1fc 9699 CASE_FLT_FN (BUILT_IN_EXP):
389dd41b 9700 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp);
467214fd 9701
4f35b1fc 9702 CASE_FLT_FN (BUILT_IN_EXP2):
389dd41b 9703 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp2);
467214fd 9704
4f35b1fc 9705 CASE_FLT_FN (BUILT_IN_EXP10):
9706 CASE_FLT_FN (BUILT_IN_POW10):
389dd41b 9707 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp10);
467214fd 9708
29f4cd78 9709 CASE_FLT_FN (BUILT_IN_EXPM1):
c2f47e15 9710 if (validate_arg (arg0, REAL_TYPE))
9711 return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0);
29f4cd78 9712 break;
48e1416a 9713
4f35b1fc 9714 CASE_FLT_FN (BUILT_IN_LOG):
389dd41b 9715 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log);
467214fd 9716
4f35b1fc 9717 CASE_FLT_FN (BUILT_IN_LOG2):
389dd41b 9718 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log2);
467214fd 9719
4f35b1fc 9720 CASE_FLT_FN (BUILT_IN_LOG10):
389dd41b 9721 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log10);
29f4cd78 9722
9723 CASE_FLT_FN (BUILT_IN_LOG1P):
c2f47e15 9724 if (validate_arg (arg0, REAL_TYPE))
9725 return do_mpfr_arg1 (arg0, type, mpfr_log1p,
29f4cd78 9726 &dconstm1, NULL, false);
9727 break;
805e22b2 9728
65dd1378 9729 CASE_FLT_FN (BUILT_IN_J0):
9730 if (validate_arg (arg0, REAL_TYPE))
9731 return do_mpfr_arg1 (arg0, type, mpfr_j0,
9732 NULL, NULL, 0);
9733 break;
9734
9735 CASE_FLT_FN (BUILT_IN_J1):
9736 if (validate_arg (arg0, REAL_TYPE))
9737 return do_mpfr_arg1 (arg0, type, mpfr_j1,
9738 NULL, NULL, 0);
9739 break;
6ff9eeff 9740
9741 CASE_FLT_FN (BUILT_IN_Y0):
9742 if (validate_arg (arg0, REAL_TYPE))
9743 return do_mpfr_arg1 (arg0, type, mpfr_y0,
9744 &dconst0, NULL, false);
9745 break;
9746
9747 CASE_FLT_FN (BUILT_IN_Y1):
9748 if (validate_arg (arg0, REAL_TYPE))
9749 return do_mpfr_arg1 (arg0, type, mpfr_y1,
9750 &dconst0, NULL, false);
9751 break;
65dd1378 9752
4f35b1fc 9753 CASE_FLT_FN (BUILT_IN_NAN):
c4503c0a 9754 case BUILT_IN_NAND32:
9755 case BUILT_IN_NAND64:
9756 case BUILT_IN_NAND128:
c2f47e15 9757 return fold_builtin_nan (arg0, type, true);
b0db7939 9758
4f35b1fc 9759 CASE_FLT_FN (BUILT_IN_NANS):
c2f47e15 9760 return fold_builtin_nan (arg0, type, false);
b0db7939 9761
4f35b1fc 9762 CASE_FLT_FN (BUILT_IN_FLOOR):
389dd41b 9763 return fold_builtin_floor (loc, fndecl, arg0);
277f8dd2 9764
4f35b1fc 9765 CASE_FLT_FN (BUILT_IN_CEIL):
389dd41b 9766 return fold_builtin_ceil (loc, fndecl, arg0);
277f8dd2 9767
4f35b1fc 9768 CASE_FLT_FN (BUILT_IN_TRUNC):
389dd41b 9769 return fold_builtin_trunc (loc, fndecl, arg0);
277f8dd2 9770
4f35b1fc 9771 CASE_FLT_FN (BUILT_IN_ROUND):
389dd41b 9772 return fold_builtin_round (loc, fndecl, arg0);
89ab3887 9773
4f35b1fc 9774 CASE_FLT_FN (BUILT_IN_NEARBYINT):
9775 CASE_FLT_FN (BUILT_IN_RINT):
389dd41b 9776 return fold_trunc_transparent_mathfn (loc, fndecl, arg0);
6528f4f4 9777
4f35b1fc 9778 CASE_FLT_FN (BUILT_IN_LCEIL):
9779 CASE_FLT_FN (BUILT_IN_LLCEIL):
9780 CASE_FLT_FN (BUILT_IN_LFLOOR):
9781 CASE_FLT_FN (BUILT_IN_LLFLOOR):
a0c938f0 9782 CASE_FLT_FN (BUILT_IN_LROUND):
4f35b1fc 9783 CASE_FLT_FN (BUILT_IN_LLROUND):
389dd41b 9784 return fold_builtin_int_roundingfn (loc, fndecl, arg0);
34f17811 9785
4f35b1fc 9786 CASE_FLT_FN (BUILT_IN_LRINT):
9787 CASE_FLT_FN (BUILT_IN_LLRINT):
389dd41b 9788 return fold_fixed_mathfn (loc, fndecl, arg0);
9ed65c7f 9789
42791117 9790 case BUILT_IN_BSWAP32:
9791 case BUILT_IN_BSWAP64:
c2f47e15 9792 return fold_builtin_bswap (fndecl, arg0);
42791117 9793
4f35b1fc 9794 CASE_INT_FN (BUILT_IN_FFS):
9795 CASE_INT_FN (BUILT_IN_CLZ):
9796 CASE_INT_FN (BUILT_IN_CTZ):
6aaa1f9e 9797 CASE_INT_FN (BUILT_IN_CLRSB):
4f35b1fc 9798 CASE_INT_FN (BUILT_IN_POPCOUNT):
9799 CASE_INT_FN (BUILT_IN_PARITY):
c2f47e15 9800 return fold_builtin_bitop (fndecl, arg0);
9c8a1629 9801
4f35b1fc 9802 CASE_FLT_FN (BUILT_IN_SIGNBIT):
389dd41b 9803 return fold_builtin_signbit (loc, arg0, type);
27f261ef 9804
cb2b9385 9805 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
389dd41b 9806 return fold_builtin_significand (loc, arg0, type);
cb2b9385 9807
9808 CASE_FLT_FN (BUILT_IN_ILOGB):
9809 CASE_FLT_FN (BUILT_IN_LOGB):
389dd41b 9810 return fold_builtin_logb (loc, arg0, type);
cb2b9385 9811
d49367d4 9812 case BUILT_IN_ISASCII:
389dd41b 9813 return fold_builtin_isascii (loc, arg0);
d49367d4 9814
9815 case BUILT_IN_TOASCII:
389dd41b 9816 return fold_builtin_toascii (loc, arg0);
d49367d4 9817
df1cf42e 9818 case BUILT_IN_ISDIGIT:
389dd41b 9819 return fold_builtin_isdigit (loc, arg0);
467214fd 9820
4f35b1fc 9821 CASE_FLT_FN (BUILT_IN_FINITE):
c4503c0a 9822 case BUILT_IN_FINITED32:
9823 case BUILT_IN_FINITED64:
9824 case BUILT_IN_FINITED128:
cde061c1 9825 case BUILT_IN_ISFINITE:
a65c4d64 9826 {
9827 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISFINITE);
9828 if (ret)
9829 return ret;
9830 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
9831 }
726069ba 9832
4f35b1fc 9833 CASE_FLT_FN (BUILT_IN_ISINF):
c4503c0a 9834 case BUILT_IN_ISINFD32:
9835 case BUILT_IN_ISINFD64:
9836 case BUILT_IN_ISINFD128:
a65c4d64 9837 {
9838 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF);
9839 if (ret)
9840 return ret;
9841 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
9842 }
9843
9844 case BUILT_IN_ISNORMAL:
9845 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
726069ba 9846
c319d56a 9847 case BUILT_IN_ISINF_SIGN:
389dd41b 9848 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF_SIGN);
c319d56a 9849
4f35b1fc 9850 CASE_FLT_FN (BUILT_IN_ISNAN):
c4503c0a 9851 case BUILT_IN_ISNAND32:
9852 case BUILT_IN_ISNAND64:
9853 case BUILT_IN_ISNAND128:
389dd41b 9854 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
c2f47e15 9855
9856 case BUILT_IN_PRINTF:
9857 case BUILT_IN_PRINTF_UNLOCKED:
9858 case BUILT_IN_VPRINTF:
389dd41b 9859 return fold_builtin_printf (loc, fndecl, arg0, NULL_TREE, ignore, fcode);
c2f47e15 9860
663870fc 9861 case BUILT_IN_FREE:
9862 if (integer_zerop (arg0))
9863 return build_empty_stmt (loc);
9864 break;
9865
c2f47e15 9866 default:
9867 break;
9868 }
9869
9870 return NULL_TREE;
9871
9872}
9873
9874/* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1.
9875 IGNORE is true if the result of the function call is ignored. This
9876 function returns NULL_TREE if no simplification was possible. */
9877
9878static tree
389dd41b 9879fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore)
c2f47e15 9880{
9881 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9882 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9883
9884 switch (fcode)
9885 {
65dd1378 9886 CASE_FLT_FN (BUILT_IN_JN):
9887 if (validate_arg (arg0, INTEGER_TYPE)
9888 && validate_arg (arg1, REAL_TYPE))
9889 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_jn, NULL, 0);
9890 break;
6ff9eeff 9891
9892 CASE_FLT_FN (BUILT_IN_YN):
9893 if (validate_arg (arg0, INTEGER_TYPE)
9894 && validate_arg (arg1, REAL_TYPE))
9895 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_yn,
9896 &dconst0, false);
9897 break;
e5407ca6 9898
9899 CASE_FLT_FN (BUILT_IN_DREM):
9900 CASE_FLT_FN (BUILT_IN_REMAINDER):
9901 if (validate_arg (arg0, REAL_TYPE)
9902 && validate_arg(arg1, REAL_TYPE))
9903 return do_mpfr_arg2 (arg0, arg1, type, mpfr_remainder);
9904 break;
e84da7c1 9905
9906 CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
9907 CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
9908 if (validate_arg (arg0, REAL_TYPE)
9909 && validate_arg(arg1, POINTER_TYPE))
9910 return do_mpfr_lgamma_r (arg0, arg1, type);
9911 break;
c2f47e15 9912
9913 CASE_FLT_FN (BUILT_IN_ATAN2):
9914 if (validate_arg (arg0, REAL_TYPE)
9915 && validate_arg(arg1, REAL_TYPE))
9916 return do_mpfr_arg2 (arg0, arg1, type, mpfr_atan2);
9917 break;
9918
9919 CASE_FLT_FN (BUILT_IN_FDIM):
9920 if (validate_arg (arg0, REAL_TYPE)
9921 && validate_arg(arg1, REAL_TYPE))
9922 return do_mpfr_arg2 (arg0, arg1, type, mpfr_dim);
9923 break;
9924
9925 CASE_FLT_FN (BUILT_IN_HYPOT):
389dd41b 9926 return fold_builtin_hypot (loc, fndecl, arg0, arg1, type);
c2f47e15 9927
c699fab8 9928 CASE_FLT_FN (BUILT_IN_CPOW):
9929 if (validate_arg (arg0, COMPLEX_TYPE)
9930 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
9931 && validate_arg (arg1, COMPLEX_TYPE)
48e1416a 9932 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE)
652d9409 9933 return do_mpc_arg2 (arg0, arg1, type, /*do_nonfinite=*/ 0, mpc_pow);
c699fab8 9934 break;
c699fab8 9935
7587301b 9936 CASE_FLT_FN (BUILT_IN_LDEXP):
389dd41b 9937 return fold_builtin_load_exponent (loc, arg0, arg1, type, /*ldexp=*/true);
7587301b 9938 CASE_FLT_FN (BUILT_IN_SCALBN):
9939 CASE_FLT_FN (BUILT_IN_SCALBLN):
389dd41b 9940 return fold_builtin_load_exponent (loc, arg0, arg1,
9941 type, /*ldexp=*/false);
7587301b 9942
3838b9ae 9943 CASE_FLT_FN (BUILT_IN_FREXP):
389dd41b 9944 return fold_builtin_frexp (loc, arg0, arg1, type);
3838b9ae 9945
ebf8b4f5 9946 CASE_FLT_FN (BUILT_IN_MODF):
389dd41b 9947 return fold_builtin_modf (loc, arg0, arg1, type);
ebf8b4f5 9948
c2f47e15 9949 case BUILT_IN_BZERO:
389dd41b 9950 return fold_builtin_bzero (loc, arg0, arg1, ignore);
c2f47e15 9951
9952 case BUILT_IN_FPUTS:
389dd41b 9953 return fold_builtin_fputs (loc, arg0, arg1, ignore, false, NULL_TREE);
c2f47e15 9954
9955 case BUILT_IN_FPUTS_UNLOCKED:
389dd41b 9956 return fold_builtin_fputs (loc, arg0, arg1, ignore, true, NULL_TREE);
c2f47e15 9957
9958 case BUILT_IN_STRSTR:
389dd41b 9959 return fold_builtin_strstr (loc, arg0, arg1, type);
c2f47e15 9960
9961 case BUILT_IN_STRCAT:
389dd41b 9962 return fold_builtin_strcat (loc, arg0, arg1);
c2f47e15 9963
9964 case BUILT_IN_STRSPN:
389dd41b 9965 return fold_builtin_strspn (loc, arg0, arg1);
c2f47e15 9966
9967 case BUILT_IN_STRCSPN:
389dd41b 9968 return fold_builtin_strcspn (loc, arg0, arg1);
c2f47e15 9969
9970 case BUILT_IN_STRCHR:
9971 case BUILT_IN_INDEX:
389dd41b 9972 return fold_builtin_strchr (loc, arg0, arg1, type);
c2f47e15 9973
9974 case BUILT_IN_STRRCHR:
9975 case BUILT_IN_RINDEX:
389dd41b 9976 return fold_builtin_strrchr (loc, arg0, arg1, type);
c2f47e15 9977
9978 case BUILT_IN_STRCPY:
389dd41b 9979 return fold_builtin_strcpy (loc, fndecl, arg0, arg1, NULL_TREE);
c2f47e15 9980
c8b17b2e 9981 case BUILT_IN_STPCPY:
9982 if (ignore)
9983 {
9984 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
9985 if (!fn)
9986 break;
9987
389dd41b 9988 return build_call_expr_loc (loc, fn, 2, arg0, arg1);
c8b17b2e 9989 }
a65c4d64 9990 else
9991 return fold_builtin_stpcpy (loc, fndecl, arg0, arg1);
c8b17b2e 9992 break;
9993
c2f47e15 9994 case BUILT_IN_STRCMP:
389dd41b 9995 return fold_builtin_strcmp (loc, arg0, arg1);
c2f47e15 9996
9997 case BUILT_IN_STRPBRK:
389dd41b 9998 return fold_builtin_strpbrk (loc, arg0, arg1, type);
c2f47e15 9999
10000 case BUILT_IN_EXPECT:
389dd41b 10001 return fold_builtin_expect (loc, arg0, arg1);
c2f47e15 10002
10003 CASE_FLT_FN (BUILT_IN_POW):
389dd41b 10004 return fold_builtin_pow (loc, fndecl, arg0, arg1, type);
c2f47e15 10005
10006 CASE_FLT_FN (BUILT_IN_POWI):
389dd41b 10007 return fold_builtin_powi (loc, fndecl, arg0, arg1, type);
c2f47e15 10008
10009 CASE_FLT_FN (BUILT_IN_COPYSIGN):
389dd41b 10010 return fold_builtin_copysign (loc, fndecl, arg0, arg1, type);
c2f47e15 10011
10012 CASE_FLT_FN (BUILT_IN_FMIN):
389dd41b 10013 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/false);
c2f47e15 10014
10015 CASE_FLT_FN (BUILT_IN_FMAX):
389dd41b 10016 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/true);
726069ba 10017
9bc9f15f 10018 case BUILT_IN_ISGREATER:
389dd41b 10019 return fold_builtin_unordered_cmp (loc, fndecl,
10020 arg0, arg1, UNLE_EXPR, LE_EXPR);
9bc9f15f 10021 case BUILT_IN_ISGREATEREQUAL:
389dd41b 10022 return fold_builtin_unordered_cmp (loc, fndecl,
10023 arg0, arg1, UNLT_EXPR, LT_EXPR);
9bc9f15f 10024 case BUILT_IN_ISLESS:
389dd41b 10025 return fold_builtin_unordered_cmp (loc, fndecl,
10026 arg0, arg1, UNGE_EXPR, GE_EXPR);
9bc9f15f 10027 case BUILT_IN_ISLESSEQUAL:
389dd41b 10028 return fold_builtin_unordered_cmp (loc, fndecl,
10029 arg0, arg1, UNGT_EXPR, GT_EXPR);
9bc9f15f 10030 case BUILT_IN_ISLESSGREATER:
389dd41b 10031 return fold_builtin_unordered_cmp (loc, fndecl,
10032 arg0, arg1, UNEQ_EXPR, EQ_EXPR);
9bc9f15f 10033 case BUILT_IN_ISUNORDERED:
389dd41b 10034 return fold_builtin_unordered_cmp (loc, fndecl,
10035 arg0, arg1, UNORDERED_EXPR,
d5019fe8 10036 NOP_EXPR);
9bc9f15f 10037
7c2f0500 10038 /* We do the folding for va_start in the expander. */
10039 case BUILT_IN_VA_START:
10040 break;
f0613857 10041
c2f47e15 10042 case BUILT_IN_SPRINTF:
389dd41b 10043 return fold_builtin_sprintf (loc, arg0, arg1, NULL_TREE, ignore);
c2f47e15 10044
0a39fd54 10045 case BUILT_IN_OBJECT_SIZE:
c2f47e15 10046 return fold_builtin_object_size (arg0, arg1);
0a39fd54 10047
10048 case BUILT_IN_PRINTF:
10049 case BUILT_IN_PRINTF_UNLOCKED:
10050 case BUILT_IN_VPRINTF:
389dd41b 10051 return fold_builtin_printf (loc, fndecl, arg0, arg1, ignore, fcode);
c2f47e15 10052
0a39fd54 10053 case BUILT_IN_PRINTF_CHK:
10054 case BUILT_IN_VPRINTF_CHK:
c2f47e15 10055 if (!validate_arg (arg0, INTEGER_TYPE)
10056 || TREE_SIDE_EFFECTS (arg0))
10057 return NULL_TREE;
10058 else
389dd41b 10059 return fold_builtin_printf (loc, fndecl,
10060 arg1, NULL_TREE, ignore, fcode);
c2f47e15 10061 break;
0a39fd54 10062
10063 case BUILT_IN_FPRINTF:
10064 case BUILT_IN_FPRINTF_UNLOCKED:
10065 case BUILT_IN_VFPRINTF:
389dd41b 10066 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, NULL_TREE,
c2f47e15 10067 ignore, fcode);
10068
10069 default:
10070 break;
10071 }
10072 return NULL_TREE;
10073}
10074
10075/* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
10076 and ARG2. IGNORE is true if the result of the function call is ignored.
10077 This function returns NULL_TREE if no simplification was possible. */
10078
10079static tree
389dd41b 10080fold_builtin_3 (location_t loc, tree fndecl,
10081 tree arg0, tree arg1, tree arg2, bool ignore)
c2f47e15 10082{
10083 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10084 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10085 switch (fcode)
10086 {
10087
10088 CASE_FLT_FN (BUILT_IN_SINCOS):
389dd41b 10089 return fold_builtin_sincos (loc, arg0, arg1, arg2);
c2f47e15 10090
10091 CASE_FLT_FN (BUILT_IN_FMA):
b9be572e 10092 return fold_builtin_fma (loc, arg0, arg1, arg2, type);
c2f47e15 10093 break;
10094
e5407ca6 10095 CASE_FLT_FN (BUILT_IN_REMQUO):
10096 if (validate_arg (arg0, REAL_TYPE)
10097 && validate_arg(arg1, REAL_TYPE)
10098 && validate_arg(arg2, POINTER_TYPE))
10099 return do_mpfr_remquo (arg0, arg1, arg2);
10100 break;
e5407ca6 10101
c2f47e15 10102 case BUILT_IN_MEMSET:
389dd41b 10103 return fold_builtin_memset (loc, arg0, arg1, arg2, type, ignore);
c2f47e15 10104
10105 case BUILT_IN_BCOPY:
389dd41b 10106 return fold_builtin_memory_op (loc, arg1, arg0, arg2,
10107 void_type_node, true, /*endp=*/3);
c2f47e15 10108
10109 case BUILT_IN_MEMCPY:
389dd41b 10110 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10111 type, ignore, /*endp=*/0);
c2f47e15 10112
10113 case BUILT_IN_MEMPCPY:
389dd41b 10114 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10115 type, ignore, /*endp=*/1);
c2f47e15 10116
10117 case BUILT_IN_MEMMOVE:
389dd41b 10118 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10119 type, ignore, /*endp=*/3);
c2f47e15 10120
10121 case BUILT_IN_STRNCAT:
389dd41b 10122 return fold_builtin_strncat (loc, arg0, arg1, arg2);
c2f47e15 10123
10124 case BUILT_IN_STRNCPY:
389dd41b 10125 return fold_builtin_strncpy (loc, fndecl, arg0, arg1, arg2, NULL_TREE);
c2f47e15 10126
10127 case BUILT_IN_STRNCMP:
389dd41b 10128 return fold_builtin_strncmp (loc, arg0, arg1, arg2);
c2f47e15 10129
7959b13b 10130 case BUILT_IN_MEMCHR:
389dd41b 10131 return fold_builtin_memchr (loc, arg0, arg1, arg2, type);
7959b13b 10132
c2f47e15 10133 case BUILT_IN_BCMP:
10134 case BUILT_IN_MEMCMP:
389dd41b 10135 return fold_builtin_memcmp (loc, arg0, arg1, arg2);;
c2f47e15 10136
10137 case BUILT_IN_SPRINTF:
389dd41b 10138 return fold_builtin_sprintf (loc, arg0, arg1, arg2, ignore);
c2f47e15 10139
750d7b16 10140 case BUILT_IN_SNPRINTF:
10141 return fold_builtin_snprintf (loc, arg0, arg1, arg2, NULL_TREE, ignore);
10142
c2f47e15 10143 case BUILT_IN_STRCPY_CHK:
10144 case BUILT_IN_STPCPY_CHK:
389dd41b 10145 return fold_builtin_stxcpy_chk (loc, fndecl, arg0, arg1, arg2, NULL_TREE,
c2f47e15 10146 ignore, fcode);
10147
10148 case BUILT_IN_STRCAT_CHK:
389dd41b 10149 return fold_builtin_strcat_chk (loc, fndecl, arg0, arg1, arg2);
c2f47e15 10150
10151 case BUILT_IN_PRINTF_CHK:
10152 case BUILT_IN_VPRINTF_CHK:
10153 if (!validate_arg (arg0, INTEGER_TYPE)
10154 || TREE_SIDE_EFFECTS (arg0))
10155 return NULL_TREE;
10156 else
389dd41b 10157 return fold_builtin_printf (loc, fndecl, arg1, arg2, ignore, fcode);
c2f47e15 10158 break;
10159
10160 case BUILT_IN_FPRINTF:
10161 case BUILT_IN_FPRINTF_UNLOCKED:
10162 case BUILT_IN_VFPRINTF:
389dd41b 10163 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, arg2,
10164 ignore, fcode);
c2f47e15 10165
0a39fd54 10166 case BUILT_IN_FPRINTF_CHK:
10167 case BUILT_IN_VFPRINTF_CHK:
c2f47e15 10168 if (!validate_arg (arg1, INTEGER_TYPE)
10169 || TREE_SIDE_EFFECTS (arg1))
10170 return NULL_TREE;
10171 else
389dd41b 10172 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, NULL_TREE,
c2f47e15 10173 ignore, fcode);
0a39fd54 10174
650e4c94 10175 default:
10176 break;
10177 }
c2f47e15 10178 return NULL_TREE;
10179}
650e4c94 10180
c2f47e15 10181/* Fold a call to built-in function FNDECL with 4 arguments, ARG0, ARG1,
10182 ARG2, and ARG3. IGNORE is true if the result of the function call is
10183 ignored. This function returns NULL_TREE if no simplification was
10184 possible. */
48e1416a 10185
c2f47e15 10186static tree
389dd41b 10187fold_builtin_4 (location_t loc, tree fndecl,
10188 tree arg0, tree arg1, tree arg2, tree arg3, bool ignore)
c2f47e15 10189{
10190 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10191
10192 switch (fcode)
10193 {
10194 case BUILT_IN_MEMCPY_CHK:
10195 case BUILT_IN_MEMPCPY_CHK:
10196 case BUILT_IN_MEMMOVE_CHK:
10197 case BUILT_IN_MEMSET_CHK:
389dd41b 10198 return fold_builtin_memory_chk (loc, fndecl, arg0, arg1, arg2, arg3,
c2f47e15 10199 NULL_TREE, ignore,
10200 DECL_FUNCTION_CODE (fndecl));
10201
10202 case BUILT_IN_STRNCPY_CHK:
389dd41b 10203 return fold_builtin_strncpy_chk (loc, arg0, arg1, arg2, arg3, NULL_TREE);
c2f47e15 10204
10205 case BUILT_IN_STRNCAT_CHK:
389dd41b 10206 return fold_builtin_strncat_chk (loc, fndecl, arg0, arg1, arg2, arg3);
c2f47e15 10207
750d7b16 10208 case BUILT_IN_SNPRINTF:
10209 return fold_builtin_snprintf (loc, arg0, arg1, arg2, arg3, ignore);
10210
c2f47e15 10211 case BUILT_IN_FPRINTF_CHK:
10212 case BUILT_IN_VFPRINTF_CHK:
10213 if (!validate_arg (arg1, INTEGER_TYPE)
10214 || TREE_SIDE_EFFECTS (arg1))
10215 return NULL_TREE;
10216 else
389dd41b 10217 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, arg3,
c2f47e15 10218 ignore, fcode);
10219 break;
10220
10221 default:
10222 break;
10223 }
10224 return NULL_TREE;
10225}
10226
10227/* Fold a call to built-in function FNDECL. ARGS is an array of NARGS
10228 arguments, where NARGS <= 4. IGNORE is true if the result of the
10229 function call is ignored. This function returns NULL_TREE if no
10230 simplification was possible. Note that this only folds builtins with
10231 fixed argument patterns. Foldings that do varargs-to-varargs
10232 transformations, or that match calls with more than 4 arguments,
10233 need to be handled with fold_builtin_varargs instead. */
48e1416a 10234
c2f47e15 10235#define MAX_ARGS_TO_FOLD_BUILTIN 4
48e1416a 10236
c2f47e15 10237static tree
389dd41b 10238fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool ignore)
c2f47e15 10239{
10240 tree ret = NULL_TREE;
a7f5bb2d 10241
c2f47e15 10242 switch (nargs)
10243 {
10244 case 0:
389dd41b 10245 ret = fold_builtin_0 (loc, fndecl, ignore);
c2f47e15 10246 break;
10247 case 1:
389dd41b 10248 ret = fold_builtin_1 (loc, fndecl, args[0], ignore);
c2f47e15 10249 break;
10250 case 2:
389dd41b 10251 ret = fold_builtin_2 (loc, fndecl, args[0], args[1], ignore);
c2f47e15 10252 break;
10253 case 3:
389dd41b 10254 ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2], ignore);
c2f47e15 10255 break;
10256 case 4:
389dd41b 10257 ret = fold_builtin_4 (loc, fndecl, args[0], args[1], args[2], args[3],
c2f47e15 10258 ignore);
10259 break;
10260 default:
10261 break;
10262 }
10263 if (ret)
10264 {
75a70cf9 10265 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
389dd41b 10266 SET_EXPR_LOCATION (ret, loc);
c2f47e15 10267 TREE_NO_WARNING (ret) = 1;
10268 return ret;
10269 }
10270 return NULL_TREE;
10271}
10272
10273/* Builtins with folding operations that operate on "..." arguments
10274 need special handling; we need to store the arguments in a convenient
10275 data structure before attempting any folding. Fortunately there are
10276 only a few builtins that fall into this category. FNDECL is the
10277 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
10278 result of the function call is ignored. */
10279
10280static tree
389dd41b 10281fold_builtin_varargs (location_t loc, tree fndecl, tree exp,
10282 bool ignore ATTRIBUTE_UNUSED)
c2f47e15 10283{
10284 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10285 tree ret = NULL_TREE;
10286
10287 switch (fcode)
10288 {
10289 case BUILT_IN_SPRINTF_CHK:
10290 case BUILT_IN_VSPRINTF_CHK:
389dd41b 10291 ret = fold_builtin_sprintf_chk (loc, exp, fcode);
c2f47e15 10292 break;
10293
10294 case BUILT_IN_SNPRINTF_CHK:
10295 case BUILT_IN_VSNPRINTF_CHK:
389dd41b 10296 ret = fold_builtin_snprintf_chk (loc, exp, NULL_TREE, fcode);
19fbe3a4 10297 break;
10298
10299 case BUILT_IN_FPCLASSIFY:
389dd41b 10300 ret = fold_builtin_fpclassify (loc, exp);
19fbe3a4 10301 break;
c2f47e15 10302
10303 default:
10304 break;
10305 }
10306 if (ret)
10307 {
10308 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
389dd41b 10309 SET_EXPR_LOCATION (ret, loc);
c2f47e15 10310 TREE_NO_WARNING (ret) = 1;
10311 return ret;
10312 }
10313 return NULL_TREE;
650e4c94 10314}
7e15618b 10315
198622c0 10316/* Return true if FNDECL shouldn't be folded right now.
10317 If a built-in function has an inline attribute always_inline
10318 wrapper, defer folding it after always_inline functions have
10319 been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
10320 might not be performed. */
10321
10322static bool
10323avoid_folding_inline_builtin (tree fndecl)
10324{
10325 return (DECL_DECLARED_INLINE_P (fndecl)
10326 && DECL_DISREGARD_INLINE_LIMITS (fndecl)
10327 && cfun
10328 && !cfun->always_inline_functions_inlined
10329 && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)));
10330}
10331
4ee9c684 10332/* A wrapper function for builtin folding that prevents warnings for
491e04ef 10333 "statement without effect" and the like, caused by removing the
4ee9c684 10334 call node earlier than the warning is generated. */
10335
10336tree
389dd41b 10337fold_call_expr (location_t loc, tree exp, bool ignore)
4ee9c684 10338{
c2f47e15 10339 tree ret = NULL_TREE;
10340 tree fndecl = get_callee_fndecl (exp);
10341 if (fndecl
10342 && TREE_CODE (fndecl) == FUNCTION_DECL
48dc2227 10343 && DECL_BUILT_IN (fndecl)
10344 /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
10345 yet. Defer folding until we see all the arguments
10346 (after inlining). */
10347 && !CALL_EXPR_VA_ARG_PACK (exp))
10348 {
10349 int nargs = call_expr_nargs (exp);
10350
10351 /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
10352 instead last argument is __builtin_va_arg_pack (). Defer folding
10353 even in that case, until arguments are finalized. */
10354 if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
10355 {
10356 tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1));
10357 if (fndecl2
10358 && TREE_CODE (fndecl2) == FUNCTION_DECL
10359 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
10360 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
10361 return NULL_TREE;
10362 }
10363
198622c0 10364 if (avoid_folding_inline_builtin (fndecl))
10365 return NULL_TREE;
10366
c2f47e15 10367 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
97d67146 10368 return targetm.fold_builtin (fndecl, call_expr_nargs (exp),
10369 CALL_EXPR_ARGP (exp), ignore);
c2f47e15 10370 else
10371 {
c2f47e15 10372 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
10373 {
10374 tree *args = CALL_EXPR_ARGP (exp);
389dd41b 10375 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
c2f47e15 10376 }
10377 if (!ret)
389dd41b 10378 ret = fold_builtin_varargs (loc, fndecl, exp, ignore);
c2f47e15 10379 if (ret)
389dd41b 10380 return ret;
c2f47e15 10381 }
4ee9c684 10382 }
c2f47e15 10383 return NULL_TREE;
10384}
48e1416a 10385
c2f47e15 10386/* Conveniently construct a function call expression. FNDECL names the
414c3a2c 10387 function to be called and N arguments are passed in the array
10388 ARGARRAY. */
48e1416a 10389
c2f47e15 10390tree
414c3a2c 10391build_call_expr_loc_array (location_t loc, tree fndecl, int n, tree *argarray)
c2f47e15 10392{
10393 tree fntype = TREE_TYPE (fndecl);
10394 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
414c3a2c 10395
389dd41b 10396 return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray);
c2f47e15 10397}
10398
414c3a2c 10399/* Conveniently construct a function call expression. FNDECL names the
10400 function to be called and the arguments are passed in the vector
10401 VEC. */
10402
10403tree
10404build_call_expr_loc_vec (location_t loc, tree fndecl, VEC(tree,gc) *vec)
10405{
10406 return build_call_expr_loc_array (loc, fndecl, VEC_length (tree, vec),
10407 VEC_address (tree, vec));
10408}
10409
10410
c2f47e15 10411/* Conveniently construct a function call expression. FNDECL names the
10412 function to be called, N is the number of arguments, and the "..."
10413 parameters are the argument expressions. */
48e1416a 10414
c2f47e15 10415tree
389dd41b 10416build_call_expr_loc (location_t loc, tree fndecl, int n, ...)
c2f47e15 10417{
10418 va_list ap;
414c3a2c 10419 tree *argarray = XALLOCAVEC (tree, n);
d01f58f9 10420 int i;
c2f47e15 10421
10422 va_start (ap, n);
d01f58f9 10423 for (i = 0; i < n; i++)
10424 argarray[i] = va_arg (ap, tree);
c2f47e15 10425 va_end (ap);
414c3a2c 10426 return build_call_expr_loc_array (loc, fndecl, n, argarray);
4ee9c684 10427}
10428
0568e9c1 10429/* Like build_call_expr_loc (UNKNOWN_LOCATION, ...). Duplicated because
10430 varargs macros aren't supported by all bootstrap compilers. */
10431
10432tree
10433build_call_expr (tree fndecl, int n, ...)
10434{
10435 va_list ap;
414c3a2c 10436 tree *argarray = XALLOCAVEC (tree, n);
0568e9c1 10437 int i;
10438
10439 va_start (ap, n);
10440 for (i = 0; i < n; i++)
10441 argarray[i] = va_arg (ap, tree);
10442 va_end (ap);
414c3a2c 10443 return build_call_expr_loc_array (UNKNOWN_LOCATION, fndecl, n, argarray);
0568e9c1 10444}
10445
c2f47e15 10446/* Construct a CALL_EXPR with type TYPE with FN as the function expression.
d01f58f9 10447 N arguments are passed in the array ARGARRAY. */
805e22b2 10448
10449tree
389dd41b 10450fold_builtin_call_array (location_t loc, tree type,
d01f58f9 10451 tree fn,
10452 int n,
10453 tree *argarray)
7e15618b 10454{
c2f47e15 10455 tree ret = NULL_TREE;
c2f47e15 10456 tree exp;
10457
10458 if (TREE_CODE (fn) == ADDR_EXPR)
10459 {
10460 tree fndecl = TREE_OPERAND (fn, 0);
10461 if (TREE_CODE (fndecl) == FUNCTION_DECL
10462 && DECL_BUILT_IN (fndecl))
10463 {
48dc2227 10464 /* If last argument is __builtin_va_arg_pack (), arguments to this
10465 function are not finalized yet. Defer folding until they are. */
10466 if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
10467 {
10468 tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
10469 if (fndecl2
10470 && TREE_CODE (fndecl2) == FUNCTION_DECL
10471 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
10472 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
389dd41b 10473 return build_call_array_loc (loc, type, fn, n, argarray);
48dc2227 10474 }
198622c0 10475 if (avoid_folding_inline_builtin (fndecl))
389dd41b 10476 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 10477 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
10478 {
97d67146 10479 ret = targetm.fold_builtin (fndecl, n, argarray, false);
10480 if (ret)
10481 return ret;
10482
389dd41b 10483 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 10484 }
10485 else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
10486 {
10487 /* First try the transformations that don't require consing up
10488 an exp. */
389dd41b 10489 ret = fold_builtin_n (loc, fndecl, argarray, n, false);
c2f47e15 10490 if (ret)
10491 return ret;
10492 }
10493
10494 /* If we got this far, we need to build an exp. */
389dd41b 10495 exp = build_call_array_loc (loc, type, fn, n, argarray);
10496 ret = fold_builtin_varargs (loc, fndecl, exp, false);
c2f47e15 10497 return ret ? ret : exp;
10498 }
10499 }
10500
389dd41b 10501 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 10502}
10503
af1409ad 10504/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
10505 list ARGS along with N new arguments in NEWARGS. SKIP is the number
10506 of arguments in ARGS to be omitted. OLDNARGS is the number of
10507 elements in ARGS. */
c2f47e15 10508
10509static tree
af1409ad 10510rewrite_call_expr_valist (location_t loc, int oldnargs, tree *args,
10511 int skip, tree fndecl, int n, va_list newargs)
c2f47e15 10512{
c2f47e15 10513 int nargs = oldnargs - skip + n;
c2f47e15 10514 tree *buffer;
10515
10516 if (n > 0)
10517 {
10518 int i, j;
7e15618b 10519
364c0c59 10520 buffer = XALLOCAVEC (tree, nargs);
c2f47e15 10521 for (i = 0; i < n; i++)
af1409ad 10522 buffer[i] = va_arg (newargs, tree);
c2f47e15 10523 for (j = skip; j < oldnargs; j++, i++)
af1409ad 10524 buffer[i] = args[j];
c2f47e15 10525 }
48e1416a 10526 else
af1409ad 10527 buffer = args + skip;
10528
10529 return build_call_expr_loc_array (loc, fndecl, nargs, buffer);
10530}
10531
10532/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
10533 list ARGS along with N new arguments specified as the "..."
10534 parameters. SKIP is the number of arguments in ARGS to be omitted.
10535 OLDNARGS is the number of elements in ARGS. */
10536
10537static tree
10538rewrite_call_expr_array (location_t loc, int oldnargs, tree *args,
10539 int skip, tree fndecl, int n, ...)
10540{
10541 va_list ap;
10542 tree t;
10543
10544 va_start (ap, n);
10545 t = rewrite_call_expr_valist (loc, oldnargs, args, skip, fndecl, n, ap);
10546 va_end (ap);
10547
10548 return t;
10549}
10550
10551/* Construct a new CALL_EXPR using the tail of the argument list of EXP
10552 along with N new arguments specified as the "..." parameters. SKIP
10553 is the number of arguments in EXP to be omitted. This function is used
10554 to do varargs-to-varargs transformations. */
10555
10556static tree
10557rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...)
10558{
10559 va_list ap;
10560 tree t;
10561
10562 va_start (ap, n);
10563 t = rewrite_call_expr_valist (loc, call_expr_nargs (exp),
10564 CALL_EXPR_ARGP (exp), skip, fndecl, n, ap);
10565 va_end (ap);
c2f47e15 10566
af1409ad 10567 return t;
c2f47e15 10568}
10569
10570/* Validate a single argument ARG against a tree code CODE representing
10571 a type. */
48e1416a 10572
c2f47e15 10573static bool
b7bf20db 10574validate_arg (const_tree arg, enum tree_code code)
c2f47e15 10575{
10576 if (!arg)
10577 return false;
10578 else if (code == POINTER_TYPE)
10579 return POINTER_TYPE_P (TREE_TYPE (arg));
c7f617c2 10580 else if (code == INTEGER_TYPE)
10581 return INTEGRAL_TYPE_P (TREE_TYPE (arg));
c2f47e15 10582 return code == TREE_CODE (TREE_TYPE (arg));
7e15618b 10583}
0eb671f7 10584
75a70cf9 10585/* This function validates the types of a function call argument list
10586 against a specified list of tree_codes. If the last specifier is a 0,
10587 that represents an ellipses, otherwise the last specifier must be a
10588 VOID_TYPE.
10589
10590 This is the GIMPLE version of validate_arglist. Eventually we want to
10591 completely convert builtins.c to work from GIMPLEs and the tree based
10592 validate_arglist will then be removed. */
10593
10594bool
10595validate_gimple_arglist (const_gimple call, ...)
10596{
10597 enum tree_code code;
10598 bool res = 0;
10599 va_list ap;
10600 const_tree arg;
10601 size_t i;
10602
10603 va_start (ap, call);
10604 i = 0;
10605
10606 do
10607 {
d62e827b 10608 code = (enum tree_code) va_arg (ap, int);
75a70cf9 10609 switch (code)
10610 {
10611 case 0:
10612 /* This signifies an ellipses, any further arguments are all ok. */
10613 res = true;
10614 goto end;
10615 case VOID_TYPE:
10616 /* This signifies an endlink, if no arguments remain, return
10617 true, otherwise return false. */
10618 res = (i == gimple_call_num_args (call));
10619 goto end;
10620 default:
10621 /* If no parameters remain or the parameter's code does not
10622 match the specified code, return false. Otherwise continue
10623 checking any remaining arguments. */
10624 arg = gimple_call_arg (call, i++);
10625 if (!validate_arg (arg, code))
10626 goto end;
10627 break;
10628 }
10629 }
10630 while (1);
10631
10632 /* We need gotos here since we can only have one VA_CLOSE in a
10633 function. */
10634 end: ;
10635 va_end (ap);
10636
10637 return res;
10638}
10639
0eb671f7 10640/* This function validates the types of a function call argument list
c2f47e15 10641 against a specified list of tree_codes. If the last specifier is a 0,
10642 that represents an ellipses, otherwise the last specifier must be a
10643 VOID_TYPE. */
27d0c333 10644
c2f47e15 10645bool
b7bf20db 10646validate_arglist (const_tree callexpr, ...)
0eb671f7 10647{
0eb671f7 10648 enum tree_code code;
c2f47e15 10649 bool res = 0;
ee582a61 10650 va_list ap;
b7bf20db 10651 const_call_expr_arg_iterator iter;
10652 const_tree arg;
aecda0d6 10653
c2f47e15 10654 va_start (ap, callexpr);
b7bf20db 10655 init_const_call_expr_arg_iterator (callexpr, &iter);
0eb671f7 10656
f0ce3b1f 10657 do
0eb671f7 10658 {
d62e827b 10659 code = (enum tree_code) va_arg (ap, int);
f0ce3b1f 10660 switch (code)
10661 {
10662 case 0:
10663 /* This signifies an ellipses, any further arguments are all ok. */
c2f47e15 10664 res = true;
f0ce3b1f 10665 goto end;
10666 case VOID_TYPE:
10667 /* This signifies an endlink, if no arguments remain, return
10668 true, otherwise return false. */
b7bf20db 10669 res = !more_const_call_expr_args_p (&iter);
f0ce3b1f 10670 goto end;
10671 default:
10672 /* If no parameters remain or the parameter's code does not
10673 match the specified code, return false. Otherwise continue
10674 checking any remaining arguments. */
b7bf20db 10675 arg = next_const_call_expr_arg (&iter);
c2f47e15 10676 if (!validate_arg (arg, code))
f0ce3b1f 10677 goto end;
10678 break;
10679 }
0eb671f7 10680 }
f0ce3b1f 10681 while (1);
0903457a 10682
10683 /* We need gotos here since we can only have one VA_CLOSE in a
10684 function. */
10685 end: ;
ee582a61 10686 va_end (ap);
0903457a 10687
10688 return res;
0eb671f7 10689}
fc2a2dcb 10690
fc2a2dcb 10691/* Default target-specific builtin expander that does nothing. */
10692
10693rtx
aecda0d6 10694default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
10695 rtx target ATTRIBUTE_UNUSED,
10696 rtx subtarget ATTRIBUTE_UNUSED,
10697 enum machine_mode mode ATTRIBUTE_UNUSED,
10698 int ignore ATTRIBUTE_UNUSED)
fc2a2dcb 10699{
10700 return NULL_RTX;
10701}
c7926a82 10702
01537105 10703/* Returns true is EXP represents data that would potentially reside
10704 in a readonly section. */
10705
10706static bool
10707readonly_data_expr (tree exp)
10708{
10709 STRIP_NOPS (exp);
10710
9ff0637e 10711 if (TREE_CODE (exp) != ADDR_EXPR)
10712 return false;
10713
10714 exp = get_base_address (TREE_OPERAND (exp, 0));
10715 if (!exp)
10716 return false;
10717
10718 /* Make sure we call decl_readonly_section only for trees it
10719 can handle (since it returns true for everything it doesn't
10720 understand). */
491e04ef 10721 if (TREE_CODE (exp) == STRING_CST
9ff0637e 10722 || TREE_CODE (exp) == CONSTRUCTOR
10723 || (TREE_CODE (exp) == VAR_DECL && TREE_STATIC (exp)))
10724 return decl_readonly_section (exp, 0);
01537105 10725 else
10726 return false;
10727}
4ee9c684 10728
c2f47e15 10729/* Simplify a call to the strstr builtin. S1 and S2 are the arguments
10730 to the call, and TYPE is its return type.
4ee9c684 10731
c2f47e15 10732 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10733 simplified form of the call as a tree.
10734
10735 The simplified form may be a constant or other expression which
10736 computes the same value, but in a more efficient manner (including
10737 calls to other builtin functions).
10738
10739 The call may contain arguments which need to be evaluated, but
10740 which are not useful to determine the result of the call. In
10741 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10742 COMPOUND_EXPR will be an argument which must be evaluated.
10743 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10744 COMPOUND_EXPR in the chain will contain the tree for the simplified
10745 form of the builtin function call. */
10746
10747static tree
389dd41b 10748fold_builtin_strstr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 10749{
c2f47e15 10750 if (!validate_arg (s1, POINTER_TYPE)
10751 || !validate_arg (s2, POINTER_TYPE))
10752 return NULL_TREE;
4ee9c684 10753 else
10754 {
4ee9c684 10755 tree fn;
10756 const char *p1, *p2;
10757
10758 p2 = c_getstr (s2);
10759 if (p2 == NULL)
c2f47e15 10760 return NULL_TREE;
4ee9c684 10761
10762 p1 = c_getstr (s1);
10763 if (p1 != NULL)
10764 {
10765 const char *r = strstr (p1, p2);
daa1d5f5 10766 tree tem;
4ee9c684 10767
4ee9c684 10768 if (r == NULL)
779b4c41 10769 return build_int_cst (TREE_TYPE (s1), 0);
c0c67e38 10770
10771 /* Return an offset into the constant string argument. */
2cc66f2a 10772 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 10773 return fold_convert_loc (loc, type, tem);
4ee9c684 10774 }
10775
7efa231c 10776 /* The argument is const char *, and the result is char *, so we need
10777 a type conversion here to avoid a warning. */
4ee9c684 10778 if (p2[0] == '\0')
389dd41b 10779 return fold_convert_loc (loc, type, s1);
4ee9c684 10780
10781 if (p2[1] != '\0')
c2f47e15 10782 return NULL_TREE;
4ee9c684 10783
10784 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
10785 if (!fn)
c2f47e15 10786 return NULL_TREE;
4ee9c684 10787
10788 /* New argument list transforming strstr(s1, s2) to
10789 strchr(s1, s2[0]). */
7002a1c8 10790 return build_call_expr_loc (loc, fn, 2, s1,
10791 build_int_cst (integer_type_node, p2[0]));
4ee9c684 10792 }
10793}
10794
c2f47e15 10795/* Simplify a call to the strchr builtin. S1 and S2 are the arguments to
10796 the call, and TYPE is its return type.
4ee9c684 10797
c2f47e15 10798 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10799 simplified form of the call as a tree.
10800
10801 The simplified form may be a constant or other expression which
10802 computes the same value, but in a more efficient manner (including
10803 calls to other builtin functions).
10804
10805 The call may contain arguments which need to be evaluated, but
10806 which are not useful to determine the result of the call. In
10807 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10808 COMPOUND_EXPR will be an argument which must be evaluated.
10809 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10810 COMPOUND_EXPR in the chain will contain the tree for the simplified
10811 form of the builtin function call. */
10812
10813static tree
389dd41b 10814fold_builtin_strchr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 10815{
c2f47e15 10816 if (!validate_arg (s1, POINTER_TYPE)
10817 || !validate_arg (s2, INTEGER_TYPE))
10818 return NULL_TREE;
4ee9c684 10819 else
10820 {
4ee9c684 10821 const char *p1;
10822
10823 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 10824 return NULL_TREE;
4ee9c684 10825
10826 p1 = c_getstr (s1);
10827 if (p1 != NULL)
10828 {
10829 char c;
10830 const char *r;
daa1d5f5 10831 tree tem;
4ee9c684 10832
10833 if (target_char_cast (s2, &c))
c2f47e15 10834 return NULL_TREE;
4ee9c684 10835
10836 r = strchr (p1, c);
10837
10838 if (r == NULL)
779b4c41 10839 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 10840
10841 /* Return an offset into the constant string argument. */
2cc66f2a 10842 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 10843 return fold_convert_loc (loc, type, tem);
4ee9c684 10844 }
c2f47e15 10845 return NULL_TREE;
4ee9c684 10846 }
10847}
10848
c2f47e15 10849/* Simplify a call to the strrchr builtin. S1 and S2 are the arguments to
10850 the call, and TYPE is its return type.
4ee9c684 10851
c2f47e15 10852 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10853 simplified form of the call as a tree.
10854
10855 The simplified form may be a constant or other expression which
10856 computes the same value, but in a more efficient manner (including
10857 calls to other builtin functions).
10858
10859 The call may contain arguments which need to be evaluated, but
10860 which are not useful to determine the result of the call. In
10861 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10862 COMPOUND_EXPR will be an argument which must be evaluated.
10863 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10864 COMPOUND_EXPR in the chain will contain the tree for the simplified
10865 form of the builtin function call. */
10866
10867static tree
389dd41b 10868fold_builtin_strrchr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 10869{
c2f47e15 10870 if (!validate_arg (s1, POINTER_TYPE)
10871 || !validate_arg (s2, INTEGER_TYPE))
10872 return NULL_TREE;
4ee9c684 10873 else
10874 {
4ee9c684 10875 tree fn;
10876 const char *p1;
10877
10878 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 10879 return NULL_TREE;
4ee9c684 10880
10881 p1 = c_getstr (s1);
10882 if (p1 != NULL)
10883 {
10884 char c;
10885 const char *r;
daa1d5f5 10886 tree tem;
4ee9c684 10887
10888 if (target_char_cast (s2, &c))
c2f47e15 10889 return NULL_TREE;
4ee9c684 10890
10891 r = strrchr (p1, c);
10892
10893 if (r == NULL)
779b4c41 10894 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 10895
10896 /* Return an offset into the constant string argument. */
2cc66f2a 10897 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 10898 return fold_convert_loc (loc, type, tem);
4ee9c684 10899 }
10900
10901 if (! integer_zerop (s2))
c2f47e15 10902 return NULL_TREE;
4ee9c684 10903
10904 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
10905 if (!fn)
c2f47e15 10906 return NULL_TREE;
4ee9c684 10907
10908 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
389dd41b 10909 return build_call_expr_loc (loc, fn, 2, s1, s2);
4ee9c684 10910 }
10911}
10912
c2f47e15 10913/* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments
10914 to the call, and TYPE is its return type.
4ee9c684 10915
c2f47e15 10916 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10917 simplified form of the call as a tree.
10918
10919 The simplified form may be a constant or other expression which
10920 computes the same value, but in a more efficient manner (including
10921 calls to other builtin functions).
10922
10923 The call may contain arguments which need to be evaluated, but
10924 which are not useful to determine the result of the call. In
10925 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10926 COMPOUND_EXPR will be an argument which must be evaluated.
10927 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10928 COMPOUND_EXPR in the chain will contain the tree for the simplified
10929 form of the builtin function call. */
10930
10931static tree
389dd41b 10932fold_builtin_strpbrk (location_t loc, tree s1, tree s2, tree type)
4ee9c684 10933{
c2f47e15 10934 if (!validate_arg (s1, POINTER_TYPE)
10935 || !validate_arg (s2, POINTER_TYPE))
10936 return NULL_TREE;
4ee9c684 10937 else
10938 {
4ee9c684 10939 tree fn;
10940 const char *p1, *p2;
10941
10942 p2 = c_getstr (s2);
10943 if (p2 == NULL)
c2f47e15 10944 return NULL_TREE;
4ee9c684 10945
10946 p1 = c_getstr (s1);
10947 if (p1 != NULL)
10948 {
10949 const char *r = strpbrk (p1, p2);
daa1d5f5 10950 tree tem;
4ee9c684 10951
10952 if (r == NULL)
779b4c41 10953 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 10954
10955 /* Return an offset into the constant string argument. */
2cc66f2a 10956 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 10957 return fold_convert_loc (loc, type, tem);
4ee9c684 10958 }
10959
10960 if (p2[0] == '\0')
05abc81b 10961 /* strpbrk(x, "") == NULL.
10962 Evaluate and ignore s1 in case it had side-effects. */
389dd41b 10963 return omit_one_operand_loc (loc, TREE_TYPE (s1), integer_zero_node, s1);
4ee9c684 10964
10965 if (p2[1] != '\0')
c2f47e15 10966 return NULL_TREE; /* Really call strpbrk. */
4ee9c684 10967
10968 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
10969 if (!fn)
c2f47e15 10970 return NULL_TREE;
4ee9c684 10971
10972 /* New argument list transforming strpbrk(s1, s2) to
10973 strchr(s1, s2[0]). */
7002a1c8 10974 return build_call_expr_loc (loc, fn, 2, s1,
10975 build_int_cst (integer_type_node, p2[0]));
4ee9c684 10976 }
10977}
10978
c2f47e15 10979/* Simplify a call to the strcat builtin. DST and SRC are the arguments
10980 to the call.
4ee9c684 10981
c2f47e15 10982 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10983 simplified form of the call as a tree.
10984
10985 The simplified form may be a constant or other expression which
10986 computes the same value, but in a more efficient manner (including
10987 calls to other builtin functions).
10988
10989 The call may contain arguments which need to be evaluated, but
10990 which are not useful to determine the result of the call. In
10991 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10992 COMPOUND_EXPR will be an argument which must be evaluated.
10993 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10994 COMPOUND_EXPR in the chain will contain the tree for the simplified
10995 form of the builtin function call. */
10996
10997static tree
389dd41b 10998fold_builtin_strcat (location_t loc ATTRIBUTE_UNUSED, tree dst, tree src)
4ee9c684 10999{
c2f47e15 11000 if (!validate_arg (dst, POINTER_TYPE)
11001 || !validate_arg (src, POINTER_TYPE))
11002 return NULL_TREE;
4ee9c684 11003 else
11004 {
4ee9c684 11005 const char *p = c_getstr (src);
11006
11007 /* If the string length is zero, return the dst parameter. */
11008 if (p && *p == '\0')
11009 return dst;
11010
a65c4d64 11011 if (optimize_insn_for_speed_p ())
11012 {
11013 /* See if we can store by pieces into (dst + strlen(dst)). */
11014 tree newdst, call;
11015 tree strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
11016 tree strcpy_fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11017
11018 if (!strlen_fn || !strcpy_fn)
11019 return NULL_TREE;
11020
11021 /* If we don't have a movstr we don't want to emit an strcpy
11022 call. We have to do that if the length of the source string
11023 isn't computable (in that case we can use memcpy probably
48e1416a 11024 later expanding to a sequence of mov instructions). If we
a65c4d64 11025 have movstr instructions we can emit strcpy calls. */
11026 if (!HAVE_movstr)
11027 {
11028 tree len = c_strlen (src, 1);
11029 if (! len || TREE_SIDE_EFFECTS (len))
11030 return NULL_TREE;
11031 }
11032
11033 /* Stabilize the argument list. */
11034 dst = builtin_save_expr (dst);
11035
11036 /* Create strlen (dst). */
11037 newdst = build_call_expr_loc (loc, strlen_fn, 1, dst);
11038 /* Create (dst p+ strlen (dst)). */
11039
2cc66f2a 11040 newdst = fold_build_pointer_plus_loc (loc, dst, newdst);
a65c4d64 11041 newdst = builtin_save_expr (newdst);
11042
11043 call = build_call_expr_loc (loc, strcpy_fn, 2, newdst, src);
11044 return build2 (COMPOUND_EXPR, TREE_TYPE (dst), call, dst);
11045 }
c2f47e15 11046 return NULL_TREE;
4ee9c684 11047 }
11048}
11049
c2f47e15 11050/* Simplify a call to the strncat builtin. DST, SRC, and LEN are the
11051 arguments to the call.
4ee9c684 11052
c2f47e15 11053 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11054 simplified form of the call as a tree.
11055
11056 The simplified form may be a constant or other expression which
11057 computes the same value, but in a more efficient manner (including
11058 calls to other builtin functions).
11059
11060 The call may contain arguments which need to be evaluated, but
11061 which are not useful to determine the result of the call. In
11062 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11063 COMPOUND_EXPR will be an argument which must be evaluated.
11064 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11065 COMPOUND_EXPR in the chain will contain the tree for the simplified
11066 form of the builtin function call. */
11067
11068static tree
389dd41b 11069fold_builtin_strncat (location_t loc, tree dst, tree src, tree len)
4ee9c684 11070{
c2f47e15 11071 if (!validate_arg (dst, POINTER_TYPE)
11072 || !validate_arg (src, POINTER_TYPE)
11073 || !validate_arg (len, INTEGER_TYPE))
11074 return NULL_TREE;
4ee9c684 11075 else
11076 {
4ee9c684 11077 const char *p = c_getstr (src);
11078
11079 /* If the requested length is zero, or the src parameter string
0a39fd54 11080 length is zero, return the dst parameter. */
4ee9c684 11081 if (integer_zerop (len) || (p && *p == '\0'))
389dd41b 11082 return omit_two_operands_loc (loc, TREE_TYPE (dst), dst, src, len);
4ee9c684 11083
11084 /* If the requested len is greater than or equal to the string
a0c938f0 11085 length, call strcat. */
4ee9c684 11086 if (TREE_CODE (len) == INTEGER_CST && p
11087 && compare_tree_int (len, strlen (p)) >= 0)
11088 {
4ee9c684 11089 tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
11090
11091 /* If the replacement _DECL isn't initialized, don't do the
11092 transformation. */
11093 if (!fn)
c2f47e15 11094 return NULL_TREE;
4ee9c684 11095
389dd41b 11096 return build_call_expr_loc (loc, fn, 2, dst, src);
4ee9c684 11097 }
c2f47e15 11098 return NULL_TREE;
4ee9c684 11099 }
11100}
11101
c2f47e15 11102/* Simplify a call to the strspn builtin. S1 and S2 are the arguments
11103 to the call.
4ee9c684 11104
c2f47e15 11105 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11106 simplified form of the call as a tree.
11107
11108 The simplified form may be a constant or other expression which
11109 computes the same value, but in a more efficient manner (including
11110 calls to other builtin functions).
11111
11112 The call may contain arguments which need to be evaluated, but
11113 which are not useful to determine the result of the call. In
11114 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11115 COMPOUND_EXPR will be an argument which must be evaluated.
11116 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11117 COMPOUND_EXPR in the chain will contain the tree for the simplified
11118 form of the builtin function call. */
11119
11120static tree
389dd41b 11121fold_builtin_strspn (location_t loc, tree s1, tree s2)
4ee9c684 11122{
c2f47e15 11123 if (!validate_arg (s1, POINTER_TYPE)
11124 || !validate_arg (s2, POINTER_TYPE))
11125 return NULL_TREE;
4ee9c684 11126 else
11127 {
4ee9c684 11128 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11129
11130 /* If both arguments are constants, evaluate at compile-time. */
11131 if (p1 && p2)
11132 {
11133 const size_t r = strspn (p1, p2);
11134 return size_int (r);
11135 }
11136
c2f47e15 11137 /* If either argument is "", return NULL_TREE. */
4ee9c684 11138 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9bc9f15f 11139 /* Evaluate and ignore both arguments in case either one has
11140 side-effects. */
389dd41b 11141 return omit_two_operands_loc (loc, size_type_node, size_zero_node,
9bc9f15f 11142 s1, s2);
c2f47e15 11143 return NULL_TREE;
4ee9c684 11144 }
11145}
11146
c2f47e15 11147/* Simplify a call to the strcspn builtin. S1 and S2 are the arguments
11148 to the call.
4ee9c684 11149
c2f47e15 11150 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11151 simplified form of the call as a tree.
11152
11153 The simplified form may be a constant or other expression which
11154 computes the same value, but in a more efficient manner (including
11155 calls to other builtin functions).
11156
11157 The call may contain arguments which need to be evaluated, but
11158 which are not useful to determine the result of the call. In
11159 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11160 COMPOUND_EXPR will be an argument which must be evaluated.
11161 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11162 COMPOUND_EXPR in the chain will contain the tree for the simplified
11163 form of the builtin function call. */
11164
11165static tree
389dd41b 11166fold_builtin_strcspn (location_t loc, tree s1, tree s2)
4ee9c684 11167{
c2f47e15 11168 if (!validate_arg (s1, POINTER_TYPE)
11169 || !validate_arg (s2, POINTER_TYPE))
11170 return NULL_TREE;
4ee9c684 11171 else
11172 {
4ee9c684 11173 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11174
11175 /* If both arguments are constants, evaluate at compile-time. */
11176 if (p1 && p2)
11177 {
11178 const size_t r = strcspn (p1, p2);
11179 return size_int (r);
11180 }
11181
c2f47e15 11182 /* If the first argument is "", return NULL_TREE. */
4ee9c684 11183 if (p1 && *p1 == '\0')
11184 {
11185 /* Evaluate and ignore argument s2 in case it has
11186 side-effects. */
389dd41b 11187 return omit_one_operand_loc (loc, size_type_node,
39761420 11188 size_zero_node, s2);
4ee9c684 11189 }
11190
11191 /* If the second argument is "", return __builtin_strlen(s1). */
11192 if (p2 && *p2 == '\0')
11193 {
c2f47e15 11194 tree fn = implicit_built_in_decls[BUILT_IN_STRLEN];
4ee9c684 11195
11196 /* If the replacement _DECL isn't initialized, don't do the
11197 transformation. */
11198 if (!fn)
c2f47e15 11199 return NULL_TREE;
4ee9c684 11200
389dd41b 11201 return build_call_expr_loc (loc, fn, 1, s1);
4ee9c684 11202 }
c2f47e15 11203 return NULL_TREE;
4ee9c684 11204 }
11205}
11206
c2f47e15 11207/* Fold a call to the fputs builtin. ARG0 and ARG1 are the arguments
11208 to the call. IGNORE is true if the value returned
f0613857 11209 by the builtin will be ignored. UNLOCKED is true is true if this
11210 actually a call to fputs_unlocked. If LEN in non-NULL, it represents
11211 the known length of the string. Return NULL_TREE if no simplification
11212 was possible. */
4ee9c684 11213
11214tree
389dd41b 11215fold_builtin_fputs (location_t loc, tree arg0, tree arg1,
11216 bool ignore, bool unlocked, tree len)
4ee9c684 11217{
6d77ed92 11218 /* If we're using an unlocked function, assume the other unlocked
11219 functions exist explicitly. */
11220 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
4ee9c684 11221 : implicit_built_in_decls[BUILT_IN_FPUTC];
6d77ed92 11222 tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
4ee9c684 11223 : implicit_built_in_decls[BUILT_IN_FWRITE];
11224
c403edd4 11225 /* If the return value is used, don't do the transformation. */
11226 if (!ignore)
c2f47e15 11227 return NULL_TREE;
4ee9c684 11228
11229 /* Verify the arguments in the original call. */
c2f47e15 11230 if (!validate_arg (arg0, POINTER_TYPE)
11231 || !validate_arg (arg1, POINTER_TYPE))
11232 return NULL_TREE;
4ee9c684 11233
f0613857 11234 if (! len)
c2f47e15 11235 len = c_strlen (arg0, 0);
4ee9c684 11236
11237 /* Get the length of the string passed to fputs. If the length
11238 can't be determined, punt. */
11239 if (!len
11240 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 11241 return NULL_TREE;
4ee9c684 11242
11243 switch (compare_tree_int (len, 1))
11244 {
11245 case -1: /* length is 0, delete the call entirely . */
389dd41b 11246 return omit_one_operand_loc (loc, integer_type_node,
11247 integer_zero_node, arg1);;
05abc81b 11248
4ee9c684 11249 case 0: /* length is 1, call fputc. */
11250 {
c2f47e15 11251 const char *p = c_getstr (arg0);
4ee9c684 11252
11253 if (p != NULL)
11254 {
c2f47e15 11255 if (fn_fputc)
389dd41b 11256 return build_call_expr_loc (loc, fn_fputc, 2,
7002a1c8 11257 build_int_cst
11258 (integer_type_node, p[0]), arg1);
c2f47e15 11259 else
11260 return NULL_TREE;
4ee9c684 11261 }
11262 }
11263 /* FALLTHROUGH */
11264 case 1: /* length is greater than 1, call fwrite. */
11265 {
0bed3869 11266 /* If optimizing for size keep fputs. */
0bfd8d5c 11267 if (optimize_function_for_size_p (cfun))
c2f47e15 11268 return NULL_TREE;
4ee9c684 11269 /* New argument list transforming fputs(string, stream) to
11270 fwrite(string, 1, len, stream). */
c2f47e15 11271 if (fn_fwrite)
389dd41b 11272 return build_call_expr_loc (loc, fn_fwrite, 4, arg0,
11273 size_one_node, len, arg1);
c2f47e15 11274 else
11275 return NULL_TREE;
4ee9c684 11276 }
11277 default:
64db345d 11278 gcc_unreachable ();
4ee9c684 11279 }
c2f47e15 11280 return NULL_TREE;
4ee9c684 11281}
11282
c2f47e15 11283/* Fold the next_arg or va_start call EXP. Returns true if there was an error
743b0c6a 11284 produced. False otherwise. This is done so that we don't output the error
11285 or warning twice or three times. */
75a70cf9 11286
743b0c6a 11287bool
c2f47e15 11288fold_builtin_next_arg (tree exp, bool va_start_p)
4ee9c684 11289{
11290 tree fntype = TREE_TYPE (current_function_decl);
c2f47e15 11291 int nargs = call_expr_nargs (exp);
11292 tree arg;
4ee9c684 11293
257d99c3 11294 if (!stdarg_p (fntype))
743b0c6a 11295 {
11296 error ("%<va_start%> used in function with fixed args");
11297 return true;
11298 }
c2f47e15 11299
11300 if (va_start_p)
79012a9d 11301 {
c2f47e15 11302 if (va_start_p && (nargs != 2))
11303 {
11304 error ("wrong number of arguments to function %<va_start%>");
11305 return true;
11306 }
11307 arg = CALL_EXPR_ARG (exp, 1);
79012a9d 11308 }
11309 /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
11310 when we checked the arguments and if needed issued a warning. */
c2f47e15 11311 else
4ee9c684 11312 {
c2f47e15 11313 if (nargs == 0)
11314 {
11315 /* Evidently an out of date version of <stdarg.h>; can't validate
11316 va_start's second argument, but can still work as intended. */
11317 warning (0, "%<__builtin_next_arg%> called without an argument");
11318 return true;
11319 }
11320 else if (nargs > 1)
a0c938f0 11321 {
c2f47e15 11322 error ("wrong number of arguments to function %<__builtin_next_arg%>");
a0c938f0 11323 return true;
11324 }
c2f47e15 11325 arg = CALL_EXPR_ARG (exp, 0);
11326 }
11327
a8dd994c 11328 if (TREE_CODE (arg) == SSA_NAME)
11329 arg = SSA_NAME_VAR (arg);
11330
c2f47e15 11331 /* We destructively modify the call to be __builtin_va_start (ap, 0)
48e1416a 11332 or __builtin_next_arg (0) the first time we see it, after checking
c2f47e15 11333 the arguments and if needed issuing a warning. */
11334 if (!integer_zerop (arg))
11335 {
11336 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
79012a9d 11337
4ee9c684 11338 /* Strip off all nops for the sake of the comparison. This
11339 is not quite the same as STRIP_NOPS. It does more.
11340 We must also strip off INDIRECT_EXPR for C++ reference
11341 parameters. */
72dd6141 11342 while (CONVERT_EXPR_P (arg)
4ee9c684 11343 || TREE_CODE (arg) == INDIRECT_REF)
11344 arg = TREE_OPERAND (arg, 0);
11345 if (arg != last_parm)
a0c938f0 11346 {
b08cf617 11347 /* FIXME: Sometimes with the tree optimizers we can get the
11348 not the last argument even though the user used the last
11349 argument. We just warn and set the arg to be the last
11350 argument so that we will get wrong-code because of
11351 it. */
c3ceba8e 11352 warning (0, "second parameter of %<va_start%> not last named argument");
743b0c6a 11353 }
24158ad7 11354
11355 /* Undefined by C99 7.15.1.4p4 (va_start):
11356 "If the parameter parmN is declared with the register storage
11357 class, with a function or array type, or with a type that is
11358 not compatible with the type that results after application of
11359 the default argument promotions, the behavior is undefined."
11360 */
11361 else if (DECL_REGISTER (arg))
11362 warning (0, "undefined behaviour when second parameter of "
11363 "%<va_start%> is declared with %<register%> storage");
11364
79012a9d 11365 /* We want to verify the second parameter just once before the tree
a0c938f0 11366 optimizers are run and then avoid keeping it in the tree,
11367 as otherwise we could warn even for correct code like:
11368 void foo (int i, ...)
11369 { va_list ap; i++; va_start (ap, i); va_end (ap); } */
c2f47e15 11370 if (va_start_p)
11371 CALL_EXPR_ARG (exp, 1) = integer_zero_node;
11372 else
11373 CALL_EXPR_ARG (exp, 0) = integer_zero_node;
743b0c6a 11374 }
11375 return false;
4ee9c684 11376}
11377
11378
c2f47e15 11379/* Simplify a call to the sprintf builtin with arguments DEST, FMT, and ORIG.
11380 ORIG may be null if this is a 2-argument call. We don't attempt to
11381 simplify calls with more than 3 arguments.
4ee9c684 11382
c2f47e15 11383 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11384 simplified form of the call as a tree. If IGNORED is true, it means that
11385 the caller does not use the returned value of the function. */
11386
11387static tree
389dd41b 11388fold_builtin_sprintf (location_t loc, tree dest, tree fmt,
11389 tree orig, int ignored)
4ee9c684 11390{
c2f47e15 11391 tree call, retval;
4ee9c684 11392 const char *fmt_str = NULL;
11393
11394 /* Verify the required arguments in the original call. We deal with two
11395 types of sprintf() calls: 'sprintf (str, fmt)' and
11396 'sprintf (dest, "%s", orig)'. */
c2f47e15 11397 if (!validate_arg (dest, POINTER_TYPE)
11398 || !validate_arg (fmt, POINTER_TYPE))
11399 return NULL_TREE;
11400 if (orig && !validate_arg (orig, POINTER_TYPE))
4ee9c684 11401 return NULL_TREE;
4ee9c684 11402
11403 /* Check whether the format is a literal string constant. */
11404 fmt_str = c_getstr (fmt);
11405 if (fmt_str == NULL)
11406 return NULL_TREE;
11407
11408 call = NULL_TREE;
11409 retval = NULL_TREE;
11410
d4473c84 11411 if (!init_target_chars ())
c2f47e15 11412 return NULL_TREE;
99eabcc1 11413
4ee9c684 11414 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 11415 if (strchr (fmt_str, target_percent) == NULL)
4ee9c684 11416 {
11417 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11418
11419 if (!fn)
11420 return NULL_TREE;
11421
72dfb3f2 11422 /* Don't optimize sprintf (buf, "abc", ptr++). */
c2f47e15 11423 if (orig)
72dfb3f2 11424 return NULL_TREE;
11425
4ee9c684 11426 /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
11427 'format' is known to contain no % formats. */
389dd41b 11428 call = build_call_expr_loc (loc, fn, 2, dest, fmt);
4ee9c684 11429 if (!ignored)
7002a1c8 11430 retval = build_int_cst (integer_type_node, strlen (fmt_str));
4ee9c684 11431 }
11432
11433 /* If the format is "%s", use strcpy if the result isn't used. */
99eabcc1 11434 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
4ee9c684 11435 {
c2f47e15 11436 tree fn;
4ee9c684 11437 fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11438
11439 if (!fn)
11440 return NULL_TREE;
11441
72dfb3f2 11442 /* Don't crash on sprintf (str1, "%s"). */
c2f47e15 11443 if (!orig)
72dfb3f2 11444 return NULL_TREE;
11445
4ee9c684 11446 /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2). */
4ee9c684 11447 if (!ignored)
11448 {
11449 retval = c_strlen (orig, 1);
11450 if (!retval || TREE_CODE (retval) != INTEGER_CST)
11451 return NULL_TREE;
11452 }
389dd41b 11453 call = build_call_expr_loc (loc, fn, 2, dest, orig);
4ee9c684 11454 }
11455
11456 if (call && retval)
11457 {
389dd41b 11458 retval = fold_convert_loc
11459 (loc, TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])),
4ee9c684 11460 retval);
05abc81b 11461 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
4ee9c684 11462 }
11463 else
11464 return call;
11465}
0a39fd54 11466
750d7b16 11467/* Simplify a call to the snprintf builtin with arguments DEST, DESTSIZE,
11468 FMT, and ORIG. ORIG may be null if this is a 3-argument call. We don't
11469 attempt to simplify calls with more than 4 arguments.
11470
11471 Return NULL_TREE if no simplification was possible, otherwise return the
11472 simplified form of the call as a tree. If IGNORED is true, it means that
11473 the caller does not use the returned value of the function. */
11474
11475static tree
11476fold_builtin_snprintf (location_t loc, tree dest, tree destsize, tree fmt,
11477 tree orig, int ignored)
11478{
11479 tree call, retval;
11480 const char *fmt_str = NULL;
11481 unsigned HOST_WIDE_INT destlen;
11482
11483 /* Verify the required arguments in the original call. We deal with two
11484 types of snprintf() calls: 'snprintf (str, cst, fmt)' and
11485 'snprintf (dest, cst, "%s", orig)'. */
11486 if (!validate_arg (dest, POINTER_TYPE)
11487 || !validate_arg (destsize, INTEGER_TYPE)
11488 || !validate_arg (fmt, POINTER_TYPE))
11489 return NULL_TREE;
11490 if (orig && !validate_arg (orig, POINTER_TYPE))
11491 return NULL_TREE;
11492
11493 if (!host_integerp (destsize, 1))
11494 return NULL_TREE;
11495
11496 /* Check whether the format is a literal string constant. */
11497 fmt_str = c_getstr (fmt);
11498 if (fmt_str == NULL)
11499 return NULL_TREE;
11500
11501 call = NULL_TREE;
11502 retval = NULL_TREE;
11503
11504 if (!init_target_chars ())
11505 return NULL_TREE;
11506
11507 destlen = tree_low_cst (destsize, 1);
11508
11509 /* If the format doesn't contain % args or %%, use strcpy. */
11510 if (strchr (fmt_str, target_percent) == NULL)
11511 {
11512 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11513 size_t len = strlen (fmt_str);
11514
11515 /* Don't optimize snprintf (buf, 4, "abc", ptr++). */
11516 if (orig)
11517 return NULL_TREE;
11518
11519 /* We could expand this as
11520 memcpy (str, fmt, cst - 1); str[cst - 1] = '\0';
11521 or to
11522 memcpy (str, fmt_with_nul_at_cstm1, cst);
11523 but in the former case that might increase code size
11524 and in the latter case grow .rodata section too much.
11525 So punt for now. */
11526 if (len >= destlen)
11527 return NULL_TREE;
11528
11529 if (!fn)
11530 return NULL_TREE;
11531
11532 /* Convert snprintf (str, cst, fmt) into strcpy (str, fmt) when
11533 'format' is known to contain no % formats and
11534 strlen (fmt) < cst. */
11535 call = build_call_expr_loc (loc, fn, 2, dest, fmt);
11536
11537 if (!ignored)
7002a1c8 11538 retval = build_int_cst (integer_type_node, strlen (fmt_str));
750d7b16 11539 }
11540
11541 /* If the format is "%s", use strcpy if the result isn't used. */
11542 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
11543 {
11544 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11545 unsigned HOST_WIDE_INT origlen;
11546
11547 /* Don't crash on snprintf (str1, cst, "%s"). */
11548 if (!orig)
11549 return NULL_TREE;
11550
11551 retval = c_strlen (orig, 1);
11552 if (!retval || !host_integerp (retval, 1))
11553 return NULL_TREE;
11554
11555 origlen = tree_low_cst (retval, 1);
11556 /* We could expand this as
11557 memcpy (str1, str2, cst - 1); str1[cst - 1] = '\0';
11558 or to
11559 memcpy (str1, str2_with_nul_at_cstm1, cst);
11560 but in the former case that might increase code size
11561 and in the latter case grow .rodata section too much.
11562 So punt for now. */
11563 if (origlen >= destlen)
11564 return NULL_TREE;
11565
11566 /* Convert snprintf (str1, cst, "%s", str2) into
11567 strcpy (str1, str2) if strlen (str2) < cst. */
11568 if (!fn)
11569 return NULL_TREE;
11570
11571 call = build_call_expr_loc (loc, fn, 2, dest, orig);
11572
11573 if (ignored)
11574 retval = NULL_TREE;
11575 }
11576
11577 if (call && retval)
11578 {
1914d98e 11579 tree fn = built_in_decls[BUILT_IN_SNPRINTF];
11580 retval = fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fn)), retval);
750d7b16 11581 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
11582 }
11583 else
11584 return call;
11585}
11586
c2f47e15 11587/* Expand a call EXP to __builtin_object_size. */
0a39fd54 11588
11589rtx
11590expand_builtin_object_size (tree exp)
11591{
11592 tree ost;
11593 int object_size_type;
11594 tree fndecl = get_callee_fndecl (exp);
0a39fd54 11595
c2f47e15 11596 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
0a39fd54 11597 {
b8c23db3 11598 error ("%Kfirst argument of %D must be a pointer, second integer constant",
11599 exp, fndecl);
0a39fd54 11600 expand_builtin_trap ();
11601 return const0_rtx;
11602 }
11603
c2f47e15 11604 ost = CALL_EXPR_ARG (exp, 1);
0a39fd54 11605 STRIP_NOPS (ost);
11606
11607 if (TREE_CODE (ost) != INTEGER_CST
11608 || tree_int_cst_sgn (ost) < 0
11609 || compare_tree_int (ost, 3) > 0)
11610 {
b8c23db3 11611 error ("%Klast argument of %D is not integer constant between 0 and 3",
11612 exp, fndecl);
0a39fd54 11613 expand_builtin_trap ();
11614 return const0_rtx;
11615 }
11616
11617 object_size_type = tree_low_cst (ost, 0);
11618
11619 return object_size_type < 2 ? constm1_rtx : const0_rtx;
11620}
11621
11622/* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
11623 FCODE is the BUILT_IN_* to use.
c2f47e15 11624 Return NULL_RTX if we failed; the caller should emit a normal call,
0a39fd54 11625 otherwise try to get the result in TARGET, if convenient (and in
11626 mode MODE if that's convenient). */
11627
11628static rtx
11629expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
11630 enum built_in_function fcode)
11631{
0a39fd54 11632 tree dest, src, len, size;
11633
c2f47e15 11634 if (!validate_arglist (exp,
0a39fd54 11635 POINTER_TYPE,
11636 fcode == BUILT_IN_MEMSET_CHK
11637 ? INTEGER_TYPE : POINTER_TYPE,
11638 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
c2f47e15 11639 return NULL_RTX;
0a39fd54 11640
c2f47e15 11641 dest = CALL_EXPR_ARG (exp, 0);
11642 src = CALL_EXPR_ARG (exp, 1);
11643 len = CALL_EXPR_ARG (exp, 2);
11644 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11645
11646 if (! host_integerp (size, 1))
c2f47e15 11647 return NULL_RTX;
0a39fd54 11648
11649 if (host_integerp (len, 1) || integer_all_onesp (size))
11650 {
11651 tree fn;
11652
11653 if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
11654 {
b430e8d9 11655 warning_at (tree_nonartificial_location (exp),
11656 0, "%Kcall to %D will always overflow destination buffer",
11657 exp, get_callee_fndecl (exp));
c2f47e15 11658 return NULL_RTX;
0a39fd54 11659 }
11660
0a39fd54 11661 fn = NULL_TREE;
11662 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
11663 mem{cpy,pcpy,move,set} is available. */
11664 switch (fcode)
11665 {
11666 case BUILT_IN_MEMCPY_CHK:
11667 fn = built_in_decls[BUILT_IN_MEMCPY];
11668 break;
11669 case BUILT_IN_MEMPCPY_CHK:
11670 fn = built_in_decls[BUILT_IN_MEMPCPY];
11671 break;
11672 case BUILT_IN_MEMMOVE_CHK:
11673 fn = built_in_decls[BUILT_IN_MEMMOVE];
11674 break;
11675 case BUILT_IN_MEMSET_CHK:
11676 fn = built_in_decls[BUILT_IN_MEMSET];
11677 break;
11678 default:
11679 break;
11680 }
11681
11682 if (! fn)
c2f47e15 11683 return NULL_RTX;
0a39fd54 11684
0568e9c1 11685 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 3, dest, src, len);
a65c4d64 11686 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
11687 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0a39fd54 11688 return expand_expr (fn, target, mode, EXPAND_NORMAL);
11689 }
11690 else if (fcode == BUILT_IN_MEMSET_CHK)
c2f47e15 11691 return NULL_RTX;
0a39fd54 11692 else
11693 {
11694 unsigned int dest_align
11695 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
11696
11697 /* If DEST is not a pointer type, call the normal function. */
11698 if (dest_align == 0)
c2f47e15 11699 return NULL_RTX;
0a39fd54 11700
11701 /* If SRC and DEST are the same (and not volatile), do nothing. */
11702 if (operand_equal_p (src, dest, 0))
11703 {
11704 tree expr;
11705
11706 if (fcode != BUILT_IN_MEMPCPY_CHK)
11707 {
11708 /* Evaluate and ignore LEN in case it has side-effects. */
11709 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
11710 return expand_expr (dest, target, mode, EXPAND_NORMAL);
11711 }
11712
2cc66f2a 11713 expr = fold_build_pointer_plus (dest, len);
0a39fd54 11714 return expand_expr (expr, target, mode, EXPAND_NORMAL);
11715 }
11716
11717 /* __memmove_chk special case. */
11718 if (fcode == BUILT_IN_MEMMOVE_CHK)
11719 {
11720 unsigned int src_align
11721 = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
11722
11723 if (src_align == 0)
c2f47e15 11724 return NULL_RTX;
0a39fd54 11725
11726 /* If src is categorized for a readonly section we can use
11727 normal __memcpy_chk. */
11728 if (readonly_data_expr (src))
11729 {
11730 tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
11731 if (!fn)
c2f47e15 11732 return NULL_RTX;
0568e9c1 11733 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 4,
11734 dest, src, len, size);
a65c4d64 11735 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
11736 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0a39fd54 11737 return expand_expr (fn, target, mode, EXPAND_NORMAL);
11738 }
11739 }
c2f47e15 11740 return NULL_RTX;
0a39fd54 11741 }
11742}
11743
11744/* Emit warning if a buffer overflow is detected at compile time. */
11745
11746static void
11747maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
11748{
c2f47e15 11749 int is_strlen = 0;
0a39fd54 11750 tree len, size;
b430e8d9 11751 location_t loc = tree_nonartificial_location (exp);
0a39fd54 11752
11753 switch (fcode)
11754 {
11755 case BUILT_IN_STRCPY_CHK:
11756 case BUILT_IN_STPCPY_CHK:
11757 /* For __strcat_chk the warning will be emitted only if overflowing
11758 by at least strlen (dest) + 1 bytes. */
11759 case BUILT_IN_STRCAT_CHK:
c2f47e15 11760 len = CALL_EXPR_ARG (exp, 1);
11761 size = CALL_EXPR_ARG (exp, 2);
0a39fd54 11762 is_strlen = 1;
11763 break;
b356dfef 11764 case BUILT_IN_STRNCAT_CHK:
0a39fd54 11765 case BUILT_IN_STRNCPY_CHK:
c2f47e15 11766 len = CALL_EXPR_ARG (exp, 2);
11767 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11768 break;
11769 case BUILT_IN_SNPRINTF_CHK:
11770 case BUILT_IN_VSNPRINTF_CHK:
c2f47e15 11771 len = CALL_EXPR_ARG (exp, 1);
11772 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11773 break;
11774 default:
11775 gcc_unreachable ();
11776 }
11777
0a39fd54 11778 if (!len || !size)
11779 return;
11780
0a39fd54 11781 if (! host_integerp (size, 1) || integer_all_onesp (size))
11782 return;
11783
11784 if (is_strlen)
11785 {
11786 len = c_strlen (len, 1);
11787 if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
11788 return;
11789 }
b356dfef 11790 else if (fcode == BUILT_IN_STRNCAT_CHK)
11791 {
c2f47e15 11792 tree src = CALL_EXPR_ARG (exp, 1);
b356dfef 11793 if (! src || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
11794 return;
11795 src = c_strlen (src, 1);
11796 if (! src || ! host_integerp (src, 1))
11797 {
b430e8d9 11798 warning_at (loc, 0, "%Kcall to %D might overflow destination buffer",
11799 exp, get_callee_fndecl (exp));
b356dfef 11800 return;
11801 }
11802 else if (tree_int_cst_lt (src, size))
11803 return;
11804 }
0a39fd54 11805 else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
11806 return;
11807
b430e8d9 11808 warning_at (loc, 0, "%Kcall to %D will always overflow destination buffer",
11809 exp, get_callee_fndecl (exp));
0a39fd54 11810}
11811
11812/* Emit warning if a buffer overflow is detected at compile time
11813 in __sprintf_chk/__vsprintf_chk calls. */
11814
11815static void
11816maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
11817{
1e4adcfc 11818 tree size, len, fmt;
0a39fd54 11819 const char *fmt_str;
c2f47e15 11820 int nargs = call_expr_nargs (exp);
0a39fd54 11821
11822 /* Verify the required arguments in the original call. */
48e1416a 11823
c2f47e15 11824 if (nargs < 4)
0a39fd54 11825 return;
c2f47e15 11826 size = CALL_EXPR_ARG (exp, 2);
11827 fmt = CALL_EXPR_ARG (exp, 3);
0a39fd54 11828
11829 if (! host_integerp (size, 1) || integer_all_onesp (size))
11830 return;
11831
11832 /* Check whether the format is a literal string constant. */
11833 fmt_str = c_getstr (fmt);
11834 if (fmt_str == NULL)
11835 return;
11836
d4473c84 11837 if (!init_target_chars ())
99eabcc1 11838 return;
11839
0a39fd54 11840 /* If the format doesn't contain % args or %%, we know its size. */
99eabcc1 11841 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 11842 len = build_int_cstu (size_type_node, strlen (fmt_str));
11843 /* If the format is "%s" and first ... argument is a string literal,
11844 we know it too. */
c2f47e15 11845 else if (fcode == BUILT_IN_SPRINTF_CHK
11846 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 11847 {
11848 tree arg;
11849
c2f47e15 11850 if (nargs < 5)
0a39fd54 11851 return;
c2f47e15 11852 arg = CALL_EXPR_ARG (exp, 4);
0a39fd54 11853 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
11854 return;
11855
11856 len = c_strlen (arg, 1);
11857 if (!len || ! host_integerp (len, 1))
11858 return;
11859 }
11860 else
11861 return;
11862
11863 if (! tree_int_cst_lt (len, size))
b430e8d9 11864 warning_at (tree_nonartificial_location (exp),
11865 0, "%Kcall to %D will always overflow destination buffer",
11866 exp, get_callee_fndecl (exp));
0a39fd54 11867}
11868
2c281b15 11869/* Emit warning if a free is called with address of a variable. */
11870
11871static void
11872maybe_emit_free_warning (tree exp)
11873{
11874 tree arg = CALL_EXPR_ARG (exp, 0);
11875
11876 STRIP_NOPS (arg);
11877 if (TREE_CODE (arg) != ADDR_EXPR)
11878 return;
11879
11880 arg = get_base_address (TREE_OPERAND (arg, 0));
182cf5a9 11881 if (arg == NULL || INDIRECT_REF_P (arg) || TREE_CODE (arg) == MEM_REF)
2c281b15 11882 return;
11883
11884 if (SSA_VAR_P (arg))
b430e8d9 11885 warning_at (tree_nonartificial_location (exp),
11886 0, "%Kattempt to free a non-heap object %qD", exp, arg);
2c281b15 11887 else
b430e8d9 11888 warning_at (tree_nonartificial_location (exp),
11889 0, "%Kattempt to free a non-heap object", exp);
2c281b15 11890}
11891
c2f47e15 11892/* Fold a call to __builtin_object_size with arguments PTR and OST,
11893 if possible. */
0a39fd54 11894
11895tree
c2f47e15 11896fold_builtin_object_size (tree ptr, tree ost)
0a39fd54 11897{
a6caa15f 11898 unsigned HOST_WIDE_INT bytes;
0a39fd54 11899 int object_size_type;
11900
c2f47e15 11901 if (!validate_arg (ptr, POINTER_TYPE)
11902 || !validate_arg (ost, INTEGER_TYPE))
11903 return NULL_TREE;
0a39fd54 11904
0a39fd54 11905 STRIP_NOPS (ost);
11906
11907 if (TREE_CODE (ost) != INTEGER_CST
11908 || tree_int_cst_sgn (ost) < 0
11909 || compare_tree_int (ost, 3) > 0)
c2f47e15 11910 return NULL_TREE;
0a39fd54 11911
11912 object_size_type = tree_low_cst (ost, 0);
11913
11914 /* __builtin_object_size doesn't evaluate side-effects in its arguments;
11915 if there are any side-effects, it returns (size_t) -1 for types 0 and 1
11916 and (size_t) 0 for types 2 and 3. */
11917 if (TREE_SIDE_EFFECTS (ptr))
697bbc3f 11918 return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
0a39fd54 11919
11920 if (TREE_CODE (ptr) == ADDR_EXPR)
a6caa15f 11921 {
11922 bytes = compute_builtin_object_size (ptr, object_size_type);
11923 if (double_int_fits_to_tree_p (size_type_node,
11924 uhwi_to_double_int (bytes)))
11925 return build_int_cstu (size_type_node, bytes);
11926 }
0a39fd54 11927 else if (TREE_CODE (ptr) == SSA_NAME)
11928 {
0a39fd54 11929 /* If object size is not known yet, delay folding until
11930 later. Maybe subsequent passes will help determining
11931 it. */
11932 bytes = compute_builtin_object_size (ptr, object_size_type);
a6caa15f 11933 if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2 ? -1 : 0)
11934 && double_int_fits_to_tree_p (size_type_node,
11935 uhwi_to_double_int (bytes)))
11936 return build_int_cstu (size_type_node, bytes);
0a39fd54 11937 }
11938
a6caa15f 11939 return NULL_TREE;
0a39fd54 11940}
11941
11942/* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
c2f47e15 11943 DEST, SRC, LEN, and SIZE are the arguments to the call.
0a39fd54 11944 IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_*
11945 code of the builtin. If MAXLEN is not NULL, it is maximum length
11946 passed as third argument. */
11947
11948tree
389dd41b 11949fold_builtin_memory_chk (location_t loc, tree fndecl,
c2f47e15 11950 tree dest, tree src, tree len, tree size,
11951 tree maxlen, bool ignore,
0a39fd54 11952 enum built_in_function fcode)
11953{
c2f47e15 11954 tree fn;
0a39fd54 11955
c2f47e15 11956 if (!validate_arg (dest, POINTER_TYPE)
11957 || !validate_arg (src,
11958 (fcode == BUILT_IN_MEMSET_CHK
11959 ? INTEGER_TYPE : POINTER_TYPE))
11960 || !validate_arg (len, INTEGER_TYPE)
11961 || !validate_arg (size, INTEGER_TYPE))
11962 return NULL_TREE;
0a39fd54 11963
11964 /* If SRC and DEST are the same (and not volatile), return DEST
11965 (resp. DEST+LEN for __mempcpy_chk). */
11966 if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
11967 {
11968 if (fcode != BUILT_IN_MEMPCPY_CHK)
389dd41b 11969 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
11970 dest, len);
0a39fd54 11971 else
11972 {
2cc66f2a 11973 tree temp = fold_build_pointer_plus_loc (loc, dest, len);
389dd41b 11974 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), temp);
0a39fd54 11975 }
11976 }
11977
11978 if (! host_integerp (size, 1))
c2f47e15 11979 return NULL_TREE;
0a39fd54 11980
11981 if (! integer_all_onesp (size))
11982 {
11983 if (! host_integerp (len, 1))
11984 {
11985 /* If LEN is not constant, try MAXLEN too.
11986 For MAXLEN only allow optimizing into non-_ocs function
11987 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
11988 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
11989 {
11990 if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
11991 {
11992 /* (void) __mempcpy_chk () can be optimized into
11993 (void) __memcpy_chk (). */
11994 fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
11995 if (!fn)
c2f47e15 11996 return NULL_TREE;
0a39fd54 11997
389dd41b 11998 return build_call_expr_loc (loc, fn, 4, dest, src, len, size);
0a39fd54 11999 }
c2f47e15 12000 return NULL_TREE;
0a39fd54 12001 }
0a39fd54 12002 }
ad89623c 12003 else
12004 maxlen = len;
0a39fd54 12005
ad89623c 12006 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12007 return NULL_TREE;
0a39fd54 12008 }
12009
0a39fd54 12010 fn = NULL_TREE;
12011 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
12012 mem{cpy,pcpy,move,set} is available. */
12013 switch (fcode)
12014 {
12015 case BUILT_IN_MEMCPY_CHK:
12016 fn = built_in_decls[BUILT_IN_MEMCPY];
12017 break;
12018 case BUILT_IN_MEMPCPY_CHK:
12019 fn = built_in_decls[BUILT_IN_MEMPCPY];
12020 break;
12021 case BUILT_IN_MEMMOVE_CHK:
12022 fn = built_in_decls[BUILT_IN_MEMMOVE];
12023 break;
12024 case BUILT_IN_MEMSET_CHK:
12025 fn = built_in_decls[BUILT_IN_MEMSET];
12026 break;
12027 default:
12028 break;
12029 }
12030
12031 if (!fn)
c2f47e15 12032 return NULL_TREE;
0a39fd54 12033
389dd41b 12034 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12035}
12036
12037/* Fold a call to the __st[rp]cpy_chk builtin.
c2f47e15 12038 DEST, SRC, and SIZE are the arguments to the call.
12039 IGNORE is true if return value can be ignored. FCODE is the BUILT_IN_*
0a39fd54 12040 code of the builtin. If MAXLEN is not NULL, it is maximum length of
12041 strings passed as second argument. */
12042
12043tree
389dd41b 12044fold_builtin_stxcpy_chk (location_t loc, tree fndecl, tree dest,
12045 tree src, tree size,
c2f47e15 12046 tree maxlen, bool ignore,
0a39fd54 12047 enum built_in_function fcode)
12048{
c2f47e15 12049 tree len, fn;
0a39fd54 12050
c2f47e15 12051 if (!validate_arg (dest, POINTER_TYPE)
12052 || !validate_arg (src, POINTER_TYPE)
12053 || !validate_arg (size, INTEGER_TYPE))
12054 return NULL_TREE;
0a39fd54 12055
12056 /* If SRC and DEST are the same (and not volatile), return DEST. */
12057 if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
389dd41b 12058 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
a0c938f0 12059
0a39fd54 12060 if (! host_integerp (size, 1))
c2f47e15 12061 return NULL_TREE;
0a39fd54 12062
12063 if (! integer_all_onesp (size))
12064 {
12065 len = c_strlen (src, 1);
12066 if (! len || ! host_integerp (len, 1))
12067 {
12068 /* If LEN is not constant, try MAXLEN too.
12069 For MAXLEN only allow optimizing into non-_ocs function
12070 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12071 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
12072 {
12073 if (fcode == BUILT_IN_STPCPY_CHK)
12074 {
12075 if (! ignore)
c2f47e15 12076 return NULL_TREE;
0a39fd54 12077
12078 /* If return value of __stpcpy_chk is ignored,
12079 optimize into __strcpy_chk. */
12080 fn = built_in_decls[BUILT_IN_STRCPY_CHK];
12081 if (!fn)
c2f47e15 12082 return NULL_TREE;
0a39fd54 12083
389dd41b 12084 return build_call_expr_loc (loc, fn, 3, dest, src, size);
0a39fd54 12085 }
12086
12087 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 12088 return NULL_TREE;
0a39fd54 12089
12090 /* If c_strlen returned something, but not a constant,
12091 transform __strcpy_chk into __memcpy_chk. */
12092 fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
12093 if (!fn)
c2f47e15 12094 return NULL_TREE;
0a39fd54 12095
389dd41b 12096 len = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
12097 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
12098 build_call_expr_loc (loc, fn, 4,
12099 dest, src, len, size));
0a39fd54 12100 }
0a39fd54 12101 }
ad89623c 12102 else
12103 maxlen = len;
12104
12105 if (! tree_int_cst_lt (maxlen, size))
c2f47e15 12106 return NULL_TREE;
0a39fd54 12107 }
12108
0a39fd54 12109 /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available. */
12110 fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK
12111 ? BUILT_IN_STPCPY : BUILT_IN_STRCPY];
12112 if (!fn)
c2f47e15 12113 return NULL_TREE;
0a39fd54 12114
389dd41b 12115 return build_call_expr_loc (loc, fn, 2, dest, src);
0a39fd54 12116}
12117
c2f47e15 12118/* Fold a call to the __strncpy_chk builtin. DEST, SRC, LEN, and SIZE
12119 are the arguments to the call. If MAXLEN is not NULL, it is maximum
12120 length passed as third argument. */
0a39fd54 12121
12122tree
389dd41b 12123fold_builtin_strncpy_chk (location_t loc, tree dest, tree src,
12124 tree len, tree size, tree maxlen)
0a39fd54 12125{
c2f47e15 12126 tree fn;
0a39fd54 12127
c2f47e15 12128 if (!validate_arg (dest, POINTER_TYPE)
12129 || !validate_arg (src, POINTER_TYPE)
12130 || !validate_arg (len, INTEGER_TYPE)
12131 || !validate_arg (size, INTEGER_TYPE))
12132 return NULL_TREE;
0a39fd54 12133
12134 if (! host_integerp (size, 1))
c2f47e15 12135 return NULL_TREE;
0a39fd54 12136
12137 if (! integer_all_onesp (size))
12138 {
12139 if (! host_integerp (len, 1))
12140 {
12141 /* If LEN is not constant, try MAXLEN too.
12142 For MAXLEN only allow optimizing into non-_ocs function
12143 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12144 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 12145 return NULL_TREE;
0a39fd54 12146 }
ad89623c 12147 else
12148 maxlen = len;
0a39fd54 12149
ad89623c 12150 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12151 return NULL_TREE;
0a39fd54 12152 }
12153
0a39fd54 12154 /* If __builtin_strncpy_chk is used, assume strncpy is available. */
12155 fn = built_in_decls[BUILT_IN_STRNCPY];
12156 if (!fn)
c2f47e15 12157 return NULL_TREE;
0a39fd54 12158
389dd41b 12159 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12160}
12161
c2f47e15 12162/* Fold a call to the __strcat_chk builtin FNDECL. DEST, SRC, and SIZE
12163 are the arguments to the call. */
0a39fd54 12164
12165static tree
389dd41b 12166fold_builtin_strcat_chk (location_t loc, tree fndecl, tree dest,
12167 tree src, tree size)
0a39fd54 12168{
c2f47e15 12169 tree fn;
0a39fd54 12170 const char *p;
12171
c2f47e15 12172 if (!validate_arg (dest, POINTER_TYPE)
12173 || !validate_arg (src, POINTER_TYPE)
12174 || !validate_arg (size, INTEGER_TYPE))
12175 return NULL_TREE;
0a39fd54 12176
12177 p = c_getstr (src);
12178 /* If the SRC parameter is "", return DEST. */
12179 if (p && *p == '\0')
389dd41b 12180 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
0a39fd54 12181
12182 if (! host_integerp (size, 1) || ! integer_all_onesp (size))
c2f47e15 12183 return NULL_TREE;
0a39fd54 12184
12185 /* If __builtin_strcat_chk is used, assume strcat is available. */
12186 fn = built_in_decls[BUILT_IN_STRCAT];
12187 if (!fn)
c2f47e15 12188 return NULL_TREE;
0a39fd54 12189
389dd41b 12190 return build_call_expr_loc (loc, fn, 2, dest, src);
0a39fd54 12191}
12192
c2f47e15 12193/* Fold a call to the __strncat_chk builtin with arguments DEST, SRC,
12194 LEN, and SIZE. */
0a39fd54 12195
12196static tree
389dd41b 12197fold_builtin_strncat_chk (location_t loc, tree fndecl,
c2f47e15 12198 tree dest, tree src, tree len, tree size)
0a39fd54 12199{
c2f47e15 12200 tree fn;
0a39fd54 12201 const char *p;
12202
c2f47e15 12203 if (!validate_arg (dest, POINTER_TYPE)
12204 || !validate_arg (src, POINTER_TYPE)
12205 || !validate_arg (size, INTEGER_TYPE)
12206 || !validate_arg (size, INTEGER_TYPE))
12207 return NULL_TREE;
0a39fd54 12208
12209 p = c_getstr (src);
12210 /* If the SRC parameter is "" or if LEN is 0, return DEST. */
12211 if (p && *p == '\0')
389dd41b 12212 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
0a39fd54 12213 else if (integer_zerop (len))
389dd41b 12214 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
0a39fd54 12215
12216 if (! host_integerp (size, 1))
c2f47e15 12217 return NULL_TREE;
0a39fd54 12218
12219 if (! integer_all_onesp (size))
12220 {
12221 tree src_len = c_strlen (src, 1);
12222 if (src_len
12223 && host_integerp (src_len, 1)
12224 && host_integerp (len, 1)
12225 && ! tree_int_cst_lt (len, src_len))
12226 {
12227 /* If LEN >= strlen (SRC), optimize into __strcat_chk. */
12228 fn = built_in_decls[BUILT_IN_STRCAT_CHK];
12229 if (!fn)
c2f47e15 12230 return NULL_TREE;
0a39fd54 12231
389dd41b 12232 return build_call_expr_loc (loc, fn, 3, dest, src, size);
0a39fd54 12233 }
c2f47e15 12234 return NULL_TREE;
0a39fd54 12235 }
12236
0a39fd54 12237 /* If __builtin_strncat_chk is used, assume strncat is available. */
12238 fn = built_in_decls[BUILT_IN_STRNCAT];
12239 if (!fn)
c2f47e15 12240 return NULL_TREE;
0a39fd54 12241
389dd41b 12242 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12243}
12244
af1409ad 12245/* Fold a call EXP to __{,v}sprintf_chk having NARGS passed as ARGS.
12246 Return NULL_TREE if a normal call should be emitted rather than
12247 expanding the function inline. FCODE is either BUILT_IN_SPRINTF_CHK
12248 or BUILT_IN_VSPRINTF_CHK. */
0a39fd54 12249
12250static tree
af1409ad 12251fold_builtin_sprintf_chk_1 (location_t loc, int nargs, tree *args,
12252 enum built_in_function fcode)
0a39fd54 12253{
12254 tree dest, size, len, fn, fmt, flag;
12255 const char *fmt_str;
12256
12257 /* Verify the required arguments in the original call. */
c2f47e15 12258 if (nargs < 4)
12259 return NULL_TREE;
af1409ad 12260 dest = args[0];
c2f47e15 12261 if (!validate_arg (dest, POINTER_TYPE))
12262 return NULL_TREE;
af1409ad 12263 flag = args[1];
c2f47e15 12264 if (!validate_arg (flag, INTEGER_TYPE))
12265 return NULL_TREE;
af1409ad 12266 size = args[2];
c2f47e15 12267 if (!validate_arg (size, INTEGER_TYPE))
12268 return NULL_TREE;
af1409ad 12269 fmt = args[3];
c2f47e15 12270 if (!validate_arg (fmt, POINTER_TYPE))
12271 return NULL_TREE;
0a39fd54 12272
12273 if (! host_integerp (size, 1))
c2f47e15 12274 return NULL_TREE;
0a39fd54 12275
12276 len = NULL_TREE;
12277
d4473c84 12278 if (!init_target_chars ())
c2f47e15 12279 return NULL_TREE;
99eabcc1 12280
0a39fd54 12281 /* Check whether the format is a literal string constant. */
12282 fmt_str = c_getstr (fmt);
12283 if (fmt_str != NULL)
12284 {
12285 /* If the format doesn't contain % args or %%, we know the size. */
99eabcc1 12286 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 12287 {
c2f47e15 12288 if (fcode != BUILT_IN_SPRINTF_CHK || nargs == 4)
0a39fd54 12289 len = build_int_cstu (size_type_node, strlen (fmt_str));
12290 }
12291 /* If the format is "%s" and first ... argument is a string literal,
12292 we know the size too. */
c2f47e15 12293 else if (fcode == BUILT_IN_SPRINTF_CHK
12294 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12295 {
12296 tree arg;
12297
c2f47e15 12298 if (nargs == 5)
0a39fd54 12299 {
af1409ad 12300 arg = args[4];
c2f47e15 12301 if (validate_arg (arg, POINTER_TYPE))
0a39fd54 12302 {
12303 len = c_strlen (arg, 1);
12304 if (! len || ! host_integerp (len, 1))
12305 len = NULL_TREE;
12306 }
12307 }
12308 }
12309 }
12310
12311 if (! integer_all_onesp (size))
12312 {
12313 if (! len || ! tree_int_cst_lt (len, size))
c2f47e15 12314 return NULL_TREE;
0a39fd54 12315 }
12316
12317 /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
12318 or if format doesn't contain % chars or is "%s". */
12319 if (! integer_zerop (flag))
12320 {
12321 if (fmt_str == NULL)
c2f47e15 12322 return NULL_TREE;
12323 if (strchr (fmt_str, target_percent) != NULL
12324 && strcmp (fmt_str, target_percent_s))
12325 return NULL_TREE;
0a39fd54 12326 }
12327
0a39fd54 12328 /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
12329 fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
12330 ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
12331 if (!fn)
c2f47e15 12332 return NULL_TREE;
0a39fd54 12333
af1409ad 12334 return rewrite_call_expr_array (loc, nargs, args, 4, fn, 2, dest, fmt);
0a39fd54 12335}
12336
af1409ad 12337/* Fold a call EXP to __{,v}sprintf_chk. Return NULL_TREE if
0a39fd54 12338 a normal call should be emitted rather than expanding the function
af1409ad 12339 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
12340
12341static tree
12342fold_builtin_sprintf_chk (location_t loc, tree exp,
12343 enum built_in_function fcode)
12344{
12345 return fold_builtin_sprintf_chk_1 (loc, call_expr_nargs (exp),
12346 CALL_EXPR_ARGP (exp), fcode);
12347}
12348
12349/* Fold a call EXP to {,v}snprintf having NARGS passed as ARGS. Return
12350 NULL_TREE if a normal call should be emitted rather than expanding
12351 the function inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
0a39fd54 12352 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
12353 passed as second argument. */
12354
af1409ad 12355static tree
12356fold_builtin_snprintf_chk_1 (location_t loc, int nargs, tree *args,
12357 tree maxlen, enum built_in_function fcode)
0a39fd54 12358{
12359 tree dest, size, len, fn, fmt, flag;
12360 const char *fmt_str;
12361
12362 /* Verify the required arguments in the original call. */
af1409ad 12363 if (nargs < 5)
c2f47e15 12364 return NULL_TREE;
af1409ad 12365 dest = args[0];
c2f47e15 12366 if (!validate_arg (dest, POINTER_TYPE))
12367 return NULL_TREE;
af1409ad 12368 len = args[1];
c2f47e15 12369 if (!validate_arg (len, INTEGER_TYPE))
12370 return NULL_TREE;
af1409ad 12371 flag = args[2];
c2f47e15 12372 if (!validate_arg (flag, INTEGER_TYPE))
12373 return NULL_TREE;
af1409ad 12374 size = args[3];
c2f47e15 12375 if (!validate_arg (size, INTEGER_TYPE))
12376 return NULL_TREE;
af1409ad 12377 fmt = args[4];
c2f47e15 12378 if (!validate_arg (fmt, POINTER_TYPE))
12379 return NULL_TREE;
0a39fd54 12380
12381 if (! host_integerp (size, 1))
c2f47e15 12382 return NULL_TREE;
0a39fd54 12383
12384 if (! integer_all_onesp (size))
12385 {
12386 if (! host_integerp (len, 1))
12387 {
12388 /* If LEN is not constant, try MAXLEN too.
12389 For MAXLEN only allow optimizing into non-_ocs function
12390 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12391 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 12392 return NULL_TREE;
0a39fd54 12393 }
ad89623c 12394 else
12395 maxlen = len;
0a39fd54 12396
ad89623c 12397 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12398 return NULL_TREE;
0a39fd54 12399 }
12400
d4473c84 12401 if (!init_target_chars ())
c2f47e15 12402 return NULL_TREE;
99eabcc1 12403
0a39fd54 12404 /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
12405 or if format doesn't contain % chars or is "%s". */
12406 if (! integer_zerop (flag))
12407 {
12408 fmt_str = c_getstr (fmt);
12409 if (fmt_str == NULL)
c2f47e15 12410 return NULL_TREE;
12411 if (strchr (fmt_str, target_percent) != NULL
12412 && strcmp (fmt_str, target_percent_s))
12413 return NULL_TREE;
0a39fd54 12414 }
12415
0a39fd54 12416 /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
12417 available. */
12418 fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
12419 ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
12420 if (!fn)
c2f47e15 12421 return NULL_TREE;
0a39fd54 12422
af1409ad 12423 return rewrite_call_expr_array (loc, nargs, args, 5, fn, 3, dest, len, fmt);
12424}
12425
12426/* Fold a call EXP to {,v}snprintf. Return NULL_TREE if
12427 a normal call should be emitted rather than expanding the function
12428 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
12429 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
12430 passed as second argument. */
12431
12432tree
12433fold_builtin_snprintf_chk (location_t loc, tree exp, tree maxlen,
12434 enum built_in_function fcode)
12435{
12436 return fold_builtin_snprintf_chk_1 (loc, call_expr_nargs (exp),
12437 CALL_EXPR_ARGP (exp), maxlen, fcode);
0a39fd54 12438}
12439
12440/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 12441 FMT and ARG are the arguments to the call; we don't fold cases with
12442 more than 2 arguments, and ARG may be null if this is a 1-argument case.
0a39fd54 12443
c2f47e15 12444 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 12445 simplified form of the call as a tree. FCODE is the BUILT_IN_*
12446 code of the function to be simplified. */
12447
12448static tree
389dd41b 12449fold_builtin_printf (location_t loc, tree fndecl, tree fmt,
12450 tree arg, bool ignore,
0a39fd54 12451 enum built_in_function fcode)
12452{
c2f47e15 12453 tree fn_putchar, fn_puts, newarg, call = NULL_TREE;
0a39fd54 12454 const char *fmt_str = NULL;
12455
12456 /* If the return value is used, don't do the transformation. */
12457 if (! ignore)
c2f47e15 12458 return NULL_TREE;
0a39fd54 12459
12460 /* Verify the required arguments in the original call. */
c2f47e15 12461 if (!validate_arg (fmt, POINTER_TYPE))
12462 return NULL_TREE;
0a39fd54 12463
12464 /* Check whether the format is a literal string constant. */
12465 fmt_str = c_getstr (fmt);
12466 if (fmt_str == NULL)
12467 return NULL_TREE;
12468
12469 if (fcode == BUILT_IN_PRINTF_UNLOCKED)
12470 {
6d77ed92 12471 /* If we're using an unlocked function, assume the other
12472 unlocked functions exist explicitly. */
12473 fn_putchar = built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED];
12474 fn_puts = built_in_decls[BUILT_IN_PUTS_UNLOCKED];
0a39fd54 12475 }
12476 else
12477 {
12478 fn_putchar = implicit_built_in_decls[BUILT_IN_PUTCHAR];
12479 fn_puts = implicit_built_in_decls[BUILT_IN_PUTS];
12480 }
12481
d4473c84 12482 if (!init_target_chars ())
c2f47e15 12483 return NULL_TREE;
a0c938f0 12484
c2f47e15 12485 if (strcmp (fmt_str, target_percent_s) == 0
12486 || strchr (fmt_str, target_percent) == NULL)
0a39fd54 12487 {
12488 const char *str;
12489
99eabcc1 12490 if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12491 {
12492 if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 12493 return NULL_TREE;
0a39fd54 12494
c2f47e15 12495 if (!arg || !validate_arg (arg, POINTER_TYPE))
12496 return NULL_TREE;
0a39fd54 12497
c2f47e15 12498 str = c_getstr (arg);
0a39fd54 12499 if (str == NULL)
c2f47e15 12500 return NULL_TREE;
0a39fd54 12501 }
12502 else
12503 {
12504 /* The format specifier doesn't contain any '%' characters. */
12505 if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
c2f47e15 12506 && arg)
12507 return NULL_TREE;
0a39fd54 12508 str = fmt_str;
12509 }
12510
12511 /* If the string was "", printf does nothing. */
12512 if (str[0] == '\0')
12513 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
12514
12515 /* If the string has length of 1, call putchar. */
12516 if (str[1] == '\0')
12517 {
12518 /* Given printf("c"), (where c is any one character,)
12519 convert "c"[0] to an int and pass that to the replacement
12520 function. */
7002a1c8 12521 newarg = build_int_cst (integer_type_node, str[0]);
c2f47e15 12522 if (fn_putchar)
389dd41b 12523 call = build_call_expr_loc (loc, fn_putchar, 1, newarg);
0a39fd54 12524 }
12525 else
12526 {
12527 /* If the string was "string\n", call puts("string"). */
12528 size_t len = strlen (str);
663dbd5e 12529 if ((unsigned char)str[len - 1] == target_newline
12530 && (size_t) (int) len == len
12531 && (int) len > 0)
0a39fd54 12532 {
663dbd5e 12533 char *newstr;
12534 tree offset_node, string_cst;
12535
0a39fd54 12536 /* Create a NUL-terminated string that's one char shorter
12537 than the original, stripping off the trailing '\n'. */
663dbd5e 12538 newarg = build_string_literal (len, str);
12539 string_cst = string_constant (newarg, &offset_node);
12540 gcc_checking_assert (string_cst
12541 && (TREE_STRING_LENGTH (string_cst)
12542 == (int) len)
12543 && integer_zerop (offset_node)
12544 && (unsigned char)
12545 TREE_STRING_POINTER (string_cst)[len - 1]
12546 == target_newline);
12547 /* build_string_literal creates a new STRING_CST,
12548 modify it in place to avoid double copying. */
12549 newstr = CONST_CAST (char *, TREE_STRING_POINTER (string_cst));
12550 newstr[len - 1] = '\0';
c2f47e15 12551 if (fn_puts)
389dd41b 12552 call = build_call_expr_loc (loc, fn_puts, 1, newarg);
0a39fd54 12553 }
12554 else
12555 /* We'd like to arrange to call fputs(string,stdout) here,
12556 but we need stdout and don't have a way to get it yet. */
c2f47e15 12557 return NULL_TREE;
0a39fd54 12558 }
12559 }
12560
12561 /* The other optimizations can be done only on the non-va_list variants. */
12562 else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 12563 return NULL_TREE;
0a39fd54 12564
12565 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
99eabcc1 12566 else if (strcmp (fmt_str, target_percent_s_newline) == 0)
0a39fd54 12567 {
c2f47e15 12568 if (!arg || !validate_arg (arg, POINTER_TYPE))
12569 return NULL_TREE;
12570 if (fn_puts)
389dd41b 12571 call = build_call_expr_loc (loc, fn_puts, 1, arg);
0a39fd54 12572 }
12573
12574 /* If the format specifier was "%c", call __builtin_putchar(arg). */
99eabcc1 12575 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 12576 {
c2f47e15 12577 if (!arg || !validate_arg (arg, INTEGER_TYPE))
12578 return NULL_TREE;
12579 if (fn_putchar)
389dd41b 12580 call = build_call_expr_loc (loc, fn_putchar, 1, arg);
0a39fd54 12581 }
12582
c2f47e15 12583 if (!call)
12584 return NULL_TREE;
0a39fd54 12585
389dd41b 12586 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
0a39fd54 12587}
12588
12589/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 12590 FP, FMT, and ARG are the arguments to the call. We don't fold calls with
12591 more than 3 arguments, and ARG may be null in the 2-argument case.
0a39fd54 12592
c2f47e15 12593 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 12594 simplified form of the call as a tree. FCODE is the BUILT_IN_*
12595 code of the function to be simplified. */
12596
12597static tree
389dd41b 12598fold_builtin_fprintf (location_t loc, tree fndecl, tree fp,
12599 tree fmt, tree arg, bool ignore,
0a39fd54 12600 enum built_in_function fcode)
12601{
c2f47e15 12602 tree fn_fputc, fn_fputs, call = NULL_TREE;
0a39fd54 12603 const char *fmt_str = NULL;
12604
12605 /* If the return value is used, don't do the transformation. */
12606 if (! ignore)
c2f47e15 12607 return NULL_TREE;
0a39fd54 12608
12609 /* Verify the required arguments in the original call. */
c2f47e15 12610 if (!validate_arg (fp, POINTER_TYPE))
12611 return NULL_TREE;
12612 if (!validate_arg (fmt, POINTER_TYPE))
12613 return NULL_TREE;
0a39fd54 12614
12615 /* Check whether the format is a literal string constant. */
12616 fmt_str = c_getstr (fmt);
12617 if (fmt_str == NULL)
12618 return NULL_TREE;
12619
12620 if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
12621 {
6d77ed92 12622 /* If we're using an unlocked function, assume the other
12623 unlocked functions exist explicitly. */
12624 fn_fputc = built_in_decls[BUILT_IN_FPUTC_UNLOCKED];
12625 fn_fputs = built_in_decls[BUILT_IN_FPUTS_UNLOCKED];
0a39fd54 12626 }
12627 else
12628 {
12629 fn_fputc = implicit_built_in_decls[BUILT_IN_FPUTC];
12630 fn_fputs = implicit_built_in_decls[BUILT_IN_FPUTS];
12631 }
12632
d4473c84 12633 if (!init_target_chars ())
c2f47e15 12634 return NULL_TREE;
a0c938f0 12635
0a39fd54 12636 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 12637 if (strchr (fmt_str, target_percent) == NULL)
0a39fd54 12638 {
12639 if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
c2f47e15 12640 && arg)
12641 return NULL_TREE;
0a39fd54 12642
12643 /* If the format specifier was "", fprintf does nothing. */
12644 if (fmt_str[0] == '\0')
12645 {
12646 /* If FP has side-effects, just wait until gimplification is
12647 done. */
12648 if (TREE_SIDE_EFFECTS (fp))
c2f47e15 12649 return NULL_TREE;
0a39fd54 12650
12651 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
12652 }
12653
12654 /* When "string" doesn't contain %, replace all cases of
12655 fprintf (fp, string) with fputs (string, fp). The fputs
12656 builtin will take care of special cases like length == 1. */
c2f47e15 12657 if (fn_fputs)
389dd41b 12658 call = build_call_expr_loc (loc, fn_fputs, 2, fmt, fp);
0a39fd54 12659 }
12660
12661 /* The other optimizations can be done only on the non-va_list variants. */
12662 else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
c2f47e15 12663 return NULL_TREE;
0a39fd54 12664
12665 /* If the format specifier was "%s", call __builtin_fputs (arg, fp). */
99eabcc1 12666 else if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12667 {
c2f47e15 12668 if (!arg || !validate_arg (arg, POINTER_TYPE))
12669 return NULL_TREE;
12670 if (fn_fputs)
389dd41b 12671 call = build_call_expr_loc (loc, fn_fputs, 2, arg, fp);
0a39fd54 12672 }
12673
12674 /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */
99eabcc1 12675 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 12676 {
c2f47e15 12677 if (!arg || !validate_arg (arg, INTEGER_TYPE))
12678 return NULL_TREE;
12679 if (fn_fputc)
389dd41b 12680 call = build_call_expr_loc (loc, fn_fputc, 2, arg, fp);
0a39fd54 12681 }
12682
c2f47e15 12683 if (!call)
12684 return NULL_TREE;
389dd41b 12685 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
0a39fd54 12686}
99eabcc1 12687
12688/* Initialize format string characters in the target charset. */
12689
12690static bool
12691init_target_chars (void)
12692{
12693 static bool init;
12694 if (!init)
12695 {
12696 target_newline = lang_hooks.to_target_charset ('\n');
12697 target_percent = lang_hooks.to_target_charset ('%');
12698 target_c = lang_hooks.to_target_charset ('c');
12699 target_s = lang_hooks.to_target_charset ('s');
12700 if (target_newline == 0 || target_percent == 0 || target_c == 0
12701 || target_s == 0)
12702 return false;
12703
12704 target_percent_c[0] = target_percent;
12705 target_percent_c[1] = target_c;
12706 target_percent_c[2] = '\0';
12707
12708 target_percent_s[0] = target_percent;
12709 target_percent_s[1] = target_s;
12710 target_percent_s[2] = '\0';
12711
12712 target_percent_s_newline[0] = target_percent;
12713 target_percent_s_newline[1] = target_s;
12714 target_percent_s_newline[2] = target_newline;
12715 target_percent_s_newline[3] = '\0';
a0c938f0 12716
99eabcc1 12717 init = true;
12718 }
12719 return true;
12720}
bffb7645 12721
f0c477f2 12722/* Helper function for do_mpfr_arg*(). Ensure M is a normal number
12723 and no overflow/underflow occurred. INEXACT is true if M was not
fa7637bd 12724 exactly calculated. TYPE is the tree type for the result. This
f0c477f2 12725 function assumes that you cleared the MPFR flags and then
12726 calculated M to see if anything subsequently set a flag prior to
12727 entering this function. Return NULL_TREE if any checks fail. */
12728
12729static tree
d4473c84 12730do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
f0c477f2 12731{
12732 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
12733 overflow/underflow occurred. If -frounding-math, proceed iff the
12734 result of calling FUNC was exact. */
d4473c84 12735 if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
f0c477f2 12736 && (!flag_rounding_math || !inexact))
12737 {
12738 REAL_VALUE_TYPE rr;
12739
66fa16e6 12740 real_from_mpfr (&rr, m, type, GMP_RNDN);
f0c477f2 12741 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
12742 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
12743 but the mpft_t is not, then we underflowed in the
12744 conversion. */
776a7bab 12745 if (real_isfinite (&rr)
f0c477f2 12746 && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
12747 {
12748 REAL_VALUE_TYPE rmode;
12749
12750 real_convert (&rmode, TYPE_MODE (type), &rr);
12751 /* Proceed iff the specified mode can hold the value. */
12752 if (real_identical (&rmode, &rr))
12753 return build_real (type, rmode);
12754 }
12755 }
12756 return NULL_TREE;
12757}
12758
239d491a 12759/* Helper function for do_mpc_arg*(). Ensure M is a normal complex
12760 number and no overflow/underflow occurred. INEXACT is true if M
12761 was not exactly calculated. TYPE is the tree type for the result.
12762 This function assumes that you cleared the MPFR flags and then
12763 calculated M to see if anything subsequently set a flag prior to
652d9409 12764 entering this function. Return NULL_TREE if any checks fail, if
12765 FORCE_CONVERT is true, then bypass the checks. */
239d491a 12766
12767static tree
652d9409 12768do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert)
239d491a 12769{
12770 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
12771 overflow/underflow occurred. If -frounding-math, proceed iff the
12772 result of calling FUNC was exact. */
652d9409 12773 if (force_convert
12774 || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m))
12775 && !mpfr_overflow_p () && !mpfr_underflow_p ()
12776 && (!flag_rounding_math || !inexact)))
239d491a 12777 {
12778 REAL_VALUE_TYPE re, im;
12779
b0e7c4d4 12780 real_from_mpfr (&re, mpc_realref (m), TREE_TYPE (type), GMP_RNDN);
12781 real_from_mpfr (&im, mpc_imagref (m), TREE_TYPE (type), GMP_RNDN);
239d491a 12782 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
12783 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
12784 but the mpft_t is not, then we underflowed in the
12785 conversion. */
652d9409 12786 if (force_convert
12787 || (real_isfinite (&re) && real_isfinite (&im)
12788 && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0)
12789 && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0)))
239d491a 12790 {
12791 REAL_VALUE_TYPE re_mode, im_mode;
12792
12793 real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re);
12794 real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im);
12795 /* Proceed iff the specified mode can hold the value. */
652d9409 12796 if (force_convert
12797 || (real_identical (&re_mode, &re)
12798 && real_identical (&im_mode, &im)))
239d491a 12799 return build_complex (type, build_real (TREE_TYPE (type), re_mode),
12800 build_real (TREE_TYPE (type), im_mode));
12801 }
12802 }
12803 return NULL_TREE;
12804}
239d491a 12805
bffb7645 12806/* If argument ARG is a REAL_CST, call the one-argument mpfr function
12807 FUNC on it and return the resulting value as a tree with type TYPE.
728bac60 12808 If MIN and/or MAX are not NULL, then the supplied ARG must be
12809 within those bounds. If INCLUSIVE is true, then MIN/MAX are
12810 acceptable values, otherwise they are not. The mpfr precision is
12811 set to the precision of TYPE. We assume that function FUNC returns
12812 zero if the result could be calculated exactly within the requested
12813 precision. */
bffb7645 12814
12815static tree
728bac60 12816do_mpfr_arg1 (tree arg, tree type, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
12817 const REAL_VALUE_TYPE *min, const REAL_VALUE_TYPE *max,
12818 bool inclusive)
bffb7645 12819{
12820 tree result = NULL_TREE;
48e1416a 12821
bffb7645 12822 STRIP_NOPS (arg);
12823
bd7d6fa4 12824 /* To proceed, MPFR must exactly represent the target floating point
12825 format, which only happens when the target base equals two. */
12826 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12827 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
bffb7645 12828 {
f0c477f2 12829 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
bffb7645 12830
776a7bab 12831 if (real_isfinite (ra)
f0c477f2 12832 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min))
12833 && (!max || real_compare (inclusive ? LE_EXPR: LT_EXPR , ra, max)))
bffb7645 12834 {
e2eb2b7f 12835 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
12836 const int prec = fmt->p;
12837 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
debf9994 12838 int inexact;
bffb7645 12839 mpfr_t m;
12840
12841 mpfr_init2 (m, prec);
66fa16e6 12842 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 12843 mpfr_clear_flags ();
e2eb2b7f 12844 inexact = func (m, m, rnd);
f0c477f2 12845 result = do_mpfr_ckconv (m, type, inexact);
bffb7645 12846 mpfr_clear (m);
12847 }
12848 }
48e1416a 12849
bffb7645 12850 return result;
12851}
f0c477f2 12852
12853/* If argument ARG is a REAL_CST, call the two-argument mpfr function
12854 FUNC on it and return the resulting value as a tree with type TYPE.
12855 The mpfr precision is set to the precision of TYPE. We assume that
12856 function FUNC returns zero if the result could be calculated
12857 exactly within the requested precision. */
12858
12859static tree
12860do_mpfr_arg2 (tree arg1, tree arg2, tree type,
12861 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
12862{
12863 tree result = NULL_TREE;
48e1416a 12864
f0c477f2 12865 STRIP_NOPS (arg1);
12866 STRIP_NOPS (arg2);
12867
bd7d6fa4 12868 /* To proceed, MPFR must exactly represent the target floating point
12869 format, which only happens when the target base equals two. */
12870 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12871 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
12872 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
f0c477f2 12873 {
12874 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
12875 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
12876
776a7bab 12877 if (real_isfinite (ra1) && real_isfinite (ra2))
f0c477f2 12878 {
e2eb2b7f 12879 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
12880 const int prec = fmt->p;
12881 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
f0c477f2 12882 int inexact;
12883 mpfr_t m1, m2;
12884
12885 mpfr_inits2 (prec, m1, m2, NULL);
66fa16e6 12886 mpfr_from_real (m1, ra1, GMP_RNDN);
12887 mpfr_from_real (m2, ra2, GMP_RNDN);
d4473c84 12888 mpfr_clear_flags ();
e2eb2b7f 12889 inexact = func (m1, m1, m2, rnd);
f0c477f2 12890 result = do_mpfr_ckconv (m1, type, inexact);
12891 mpfr_clears (m1, m2, NULL);
12892 }
12893 }
48e1416a 12894
f0c477f2 12895 return result;
12896}
d92f994c 12897
9917422b 12898/* If argument ARG is a REAL_CST, call the three-argument mpfr function
12899 FUNC on it and return the resulting value as a tree with type TYPE.
12900 The mpfr precision is set to the precision of TYPE. We assume that
12901 function FUNC returns zero if the result could be calculated
12902 exactly within the requested precision. */
12903
12904static tree
12905do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type,
12906 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
12907{
12908 tree result = NULL_TREE;
48e1416a 12909
9917422b 12910 STRIP_NOPS (arg1);
12911 STRIP_NOPS (arg2);
12912 STRIP_NOPS (arg3);
12913
bd7d6fa4 12914 /* To proceed, MPFR must exactly represent the target floating point
12915 format, which only happens when the target base equals two. */
12916 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12917 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
12918 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2)
12919 && TREE_CODE (arg3) == REAL_CST && !TREE_OVERFLOW (arg3))
9917422b 12920 {
12921 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
12922 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
12923 const REAL_VALUE_TYPE *const ra3 = &TREE_REAL_CST (arg3);
12924
776a7bab 12925 if (real_isfinite (ra1) && real_isfinite (ra2) && real_isfinite (ra3))
9917422b 12926 {
e2eb2b7f 12927 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
12928 const int prec = fmt->p;
12929 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
9917422b 12930 int inexact;
12931 mpfr_t m1, m2, m3;
12932
12933 mpfr_inits2 (prec, m1, m2, m3, NULL);
66fa16e6 12934 mpfr_from_real (m1, ra1, GMP_RNDN);
12935 mpfr_from_real (m2, ra2, GMP_RNDN);
12936 mpfr_from_real (m3, ra3, GMP_RNDN);
d4473c84 12937 mpfr_clear_flags ();
e2eb2b7f 12938 inexact = func (m1, m1, m2, m3, rnd);
9917422b 12939 result = do_mpfr_ckconv (m1, type, inexact);
12940 mpfr_clears (m1, m2, m3, NULL);
12941 }
12942 }
48e1416a 12943
9917422b 12944 return result;
12945}
12946
d92f994c 12947/* If argument ARG is a REAL_CST, call mpfr_sin_cos() on it and set
12948 the pointers *(ARG_SINP) and *(ARG_COSP) to the resulting values.
d735c391 12949 If ARG_SINP and ARG_COSP are NULL then the result is returned
12950 as a complex value.
d92f994c 12951 The type is taken from the type of ARG and is used for setting the
12952 precision of the calculation and results. */
12953
12954static tree
12955do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp)
12956{
bd7d6fa4 12957 tree const type = TREE_TYPE (arg);
d92f994c 12958 tree result = NULL_TREE;
48e1416a 12959
d92f994c 12960 STRIP_NOPS (arg);
48e1416a 12961
bd7d6fa4 12962 /* To proceed, MPFR must exactly represent the target floating point
12963 format, which only happens when the target base equals two. */
12964 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12965 && TREE_CODE (arg) == REAL_CST
12966 && !TREE_OVERFLOW (arg))
d92f994c 12967 {
12968 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
12969
776a7bab 12970 if (real_isfinite (ra))
d92f994c 12971 {
e2eb2b7f 12972 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
12973 const int prec = fmt->p;
12974 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
d92f994c 12975 tree result_s, result_c;
12976 int inexact;
12977 mpfr_t m, ms, mc;
12978
12979 mpfr_inits2 (prec, m, ms, mc, NULL);
66fa16e6 12980 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 12981 mpfr_clear_flags ();
e2eb2b7f 12982 inexact = mpfr_sin_cos (ms, mc, m, rnd);
d92f994c 12983 result_s = do_mpfr_ckconv (ms, type, inexact);
12984 result_c = do_mpfr_ckconv (mc, type, inexact);
12985 mpfr_clears (m, ms, mc, NULL);
12986 if (result_s && result_c)
12987 {
d735c391 12988 /* If we are to return in a complex value do so. */
12989 if (!arg_sinp && !arg_cosp)
12990 return build_complex (build_complex_type (type),
12991 result_c, result_s);
12992
d92f994c 12993 /* Dereference the sin/cos pointer arguments. */
12994 arg_sinp = build_fold_indirect_ref (arg_sinp);
12995 arg_cosp = build_fold_indirect_ref (arg_cosp);
12996 /* Proceed if valid pointer type were passed in. */
12997 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_sinp)) == TYPE_MAIN_VARIANT (type)
12998 && TYPE_MAIN_VARIANT (TREE_TYPE (arg_cosp)) == TYPE_MAIN_VARIANT (type))
12999 {
13000 /* Set the values. */
41076ef6 13001 result_s = fold_build2 (MODIFY_EXPR, type, arg_sinp,
35cc02b5 13002 result_s);
d92f994c 13003 TREE_SIDE_EFFECTS (result_s) = 1;
41076ef6 13004 result_c = fold_build2 (MODIFY_EXPR, type, arg_cosp,
35cc02b5 13005 result_c);
d92f994c 13006 TREE_SIDE_EFFECTS (result_c) = 1;
13007 /* Combine the assignments into a compound expr. */
13008 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13009 result_s, result_c));
13010 }
13011 }
13012 }
13013 }
13014 return result;
13015}
65dd1378 13016
65dd1378 13017/* If argument ARG1 is an INTEGER_CST and ARG2 is a REAL_CST, call the
13018 two-argument mpfr order N Bessel function FUNC on them and return
13019 the resulting value as a tree with type TYPE. The mpfr precision
13020 is set to the precision of TYPE. We assume that function FUNC
13021 returns zero if the result could be calculated exactly within the
13022 requested precision. */
13023static tree
13024do_mpfr_bessel_n (tree arg1, tree arg2, tree type,
13025 int (*func)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
13026 const REAL_VALUE_TYPE *min, bool inclusive)
13027{
13028 tree result = NULL_TREE;
13029
13030 STRIP_NOPS (arg1);
13031 STRIP_NOPS (arg2);
13032
13033 /* To proceed, MPFR must exactly represent the target floating point
13034 format, which only happens when the target base equals two. */
13035 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13036 && host_integerp (arg1, 0)
13037 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
13038 {
13039 const HOST_WIDE_INT n = tree_low_cst(arg1, 0);
13040 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg2);
13041
13042 if (n == (long)n
776a7bab 13043 && real_isfinite (ra)
65dd1378 13044 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min)))
13045 {
e2eb2b7f 13046 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13047 const int prec = fmt->p;
13048 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
65dd1378 13049 int inexact;
13050 mpfr_t m;
13051
13052 mpfr_init2 (m, prec);
13053 mpfr_from_real (m, ra, GMP_RNDN);
13054 mpfr_clear_flags ();
e2eb2b7f 13055 inexact = func (m, n, m, rnd);
65dd1378 13056 result = do_mpfr_ckconv (m, type, inexact);
13057 mpfr_clear (m);
13058 }
13059 }
48e1416a 13060
65dd1378 13061 return result;
13062}
e5407ca6 13063
13064/* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
13065 the pointer *(ARG_QUO) and return the result. The type is taken
13066 from the type of ARG0 and is used for setting the precision of the
13067 calculation and results. */
13068
13069static tree
13070do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
13071{
13072 tree const type = TREE_TYPE (arg0);
13073 tree result = NULL_TREE;
48e1416a 13074
e5407ca6 13075 STRIP_NOPS (arg0);
13076 STRIP_NOPS (arg1);
48e1416a 13077
e5407ca6 13078 /* To proceed, MPFR must exactly represent the target floating point
13079 format, which only happens when the target base equals two. */
13080 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13081 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
13082 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
13083 {
13084 const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
13085 const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
13086
776a7bab 13087 if (real_isfinite (ra0) && real_isfinite (ra1))
e5407ca6 13088 {
e2eb2b7f 13089 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13090 const int prec = fmt->p;
13091 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
e5407ca6 13092 tree result_rem;
13093 long integer_quo;
13094 mpfr_t m0, m1;
13095
13096 mpfr_inits2 (prec, m0, m1, NULL);
13097 mpfr_from_real (m0, ra0, GMP_RNDN);
13098 mpfr_from_real (m1, ra1, GMP_RNDN);
13099 mpfr_clear_flags ();
e2eb2b7f 13100 mpfr_remquo (m0, &integer_quo, m0, m1, rnd);
e5407ca6 13101 /* Remquo is independent of the rounding mode, so pass
13102 inexact=0 to do_mpfr_ckconv(). */
13103 result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
13104 mpfr_clears (m0, m1, NULL);
13105 if (result_rem)
13106 {
13107 /* MPFR calculates quo in the host's long so it may
13108 return more bits in quo than the target int can hold
13109 if sizeof(host long) > sizeof(target int). This can
13110 happen even for native compilers in LP64 mode. In
13111 these cases, modulo the quo value with the largest
13112 number that the target int can hold while leaving one
13113 bit for the sign. */
13114 if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
13115 integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
13116
13117 /* Dereference the quo pointer argument. */
13118 arg_quo = build_fold_indirect_ref (arg_quo);
13119 /* Proceed iff a valid pointer type was passed in. */
13120 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
13121 {
13122 /* Set the value. */
7002a1c8 13123 tree result_quo
13124 = fold_build2 (MODIFY_EXPR, TREE_TYPE (arg_quo), arg_quo,
13125 build_int_cst (TREE_TYPE (arg_quo),
13126 integer_quo));
e5407ca6 13127 TREE_SIDE_EFFECTS (result_quo) = 1;
13128 /* Combine the quo assignment with the rem. */
13129 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13130 result_quo, result_rem));
13131 }
13132 }
13133 }
13134 }
13135 return result;
13136}
e84da7c1 13137
13138/* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
13139 resulting value as a tree with type TYPE. The mpfr precision is
13140 set to the precision of TYPE. We assume that this mpfr function
13141 returns zero if the result could be calculated exactly within the
13142 requested precision. In addition, the integer pointer represented
13143 by ARG_SG will be dereferenced and set to the appropriate signgam
13144 (-1,1) value. */
13145
13146static tree
13147do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
13148{
13149 tree result = NULL_TREE;
13150
13151 STRIP_NOPS (arg);
48e1416a 13152
e84da7c1 13153 /* To proceed, MPFR must exactly represent the target floating point
13154 format, which only happens when the target base equals two. Also
13155 verify ARG is a constant and that ARG_SG is an int pointer. */
13156 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13157 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
13158 && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
13159 && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
13160 {
13161 const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
13162
13163 /* In addition to NaN and Inf, the argument cannot be zero or a
13164 negative integer. */
776a7bab 13165 if (real_isfinite (ra)
e84da7c1 13166 && ra->cl != rvc_zero
13167 && !(real_isneg(ra) && real_isinteger(ra, TYPE_MODE (type))))
13168 {
e2eb2b7f 13169 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13170 const int prec = fmt->p;
13171 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
e84da7c1 13172 int inexact, sg;
13173 mpfr_t m;
13174 tree result_lg;
13175
13176 mpfr_init2 (m, prec);
13177 mpfr_from_real (m, ra, GMP_RNDN);
13178 mpfr_clear_flags ();
e2eb2b7f 13179 inexact = mpfr_lgamma (m, &sg, m, rnd);
e84da7c1 13180 result_lg = do_mpfr_ckconv (m, type, inexact);
13181 mpfr_clear (m);
13182 if (result_lg)
13183 {
13184 tree result_sg;
13185
13186 /* Dereference the arg_sg pointer argument. */
13187 arg_sg = build_fold_indirect_ref (arg_sg);
13188 /* Assign the signgam value into *arg_sg. */
13189 result_sg = fold_build2 (MODIFY_EXPR,
13190 TREE_TYPE (arg_sg), arg_sg,
7002a1c8 13191 build_int_cst (TREE_TYPE (arg_sg), sg));
e84da7c1 13192 TREE_SIDE_EFFECTS (result_sg) = 1;
13193 /* Combine the signgam assignment with the lgamma result. */
13194 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13195 result_sg, result_lg));
13196 }
13197 }
13198 }
13199
13200 return result;
13201}
75a70cf9 13202
239d491a 13203/* If argument ARG is a COMPLEX_CST, call the one-argument mpc
13204 function FUNC on it and return the resulting value as a tree with
13205 type TYPE. The mpfr precision is set to the precision of TYPE. We
13206 assume that function FUNC returns zero if the result could be
13207 calculated exactly within the requested precision. */
13208
13209static tree
13210do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t))
13211{
13212 tree result = NULL_TREE;
48e1416a 13213
239d491a 13214 STRIP_NOPS (arg);
13215
13216 /* To proceed, MPFR must exactly represent the target floating point
13217 format, which only happens when the target base equals two. */
13218 if (TREE_CODE (arg) == COMPLEX_CST && !TREE_OVERFLOW (arg)
13219 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE
13220 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))))->b == 2)
13221 {
13222 const REAL_VALUE_TYPE *const re = TREE_REAL_CST_PTR (TREE_REALPART (arg));
13223 const REAL_VALUE_TYPE *const im = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
13224
13225 if (real_isfinite (re) && real_isfinite (im))
13226 {
13227 const struct real_format *const fmt =
13228 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
13229 const int prec = fmt->p;
13230 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
44d89feb 13231 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
239d491a 13232 int inexact;
13233 mpc_t m;
48e1416a 13234
239d491a 13235 mpc_init2 (m, prec);
c3cfad90 13236 mpfr_from_real (mpc_realref(m), re, rnd);
13237 mpfr_from_real (mpc_imagref(m), im, rnd);
239d491a 13238 mpfr_clear_flags ();
44d89feb 13239 inexact = func (m, m, crnd);
652d9409 13240 result = do_mpc_ckconv (m, type, inexact, /*force_convert=*/ 0);
239d491a 13241 mpc_clear (m);
13242 }
13243 }
13244
13245 return result;
13246}
c699fab8 13247
13248/* If arguments ARG0 and ARG1 are a COMPLEX_CST, call the two-argument
13249 mpc function FUNC on it and return the resulting value as a tree
13250 with type TYPE. The mpfr precision is set to the precision of
13251 TYPE. We assume that function FUNC returns zero if the result
652d9409 13252 could be calculated exactly within the requested precision. If
13253 DO_NONFINITE is true, then fold expressions containing Inf or NaN
13254 in the arguments and/or results. */
c699fab8 13255
63e89698 13256tree
652d9409 13257do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
c699fab8 13258 int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
13259{
13260 tree result = NULL_TREE;
48e1416a 13261
c699fab8 13262 STRIP_NOPS (arg0);
13263 STRIP_NOPS (arg1);
13264
13265 /* To proceed, MPFR must exactly represent the target floating point
13266 format, which only happens when the target base equals two. */
13267 if (TREE_CODE (arg0) == COMPLEX_CST && !TREE_OVERFLOW (arg0)
13268 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
13269 && TREE_CODE (arg1) == COMPLEX_CST && !TREE_OVERFLOW (arg1)
13270 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE
13271 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))))->b == 2)
13272 {
13273 const REAL_VALUE_TYPE *const re0 = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
13274 const REAL_VALUE_TYPE *const im0 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
13275 const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1));
13276 const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1));
13277
652d9409 13278 if (do_nonfinite
13279 || (real_isfinite (re0) && real_isfinite (im0)
13280 && real_isfinite (re1) && real_isfinite (im1)))
c699fab8 13281 {
13282 const struct real_format *const fmt =
13283 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
13284 const int prec = fmt->p;
13285 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
13286 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
13287 int inexact;
13288 mpc_t m0, m1;
48e1416a 13289
c699fab8 13290 mpc_init2 (m0, prec);
13291 mpc_init2 (m1, prec);
13292 mpfr_from_real (mpc_realref(m0), re0, rnd);
13293 mpfr_from_real (mpc_imagref(m0), im0, rnd);
13294 mpfr_from_real (mpc_realref(m1), re1, rnd);
13295 mpfr_from_real (mpc_imagref(m1), im1, rnd);
13296 mpfr_clear_flags ();
13297 inexact = func (m0, m0, m1, crnd);
652d9409 13298 result = do_mpc_ckconv (m0, type, inexact, do_nonfinite);
c699fab8 13299 mpc_clear (m0);
13300 mpc_clear (m1);
13301 }
13302 }
13303
13304 return result;
13305}
239d491a 13306
75a70cf9 13307/* Fold a call STMT to __{,v}sprintf_chk. Return NULL_TREE if
13308 a normal call should be emitted rather than expanding the function
13309 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
13310
13311static tree
13312gimple_fold_builtin_sprintf_chk (gimple stmt, enum built_in_function fcode)
13313{
75a70cf9 13314 int nargs = gimple_call_num_args (stmt);
13315
af1409ad 13316 return fold_builtin_sprintf_chk_1 (gimple_location (stmt), nargs,
13317 (nargs > 0
13318 ? gimple_call_arg_ptr (stmt, 0)
13319 : &error_mark_node), fcode);
75a70cf9 13320}
13321
13322/* Fold a call STMT to {,v}snprintf. Return NULL_TREE if
13323 a normal call should be emitted rather than expanding the function
13324 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
13325 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
13326 passed as second argument. */
13327
13328tree
13329gimple_fold_builtin_snprintf_chk (gimple stmt, tree maxlen,
13330 enum built_in_function fcode)
13331{
af1409ad 13332 int nargs = gimple_call_num_args (stmt);
75a70cf9 13333
af1409ad 13334 return fold_builtin_snprintf_chk_1 (gimple_location (stmt), nargs,
13335 (nargs > 0
13336 ? gimple_call_arg_ptr (stmt, 0)
13337 : &error_mark_node), maxlen, fcode);
75a70cf9 13338}
13339
13340/* Builtins with folding operations that operate on "..." arguments
13341 need special handling; we need to store the arguments in a convenient
13342 data structure before attempting any folding. Fortunately there are
13343 only a few builtins that fall into this category. FNDECL is the
13344 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
13345 result of the function call is ignored. */
13346
13347static tree
389dd41b 13348gimple_fold_builtin_varargs (tree fndecl, gimple stmt,
13349 bool ignore ATTRIBUTE_UNUSED)
75a70cf9 13350{
13351 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
13352 tree ret = NULL_TREE;
13353
13354 switch (fcode)
13355 {
13356 case BUILT_IN_SPRINTF_CHK:
13357 case BUILT_IN_VSPRINTF_CHK:
13358 ret = gimple_fold_builtin_sprintf_chk (stmt, fcode);
13359 break;
13360
13361 case BUILT_IN_SNPRINTF_CHK:
13362 case BUILT_IN_VSNPRINTF_CHK:
13363 ret = gimple_fold_builtin_snprintf_chk (stmt, NULL_TREE, fcode);
13364
13365 default:
13366 break;
13367 }
13368 if (ret)
13369 {
13370 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
13371 TREE_NO_WARNING (ret) = 1;
13372 return ret;
13373 }
13374 return NULL_TREE;
13375}
13376
13377/* A wrapper function for builtin folding that prevents warnings for
13378 "statement without effect" and the like, caused by removing the
13379 call node earlier than the warning is generated. */
13380
13381tree
13382fold_call_stmt (gimple stmt, bool ignore)
13383{
13384 tree ret = NULL_TREE;
13385 tree fndecl = gimple_call_fndecl (stmt);
389dd41b 13386 location_t loc = gimple_location (stmt);
75a70cf9 13387 if (fndecl
13388 && TREE_CODE (fndecl) == FUNCTION_DECL
13389 && DECL_BUILT_IN (fndecl)
13390 && !gimple_call_va_arg_pack_p (stmt))
13391 {
13392 int nargs = gimple_call_num_args (stmt);
9845fb99 13393 tree *args = (nargs > 0
13394 ? gimple_call_arg_ptr (stmt, 0)
13395 : &error_mark_node);
75a70cf9 13396
198622c0 13397 if (avoid_folding_inline_builtin (fndecl))
13398 return NULL_TREE;
75a70cf9 13399 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
13400 {
9845fb99 13401 return targetm.fold_builtin (fndecl, nargs, args, ignore);
75a70cf9 13402 }
13403 else
13404 {
13405 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
9845fb99 13406 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
75a70cf9 13407 if (!ret)
13408 ret = gimple_fold_builtin_varargs (fndecl, stmt, ignore);
13409 if (ret)
13410 {
13411 /* Propagate location information from original call to
13412 expansion of builtin. Otherwise things like
13413 maybe_emit_chk_warning, that operate on the expansion
13414 of a builtin, will use the wrong location information. */
13415 if (gimple_has_location (stmt))
13416 {
13417 tree realret = ret;
13418 if (TREE_CODE (ret) == NOP_EXPR)
13419 realret = TREE_OPERAND (ret, 0);
13420 if (CAN_HAVE_LOCATION_P (realret)
13421 && !EXPR_HAS_LOCATION (realret))
389dd41b 13422 SET_EXPR_LOCATION (realret, loc);
75a70cf9 13423 return realret;
13424 }
13425 return ret;
13426 }
13427 }
13428 }
13429 return NULL_TREE;
13430}
7bfefa9d 13431
13432/* Look up the function in built_in_decls that corresponds to DECL
13433 and set ASMSPEC as its user assembler name. DECL must be a
13434 function decl that declares a builtin. */
13435
13436void
13437set_builtin_user_assembler_name (tree decl, const char *asmspec)
13438{
13439 tree builtin;
13440 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
13441 && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
13442 && asmspec != 0);
13443
13444 builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
13445 set_user_assembler_name (builtin, asmspec);
13446 switch (DECL_FUNCTION_CODE (decl))
13447 {
13448 case BUILT_IN_MEMCPY:
13449 init_block_move_fn (asmspec);
13450 memcpy_libfunc = set_user_assembler_libfunc ("memcpy", asmspec);
13451 break;
13452 case BUILT_IN_MEMSET:
13453 init_block_clear_fn (asmspec);
13454 memset_libfunc = set_user_assembler_libfunc ("memset", asmspec);
13455 break;
13456 case BUILT_IN_MEMMOVE:
13457 memmove_libfunc = set_user_assembler_libfunc ("memmove", asmspec);
13458 break;
13459 case BUILT_IN_MEMCMP:
13460 memcmp_libfunc = set_user_assembler_libfunc ("memcmp", asmspec);
13461 break;
13462 case BUILT_IN_ABORT:
13463 abort_libfunc = set_user_assembler_libfunc ("abort", asmspec);
13464 break;
5a80a58b 13465 case BUILT_IN_FFS:
13466 if (INT_TYPE_SIZE < BITS_PER_WORD)
13467 {
13468 set_user_assembler_libfunc ("ffs", asmspec);
13469 set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE,
13470 MODE_INT, 0), "ffs");
13471 }
13472 break;
7bfefa9d 13473 default:
13474 break;
13475 }
13476}
a6b74a67 13477
13478/* Return true if DECL is a builtin that expands to a constant or similarly
13479 simple code. */
13480bool
13481is_simple_builtin (tree decl)
13482{
13483 if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
13484 switch (DECL_FUNCTION_CODE (decl))
13485 {
13486 /* Builtins that expand to constants. */
13487 case BUILT_IN_CONSTANT_P:
13488 case BUILT_IN_EXPECT:
13489 case BUILT_IN_OBJECT_SIZE:
13490 case BUILT_IN_UNREACHABLE:
13491 /* Simple register moves or loads from stack. */
fca0886c 13492 case BUILT_IN_ASSUME_ALIGNED:
a6b74a67 13493 case BUILT_IN_RETURN_ADDRESS:
13494 case BUILT_IN_EXTRACT_RETURN_ADDR:
13495 case BUILT_IN_FROB_RETURN_ADDR:
13496 case BUILT_IN_RETURN:
13497 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
13498 case BUILT_IN_FRAME_ADDRESS:
13499 case BUILT_IN_VA_END:
13500 case BUILT_IN_STACK_SAVE:
13501 case BUILT_IN_STACK_RESTORE:
13502 /* Exception state returns or moves registers around. */
13503 case BUILT_IN_EH_FILTER:
13504 case BUILT_IN_EH_POINTER:
13505 case BUILT_IN_EH_COPY_VALUES:
13506 return true;
13507
13508 default:
13509 return false;
13510 }
13511
13512 return false;
13513}
13514
13515/* Return true if DECL is a builtin that is not expensive, i.e., they are
13516 most probably expanded inline into reasonably simple code. This is a
13517 superset of is_simple_builtin. */
13518bool
13519is_inexpensive_builtin (tree decl)
13520{
13521 if (!decl)
13522 return false;
13523 else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_MD)
13524 return true;
13525 else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
13526 switch (DECL_FUNCTION_CODE (decl))
13527 {
13528 case BUILT_IN_ABS:
13529 case BUILT_IN_ALLOCA:
13530 case BUILT_IN_BSWAP32:
13531 case BUILT_IN_BSWAP64:
13532 case BUILT_IN_CLZ:
13533 case BUILT_IN_CLZIMAX:
13534 case BUILT_IN_CLZL:
13535 case BUILT_IN_CLZLL:
13536 case BUILT_IN_CTZ:
13537 case BUILT_IN_CTZIMAX:
13538 case BUILT_IN_CTZL:
13539 case BUILT_IN_CTZLL:
13540 case BUILT_IN_FFS:
13541 case BUILT_IN_FFSIMAX:
13542 case BUILT_IN_FFSL:
13543 case BUILT_IN_FFSLL:
13544 case BUILT_IN_IMAXABS:
13545 case BUILT_IN_FINITE:
13546 case BUILT_IN_FINITEF:
13547 case BUILT_IN_FINITEL:
13548 case BUILT_IN_FINITED32:
13549 case BUILT_IN_FINITED64:
13550 case BUILT_IN_FINITED128:
13551 case BUILT_IN_FPCLASSIFY:
13552 case BUILT_IN_ISFINITE:
13553 case BUILT_IN_ISINF_SIGN:
13554 case BUILT_IN_ISINF:
13555 case BUILT_IN_ISINFF:
13556 case BUILT_IN_ISINFL:
13557 case BUILT_IN_ISINFD32:
13558 case BUILT_IN_ISINFD64:
13559 case BUILT_IN_ISINFD128:
13560 case BUILT_IN_ISNAN:
13561 case BUILT_IN_ISNANF:
13562 case BUILT_IN_ISNANL:
13563 case BUILT_IN_ISNAND32:
13564 case BUILT_IN_ISNAND64:
13565 case BUILT_IN_ISNAND128:
13566 case BUILT_IN_ISNORMAL:
13567 case BUILT_IN_ISGREATER:
13568 case BUILT_IN_ISGREATEREQUAL:
13569 case BUILT_IN_ISLESS:
13570 case BUILT_IN_ISLESSEQUAL:
13571 case BUILT_IN_ISLESSGREATER:
13572 case BUILT_IN_ISUNORDERED:
13573 case BUILT_IN_VA_ARG_PACK:
13574 case BUILT_IN_VA_ARG_PACK_LEN:
13575 case BUILT_IN_VA_COPY:
13576 case BUILT_IN_TRAP:
13577 case BUILT_IN_SAVEREGS:
13578 case BUILT_IN_POPCOUNTL:
13579 case BUILT_IN_POPCOUNTLL:
13580 case BUILT_IN_POPCOUNTIMAX:
13581 case BUILT_IN_POPCOUNT:
13582 case BUILT_IN_PARITYL:
13583 case BUILT_IN_PARITYLL:
13584 case BUILT_IN_PARITYIMAX:
13585 case BUILT_IN_PARITY:
13586 case BUILT_IN_LABS:
13587 case BUILT_IN_LLABS:
13588 case BUILT_IN_PREFETCH:
13589 return true;
13590
13591 default:
13592 return is_simple_builtin (decl);
13593 }
13594
13595 return false;
13596}