]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/builtins.c
* trans-expr.c (gfc_trans_string_copy): Convert both dest and
[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,
f96bd2bf 3 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
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"
ef258422 27#include "real.h"
53800dbe 28#include "rtl.h"
29#include "tree.h"
9ff0637e 30#include "tree-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"
53800dbe 43#include "toplev.h"
689df48e 44#include "predict.h"
1dd6c958 45#include "tm_p.h"
fc2a2dcb 46#include "target.h"
63c62881 47#include "langhooks.h"
0ec80471 48#include "basic-block.h"
fd62c19a 49#include "tree-mudflap.h"
5a84fdd6 50#include "tree-flow.h"
162719b3 51#include "value-prof.h"
07311427 52#include "diagnostic.h"
53800dbe 53
726e2588 54#ifndef PAD_VARARGS_DOWN
55#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
56#endif
57
ab7943b9 58/* Define the names of the builtin function types and codes. */
8934cb0c 59const char *const built_in_class_names[4]
ab7943b9 60 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
61
9cfddb70 62#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
0dfc45b5 63const char * built_in_names[(int) END_BUILTINS] =
4e9d90c7 64{
65#include "builtins.def"
66};
67#undef DEF_BUILTIN
ab7943b9 68
df94cd3b 69/* Setup an array of _DECL trees, make sure each element is
70 initialized to NULL_TREE. */
d2d4bdde 71tree built_in_decls[(int) END_BUILTINS];
0a68165a 72/* Declarations used when constructing the builtin implicitly in the compiler.
73 It may be NULL_TREE when this is invalid (for instance runtime is not
4ee9c684 74 required to implement the function call in all cases). */
0a68165a 75tree implicit_built_in_decls[(int) END_BUILTINS];
df94cd3b 76
aecda0d6 77static const char *c_getstr (tree);
78static rtx c_readstr (const char *, enum machine_mode);
79static int target_char_cast (tree, char *);
d8ae1baa 80static rtx get_memory_rtx (tree, tree);
aecda0d6 81static int apply_args_size (void);
82static int apply_result_size (void);
d8c9779c 83#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
aecda0d6 84static rtx result_vector (int, rtx);
d8c9779c 85#endif
843d08a9 86static void expand_builtin_update_setjmp_buf (rtx);
aecda0d6 87static void expand_builtin_prefetch (tree);
88static rtx expand_builtin_apply_args (void);
89static rtx expand_builtin_apply_args_1 (void);
90static rtx expand_builtin_apply (rtx, rtx, rtx);
91static void expand_builtin_return (rtx);
92static enum type_class type_to_class (tree);
93static rtx expand_builtin_classify_type (tree);
94static void expand_errno_check (tree, rtx);
95static rtx expand_builtin_mathfn (tree, rtx, rtx);
96static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
6b43bae4 97static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
a67a90e5 98static rtx expand_builtin_interclass_mathfn (tree, rtx, rtx);
c3147c1a 99static rtx expand_builtin_sincos (tree);
d735c391 100static rtx expand_builtin_cexpi (tree, rtx, rtx);
ad52b9b7 101static rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
7d3afc77 102static rtx expand_builtin_int_roundingfn_2 (tree, rtx, rtx);
aecda0d6 103static rtx expand_builtin_args_info (tree);
79012a9d 104static rtx expand_builtin_next_arg (void);
aecda0d6 105static rtx expand_builtin_va_start (tree);
106static rtx expand_builtin_va_end (tree);
107static rtx expand_builtin_va_copy (tree);
7959b13b 108static rtx expand_builtin_memchr (tree, rtx, enum machine_mode);
c2f47e15 109static rtx expand_builtin_memcmp (tree, rtx, enum machine_mode);
aecda0d6 110static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
111static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
112static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
7da1412b 113static rtx expand_builtin_strcat (tree, tree, rtx, enum machine_mode);
aecda0d6 114static rtx expand_builtin_strncat (tree, rtx, enum machine_mode);
115static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
116static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
117static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
c2f47e15 118static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode);
119static rtx expand_builtin_mempcpy_args (tree, tree, tree, tree, rtx,
120 enum machine_mode, int);
121static rtx expand_builtin_memmove (tree, rtx, enum machine_mode, int);
122static rtx expand_builtin_memmove_args (tree, tree, tree, tree, rtx,
123 enum machine_mode, int);
124static rtx expand_builtin_bcopy (tree, int);
1d89860b 125static rtx expand_builtin_strcpy (tree, tree, rtx, enum machine_mode);
c2f47e15 126static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx, enum machine_mode);
aecda0d6 127static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
aecda0d6 128static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
aecda0d6 129static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
c2f47e15 130static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
131static rtx expand_builtin_memset_args (tree, tree, tree, rtx, enum machine_mode, tree);
aecda0d6 132static rtx expand_builtin_bzero (tree);
133static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
c2f47e15 134static rtx expand_builtin_strstr (tree, rtx, enum machine_mode);
135static rtx expand_builtin_strpbrk (tree, rtx, enum machine_mode);
136static rtx expand_builtin_strchr (tree, rtx, enum machine_mode);
137static rtx expand_builtin_strrchr (tree, rtx, enum machine_mode);
aecda0d6 138static rtx expand_builtin_alloca (tree, rtx);
139static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
140static rtx expand_builtin_frame_address (tree, tree);
19bf118a 141static rtx expand_builtin_fputs (tree, rtx, bool);
142static rtx expand_builtin_printf (tree, rtx, enum machine_mode, bool);
143static rtx expand_builtin_fprintf (tree, rtx, enum machine_mode, bool);
6411575e 144static rtx expand_builtin_sprintf (tree, rtx, enum machine_mode);
aecda0d6 145static tree stabilize_va_list (tree, int);
146static rtx expand_builtin_expect (tree, rtx);
147static tree fold_builtin_constant_p (tree);
76f5a783 148static tree fold_builtin_expect (tree, tree);
aecda0d6 149static tree fold_builtin_classify_type (tree);
e6e27594 150static tree fold_builtin_strlen (tree);
aecda0d6 151static tree fold_builtin_inf (tree, int);
152static tree fold_builtin_nan (tree, tree, int);
c2f47e15 153static tree rewrite_call_expr (tree, int, tree, int, ...);
b7bf20db 154static bool validate_arg (const_tree, enum tree_code code);
277f8dd2 155static bool integer_valued_real_p (tree);
76b9b24b 156static tree fold_trunc_transparent_mathfn (tree, tree);
aecda0d6 157static bool readonly_data_expr (tree);
158static rtx expand_builtin_fabs (tree, rtx, rtx);
27f261ef 159static rtx expand_builtin_signbit (tree, rtx);
e6e27594 160static tree fold_builtin_sqrt (tree, tree);
161static tree fold_builtin_cbrt (tree, tree);
c2f47e15 162static tree fold_builtin_pow (tree, tree, tree, tree);
163static tree fold_builtin_powi (tree, tree, tree, tree);
e6e27594 164static tree fold_builtin_cos (tree, tree, tree);
cacdc1af 165static tree fold_builtin_cosh (tree, tree, tree);
bffb7645 166static tree fold_builtin_tan (tree, tree);
7169af54 167static tree fold_builtin_trunc (tree, tree);
168static tree fold_builtin_floor (tree, tree);
169static tree fold_builtin_ceil (tree, tree);
170static tree fold_builtin_round (tree, tree);
ad52b9b7 171static tree fold_builtin_int_roundingfn (tree, tree);
10b9666f 172static tree fold_builtin_bitop (tree, tree);
c2f47e15 173static tree fold_builtin_memory_op (tree, tree, tree, tree, bool, int);
174static tree fold_builtin_strchr (tree, tree, tree);
7959b13b 175static tree fold_builtin_memchr (tree, tree, tree, tree);
c2f47e15 176static tree fold_builtin_memcmp (tree, tree, tree);
177static tree fold_builtin_strcmp (tree, tree);
178static tree fold_builtin_strncmp (tree, tree, tree);
64c18e8d 179static tree fold_builtin_signbit (tree, tree);
c2f47e15 180static tree fold_builtin_copysign (tree, tree, tree, tree);
467214fd 181static tree fold_builtin_isascii (tree);
182static tree fold_builtin_toascii (tree);
183static tree fold_builtin_isdigit (tree);
d1aade50 184static tree fold_builtin_fabs (tree, tree);
185static tree fold_builtin_abs (tree, tree);
c2f47e15 186static tree fold_builtin_unordered_cmp (tree, tree, tree, enum tree_code,
d5019fe8 187 enum tree_code);
c2f47e15 188static tree fold_builtin_n (tree, tree *, int, bool);
189static tree fold_builtin_0 (tree, bool);
3d3d84b8 190static tree fold_builtin_1 (tree, tree, bool);
c2f47e15 191static tree fold_builtin_2 (tree, tree, tree, bool);
192static tree fold_builtin_3 (tree, tree, tree, tree, bool);
193static tree fold_builtin_4 (tree, tree, tree, tree, tree, bool);
194static tree fold_builtin_varargs (tree, tree, bool);
195
196static tree fold_builtin_strpbrk (tree, tree, tree);
197static tree fold_builtin_strstr (tree, tree, tree);
198static tree fold_builtin_strrchr (tree, tree, tree);
199static tree fold_builtin_strcat (tree, tree);
200static tree fold_builtin_strncat (tree, tree, tree);
201static tree fold_builtin_strspn (tree, tree);
202static tree fold_builtin_strcspn (tree, tree);
203static tree fold_builtin_sprintf (tree, tree, tree, int);
4ee9c684 204
0a39fd54 205static rtx expand_builtin_object_size (tree);
206static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
207 enum built_in_function);
208static void maybe_emit_chk_warning (tree, enum built_in_function);
209static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
c2f47e15 210static tree fold_builtin_object_size (tree, tree);
211static tree fold_builtin_strcat_chk (tree, tree, tree, tree);
212static tree fold_builtin_strncat_chk (tree, tree, tree, tree, tree);
0a39fd54 213static tree fold_builtin_sprintf_chk (tree, enum built_in_function);
c2f47e15 214static tree fold_builtin_printf (tree, tree, tree, bool, enum built_in_function);
215static tree fold_builtin_fprintf (tree, tree, tree, tree, bool,
216 enum built_in_function);
99eabcc1 217static bool init_target_chars (void);
218
219static unsigned HOST_WIDE_INT target_newline;
220static unsigned HOST_WIDE_INT target_percent;
221static unsigned HOST_WIDE_INT target_c;
222static unsigned HOST_WIDE_INT target_s;
223static char target_percent_c[3];
224static char target_percent_s[3];
225static char target_percent_s_newline[4];
728bac60 226static tree do_mpfr_arg1 (tree, tree, int (*)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
227 const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, bool);
f0c477f2 228static tree do_mpfr_arg2 (tree, tree, tree,
229 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
9917422b 230static tree do_mpfr_arg3 (tree, tree, tree, tree,
231 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
d92f994c 232static tree do_mpfr_sincos (tree, tree, tree);
65dd1378 233#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
234static tree do_mpfr_bessel_n (tree, tree, tree,
235 int (*)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
236 const REAL_VALUE_TYPE *, bool);
e5407ca6 237static tree do_mpfr_remquo (tree, tree, tree);
e84da7c1 238static tree do_mpfr_lgamma_r (tree, tree, tree);
65dd1378 239#endif
0a39fd54 240
b6a5fc45 241/* Return true if NODE should be considered for inline expansion regardless
242 of the optimization level. This means whenever a function is invoked with
243 its "internal" name, which normally contains the prefix "__builtin". */
244
245static bool called_as_built_in (tree node)
246{
247 const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
248 if (strncmp (name, "__builtin_", 10) == 0)
249 return true;
250 if (strncmp (name, "__sync_", 7) == 0)
251 return true;
252 return false;
253}
4ee9c684 254
53800dbe 255/* Return the alignment in bits of EXP, a pointer valued expression.
256 But don't return more than MAX_ALIGN no matter what.
257 The alignment returned is, by default, the alignment of the thing that
27d0c333 258 EXP points to. If it is not a POINTER_TYPE, 0 is returned.
53800dbe 259
260 Otherwise, look at the expression to see if we can do better, i.e., if the
261 expression is actually pointing at an object whose alignment is tighter. */
262
f656b751 263int
aecda0d6 264get_pointer_alignment (tree exp, unsigned int max_align)
53800dbe 265{
27d0c333 266 unsigned int align, inner;
53800dbe 267
189575ff 268 /* We rely on TER to compute accurate alignment information. */
269 if (!(optimize && flag_tree_ter))
270 return 0;
271
535e2026 272 if (!POINTER_TYPE_P (TREE_TYPE (exp)))
273 return 0;
274
53800dbe 275 align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
276 align = MIN (align, max_align);
277
278 while (1)
279 {
280 switch (TREE_CODE (exp))
281 {
282 case NOP_EXPR:
283 case CONVERT_EXPR:
284 case NON_LVALUE_EXPR:
285 exp = TREE_OPERAND (exp, 0);
552752f7 286 if (! POINTER_TYPE_P (TREE_TYPE (exp)))
53800dbe 287 return align;
325d1c45 288
53800dbe 289 inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
290 align = MIN (inner, max_align);
291 break;
292
0de36bdb 293 case POINTER_PLUS_EXPR:
53800dbe 294 /* If sum of pointer + int, restrict our maximum alignment to that
295 imposed by the integer. If not, we can't do any better than
296 ALIGN. */
325d1c45 297 if (! host_integerp (TREE_OPERAND (exp, 1), 1))
53800dbe 298 return align;
299
0994d2ed 300 while (((tree_low_cst (TREE_OPERAND (exp, 1), 1))
301 & (max_align / BITS_PER_UNIT - 1))
53800dbe 302 != 0)
303 max_align >>= 1;
304
305 exp = TREE_OPERAND (exp, 0);
306 break;
307
308 case ADDR_EXPR:
309 /* See what we are pointing at and look at its alignment. */
310 exp = TREE_OPERAND (exp, 0);
3c15318e 311 inner = max_align;
d2df7679 312 if (handled_component_p (exp))
1eee24cf 313 {
d2df7679 314 HOST_WIDE_INT bitsize, bitpos;
315 tree offset;
316 enum machine_mode mode;
317 int unsignedp, volatilep;
318
319 exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
320 &mode, &unsignedp, &volatilep, true);
321 if (bitpos)
322 inner = MIN (inner, (unsigned) (bitpos & -bitpos));
323 if (offset && TREE_CODE (offset) == PLUS_EXPR
324 && host_integerp (TREE_OPERAND (offset, 1), 1))
325 {
326 /* Any overflow in calculating offset_bits won't change
327 the alignment. */
328 unsigned offset_bits
329 = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
330 * BITS_PER_UNIT);
331
332 if (offset_bits)
333 inner = MIN (inner, (offset_bits & -offset_bits));
334 offset = TREE_OPERAND (offset, 0);
335 }
336 if (offset && TREE_CODE (offset) == MULT_EXPR
337 && host_integerp (TREE_OPERAND (offset, 1), 1))
338 {
339 /* Any overflow in calculating offset_factor won't change
340 the alignment. */
341 unsigned offset_factor
342 = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
343 * BITS_PER_UNIT);
344
345 if (offset_factor)
346 inner = MIN (inner, (offset_factor & -offset_factor));
347 }
348 else if (offset)
349 inner = MIN (inner, BITS_PER_UNIT);
1eee24cf 350 }
6c96b31e 351 if (DECL_P (exp))
3c15318e 352 align = MIN (inner, DECL_ALIGN (exp));
53800dbe 353#ifdef CONSTANT_ALIGNMENT
ce45a448 354 else if (CONSTANT_CLASS_P (exp))
e068b646 355 align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align));
53800dbe 356#endif
d2df7679 357 else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR
358 || TREE_CODE (exp) == INDIRECT_REF)
359 align = MIN (TYPE_ALIGN (TREE_TYPE (exp)), inner);
3c15318e 360 else
361 align = MIN (align, inner);
362 return MIN (align, max_align);
53800dbe 363
364 default:
365 return align;
366 }
367 }
368}
369
370/* Compute the length of a C string. TREE_STRING_LENGTH is not the right
371 way, because it could contain a zero byte in the middle.
372 TREE_STRING_LENGTH is the size of the character array, not the string.
373
4172d65e 374 ONLY_VALUE should be nonzero if the result is not going to be emitted
c09841f6 375 into the instruction stream and zero if it is going to be expanded.
4172d65e 376 E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
681fab1e 377 is returned, otherwise NULL, since
378 len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
379 evaluate the side-effects.
380
902de8ed 381 The value returned is of type `ssizetype'.
382
53800dbe 383 Unfortunately, string_constant can't access the values of const char
384 arrays with initializers, so neither can we do so here. */
385
4ee9c684 386tree
681fab1e 387c_strlen (tree src, int only_value)
53800dbe 388{
389 tree offset_node;
27d0c333 390 HOST_WIDE_INT offset;
391 int max;
44acf429 392 const char *ptr;
53800dbe 393
681fab1e 394 STRIP_NOPS (src);
395 if (TREE_CODE (src) == COND_EXPR
396 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
397 {
398 tree len1, len2;
399
400 len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
401 len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
0862b7e9 402 if (tree_int_cst_equal (len1, len2))
681fab1e 403 return len1;
404 }
405
406 if (TREE_CODE (src) == COMPOUND_EXPR
407 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
408 return c_strlen (TREE_OPERAND (src, 1), only_value);
409
53800dbe 410 src = string_constant (src, &offset_node);
411 if (src == 0)
c2f47e15 412 return NULL_TREE;
902de8ed 413
83d79705 414 max = TREE_STRING_LENGTH (src) - 1;
53800dbe 415 ptr = TREE_STRING_POINTER (src);
902de8ed 416
53800dbe 417 if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
418 {
419 /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
420 compute the offset to the following null if we don't know where to
421 start searching for it. */
422 int i;
902de8ed 423
53800dbe 424 for (i = 0; i < max; i++)
425 if (ptr[i] == 0)
c2f47e15 426 return NULL_TREE;
902de8ed 427
53800dbe 428 /* We don't know the starting offset, but we do know that the string
429 has no internal zero bytes. We can assume that the offset falls
430 within the bounds of the string; otherwise, the programmer deserves
431 what he gets. Subtract the offset from the length of the string,
902de8ed 432 and return that. This would perhaps not be valid if we were dealing
433 with named arrays in addition to literal string constants. */
434
435 return size_diffop (size_int (max), offset_node);
53800dbe 436 }
437
438 /* We have a known offset into the string. Start searching there for
27d0c333 439 a null character if we can represent it as a single HOST_WIDE_INT. */
dabc4084 440 if (offset_node == 0)
53800dbe 441 offset = 0;
dabc4084 442 else if (! host_integerp (offset_node, 0))
443 offset = -1;
53800dbe 444 else
27d0c333 445 offset = tree_low_cst (offset_node, 0);
902de8ed 446
53800dbe 447 /* If the offset is known to be out of bounds, warn, and call strlen at
448 runtime. */
449 if (offset < 0 || offset > max)
450 {
c3ceba8e 451 warning (0, "offset outside bounds of constant string");
c2f47e15 452 return NULL_TREE;
53800dbe 453 }
902de8ed 454
53800dbe 455 /* Use strlen to search for the first zero byte. Since any strings
456 constructed with build_string will have nulls appended, we win even
457 if we get handed something like (char[4])"abcd".
458
459 Since OFFSET is our starting index into the string, no further
460 calculation is needed. */
902de8ed 461 return ssize_int (strlen (ptr + offset));
53800dbe 462}
463
83d79705 464/* Return a char pointer for a C string if it is a string constant
465 or sum of string constant and integer constant. */
466
467static const char *
aecda0d6 468c_getstr (tree src)
83d79705 469{
470 tree offset_node;
83d79705 471
472 src = string_constant (src, &offset_node);
473 if (src == 0)
474 return 0;
475
8c85fcb7 476 if (offset_node == 0)
477 return TREE_STRING_POINTER (src);
478 else if (!host_integerp (offset_node, 1)
479 || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
83d79705 480 return 0;
83d79705 481
8c85fcb7 482 return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
83d79705 483}
484
8c85fcb7 485/* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
486 GET_MODE_BITSIZE (MODE) bits from string constant STR. */
ecc318ff 487
6840589f 488static rtx
aecda0d6 489c_readstr (const char *str, enum machine_mode mode)
6840589f 490{
491 HOST_WIDE_INT c[2];
492 HOST_WIDE_INT ch;
493 unsigned int i, j;
494
64db345d 495 gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
7d3f6cc7 496
6840589f 497 c[0] = 0;
498 c[1] = 0;
499 ch = 1;
500 for (i = 0; i < GET_MODE_SIZE (mode); i++)
501 {
502 j = i;
503 if (WORDS_BIG_ENDIAN)
504 j = GET_MODE_SIZE (mode) - i - 1;
505 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
506 && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
507 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
508 j *= BITS_PER_UNIT;
64db345d 509 gcc_assert (j <= 2 * HOST_BITS_PER_WIDE_INT);
7d3f6cc7 510
6840589f 511 if (ch)
512 ch = (unsigned char) str[i];
513 c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
514 }
515 return immed_double_const (c[0], c[1], mode);
516}
517
ecc318ff 518/* Cast a target constant CST to target CHAR and if that value fits into
5206b159 519 host char type, return zero and put that value into variable pointed to by
ecc318ff 520 P. */
521
522static int
aecda0d6 523target_char_cast (tree cst, char *p)
ecc318ff 524{
525 unsigned HOST_WIDE_INT val, hostval;
526
27d0c333 527 if (!host_integerp (cst, 1)
ecc318ff 528 || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
529 return 1;
530
27d0c333 531 val = tree_low_cst (cst, 1);
ecc318ff 532 if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
533 val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
534
535 hostval = val;
536 if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
537 hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
538
539 if (val != hostval)
540 return 1;
541
542 *p = hostval;
543 return 0;
544}
545
4ee9c684 546/* Similar to save_expr, but assumes that arbitrary code is not executed
547 in between the multiple evaluations. In particular, we assume that a
548 non-addressable local variable will not be modified. */
549
550static tree
551builtin_save_expr (tree exp)
552{
553 if (TREE_ADDRESSABLE (exp) == 0
554 && (TREE_CODE (exp) == PARM_DECL
555 || (TREE_CODE (exp) == VAR_DECL && !TREE_STATIC (exp))))
556 return exp;
557
558 return save_expr (exp);
559}
560
53800dbe 561/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
562 times to get the address of either a higher stack frame, or a return
563 address located within it (depending on FNDECL_CODE). */
902de8ed 564
c626df3d 565static rtx
869d0ef0 566expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
53800dbe 567{
568 int i;
569
869d0ef0 570#ifdef INITIAL_FRAME_ADDRESS_RTX
571 rtx tem = INITIAL_FRAME_ADDRESS_RTX;
572#else
e3e15c50 573 rtx tem;
574
1b74fde7 575 /* For a zero count with __builtin_return_address, we don't care what
576 frame address we return, because target-specific definitions will
577 override us. Therefore frame pointer elimination is OK, and using
578 the soft frame pointer is OK.
579
fa7637bd 580 For a nonzero count, or a zero count with __builtin_frame_address,
1b74fde7 581 we require a stable offset from the current frame pointer to the
582 previous one, so we must use the hard frame pointer, and
e3e15c50 583 we must disable frame pointer elimination. */
1b74fde7 584 if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
e3e15c50 585 tem = frame_pointer_rtx;
a0c938f0 586 else
e3e15c50 587 {
588 tem = hard_frame_pointer_rtx;
589
590 /* Tell reload not to eliminate the frame pointer. */
591 current_function_accesses_prior_frames = 1;
592 }
869d0ef0 593#endif
594
53800dbe 595 /* Some machines need special handling before we can access
3a69c60c 596 arbitrary frames. For example, on the SPARC, we must first flush
53800dbe 597 all register windows to the stack. */
598#ifdef SETUP_FRAME_ADDRESSES
599 if (count > 0)
600 SETUP_FRAME_ADDRESSES ();
601#endif
602
3a69c60c 603 /* On the SPARC, the return address is not in the frame, it is in a
53800dbe 604 register. There is no way to access it off of the current frame
605 pointer, but it can be accessed off the previous frame pointer by
606 reading the value from the register window save area. */
607#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
608 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
609 count--;
610#endif
611
612 /* Scan back COUNT frames to the specified frame. */
613 for (i = 0; i < count; i++)
614 {
615 /* Assume the dynamic chain pointer is in the word that the
616 frame address points to, unless otherwise specified. */
617#ifdef DYNAMIC_CHAIN_ADDRESS
618 tem = DYNAMIC_CHAIN_ADDRESS (tem);
619#endif
620 tem = memory_address (Pmode, tem);
00060fc2 621 tem = gen_frame_mem (Pmode, tem);
83fc1478 622 tem = copy_to_reg (tem);
53800dbe 623 }
624
3a69c60c 625 /* For __builtin_frame_address, return what we've got. But, on
626 the SPARC for example, we may have to add a bias. */
53800dbe 627 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
3a69c60c 628#ifdef FRAME_ADDR_RTX
629 return FRAME_ADDR_RTX (tem);
630#else
53800dbe 631 return tem;
3a69c60c 632#endif
53800dbe 633
3a69c60c 634 /* For __builtin_return_address, get the return address from that frame. */
53800dbe 635#ifdef RETURN_ADDR_RTX
636 tem = RETURN_ADDR_RTX (count, tem);
637#else
638 tem = memory_address (Pmode,
639 plus_constant (tem, GET_MODE_SIZE (Pmode)));
00060fc2 640 tem = gen_frame_mem (Pmode, tem);
53800dbe 641#endif
642 return tem;
643}
644
f7c44134 645/* Alias set used for setjmp buffer. */
32c2fdea 646static alias_set_type setjmp_alias_set = -1;
f7c44134 647
6b7f6858 648/* Construct the leading half of a __builtin_setjmp call. Control will
2c8a1497 649 return to RECEIVER_LABEL. This is also called directly by the SJLJ
650 exception handling code. */
53800dbe 651
6b7f6858 652void
aecda0d6 653expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
53800dbe 654{
53800dbe 655 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
53800dbe 656 rtx stack_save;
f7c44134 657 rtx mem;
53800dbe 658
f7c44134 659 if (setjmp_alias_set == -1)
660 setjmp_alias_set = new_alias_set ();
661
85d654dd 662 buf_addr = convert_memory_address (Pmode, buf_addr);
53800dbe 663
37ae8504 664 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
53800dbe 665
6b7f6858 666 /* We store the frame pointer and the address of receiver_label in
667 the buffer and use the rest of it for the stack save area, which
668 is machine-dependent. */
53800dbe 669
f7c44134 670 mem = gen_rtx_MEM (Pmode, buf_addr);
ab6ab77e 671 set_mem_alias_set (mem, setjmp_alias_set);
e3e026e8 672 emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
f7c44134 673
674 mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
ab6ab77e 675 set_mem_alias_set (mem, setjmp_alias_set);
f7c44134 676
677 emit_move_insn (validize_mem (mem),
6b7f6858 678 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
53800dbe 679
680 stack_save = gen_rtx_MEM (sa_mode,
681 plus_constant (buf_addr,
682 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 683 set_mem_alias_set (stack_save, setjmp_alias_set);
53800dbe 684 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
685
686 /* If there is further processing to do, do it. */
687#ifdef HAVE_builtin_setjmp_setup
688 if (HAVE_builtin_setjmp_setup)
689 emit_insn (gen_builtin_setjmp_setup (buf_addr));
690#endif
691
6b7f6858 692 /* Tell optimize_save_area_alloca that extra work is going to
693 need to go on during alloca. */
3b0fa6b6 694 current_function_calls_setjmp = 1;
80ab81b9 695
29f09705 696 /* We have a nonlocal label. */
80ab81b9 697 current_function_has_nonlocal_label = 1;
6b7f6858 698}
53800dbe 699
2c8a1497 700/* Construct the trailing part of a __builtin_setjmp call. This is
701 also called directly by the SJLJ exception handling code. */
6b7f6858 702
703void
aecda0d6 704expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
6b7f6858 705{
53800dbe 706 /* Clobber the FP when we get here, so we have to make sure it's
707 marked as used by this function. */
708 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
709
710 /* Mark the static chain as clobbered here so life information
711 doesn't get messed up for it. */
712 emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
713
714 /* Now put in the code to restore the frame pointer, and argument
491e04ef 715 pointer, if needed. */
53800dbe 716#ifdef HAVE_nonlocal_goto
717 if (! HAVE_nonlocal_goto)
718#endif
5a1c3f40 719 {
720 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
721 /* This might change the hard frame pointer in ways that aren't
722 apparent to early optimization passes, so force a clobber. */
723 emit_insn (gen_rtx_CLOBBER (VOIDmode, hard_frame_pointer_rtx));
724 }
53800dbe 725
726#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
727 if (fixed_regs[ARG_POINTER_REGNUM])
728 {
729#ifdef ELIMINABLE_REGS
730 size_t i;
e99c3a1d 731 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
53800dbe 732
3098b2d3 733 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
53800dbe 734 if (elim_regs[i].from == ARG_POINTER_REGNUM
735 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
736 break;
737
3098b2d3 738 if (i == ARRAY_SIZE (elim_regs))
53800dbe 739#endif
740 {
741 /* Now restore our arg pointer from the address at which it
05927e40 742 was saved in our stack frame. */
53800dbe 743 emit_move_insn (virtual_incoming_args_rtx,
05927e40 744 copy_to_reg (get_arg_pointer_save_area (cfun)));
53800dbe 745 }
746 }
747#endif
748
749#ifdef HAVE_builtin_setjmp_receiver
750 if (HAVE_builtin_setjmp_receiver)
6b7f6858 751 emit_insn (gen_builtin_setjmp_receiver (receiver_label));
53800dbe 752 else
753#endif
754#ifdef HAVE_nonlocal_goto_receiver
755 if (HAVE_nonlocal_goto_receiver)
756 emit_insn (gen_nonlocal_goto_receiver ());
757 else
758#endif
6b7f6858 759 { /* Nothing */ }
57f6bb94 760
3072d30e 761 /* We must not allow the code we just generated to be reordered by
762 scheduling. Specifically, the update of the frame pointer must
763 happen immediately, not later. */
764 emit_insn (gen_blockage ());
6b7f6858 765}
53800dbe 766
53800dbe 767/* __builtin_longjmp is passed a pointer to an array of five words (not
768 all will be used on all machines). It operates similarly to the C
769 library function of the same name, but is more efficient. Much of
2c8a1497 770 the code below is copied from the handling of non-local gotos. */
53800dbe 771
c626df3d 772static void
aecda0d6 773expand_builtin_longjmp (rtx buf_addr, rtx value)
53800dbe 774{
4712c7d6 775 rtx fp, lab, stack, insn, last;
53800dbe 776 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
777
f7c44134 778 if (setjmp_alias_set == -1)
779 setjmp_alias_set = new_alias_set ();
780
85d654dd 781 buf_addr = convert_memory_address (Pmode, buf_addr);
479e4d5e 782
53800dbe 783 buf_addr = force_reg (Pmode, buf_addr);
784
785 /* We used to store value in static_chain_rtx, but that fails if pointers
786 are smaller than integers. We instead require that the user must pass
787 a second argument of 1, because that is what builtin_setjmp will
788 return. This also makes EH slightly more efficient, since we are no
789 longer copying around a value that we don't care about. */
64db345d 790 gcc_assert (value == const1_rtx);
53800dbe 791
4712c7d6 792 last = get_last_insn ();
53800dbe 793#ifdef HAVE_builtin_longjmp
794 if (HAVE_builtin_longjmp)
795 emit_insn (gen_builtin_longjmp (buf_addr));
796 else
797#endif
798 {
799 fp = gen_rtx_MEM (Pmode, buf_addr);
800 lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
801 GET_MODE_SIZE (Pmode)));
802
803 stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
804 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 805 set_mem_alias_set (fp, setjmp_alias_set);
806 set_mem_alias_set (lab, setjmp_alias_set);
807 set_mem_alias_set (stack, setjmp_alias_set);
53800dbe 808
809 /* Pick up FP, label, and SP from the block and jump. This code is
810 from expand_goto in stmt.c; see there for detailed comments. */
03fd9d2c 811#ifdef HAVE_nonlocal_goto
53800dbe 812 if (HAVE_nonlocal_goto)
813 /* We have to pass a value to the nonlocal_goto pattern that will
814 get copied into the static_chain pointer, but it does not matter
815 what that value is, because builtin_setjmp does not use it. */
28d202a8 816 emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
53800dbe 817 else
818#endif
819 {
820 lab = copy_to_reg (lab);
821
2a871ad1 822 emit_insn (gen_rtx_CLOBBER (VOIDmode,
823 gen_rtx_MEM (BLKmode,
824 gen_rtx_SCRATCH (VOIDmode))));
825 emit_insn (gen_rtx_CLOBBER (VOIDmode,
826 gen_rtx_MEM (BLKmode,
827 hard_frame_pointer_rtx)));
828
53800dbe 829 emit_move_insn (hard_frame_pointer_rtx, fp);
830 emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
831
832 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
833 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
834 emit_indirect_jump (lab);
835 }
836 }
615166bb 837
838 /* Search backwards and mark the jump insn as a non-local goto.
839 Note that this precludes the use of __builtin_longjmp to a
840 __builtin_setjmp target in the same function. However, we've
841 already cautioned the user that these functions are for
842 internal exception handling use only. */
449c0509 843 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
844 {
64db345d 845 gcc_assert (insn != last);
7d3f6cc7 846
6d7dc5b9 847 if (JUMP_P (insn))
449c0509 848 {
849 REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
850 REG_NOTES (insn));
851 break;
852 }
6d7dc5b9 853 else if (CALL_P (insn))
9342ee68 854 break;
449c0509 855 }
53800dbe 856}
857
4ee9c684 858/* Expand a call to __builtin_nonlocal_goto. We're passed the target label
859 and the address of the save area. */
860
861static rtx
c2f47e15 862expand_builtin_nonlocal_goto (tree exp)
4ee9c684 863{
864 tree t_label, t_save_area;
865 rtx r_label, r_save_area, r_fp, r_sp, insn;
866
c2f47e15 867 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4ee9c684 868 return NULL_RTX;
869
c2f47e15 870 t_label = CALL_EXPR_ARG (exp, 0);
871 t_save_area = CALL_EXPR_ARG (exp, 1);
4ee9c684 872
8ec3c5c2 873 r_label = expand_normal (t_label);
3dce56cc 874 r_label = convert_memory_address (Pmode, r_label);
8ec3c5c2 875 r_save_area = expand_normal (t_save_area);
3dce56cc 876 r_save_area = convert_memory_address (Pmode, r_save_area);
4ee9c684 877 r_fp = gen_rtx_MEM (Pmode, r_save_area);
878 r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
879 plus_constant (r_save_area, GET_MODE_SIZE (Pmode)));
880
881 current_function_has_nonlocal_goto = 1;
882
03fd9d2c 883#ifdef HAVE_nonlocal_goto
4ee9c684 884 /* ??? We no longer need to pass the static chain value, afaik. */
885 if (HAVE_nonlocal_goto)
886 emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
887 else
888#endif
889 {
890 r_label = copy_to_reg (r_label);
891
892 emit_insn (gen_rtx_CLOBBER (VOIDmode,
893 gen_rtx_MEM (BLKmode,
894 gen_rtx_SCRATCH (VOIDmode))));
895
896 emit_insn (gen_rtx_CLOBBER (VOIDmode,
897 gen_rtx_MEM (BLKmode,
898 hard_frame_pointer_rtx)));
491e04ef 899
4ee9c684 900 /* Restore frame pointer for containing function.
901 This sets the actual hard register used for the frame pointer
902 to the location of the function's incoming static chain info.
903 The non-local goto handler will then adjust it to contain the
904 proper value and reload the argument pointer, if needed. */
905 emit_move_insn (hard_frame_pointer_rtx, r_fp);
906 emit_stack_restore (SAVE_NONLOCAL, r_sp, NULL_RTX);
491e04ef 907
4ee9c684 908 /* USE of hard_frame_pointer_rtx added for consistency;
909 not clear if really needed. */
910 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
911 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
912 emit_indirect_jump (r_label);
913 }
491e04ef 914
4ee9c684 915 /* Search backwards to the jump insn and mark it as a
916 non-local goto. */
917 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
918 {
6d7dc5b9 919 if (JUMP_P (insn))
4ee9c684 920 {
921 REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO,
922 const0_rtx, REG_NOTES (insn));
923 break;
924 }
6d7dc5b9 925 else if (CALL_P (insn))
4ee9c684 926 break;
927 }
928
929 return const0_rtx;
930}
931
843d08a9 932/* __builtin_update_setjmp_buf is passed a pointer to an array of five words
933 (not all will be used on all machines) that was passed to __builtin_setjmp.
934 It updates the stack pointer in that block to correspond to the current
935 stack pointer. */
936
937static void
938expand_builtin_update_setjmp_buf (rtx buf_addr)
939{
940 enum machine_mode sa_mode = Pmode;
941 rtx stack_save;
942
943
944#ifdef HAVE_save_stack_nonlocal
945 if (HAVE_save_stack_nonlocal)
946 sa_mode = insn_data[(int) CODE_FOR_save_stack_nonlocal].operand[0].mode;
947#endif
948#ifdef STACK_SAVEAREA_MODE
949 sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
950#endif
951
952 stack_save
953 = gen_rtx_MEM (sa_mode,
954 memory_address
955 (sa_mode,
956 plus_constant (buf_addr, 2 * GET_MODE_SIZE (Pmode))));
957
958#ifdef HAVE_setjmp
959 if (HAVE_setjmp)
960 emit_insn (gen_setjmp ());
961#endif
962
963 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
964}
965
5e3608d8 966/* Expand a call to __builtin_prefetch. For a target that does not support
967 data prefetch, evaluate the memory address argument in case it has side
968 effects. */
969
970static void
c2f47e15 971expand_builtin_prefetch (tree exp)
5e3608d8 972{
973 tree arg0, arg1, arg2;
c2f47e15 974 int nargs;
5e3608d8 975 rtx op0, op1, op2;
976
c2f47e15 977 if (!validate_arglist (exp, POINTER_TYPE, 0))
26a5cadb 978 return;
979
c2f47e15 980 arg0 = CALL_EXPR_ARG (exp, 0);
981
26a5cadb 982 /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
983 zero (read) and argument 2 (locality) defaults to 3 (high degree of
984 locality). */
c2f47e15 985 nargs = call_expr_nargs (exp);
986 if (nargs > 1)
987 arg1 = CALL_EXPR_ARG (exp, 1);
26a5cadb 988 else
c2f47e15 989 arg1 = integer_zero_node;
990 if (nargs > 2)
991 arg2 = CALL_EXPR_ARG (exp, 2);
992 else
993 arg2 = build_int_cst (NULL_TREE, 3);
5e3608d8 994
995 /* Argument 0 is an address. */
996 op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
997
998 /* Argument 1 (read/write flag) must be a compile-time constant int. */
999 if (TREE_CODE (arg1) != INTEGER_CST)
1000 {
07e3a3d2 1001 error ("second argument to %<__builtin_prefetch%> must be a constant");
9342ee68 1002 arg1 = integer_zero_node;
5e3608d8 1003 }
8ec3c5c2 1004 op1 = expand_normal (arg1);
5e3608d8 1005 /* Argument 1 must be either zero or one. */
1006 if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
1007 {
c3ceba8e 1008 warning (0, "invalid second argument to %<__builtin_prefetch%>;"
07e3a3d2 1009 " using zero");
5e3608d8 1010 op1 = const0_rtx;
1011 }
1012
1013 /* Argument 2 (locality) must be a compile-time constant int. */
1014 if (TREE_CODE (arg2) != INTEGER_CST)
1015 {
07e3a3d2 1016 error ("third argument to %<__builtin_prefetch%> must be a constant");
5e3608d8 1017 arg2 = integer_zero_node;
1018 }
8ec3c5c2 1019 op2 = expand_normal (arg2);
5e3608d8 1020 /* Argument 2 must be 0, 1, 2, or 3. */
1021 if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
1022 {
c3ceba8e 1023 warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
5e3608d8 1024 op2 = const0_rtx;
1025 }
1026
1027#ifdef HAVE_prefetch
1028 if (HAVE_prefetch)
1029 {
f0ce3b1f 1030 if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate)
4cd21437 1031 (op0,
f0ce3b1f 1032 insn_data[(int) CODE_FOR_prefetch].operand[0].mode))
19bf118a 1033 || (GET_MODE (op0) != Pmode))
9342ee68 1034 {
85d654dd 1035 op0 = convert_memory_address (Pmode, op0);
9342ee68 1036 op0 = force_reg (Pmode, op0);
1037 }
5e3608d8 1038 emit_insn (gen_prefetch (op0, op1, op2));
1039 }
5e3608d8 1040#endif
0a534ba7 1041
f0ce3b1f 1042 /* Don't do anything with direct references to volatile memory, but
1043 generate code to handle other side effects. */
e16ceb8e 1044 if (!MEM_P (op0) && side_effects_p (op0))
f0ce3b1f 1045 emit_insn (op0);
5e3608d8 1046}
1047
f7c44134 1048/* Get a MEM rtx for expression EXP which is the address of an operand
d8ae1baa 1049 to be used in a string instruction (cmpstrsi, movmemsi, ..). LEN is
1050 the maximum length of the block of memory that might be accessed or
1051 NULL if unknown. */
f7c44134 1052
53800dbe 1053static rtx
d8ae1baa 1054get_memory_rtx (tree exp, tree len)
53800dbe 1055{
bb2327a8 1056 rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
1057 rtx mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
2a631e19 1058
f7c44134 1059 /* Get an expression we can use to find the attributes to assign to MEM.
1060 If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
1061 we can. First remove any nops. */
1062 while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
f0ce3b1f 1063 || TREE_CODE (exp) == NON_LVALUE_EXPR)
f7c44134 1064 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
1065 exp = TREE_OPERAND (exp, 0);
1066
1067 if (TREE_CODE (exp) == ADDR_EXPR)
a1a25d19 1068 exp = TREE_OPERAND (exp, 0);
f7c44134 1069 else if (POINTER_TYPE_P (TREE_TYPE (exp)))
a1a25d19 1070 exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
1071 else
1072 exp = NULL;
1073
1074 /* Honor attributes derived from exp, except for the alias set
1075 (as builtin stringops may alias with anything) and the size
1076 (as stringops may access multiple array elements). */
1077 if (exp)
eec8e941 1078 {
a1a25d19 1079 set_mem_attributes (mem, exp, 0);
d8ae1baa 1080
1081 /* Allow the string and memory builtins to overflow from one
1082 field into another, see http://gcc.gnu.org/PR23561.
1083 Thus avoid COMPONENT_REFs in MEM_EXPR unless we know the whole
1084 memory accessed by the string or memory builtin will fit
1085 within the field. */
1086 if (MEM_EXPR (mem) && TREE_CODE (MEM_EXPR (mem)) == COMPONENT_REF)
1087 {
1088 tree mem_expr = MEM_EXPR (mem);
1089 HOST_WIDE_INT offset = -1, length = -1;
1090 tree inner = exp;
1091
1092 while (TREE_CODE (inner) == ARRAY_REF
1093 || TREE_CODE (inner) == NOP_EXPR
1094 || TREE_CODE (inner) == CONVERT_EXPR
1095 || TREE_CODE (inner) == NON_LVALUE_EXPR
1096 || TREE_CODE (inner) == VIEW_CONVERT_EXPR
1097 || TREE_CODE (inner) == SAVE_EXPR)
1098 inner = TREE_OPERAND (inner, 0);
1099
1100 gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
1101
1102 if (MEM_OFFSET (mem)
1103 && GET_CODE (MEM_OFFSET (mem)) == CONST_INT)
1104 offset = INTVAL (MEM_OFFSET (mem));
1105
1106 if (offset >= 0 && len && host_integerp (len, 0))
1107 length = tree_low_cst (len, 0);
1108
1109 while (TREE_CODE (inner) == COMPONENT_REF)
1110 {
1111 tree field = TREE_OPERAND (inner, 1);
1112 gcc_assert (! DECL_BIT_FIELD (field));
1113 gcc_assert (TREE_CODE (mem_expr) == COMPONENT_REF);
1114 gcc_assert (field == TREE_OPERAND (mem_expr, 1));
1115
1116 if (length >= 0
1117 && TYPE_SIZE_UNIT (TREE_TYPE (inner))
1118 && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0))
1119 {
1120 HOST_WIDE_INT size
1121 = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0);
1122 /* If we can prove the memory starting at XEXP (mem, 0)
1123 and ending at XEXP (mem, 0) + LENGTH will fit into
1124 this field, we can keep that COMPONENT_REF in MEM_EXPR. */
1125 if (offset <= size
1126 && length <= size
1127 && offset + length <= size)
1128 break;
1129 }
1130
1131 if (offset >= 0
1132 && host_integerp (DECL_FIELD_OFFSET (field), 0))
1133 offset += tree_low_cst (DECL_FIELD_OFFSET (field), 0)
1134 + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
1135 / BITS_PER_UNIT;
1136 else
1137 {
1138 offset = -1;
1139 length = -1;
1140 }
1141
1142 mem_expr = TREE_OPERAND (mem_expr, 0);
1143 inner = TREE_OPERAND (inner, 0);
d8ae1baa 1144 }
1145
1146 if (mem_expr == NULL)
1147 offset = -1;
1148 if (mem_expr != MEM_EXPR (mem))
1149 {
1150 set_mem_expr (mem, mem_expr);
1151 set_mem_offset (mem, offset >= 0 ? GEN_INT (offset) : NULL_RTX);
1152 }
1153 }
eec8e941 1154 set_mem_alias_set (mem, 0);
a1a25d19 1155 set_mem_size (mem, NULL_RTX);
eec8e941 1156 }
53800dbe 1157
53800dbe 1158 return mem;
1159}
1160\f
1161/* Built-in functions to perform an untyped call and return. */
1162
1163/* For each register that may be used for calling a function, this
1164 gives a mode used to copy the register's value. VOIDmode indicates
1165 the register is not used for calling a function. If the machine
1166 has register windows, this gives only the outbound registers.
1167 INCOMING_REGNO gives the corresponding inbound register. */
1168static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
1169
1170/* For each register that may be used for returning values, this gives
1171 a mode used to copy the register's value. VOIDmode indicates the
1172 register is not used for returning values. If the machine has
1173 register windows, this gives only the outbound registers.
1174 INCOMING_REGNO gives the corresponding inbound register. */
1175static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
1176
1177/* For each register that may be used for calling a function, this
1178 gives the offset of that register into the block returned by
1179 __builtin_apply_args. 0 indicates that the register is not
1180 used for calling a function. */
1181static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
1182
53800dbe 1183/* Return the size required for the block returned by __builtin_apply_args,
1184 and initialize apply_args_mode. */
1185
1186static int
aecda0d6 1187apply_args_size (void)
53800dbe 1188{
1189 static int size = -1;
58e9ce8f 1190 int align;
1191 unsigned int regno;
53800dbe 1192 enum machine_mode mode;
1193
1194 /* The values computed by this function never change. */
1195 if (size < 0)
1196 {
1197 /* The first value is the incoming arg-pointer. */
1198 size = GET_MODE_SIZE (Pmode);
1199
1200 /* The second value is the structure value address unless this is
1201 passed as an "invisible" first argument. */
6812c89e 1202 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1203 size += GET_MODE_SIZE (Pmode);
1204
1205 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1206 if (FUNCTION_ARG_REGNO_P (regno))
1207 {
0862b7e9 1208 mode = reg_raw_mode[regno];
1209
64db345d 1210 gcc_assert (mode != VOIDmode);
53800dbe 1211
1212 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1213 if (size % align != 0)
1214 size = CEIL (size, align) * align;
1215 apply_args_reg_offset[regno] = size;
1216 size += GET_MODE_SIZE (mode);
1217 apply_args_mode[regno] = mode;
1218 }
1219 else
1220 {
1221 apply_args_mode[regno] = VOIDmode;
1222 apply_args_reg_offset[regno] = 0;
1223 }
1224 }
1225 return size;
1226}
1227
1228/* Return the size required for the block returned by __builtin_apply,
1229 and initialize apply_result_mode. */
1230
1231static int
aecda0d6 1232apply_result_size (void)
53800dbe 1233{
1234 static int size = -1;
1235 int align, regno;
1236 enum machine_mode mode;
1237
1238 /* The values computed by this function never change. */
1239 if (size < 0)
1240 {
1241 size = 0;
1242
1243 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1244 if (FUNCTION_VALUE_REGNO_P (regno))
1245 {
0862b7e9 1246 mode = reg_raw_mode[regno];
1247
64db345d 1248 gcc_assert (mode != VOIDmode);
53800dbe 1249
1250 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1251 if (size % align != 0)
1252 size = CEIL (size, align) * align;
1253 size += GET_MODE_SIZE (mode);
1254 apply_result_mode[regno] = mode;
1255 }
1256 else
1257 apply_result_mode[regno] = VOIDmode;
1258
1259 /* Allow targets that use untyped_call and untyped_return to override
1260 the size so that machine-specific information can be stored here. */
1261#ifdef APPLY_RESULT_SIZE
1262 size = APPLY_RESULT_SIZE;
1263#endif
1264 }
1265 return size;
1266}
1267
1268#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1269/* Create a vector describing the result block RESULT. If SAVEP is true,
1270 the result block is used to save the values; otherwise it is used to
1271 restore the values. */
1272
1273static rtx
aecda0d6 1274result_vector (int savep, rtx result)
53800dbe 1275{
1276 int regno, size, align, nelts;
1277 enum machine_mode mode;
1278 rtx reg, mem;
f0af5a88 1279 rtx *savevec = alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
bf8e3599 1280
53800dbe 1281 size = nelts = 0;
1282 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1283 if ((mode = apply_result_mode[regno]) != VOIDmode)
1284 {
1285 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1286 if (size % align != 0)
1287 size = CEIL (size, align) * align;
1288 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
e513d163 1289 mem = adjust_address (result, mode, size);
53800dbe 1290 savevec[nelts++] = (savep
1291 ? gen_rtx_SET (VOIDmode, mem, reg)
1292 : gen_rtx_SET (VOIDmode, reg, mem));
1293 size += GET_MODE_SIZE (mode);
1294 }
1295 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1296}
1297#endif /* HAVE_untyped_call or HAVE_untyped_return */
1298
1299/* Save the state required to perform an untyped call with the same
1300 arguments as were passed to the current function. */
1301
1302static rtx
aecda0d6 1303expand_builtin_apply_args_1 (void)
53800dbe 1304{
1c7e61a7 1305 rtx registers, tem;
53800dbe 1306 int size, align, regno;
1307 enum machine_mode mode;
6812c89e 1308 rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
53800dbe 1309
1310 /* Create a block where the arg-pointer, structure value address,
1311 and argument registers can be saved. */
1312 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1313
1314 /* Walk past the arg-pointer and structure value address. */
1315 size = GET_MODE_SIZE (Pmode);
6812c89e 1316 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1317 size += GET_MODE_SIZE (Pmode);
1318
1319 /* Save each register used in calling a function to the block. */
1320 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1321 if ((mode = apply_args_mode[regno]) != VOIDmode)
1322 {
53800dbe 1323 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1324 if (size % align != 0)
1325 size = CEIL (size, align) * align;
1326
1327 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1328
e513d163 1329 emit_move_insn (adjust_address (registers, mode, size), tem);
53800dbe 1330 size += GET_MODE_SIZE (mode);
1331 }
1332
1333 /* Save the arg pointer to the block. */
1c7e61a7 1334 tem = copy_to_reg (virtual_incoming_args_rtx);
f083a92b 1335#ifdef STACK_GROWS_DOWNWARD
1c7e61a7 1336 /* We need the pointer as the caller actually passed them to us, not
9d4b544c 1337 as we might have pretended they were passed. Make sure it's a valid
1338 operand, as emit_move_insn isn't expected to handle a PLUS. */
1339 tem
1340 = force_operand (plus_constant (tem, current_function_pretend_args_size),
1341 NULL_RTX);
1c7e61a7 1342#endif
1343 emit_move_insn (adjust_address (registers, Pmode, 0), tem);
0862b7e9 1344
53800dbe 1345 size = GET_MODE_SIZE (Pmode);
1346
1347 /* Save the structure value address unless this is passed as an
1348 "invisible" first argument. */
45550790 1349 if (struct_incoming_value)
53800dbe 1350 {
e513d163 1351 emit_move_insn (adjust_address (registers, Pmode, size),
45550790 1352 copy_to_reg (struct_incoming_value));
53800dbe 1353 size += GET_MODE_SIZE (Pmode);
1354 }
1355
1356 /* Return the address of the block. */
1357 return copy_addr_to_reg (XEXP (registers, 0));
1358}
1359
1360/* __builtin_apply_args returns block of memory allocated on
1361 the stack into which is stored the arg pointer, structure
1362 value address, static chain, and all the registers that might
1363 possibly be used in performing a function call. The code is
1364 moved to the start of the function so the incoming values are
1365 saved. */
27d0c333 1366
53800dbe 1367static rtx
aecda0d6 1368expand_builtin_apply_args (void)
53800dbe 1369{
1370 /* Don't do __builtin_apply_args more than once in a function.
1371 Save the result of the first call and reuse it. */
1372 if (apply_args_value != 0)
1373 return apply_args_value;
1374 {
1375 /* When this function is called, it means that registers must be
1376 saved on entry to this function. So we migrate the
1377 call to the first insn of this function. */
1378 rtx temp;
1379 rtx seq;
1380
1381 start_sequence ();
1382 temp = expand_builtin_apply_args_1 ();
1383 seq = get_insns ();
1384 end_sequence ();
1385
1386 apply_args_value = temp;
1387
31d3e01c 1388 /* Put the insns after the NOTE that starts the function.
1389 If this is inside a start_sequence, make the outer-level insn
53800dbe 1390 chain current, so the code is placed at the start of the
1391 function. */
1392 push_topmost_sequence ();
0ec80471 1393 emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
53800dbe 1394 pop_topmost_sequence ();
1395 return temp;
1396 }
1397}
1398
1399/* Perform an untyped call and save the state required to perform an
1400 untyped return of whatever value was returned by the given function. */
1401
1402static rtx
aecda0d6 1403expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
53800dbe 1404{
1405 int size, align, regno;
1406 enum machine_mode mode;
2a631e19 1407 rtx incoming_args, result, reg, dest, src, call_insn;
53800dbe 1408 rtx old_stack_level = 0;
1409 rtx call_fusage = 0;
6812c89e 1410 rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
53800dbe 1411
85d654dd 1412 arguments = convert_memory_address (Pmode, arguments);
726ec87c 1413
53800dbe 1414 /* Create a block where the return registers can be saved. */
1415 result = assign_stack_local (BLKmode, apply_result_size (), -1);
1416
53800dbe 1417 /* Fetch the arg pointer from the ARGUMENTS block. */
1418 incoming_args = gen_reg_rtx (Pmode);
726ec87c 1419 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
53800dbe 1420#ifndef STACK_GROWS_DOWNWARD
ad99e708 1421 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1422 incoming_args, 0, OPTAB_LIB_WIDEN);
53800dbe 1423#endif
1424
04a46d40 1425 /* Push a new argument block and copy the arguments. Do not allow
1426 the (potential) memcpy call below to interfere with our stack
1427 manipulations. */
53800dbe 1428 do_pending_stack_adjust ();
04a46d40 1429 NO_DEFER_POP;
53800dbe 1430
2358393e 1431 /* Save the stack with nonlocal if available. */
53800dbe 1432#ifdef HAVE_save_stack_nonlocal
1433 if (HAVE_save_stack_nonlocal)
1434 emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
1435 else
1436#endif
1437 emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
1438
59647703 1439 /* Allocate a block of memory onto the stack and copy the memory
1440 arguments to the outgoing arguments address. */
1441 allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
1442 dest = virtual_outgoing_args_rtx;
1443#ifndef STACK_GROWS_DOWNWARD
1444 if (GET_CODE (argsize) == CONST_INT)
1445 dest = plus_constant (dest, -INTVAL (argsize));
1446 else
1447 dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1448#endif
2a631e19 1449 dest = gen_rtx_MEM (BLKmode, dest);
1450 set_mem_align (dest, PARM_BOUNDARY);
1451 src = gen_rtx_MEM (BLKmode, incoming_args);
1452 set_mem_align (src, PARM_BOUNDARY);
0378dbdc 1453 emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
53800dbe 1454
1455 /* Refer to the argument block. */
1456 apply_args_size ();
1457 arguments = gen_rtx_MEM (BLKmode, arguments);
2a631e19 1458 set_mem_align (arguments, PARM_BOUNDARY);
53800dbe 1459
1460 /* Walk past the arg-pointer and structure value address. */
1461 size = GET_MODE_SIZE (Pmode);
45550790 1462 if (struct_value)
53800dbe 1463 size += GET_MODE_SIZE (Pmode);
1464
1465 /* Restore each of the registers previously saved. Make USE insns
1466 for each of these registers for use in making the call. */
1467 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1468 if ((mode = apply_args_mode[regno]) != VOIDmode)
1469 {
1470 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1471 if (size % align != 0)
1472 size = CEIL (size, align) * align;
1473 reg = gen_rtx_REG (mode, regno);
e513d163 1474 emit_move_insn (reg, adjust_address (arguments, mode, size));
53800dbe 1475 use_reg (&call_fusage, reg);
1476 size += GET_MODE_SIZE (mode);
1477 }
1478
1479 /* Restore the structure value address unless this is passed as an
1480 "invisible" first argument. */
1481 size = GET_MODE_SIZE (Pmode);
45550790 1482 if (struct_value)
53800dbe 1483 {
1484 rtx value = gen_reg_rtx (Pmode);
e513d163 1485 emit_move_insn (value, adjust_address (arguments, Pmode, size));
45550790 1486 emit_move_insn (struct_value, value);
8ad4c111 1487 if (REG_P (struct_value))
45550790 1488 use_reg (&call_fusage, struct_value);
53800dbe 1489 size += GET_MODE_SIZE (Pmode);
1490 }
1491
1492 /* All arguments and registers used for the call are set up by now! */
4ee9c684 1493 function = prepare_call_address (function, NULL, &call_fusage, 0, 0);
53800dbe 1494
1495 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1496 and we don't want to load it into a register as an optimization,
1497 because prepare_call_address already did it if it should be done. */
1498 if (GET_CODE (function) != SYMBOL_REF)
1499 function = memory_address (FUNCTION_MODE, function);
1500
1501 /* Generate the actual call instruction and save the return value. */
1502#ifdef HAVE_untyped_call
1503 if (HAVE_untyped_call)
1504 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1505 result, result_vector (1, result)));
1506 else
1507#endif
1508#ifdef HAVE_call_value
1509 if (HAVE_call_value)
1510 {
1511 rtx valreg = 0;
1512
1513 /* Locate the unique return register. It is not possible to
1514 express a call that sets more than one return register using
1515 call_value; use untyped_call for that. In fact, untyped_call
1516 only needs to save the return registers in the given block. */
1517 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1518 if ((mode = apply_result_mode[regno]) != VOIDmode)
1519 {
64db345d 1520 gcc_assert (!valreg); /* HAVE_untyped_call required. */
7d3f6cc7 1521
53800dbe 1522 valreg = gen_rtx_REG (mode, regno);
1523 }
1524
2ed6c343 1525 emit_call_insn (GEN_CALL_VALUE (valreg,
53800dbe 1526 gen_rtx_MEM (FUNCTION_MODE, function),
1527 const0_rtx, NULL_RTX, const0_rtx));
1528
e513d163 1529 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
53800dbe 1530 }
1531 else
1532#endif
64db345d 1533 gcc_unreachable ();
53800dbe 1534
d5f9786f 1535 /* Find the CALL insn we just emitted, and attach the register usage
1536 information. */
1537 call_insn = last_call_insn ();
1538 add_function_usage_to (call_insn, call_fusage);
53800dbe 1539
1540 /* Restore the stack. */
1541#ifdef HAVE_save_stack_nonlocal
1542 if (HAVE_save_stack_nonlocal)
1543 emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1544 else
1545#endif
1546 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1547
04a46d40 1548 OK_DEFER_POP;
1549
53800dbe 1550 /* Return the address of the result block. */
85d654dd 1551 result = copy_addr_to_reg (XEXP (result, 0));
1552 return convert_memory_address (ptr_mode, result);
53800dbe 1553}
1554
1555/* Perform an untyped return. */
1556
1557static void
aecda0d6 1558expand_builtin_return (rtx result)
53800dbe 1559{
1560 int size, align, regno;
1561 enum machine_mode mode;
1562 rtx reg;
1563 rtx call_fusage = 0;
1564
85d654dd 1565 result = convert_memory_address (Pmode, result);
726ec87c 1566
53800dbe 1567 apply_result_size ();
1568 result = gen_rtx_MEM (BLKmode, result);
1569
1570#ifdef HAVE_untyped_return
1571 if (HAVE_untyped_return)
1572 {
1573 emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1574 emit_barrier ();
1575 return;
1576 }
1577#endif
1578
1579 /* Restore the return value and note that each value is used. */
1580 size = 0;
1581 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1582 if ((mode = apply_result_mode[regno]) != VOIDmode)
1583 {
1584 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1585 if (size % align != 0)
1586 size = CEIL (size, align) * align;
1587 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
e513d163 1588 emit_move_insn (reg, adjust_address (result, mode, size));
53800dbe 1589
1590 push_to_sequence (call_fusage);
1591 emit_insn (gen_rtx_USE (VOIDmode, reg));
1592 call_fusage = get_insns ();
1593 end_sequence ();
1594 size += GET_MODE_SIZE (mode);
1595 }
1596
1597 /* Put the USE insns before the return. */
31d3e01c 1598 emit_insn (call_fusage);
53800dbe 1599
1600 /* Return whatever values was restored by jumping directly to the end
1601 of the function. */
62380d2d 1602 expand_naked_return ();
53800dbe 1603}
1604
539a3a92 1605/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
27d0c333 1606
539a3a92 1607static enum type_class
aecda0d6 1608type_to_class (tree type)
539a3a92 1609{
1610 switch (TREE_CODE (type))
1611 {
1612 case VOID_TYPE: return void_type_class;
1613 case INTEGER_TYPE: return integer_type_class;
539a3a92 1614 case ENUMERAL_TYPE: return enumeral_type_class;
1615 case BOOLEAN_TYPE: return boolean_type_class;
1616 case POINTER_TYPE: return pointer_type_class;
1617 case REFERENCE_TYPE: return reference_type_class;
1618 case OFFSET_TYPE: return offset_type_class;
1619 case REAL_TYPE: return real_type_class;
1620 case COMPLEX_TYPE: return complex_type_class;
1621 case FUNCTION_TYPE: return function_type_class;
1622 case METHOD_TYPE: return method_type_class;
1623 case RECORD_TYPE: return record_type_class;
1624 case UNION_TYPE:
1625 case QUAL_UNION_TYPE: return union_type_class;
1626 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1627 ? string_type_class : array_type_class);
539a3a92 1628 case LANG_TYPE: return lang_type_class;
1629 default: return no_type_class;
1630 }
1631}
bf8e3599 1632
c2f47e15 1633/* Expand a call EXP to __builtin_classify_type. */
27d0c333 1634
53800dbe 1635static rtx
c2f47e15 1636expand_builtin_classify_type (tree exp)
53800dbe 1637{
c2f47e15 1638 if (call_expr_nargs (exp))
1639 return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0))));
53800dbe 1640 return GEN_INT (no_type_class);
1641}
1642
07976da7 1643/* This helper macro, meant to be used in mathfn_built_in below,
1644 determines which among a set of three builtin math functions is
1645 appropriate for a given type mode. The `F' and `L' cases are
1646 automatically generated from the `double' case. */
1647#define CASE_MATHFN(BUILT_IN_MATHFN) \
1648 case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1649 fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1650 fcodel = BUILT_IN_MATHFN##L ; break;
cd2656b0 1651/* Similar to above, but appends _R after any F/L suffix. */
1652#define CASE_MATHFN_REENT(BUILT_IN_MATHFN) \
1653 case BUILT_IN_MATHFN##_R: case BUILT_IN_MATHFN##F_R: case BUILT_IN_MATHFN##L_R: \
1654 fcode = BUILT_IN_MATHFN##_R; fcodef = BUILT_IN_MATHFN##F_R ; \
1655 fcodel = BUILT_IN_MATHFN##L_R ; break;
07976da7 1656
1657/* Return mathematic function equivalent to FN but operating directly
1658 on TYPE, if available. If we can't do the conversion, return zero. */
0a68165a 1659tree
aecda0d6 1660mathfn_built_in (tree type, enum built_in_function fn)
0a68165a 1661{
07976da7 1662 enum built_in_function fcode, fcodef, fcodel;
1663
1664 switch (fn)
1665 {
746114e8 1666 CASE_MATHFN (BUILT_IN_ACOS)
1667 CASE_MATHFN (BUILT_IN_ACOSH)
1668 CASE_MATHFN (BUILT_IN_ASIN)
1669 CASE_MATHFN (BUILT_IN_ASINH)
07976da7 1670 CASE_MATHFN (BUILT_IN_ATAN)
746114e8 1671 CASE_MATHFN (BUILT_IN_ATAN2)
1672 CASE_MATHFN (BUILT_IN_ATANH)
1673 CASE_MATHFN (BUILT_IN_CBRT)
07976da7 1674 CASE_MATHFN (BUILT_IN_CEIL)
d735c391 1675 CASE_MATHFN (BUILT_IN_CEXPI)
746114e8 1676 CASE_MATHFN (BUILT_IN_COPYSIGN)
07976da7 1677 CASE_MATHFN (BUILT_IN_COS)
746114e8 1678 CASE_MATHFN (BUILT_IN_COSH)
1679 CASE_MATHFN (BUILT_IN_DREM)
1680 CASE_MATHFN (BUILT_IN_ERF)
1681 CASE_MATHFN (BUILT_IN_ERFC)
07976da7 1682 CASE_MATHFN (BUILT_IN_EXP)
746114e8 1683 CASE_MATHFN (BUILT_IN_EXP10)
1684 CASE_MATHFN (BUILT_IN_EXP2)
1685 CASE_MATHFN (BUILT_IN_EXPM1)
1686 CASE_MATHFN (BUILT_IN_FABS)
1687 CASE_MATHFN (BUILT_IN_FDIM)
07976da7 1688 CASE_MATHFN (BUILT_IN_FLOOR)
746114e8 1689 CASE_MATHFN (BUILT_IN_FMA)
1690 CASE_MATHFN (BUILT_IN_FMAX)
1691 CASE_MATHFN (BUILT_IN_FMIN)
1692 CASE_MATHFN (BUILT_IN_FMOD)
1693 CASE_MATHFN (BUILT_IN_FREXP)
1694 CASE_MATHFN (BUILT_IN_GAMMA)
cd2656b0 1695 CASE_MATHFN_REENT (BUILT_IN_GAMMA) /* GAMMA_R */
746114e8 1696 CASE_MATHFN (BUILT_IN_HUGE_VAL)
1697 CASE_MATHFN (BUILT_IN_HYPOT)
1698 CASE_MATHFN (BUILT_IN_ILOGB)
1699 CASE_MATHFN (BUILT_IN_INF)
69b779ea 1700 CASE_MATHFN (BUILT_IN_ISINF)
746114e8 1701 CASE_MATHFN (BUILT_IN_J0)
1702 CASE_MATHFN (BUILT_IN_J1)
1703 CASE_MATHFN (BUILT_IN_JN)
ac148751 1704 CASE_MATHFN (BUILT_IN_LCEIL)
746114e8 1705 CASE_MATHFN (BUILT_IN_LDEXP)
ad52b9b7 1706 CASE_MATHFN (BUILT_IN_LFLOOR)
746114e8 1707 CASE_MATHFN (BUILT_IN_LGAMMA)
cd2656b0 1708 CASE_MATHFN_REENT (BUILT_IN_LGAMMA) /* LGAMMA_R */
ac148751 1709 CASE_MATHFN (BUILT_IN_LLCEIL)
ad52b9b7 1710 CASE_MATHFN (BUILT_IN_LLFLOOR)
746114e8 1711 CASE_MATHFN (BUILT_IN_LLRINT)
1712 CASE_MATHFN (BUILT_IN_LLROUND)
07976da7 1713 CASE_MATHFN (BUILT_IN_LOG)
746114e8 1714 CASE_MATHFN (BUILT_IN_LOG10)
1715 CASE_MATHFN (BUILT_IN_LOG1P)
1716 CASE_MATHFN (BUILT_IN_LOG2)
1717 CASE_MATHFN (BUILT_IN_LOGB)
1718 CASE_MATHFN (BUILT_IN_LRINT)
1719 CASE_MATHFN (BUILT_IN_LROUND)
1720 CASE_MATHFN (BUILT_IN_MODF)
1721 CASE_MATHFN (BUILT_IN_NAN)
1722 CASE_MATHFN (BUILT_IN_NANS)
07976da7 1723 CASE_MATHFN (BUILT_IN_NEARBYINT)
746114e8 1724 CASE_MATHFN (BUILT_IN_NEXTAFTER)
1725 CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1726 CASE_MATHFN (BUILT_IN_POW)
757c219d 1727 CASE_MATHFN (BUILT_IN_POWI)
746114e8 1728 CASE_MATHFN (BUILT_IN_POW10)
1729 CASE_MATHFN (BUILT_IN_REMAINDER)
1730 CASE_MATHFN (BUILT_IN_REMQUO)
1731 CASE_MATHFN (BUILT_IN_RINT)
07976da7 1732 CASE_MATHFN (BUILT_IN_ROUND)
746114e8 1733 CASE_MATHFN (BUILT_IN_SCALB)
1734 CASE_MATHFN (BUILT_IN_SCALBLN)
1735 CASE_MATHFN (BUILT_IN_SCALBN)
1736 CASE_MATHFN (BUILT_IN_SIGNIFICAND)
07976da7 1737 CASE_MATHFN (BUILT_IN_SIN)
746114e8 1738 CASE_MATHFN (BUILT_IN_SINCOS)
1739 CASE_MATHFN (BUILT_IN_SINH)
07976da7 1740 CASE_MATHFN (BUILT_IN_SQRT)
1741 CASE_MATHFN (BUILT_IN_TAN)
746114e8 1742 CASE_MATHFN (BUILT_IN_TANH)
1743 CASE_MATHFN (BUILT_IN_TGAMMA)
07976da7 1744 CASE_MATHFN (BUILT_IN_TRUNC)
746114e8 1745 CASE_MATHFN (BUILT_IN_Y0)
1746 CASE_MATHFN (BUILT_IN_Y1)
1747 CASE_MATHFN (BUILT_IN_YN)
07976da7 1748
0a68165a 1749 default:
c2f47e15 1750 return NULL_TREE;
0a68165a 1751 }
07976da7 1752
96b9f485 1753 if (TYPE_MAIN_VARIANT (type) == double_type_node)
07976da7 1754 return implicit_built_in_decls[fcode];
96b9f485 1755 else if (TYPE_MAIN_VARIANT (type) == float_type_node)
07976da7 1756 return implicit_built_in_decls[fcodef];
96b9f485 1757 else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
07976da7 1758 return implicit_built_in_decls[fcodel];
1759 else
c2f47e15 1760 return NULL_TREE;
0a68165a 1761}
1762
0fd605a5 1763/* If errno must be maintained, expand the RTL to check if the result,
1764 TARGET, of a built-in function call, EXP, is NaN, and if so set
1765 errno to EDOM. */
1766
1767static void
aecda0d6 1768expand_errno_check (tree exp, rtx target)
0fd605a5 1769{
7f05340e 1770 rtx lab = gen_label_rtx ();
0fd605a5 1771
7f05340e 1772 /* Test the result; if it is NaN, set errno=EDOM because
1773 the argument was not in the domain. */
1774 emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
1775 0, lab);
0fd605a5 1776
1777#ifdef TARGET_EDOM
7f05340e 1778 /* If this built-in doesn't throw an exception, set errno directly. */
c2f47e15 1779 if (TREE_NOTHROW (TREE_OPERAND (CALL_EXPR_FN (exp), 0)))
7f05340e 1780 {
0fd605a5 1781#ifdef GEN_ERRNO_RTX
7f05340e 1782 rtx errno_rtx = GEN_ERRNO_RTX;
0fd605a5 1783#else
7f05340e 1784 rtx errno_rtx
0fd605a5 1785 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1786#endif
7f05340e 1787 emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
0fd605a5 1788 emit_label (lab);
7f05340e 1789 return;
0fd605a5 1790 }
7f05340e 1791#endif
1792
1793 /* We can't set errno=EDOM directly; let the library call do it.
1794 Pop the arguments right away in case the call gets deleted. */
1795 NO_DEFER_POP;
1796 expand_call (exp, target, 0);
1797 OK_DEFER_POP;
1798 emit_label (lab);
0fd605a5 1799}
1800
6b43bae4 1801/* Expand a call to one of the builtin math functions (sqrt, exp, or log).
c2f47e15 1802 Return NULL_RTX if a normal call should be emitted rather than expanding
1803 the function in-line. EXP is the expression that is a call to the builtin
53800dbe 1804 function; if convenient, the result should be placed in TARGET.
1805 SUBTARGET may be used as the target for computing one of EXP's operands. */
27d0c333 1806
53800dbe 1807static rtx
aecda0d6 1808expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
53800dbe 1809{
bf8e3599 1810 optab builtin_optab;
bd421108 1811 rtx op0, insns, before_call;
c6e6ecb1 1812 tree fndecl = get_callee_fndecl (exp);
7f05340e 1813 enum machine_mode mode;
528ee710 1814 bool errno_set = false;
abfea505 1815 tree arg;
53800dbe 1816
c2f47e15 1817 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
1818 return NULL_RTX;
53800dbe 1819
c2f47e15 1820 arg = CALL_EXPR_ARG (exp, 0);
53800dbe 1821
1822 switch (DECL_FUNCTION_CODE (fndecl))
1823 {
4f35b1fc 1824 CASE_FLT_FN (BUILT_IN_SQRT):
7f05340e 1825 errno_set = ! tree_expr_nonnegative_p (arg);
1826 builtin_optab = sqrt_optab;
1827 break;
4f35b1fc 1828 CASE_FLT_FN (BUILT_IN_EXP):
528ee710 1829 errno_set = true; builtin_optab = exp_optab; break;
4f35b1fc 1830 CASE_FLT_FN (BUILT_IN_EXP10):
1831 CASE_FLT_FN (BUILT_IN_POW10):
750ef9f5 1832 errno_set = true; builtin_optab = exp10_optab; break;
4f35b1fc 1833 CASE_FLT_FN (BUILT_IN_EXP2):
750ef9f5 1834 errno_set = true; builtin_optab = exp2_optab; break;
4f35b1fc 1835 CASE_FLT_FN (BUILT_IN_EXPM1):
a6b4eed2 1836 errno_set = true; builtin_optab = expm1_optab; break;
4f35b1fc 1837 CASE_FLT_FN (BUILT_IN_LOGB):
4efbc641 1838 errno_set = true; builtin_optab = logb_optab; break;
4f35b1fc 1839 CASE_FLT_FN (BUILT_IN_LOG):
528ee710 1840 errno_set = true; builtin_optab = log_optab; break;
4f35b1fc 1841 CASE_FLT_FN (BUILT_IN_LOG10):
d3cd9bde 1842 errno_set = true; builtin_optab = log10_optab; break;
4f35b1fc 1843 CASE_FLT_FN (BUILT_IN_LOG2):
d3cd9bde 1844 errno_set = true; builtin_optab = log2_optab; break;
4f35b1fc 1845 CASE_FLT_FN (BUILT_IN_LOG1P):
f474cd93 1846 errno_set = true; builtin_optab = log1p_optab; break;
4f35b1fc 1847 CASE_FLT_FN (BUILT_IN_ASIN):
8de2f465 1848 builtin_optab = asin_optab; break;
4f35b1fc 1849 CASE_FLT_FN (BUILT_IN_ACOS):
8de2f465 1850 builtin_optab = acos_optab; break;
4f35b1fc 1851 CASE_FLT_FN (BUILT_IN_TAN):
528ee710 1852 builtin_optab = tan_optab; break;
4f35b1fc 1853 CASE_FLT_FN (BUILT_IN_ATAN):
528ee710 1854 builtin_optab = atan_optab; break;
4f35b1fc 1855 CASE_FLT_FN (BUILT_IN_FLOOR):
528ee710 1856 builtin_optab = floor_optab; break;
4f35b1fc 1857 CASE_FLT_FN (BUILT_IN_CEIL):
528ee710 1858 builtin_optab = ceil_optab; break;
4f35b1fc 1859 CASE_FLT_FN (BUILT_IN_TRUNC):
a7cc195f 1860 builtin_optab = btrunc_optab; break;
4f35b1fc 1861 CASE_FLT_FN (BUILT_IN_ROUND):
528ee710 1862 builtin_optab = round_optab; break;
4f35b1fc 1863 CASE_FLT_FN (BUILT_IN_NEARBYINT):
0ddf4ad9 1864 builtin_optab = nearbyint_optab;
1865 if (flag_trapping_math)
1866 break;
1867 /* Else fallthrough and expand as rint. */
4f35b1fc 1868 CASE_FLT_FN (BUILT_IN_RINT):
aef94a0f 1869 builtin_optab = rint_optab; break;
42721db0 1870 default:
64db345d 1871 gcc_unreachable ();
53800dbe 1872 }
1873
7f05340e 1874 /* Make a suitable register to place result in. */
1875 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 1876
7f05340e 1877 if (! flag_errno_math || ! HONOR_NANS (mode))
1878 errno_set = false;
1879
bd421108 1880 /* Before working hard, check whether the instruction is available. */
99bdde56 1881 if (optab_handler (builtin_optab, mode)->insn_code != CODE_FOR_nothing)
68e6cb9d 1882 {
bd421108 1883 target = gen_reg_rtx (mode);
7f05340e 1884
bd421108 1885 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
1886 need to expand the argument again. This way, we will not perform
1887 side-effects more the once. */
abfea505 1888 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7f05340e 1889
1db6d067 1890 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
7f05340e 1891
bd421108 1892 start_sequence ();
53800dbe 1893
bd421108 1894 /* Compute into TARGET.
1895 Set TARGET to wherever the result comes back. */
1896 target = expand_unop (mode, builtin_optab, op0, target, 0);
1897
1898 if (target != 0)
1899 {
1900 if (errno_set)
1901 expand_errno_check (exp, target);
1902
1903 /* Output the entire sequence. */
1904 insns = get_insns ();
1905 end_sequence ();
1906 emit_insn (insns);
1907 return target;
1908 }
1909
1910 /* If we were unable to expand via the builtin, stop the sequence
1911 (without outputting the insns) and call to the library function
1912 with the stabilized argument list. */
53800dbe 1913 end_sequence ();
53800dbe 1914 }
1915
bd421108 1916 before_call = get_last_insn ();
1917
1918 target = expand_call (exp, target, target == const0_rtx);
53800dbe 1919
bd421108 1920 /* If this is a sqrt operation and we don't care about errno, try to
1921 attach a REG_EQUAL note with a SQRT rtx to the emitted libcall.
1922 This allows the semantics of the libcall to be visible to the RTL
1923 optimizers. */
1924 if (builtin_optab == sqrt_optab && !errno_set)
1925 {
1926 /* Search backwards through the insns emitted by expand_call looking
1927 for the instruction with the REG_RETVAL note. */
1928 rtx last = get_last_insn ();
1929 while (last != before_call)
1930 {
1931 if (find_reg_note (last, REG_RETVAL, NULL))
1932 {
1933 rtx note = find_reg_note (last, REG_EQUAL, NULL);
1934 /* Check that the REQ_EQUAL note is an EXPR_LIST with
1935 two elements, i.e. symbol_ref(sqrt) and the operand. */
1936 if (note
1937 && GET_CODE (note) == EXPR_LIST
1938 && GET_CODE (XEXP (note, 0)) == EXPR_LIST
1939 && XEXP (XEXP (note, 0), 1) != NULL_RTX
1940 && XEXP (XEXP (XEXP (note, 0), 1), 1) == NULL_RTX)
1941 {
1942 rtx operand = XEXP (XEXP (XEXP (note, 0), 1), 0);
1943 /* Check operand is a register with expected mode. */
1944 if (operand
8ad4c111 1945 && REG_P (operand)
bd421108 1946 && GET_MODE (operand) == mode)
1947 {
1948 /* Replace the REG_EQUAL note with a SQRT rtx. */
1949 rtx equiv = gen_rtx_SQRT (mode, operand);
1950 set_unique_reg_note (last, REG_EQUAL, equiv);
1951 }
1952 }
1953 break;
1954 }
1955 last = PREV_INSN (last);
1956 }
1957 }
0fd605a5 1958
1959 return target;
1960}
1961
1962/* Expand a call to the builtin binary math functions (pow and atan2).
c2f47e15 1963 Return NULL_RTX if a normal call should be emitted rather than expanding the
0fd605a5 1964 function in-line. EXP is the expression that is a call to the builtin
1965 function; if convenient, the result should be placed in TARGET.
1966 SUBTARGET may be used as the target for computing one of EXP's
1967 operands. */
1968
1969static rtx
aecda0d6 1970expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
0fd605a5 1971{
1972 optab builtin_optab;
1973 rtx op0, op1, insns;
4737caf2 1974 int op1_type = REAL_TYPE;
c6e6ecb1 1975 tree fndecl = get_callee_fndecl (exp);
abfea505 1976 tree arg0, arg1;
7f05340e 1977 enum machine_mode mode;
0fd605a5 1978 bool errno_set = true;
0fd605a5 1979
73a954a1 1980 switch (DECL_FUNCTION_CODE (fndecl))
1981 {
1982 CASE_FLT_FN (BUILT_IN_SCALBN):
1983 CASE_FLT_FN (BUILT_IN_SCALBLN):
1984 CASE_FLT_FN (BUILT_IN_LDEXP):
1985 op1_type = INTEGER_TYPE;
1986 default:
1987 break;
1988 }
4737caf2 1989
c2f47e15 1990 if (!validate_arglist (exp, REAL_TYPE, op1_type, VOID_TYPE))
1991 return NULL_RTX;
0fd605a5 1992
c2f47e15 1993 arg0 = CALL_EXPR_ARG (exp, 0);
1994 arg1 = CALL_EXPR_ARG (exp, 1);
0fd605a5 1995
0fd605a5 1996 switch (DECL_FUNCTION_CODE (fndecl))
1997 {
4f35b1fc 1998 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 1999 builtin_optab = pow_optab; break;
4f35b1fc 2000 CASE_FLT_FN (BUILT_IN_ATAN2):
0fd605a5 2001 builtin_optab = atan2_optab; break;
73a954a1 2002 CASE_FLT_FN (BUILT_IN_SCALB):
2003 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2004 return 0;
2005 builtin_optab = scalb_optab; break;
2006 CASE_FLT_FN (BUILT_IN_SCALBN):
2007 CASE_FLT_FN (BUILT_IN_SCALBLN):
2008 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2009 return 0;
2010 /* Fall through... */
4f35b1fc 2011 CASE_FLT_FN (BUILT_IN_LDEXP):
4737caf2 2012 builtin_optab = ldexp_optab; break;
4f35b1fc 2013 CASE_FLT_FN (BUILT_IN_FMOD):
80ed5c06 2014 builtin_optab = fmod_optab; break;
ef722005 2015 CASE_FLT_FN (BUILT_IN_REMAINDER):
4f35b1fc 2016 CASE_FLT_FN (BUILT_IN_DREM):
ef722005 2017 builtin_optab = remainder_optab; break;
0fd605a5 2018 default:
64db345d 2019 gcc_unreachable ();
0fd605a5 2020 }
2021
7f05340e 2022 /* Make a suitable register to place result in. */
2023 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2024
2025 /* Before working hard, check whether the instruction is available. */
99bdde56 2026 if (optab_handler (builtin_optab, mode)->insn_code == CODE_FOR_nothing)
c2f47e15 2027 return NULL_RTX;
fc4eef90 2028
7f05340e 2029 target = gen_reg_rtx (mode);
2030
2031 if (! flag_errno_math || ! HONOR_NANS (mode))
2032 errno_set = false;
2033
4ee9c684 2034 /* Always stabilize the argument list. */
abfea505 2035 CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
2036 CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
7f05340e 2037
8ec3c5c2 2038 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2039 op1 = expand_normal (arg1);
7f05340e 2040
7f05340e 2041 start_sequence ();
2042
0fd605a5 2043 /* Compute into TARGET.
2044 Set TARGET to wherever the result comes back. */
7f05340e 2045 target = expand_binop (mode, builtin_optab, op0, op1,
0fd605a5 2046 target, 0, OPTAB_DIRECT);
53800dbe 2047
68e6cb9d 2048 /* If we were unable to expand via the builtin, stop the sequence
2049 (without outputting the insns) and call to the library function
2050 with the stabilized argument list. */
0fd605a5 2051 if (target == 0)
2052 {
2053 end_sequence ();
68e6cb9d 2054 return expand_call (exp, target, target == const0_rtx);
53800dbe 2055 }
2056
a4356fb9 2057 if (errno_set)
2058 expand_errno_check (exp, target);
0fd605a5 2059
53800dbe 2060 /* Output the entire sequence. */
2061 insns = get_insns ();
2062 end_sequence ();
31d3e01c 2063 emit_insn (insns);
bf8e3599 2064
53800dbe 2065 return target;
2066}
2067
6b43bae4 2068/* Expand a call to the builtin sin and cos math functions.
c2f47e15 2069 Return NULL_RTX if a normal call should be emitted rather than expanding the
6b43bae4 2070 function in-line. EXP is the expression that is a call to the builtin
2071 function; if convenient, the result should be placed in TARGET.
2072 SUBTARGET may be used as the target for computing one of EXP's
2073 operands. */
2074
2075static rtx
2076expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
2077{
2078 optab builtin_optab;
7511b819 2079 rtx op0, insns;
6b43bae4 2080 tree fndecl = get_callee_fndecl (exp);
6b43bae4 2081 enum machine_mode mode;
abfea505 2082 tree arg;
6b43bae4 2083
c2f47e15 2084 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2085 return NULL_RTX;
6b43bae4 2086
c2f47e15 2087 arg = CALL_EXPR_ARG (exp, 0);
6b43bae4 2088
2089 switch (DECL_FUNCTION_CODE (fndecl))
2090 {
4f35b1fc 2091 CASE_FLT_FN (BUILT_IN_SIN):
2092 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2093 builtin_optab = sincos_optab; break;
2094 default:
64db345d 2095 gcc_unreachable ();
6b43bae4 2096 }
2097
2098 /* Make a suitable register to place result in. */
2099 mode = TYPE_MODE (TREE_TYPE (exp));
2100
6b43bae4 2101 /* Check if sincos insn is available, otherwise fallback
0bed3869 2102 to sin or cos insn. */
99bdde56 2103 if (optab_handler (builtin_optab, mode)->insn_code == CODE_FOR_nothing)
6b43bae4 2104 switch (DECL_FUNCTION_CODE (fndecl))
2105 {
4f35b1fc 2106 CASE_FLT_FN (BUILT_IN_SIN):
6b43bae4 2107 builtin_optab = sin_optab; break;
4f35b1fc 2108 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2109 builtin_optab = cos_optab; break;
2110 default:
64db345d 2111 gcc_unreachable ();
6b43bae4 2112 }
6b43bae4 2113
2114 /* Before working hard, check whether the instruction is available. */
99bdde56 2115 if (optab_handler (builtin_optab, mode)->insn_code != CODE_FOR_nothing)
6b43bae4 2116 {
2117 target = gen_reg_rtx (mode);
2118
2119 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2120 need to expand the argument again. This way, we will not perform
2121 side-effects more the once. */
abfea505 2122 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
6b43bae4 2123
1db6d067 2124 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
6b43bae4 2125
6b43bae4 2126 start_sequence ();
2127
2128 /* Compute into TARGET.
2129 Set TARGET to wherever the result comes back. */
2130 if (builtin_optab == sincos_optab)
2131 {
64db345d 2132 int result;
7d3f6cc7 2133
6b43bae4 2134 switch (DECL_FUNCTION_CODE (fndecl))
2135 {
4f35b1fc 2136 CASE_FLT_FN (BUILT_IN_SIN):
64db345d 2137 result = expand_twoval_unop (builtin_optab, op0, 0, target, 0);
6b43bae4 2138 break;
4f35b1fc 2139 CASE_FLT_FN (BUILT_IN_COS):
64db345d 2140 result = expand_twoval_unop (builtin_optab, op0, target, 0, 0);
6b43bae4 2141 break;
2142 default:
64db345d 2143 gcc_unreachable ();
6b43bae4 2144 }
64db345d 2145 gcc_assert (result);
6b43bae4 2146 }
2147 else
2148 {
2149 target = expand_unop (mode, builtin_optab, op0, target, 0);
2150 }
2151
2152 if (target != 0)
2153 {
6b43bae4 2154 /* Output the entire sequence. */
2155 insns = get_insns ();
2156 end_sequence ();
2157 emit_insn (insns);
2158 return target;
2159 }
2160
2161 /* If we were unable to expand via the builtin, stop the sequence
2162 (without outputting the insns) and call to the library function
2163 with the stabilized argument list. */
2164 end_sequence ();
2165 }
2166
6b43bae4 2167 target = expand_call (exp, target, target == const0_rtx);
2168
2169 return target;
2170}
2171
a67a90e5 2172/* Expand a call to one of the builtin math functions that operate on
2173 floating point argument and output an integer result (ilogb, isinf,
2174 isnan, etc).
2175 Return 0 if a normal call should be emitted rather than expanding the
2176 function in-line. EXP is the expression that is a call to the builtin
2177 function; if convenient, the result should be placed in TARGET.
2178 SUBTARGET may be used as the target for computing one of EXP's operands. */
2179
2180static rtx
2181expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
2182{
cde061c1 2183 optab builtin_optab = 0;
2184 enum insn_code icode = CODE_FOR_nothing;
a67a90e5 2185 rtx op0;
2186 tree fndecl = get_callee_fndecl (exp);
a67a90e5 2187 enum machine_mode mode;
2188 bool errno_set = false;
abfea505 2189 tree arg;
a67a90e5 2190
c2f47e15 2191 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2192 return NULL_RTX;
a67a90e5 2193
c2f47e15 2194 arg = CALL_EXPR_ARG (exp, 0);
a67a90e5 2195
2196 switch (DECL_FUNCTION_CODE (fndecl))
2197 {
2198 CASE_FLT_FN (BUILT_IN_ILOGB):
2199 errno_set = true; builtin_optab = ilogb_optab; break;
69b779ea 2200 CASE_FLT_FN (BUILT_IN_ISINF):
2201 builtin_optab = isinf_optab; break;
8a1a9cb7 2202 case BUILT_IN_ISNORMAL:
cde061c1 2203 case BUILT_IN_ISFINITE:
2204 CASE_FLT_FN (BUILT_IN_FINITE):
2205 /* These builtins have no optabs (yet). */
2206 break;
a67a90e5 2207 default:
2208 gcc_unreachable ();
2209 }
2210
2211 /* There's no easy way to detect the case we need to set EDOM. */
2212 if (flag_errno_math && errno_set)
2213 return NULL_RTX;
2214
2215 /* Optab mode depends on the mode of the input argument. */
2216 mode = TYPE_MODE (TREE_TYPE (arg));
2217
cde061c1 2218 if (builtin_optab)
99bdde56 2219 icode = optab_handler (builtin_optab, mode)->insn_code;
a67a90e5 2220
2221 /* Before working hard, check whether the instruction is available. */
2222 if (icode != CODE_FOR_nothing)
2223 {
2224 /* Make a suitable register to place result in. */
2225 if (!target
2226 || GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
2227 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
2228
2229 gcc_assert (insn_data[icode].operand[0].predicate
2230 (target, GET_MODE (target)));
2231
2232 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2233 need to expand the argument again. This way, we will not perform
2234 side-effects more the once. */
abfea505 2235 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
a67a90e5 2236
1db6d067 2237 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
a67a90e5 2238
2239 if (mode != GET_MODE (op0))
2240 op0 = convert_to_mode (mode, op0, 0);
2241
2242 /* Compute into TARGET.
2243 Set TARGET to wherever the result comes back. */
2244 emit_unop_insn (icode, target, op0, UNKNOWN);
2245 return target;
2246 }
2247
06f7a99d 2248 /* If there is no optab, try generic code. */
2249 switch (DECL_FUNCTION_CODE (fndecl))
2250 {
2251 tree result;
2252
2253 CASE_FLT_FN (BUILT_IN_ISINF):
2254 {
2255 /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
2256 tree const isgr_fn = built_in_decls[BUILT_IN_ISGREATER];
2257 tree const type = TREE_TYPE (arg);
2258 REAL_VALUE_TYPE r;
2259 char buf[128];
2260
2261 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
2262 real_from_string (&r, buf);
2263 result = build_call_expr (isgr_fn, 2,
2264 fold_build1 (ABS_EXPR, type, arg),
2265 build_real (type, r));
2266 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
2267 }
cde061c1 2268 CASE_FLT_FN (BUILT_IN_FINITE):
2269 case BUILT_IN_ISFINITE:
2270 {
2271 /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
2272 tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
2273 tree const type = TREE_TYPE (arg);
2274 REAL_VALUE_TYPE r;
2275 char buf[128];
2276
2277 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
2278 real_from_string (&r, buf);
2279 result = build_call_expr (isle_fn, 2,
2280 fold_build1 (ABS_EXPR, type, arg),
2281 build_real (type, r));
2282 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
2283 }
8a1a9cb7 2284 case BUILT_IN_ISNORMAL:
2285 {
2286 /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
2287 islessequal(fabs(x),DBL_MAX). */
2288 tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
2289 tree const isge_fn = built_in_decls[BUILT_IN_ISGREATEREQUAL];
2290 tree const type = TREE_TYPE (arg);
2291 REAL_VALUE_TYPE rmax, rmin;
2292 char buf[128];
2293
2294 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
2295 real_from_string (&rmax, buf);
2296 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
2297 real_from_string (&rmin, buf);
2298 arg = builtin_save_expr (fold_build1 (ABS_EXPR, type, arg));
2299 result = build_call_expr (isle_fn, 2, arg,
2300 build_real (type, rmax));
2301 result = fold_build2 (BIT_AND_EXPR, integer_type_node, result,
2302 build_call_expr (isge_fn, 2, arg,
2303 build_real (type, rmin)));
2304 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
2305 }
06f7a99d 2306 default:
2307 break;
2308 }
2309
a67a90e5 2310 target = expand_call (exp, target, target == const0_rtx);
2311
2312 return target;
2313}
2314
c3147c1a 2315/* Expand a call to the builtin sincos math function.
c2f47e15 2316 Return NULL_RTX if a normal call should be emitted rather than expanding the
c3147c1a 2317 function in-line. EXP is the expression that is a call to the builtin
2318 function. */
2319
2320static rtx
2321expand_builtin_sincos (tree exp)
2322{
2323 rtx op0, op1, op2, target1, target2;
c3147c1a 2324 enum machine_mode mode;
2325 tree arg, sinp, cosp;
2326 int result;
2327
c2f47e15 2328 if (!validate_arglist (exp, REAL_TYPE,
2329 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2330 return NULL_RTX;
c3147c1a 2331
c2f47e15 2332 arg = CALL_EXPR_ARG (exp, 0);
2333 sinp = CALL_EXPR_ARG (exp, 1);
2334 cosp = CALL_EXPR_ARG (exp, 2);
c3147c1a 2335
2336 /* Make a suitable register to place result in. */
2337 mode = TYPE_MODE (TREE_TYPE (arg));
2338
2339 /* Check if sincos insn is available, otherwise emit the call. */
99bdde56 2340 if (optab_handler (sincos_optab, mode)->insn_code == CODE_FOR_nothing)
c3147c1a 2341 return NULL_RTX;
2342
2343 target1 = gen_reg_rtx (mode);
2344 target2 = gen_reg_rtx (mode);
2345
8ec3c5c2 2346 op0 = expand_normal (arg);
2347 op1 = expand_normal (build_fold_indirect_ref (sinp));
2348 op2 = expand_normal (build_fold_indirect_ref (cosp));
c3147c1a 2349
2350 /* Compute into target1 and target2.
2351 Set TARGET to wherever the result comes back. */
2352 result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
2353 gcc_assert (result);
2354
2355 /* Move target1 and target2 to the memory locations indicated
2356 by op1 and op2. */
2357 emit_move_insn (op1, target1);
2358 emit_move_insn (op2, target2);
2359
2360 return const0_rtx;
2361}
2362
d735c391 2363/* Expand a call to the internal cexpi builtin to the sincos math function.
2364 EXP is the expression that is a call to the builtin function; if convenient,
2365 the result should be placed in TARGET. SUBTARGET may be used as the target
2366 for computing one of EXP's operands. */
2367
2368static rtx
2369expand_builtin_cexpi (tree exp, rtx target, rtx subtarget)
2370{
2371 tree fndecl = get_callee_fndecl (exp);
d735c391 2372 tree arg, type;
c2f47e15 2373 enum machine_mode mode;
d735c391 2374 rtx op0, op1, op2;
2375
c2f47e15 2376 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2377 return NULL_RTX;
d735c391 2378
c2f47e15 2379 arg = CALL_EXPR_ARG (exp, 0);
d735c391 2380 type = TREE_TYPE (arg);
2381 mode = TYPE_MODE (TREE_TYPE (arg));
2382
2383 /* Try expanding via a sincos optab, fall back to emitting a libcall
18b8d8ae 2384 to sincos or cexp. We are sure we have sincos or cexp because cexpi
2385 is only generated from sincos, cexp or if we have either of them. */
99bdde56 2386 if (optab_handler (sincos_optab, mode)->insn_code != CODE_FOR_nothing)
d735c391 2387 {
2388 op1 = gen_reg_rtx (mode);
2389 op2 = gen_reg_rtx (mode);
2390
1db6d067 2391 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
d735c391 2392
2393 /* Compute into op1 and op2. */
2394 expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
2395 }
18b8d8ae 2396 else if (TARGET_HAS_SINCOS)
d735c391 2397 {
c2f47e15 2398 tree call, fn = NULL_TREE;
d735c391 2399 tree top1, top2;
2400 rtx op1a, op2a;
2401
2402 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2403 fn = built_in_decls[BUILT_IN_SINCOSF];
2404 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2405 fn = built_in_decls[BUILT_IN_SINCOS];
2406 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2407 fn = built_in_decls[BUILT_IN_SINCOSL];
c2f47e15 2408 else
2409 gcc_unreachable ();
d735c391 2410
2411 op1 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
2412 op2 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
2413 op1a = copy_to_mode_reg (Pmode, XEXP (op1, 0));
2414 op2a = copy_to_mode_reg (Pmode, XEXP (op2, 0));
2415 top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
2416 top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
2417
d735c391 2418 /* Make sure not to fold the sincos call again. */
2419 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
c2f47e15 2420 expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
2421 call, 3, arg, top1, top2));
d735c391 2422 }
18b8d8ae 2423 else
2424 {
0ecbc158 2425 tree call, fn = NULL_TREE, narg;
18b8d8ae 2426 tree ctype = build_complex_type (type);
2427
0ecbc158 2428 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2429 fn = built_in_decls[BUILT_IN_CEXPF];
2430 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2431 fn = built_in_decls[BUILT_IN_CEXP];
2432 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2433 fn = built_in_decls[BUILT_IN_CEXPL];
c2f47e15 2434 else
2435 gcc_unreachable ();
fc0dfa6e 2436
2437 /* If we don't have a decl for cexp create one. This is the
2438 friendliest fallback if the user calls __builtin_cexpi
2439 without full target C99 function support. */
2440 if (fn == NULL_TREE)
2441 {
2442 tree fntype;
2443 const char *name = NULL;
2444
2445 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2446 name = "cexpf";
2447 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2448 name = "cexp";
2449 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2450 name = "cexpl";
2451
2452 fntype = build_function_type_list (ctype, ctype, NULL_TREE);
2453 fn = build_fn_decl (name, fntype);
2454 }
2455
18b8d8ae 2456 narg = fold_build2 (COMPLEX_EXPR, ctype,
2457 build_real (type, dconst0), arg);
2458
2459 /* Make sure not to fold the cexp call again. */
2460 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
3737e769 2461 return expand_expr (build_call_nary (ctype, call, 1, narg),
1db6d067 2462 target, VOIDmode, EXPAND_NORMAL);
18b8d8ae 2463 }
d735c391 2464
2465 /* Now build the proper return type. */
2466 return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
2467 make_tree (TREE_TYPE (arg), op2),
2468 make_tree (TREE_TYPE (arg), op1)),
1db6d067 2469 target, VOIDmode, EXPAND_NORMAL);
d735c391 2470}
2471
7d3afc77 2472/* Expand a call to one of the builtin rounding functions gcc defines
2473 as an extension (lfloor and lceil). As these are gcc extensions we
2474 do not need to worry about setting errno to EDOM.
ad52b9b7 2475 If expanding via optab fails, lower expression to (int)(floor(x)).
2476 EXP is the expression that is a call to the builtin function;
2477 if convenient, the result should be placed in TARGET. SUBTARGET may
2478 be used as the target for computing one of EXP's operands. */
2479
2480static rtx
2481expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget)
2482{
9c42dd28 2483 convert_optab builtin_optab;
ad52b9b7 2484 rtx op0, insns, tmp;
2485 tree fndecl = get_callee_fndecl (exp);
ad52b9b7 2486 enum built_in_function fallback_fn;
2487 tree fallback_fndecl;
2488 enum machine_mode mode;
4de0924f 2489 tree arg;
ad52b9b7 2490
c2f47e15 2491 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
ad52b9b7 2492 gcc_unreachable ();
2493
c2f47e15 2494 arg = CALL_EXPR_ARG (exp, 0);
ad52b9b7 2495
2496 switch (DECL_FUNCTION_CODE (fndecl))
2497 {
4f35b1fc 2498 CASE_FLT_FN (BUILT_IN_LCEIL):
2499 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 2500 builtin_optab = lceil_optab;
2501 fallback_fn = BUILT_IN_CEIL;
2502 break;
2503
4f35b1fc 2504 CASE_FLT_FN (BUILT_IN_LFLOOR):
2505 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 2506 builtin_optab = lfloor_optab;
2507 fallback_fn = BUILT_IN_FLOOR;
2508 break;
2509
2510 default:
2511 gcc_unreachable ();
2512 }
2513
2514 /* Make a suitable register to place result in. */
2515 mode = TYPE_MODE (TREE_TYPE (exp));
2516
9c42dd28 2517 target = gen_reg_rtx (mode);
ad52b9b7 2518
9c42dd28 2519 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2520 need to expand the argument again. This way, we will not perform
2521 side-effects more the once. */
abfea505 2522 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
ad52b9b7 2523
1db6d067 2524 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
ad52b9b7 2525
9c42dd28 2526 start_sequence ();
ad52b9b7 2527
9c42dd28 2528 /* Compute into TARGET. */
2529 if (expand_sfix_optab (target, op0, builtin_optab))
2530 {
2531 /* Output the entire sequence. */
2532 insns = get_insns ();
ad52b9b7 2533 end_sequence ();
9c42dd28 2534 emit_insn (insns);
2535 return target;
ad52b9b7 2536 }
2537
9c42dd28 2538 /* If we were unable to expand via the builtin, stop the sequence
2539 (without outputting the insns). */
2540 end_sequence ();
2541
ad52b9b7 2542 /* Fall back to floating point rounding optab. */
2543 fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
fc0dfa6e 2544
2545 /* For non-C99 targets we may end up without a fallback fndecl here
2546 if the user called __builtin_lfloor directly. In this case emit
2547 a call to the floor/ceil variants nevertheless. This should result
2548 in the best user experience for not full C99 targets. */
2549 if (fallback_fndecl == NULL_TREE)
2550 {
2551 tree fntype;
2552 const char *name = NULL;
2553
2554 switch (DECL_FUNCTION_CODE (fndecl))
2555 {
2556 case BUILT_IN_LCEIL:
2557 case BUILT_IN_LLCEIL:
2558 name = "ceil";
2559 break;
2560 case BUILT_IN_LCEILF:
2561 case BUILT_IN_LLCEILF:
2562 name = "ceilf";
2563 break;
2564 case BUILT_IN_LCEILL:
2565 case BUILT_IN_LLCEILL:
2566 name = "ceill";
2567 break;
2568 case BUILT_IN_LFLOOR:
2569 case BUILT_IN_LLFLOOR:
2570 name = "floor";
2571 break;
2572 case BUILT_IN_LFLOORF:
2573 case BUILT_IN_LLFLOORF:
2574 name = "floorf";
2575 break;
2576 case BUILT_IN_LFLOORL:
2577 case BUILT_IN_LLFLOORL:
2578 name = "floorl";
2579 break;
2580 default:
2581 gcc_unreachable ();
2582 }
2583
2584 fntype = build_function_type_list (TREE_TYPE (arg),
2585 TREE_TYPE (arg), NULL_TREE);
2586 fallback_fndecl = build_fn_decl (name, fntype);
2587 }
2588
c2f47e15 2589 exp = build_call_expr (fallback_fndecl, 1, arg);
ad52b9b7 2590
d4c690af 2591 tmp = expand_normal (exp);
ad52b9b7 2592
2593 /* Truncate the result of floating point optab to integer
2594 via expand_fix (). */
2595 target = gen_reg_rtx (mode);
2596 expand_fix (target, tmp, 0);
2597
2598 return target;
2599}
2600
7d3afc77 2601/* Expand a call to one of the builtin math functions doing integer
2602 conversion (lrint).
2603 Return 0 if a normal call should be emitted rather than expanding the
2604 function in-line. EXP is the expression that is a call to the builtin
2605 function; if convenient, the result should be placed in TARGET.
2606 SUBTARGET may be used as the target for computing one of EXP's operands. */
2607
2608static rtx
2609expand_builtin_int_roundingfn_2 (tree exp, rtx target, rtx subtarget)
2610{
5f51ee59 2611 convert_optab builtin_optab;
7d3afc77 2612 rtx op0, insns;
2613 tree fndecl = get_callee_fndecl (exp);
4de0924f 2614 tree arg;
c2f47e15 2615 enum machine_mode mode;
7d3afc77 2616
2617 /* There's no easy way to detect the case we need to set EDOM. */
2618 if (flag_errno_math)
2619 return NULL_RTX;
2620
c2f47e15 2621 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2622 gcc_unreachable ();
2623
2624 arg = CALL_EXPR_ARG (exp, 0);
7d3afc77 2625
2626 switch (DECL_FUNCTION_CODE (fndecl))
2627 {
2628 CASE_FLT_FN (BUILT_IN_LRINT):
2629 CASE_FLT_FN (BUILT_IN_LLRINT):
2630 builtin_optab = lrint_optab; break;
ef2f1a10 2631 CASE_FLT_FN (BUILT_IN_LROUND):
2632 CASE_FLT_FN (BUILT_IN_LLROUND):
2633 builtin_optab = lround_optab; break;
7d3afc77 2634 default:
2635 gcc_unreachable ();
2636 }
2637
2638 /* Make a suitable register to place result in. */
2639 mode = TYPE_MODE (TREE_TYPE (exp));
2640
5f51ee59 2641 target = gen_reg_rtx (mode);
7d3afc77 2642
5f51ee59 2643 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2644 need to expand the argument again. This way, we will not perform
2645 side-effects more the once. */
abfea505 2646 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7d3afc77 2647
1db6d067 2648 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
7d3afc77 2649
5f51ee59 2650 start_sequence ();
7d3afc77 2651
5f51ee59 2652 if (expand_sfix_optab (target, op0, builtin_optab))
2653 {
2654 /* Output the entire sequence. */
2655 insns = get_insns ();
7d3afc77 2656 end_sequence ();
5f51ee59 2657 emit_insn (insns);
2658 return target;
7d3afc77 2659 }
2660
5f51ee59 2661 /* If we were unable to expand via the builtin, stop the sequence
2662 (without outputting the insns) and call to the library function
2663 with the stabilized argument list. */
2664 end_sequence ();
2665
7d3afc77 2666 target = expand_call (exp, target, target == const0_rtx);
2667
2668 return target;
2669}
2670
f1b844c6 2671/* To evaluate powi(x,n), the floating point value x raised to the
2672 constant integer exponent n, we use a hybrid algorithm that
2673 combines the "window method" with look-up tables. For an
2674 introduction to exponentiation algorithms and "addition chains",
2675 see section 4.6.3, "Evaluation of Powers" of Donald E. Knuth,
2676 "Seminumerical Algorithms", Vol. 2, "The Art of Computer Programming",
2677 3rd Edition, 1998, and Daniel M. Gordon, "A Survey of Fast Exponentiation
2678 Methods", Journal of Algorithms, Vol. 27, pp. 129-146, 1998. */
2679
2680/* Provide a default value for POWI_MAX_MULTS, the maximum number of
2681 multiplications to inline before calling the system library's pow
2682 function. powi(x,n) requires at worst 2*bits(n)-2 multiplications,
2683 so this default never requires calling pow, powf or powl. */
0862b7e9 2684
f1b844c6 2685#ifndef POWI_MAX_MULTS
2686#define POWI_MAX_MULTS (2*HOST_BITS_PER_WIDE_INT-2)
2687#endif
2688
2689/* The size of the "optimal power tree" lookup table. All
2690 exponents less than this value are simply looked up in the
2691 powi_table below. This threshold is also used to size the
2692 cache of pseudo registers that hold intermediate results. */
2693#define POWI_TABLE_SIZE 256
2694
2695/* The size, in bits of the window, used in the "window method"
2696 exponentiation algorithm. This is equivalent to a radix of
2697 (1<<POWI_WINDOW_SIZE) in the corresponding "m-ary method". */
2698#define POWI_WINDOW_SIZE 3
2699
2700/* The following table is an efficient representation of an
2701 "optimal power tree". For each value, i, the corresponding
2702 value, j, in the table states than an optimal evaluation
2703 sequence for calculating pow(x,i) can be found by evaluating
2704 pow(x,j)*pow(x,i-j). An optimal power tree for the first
2705 100 integers is given in Knuth's "Seminumerical algorithms". */
2706
2707static const unsigned char powi_table[POWI_TABLE_SIZE] =
2708 {
2709 0, 1, 1, 2, 2, 3, 3, 4, /* 0 - 7 */
2710 4, 6, 5, 6, 6, 10, 7, 9, /* 8 - 15 */
2711 8, 16, 9, 16, 10, 12, 11, 13, /* 16 - 23 */
2712 12, 17, 13, 18, 14, 24, 15, 26, /* 24 - 31 */
2713 16, 17, 17, 19, 18, 33, 19, 26, /* 32 - 39 */
2714 20, 25, 21, 40, 22, 27, 23, 44, /* 40 - 47 */
2715 24, 32, 25, 34, 26, 29, 27, 44, /* 48 - 55 */
2716 28, 31, 29, 34, 30, 60, 31, 36, /* 56 - 63 */
2717 32, 64, 33, 34, 34, 46, 35, 37, /* 64 - 71 */
2718 36, 65, 37, 50, 38, 48, 39, 69, /* 72 - 79 */
2719 40, 49, 41, 43, 42, 51, 43, 58, /* 80 - 87 */
2720 44, 64, 45, 47, 46, 59, 47, 76, /* 88 - 95 */
2721 48, 65, 49, 66, 50, 67, 51, 66, /* 96 - 103 */
2722 52, 70, 53, 74, 54, 104, 55, 74, /* 104 - 111 */
2723 56, 64, 57, 69, 58, 78, 59, 68, /* 112 - 119 */
2724 60, 61, 61, 80, 62, 75, 63, 68, /* 120 - 127 */
2725 64, 65, 65, 128, 66, 129, 67, 90, /* 128 - 135 */
2726 68, 73, 69, 131, 70, 94, 71, 88, /* 136 - 143 */
2727 72, 128, 73, 98, 74, 132, 75, 121, /* 144 - 151 */
2728 76, 102, 77, 124, 78, 132, 79, 106, /* 152 - 159 */
2729 80, 97, 81, 160, 82, 99, 83, 134, /* 160 - 167 */
2730 84, 86, 85, 95, 86, 160, 87, 100, /* 168 - 175 */
2731 88, 113, 89, 98, 90, 107, 91, 122, /* 176 - 183 */
2732 92, 111, 93, 102, 94, 126, 95, 150, /* 184 - 191 */
2733 96, 128, 97, 130, 98, 133, 99, 195, /* 192 - 199 */
2734 100, 128, 101, 123, 102, 164, 103, 138, /* 200 - 207 */
2735 104, 145, 105, 146, 106, 109, 107, 149, /* 208 - 215 */
2736 108, 200, 109, 146, 110, 170, 111, 157, /* 216 - 223 */
2737 112, 128, 113, 130, 114, 182, 115, 132, /* 224 - 231 */
2738 116, 200, 117, 132, 118, 158, 119, 206, /* 232 - 239 */
2739 120, 240, 121, 162, 122, 147, 123, 152, /* 240 - 247 */
2740 124, 166, 125, 214, 126, 138, 127, 153, /* 248 - 255 */
2741 };
2742
2743
2744/* Return the number of multiplications required to calculate
2745 powi(x,n) where n is less than POWI_TABLE_SIZE. This is a
2746 subroutine of powi_cost. CACHE is an array indicating
2747 which exponents have already been calculated. */
2748
2749static int
2750powi_lookup_cost (unsigned HOST_WIDE_INT n, bool *cache)
2751{
2752 /* If we've already calculated this exponent, then this evaluation
2753 doesn't require any additional multiplications. */
2754 if (cache[n])
2755 return 0;
2756
2757 cache[n] = true;
2758 return powi_lookup_cost (n - powi_table[n], cache)
2759 + powi_lookup_cost (powi_table[n], cache) + 1;
2760}
2761
2762/* Return the number of multiplications required to calculate
2763 powi(x,n) for an arbitrary x, given the exponent N. This
2764 function needs to be kept in sync with expand_powi below. */
2765
2766static int
2767powi_cost (HOST_WIDE_INT n)
2768{
2769 bool cache[POWI_TABLE_SIZE];
2770 unsigned HOST_WIDE_INT digit;
2771 unsigned HOST_WIDE_INT val;
2772 int result;
2773
2774 if (n == 0)
2775 return 0;
2776
2777 /* Ignore the reciprocal when calculating the cost. */
2778 val = (n < 0) ? -n : n;
2779
2780 /* Initialize the exponent cache. */
2781 memset (cache, 0, POWI_TABLE_SIZE * sizeof (bool));
2782 cache[1] = true;
2783
2784 result = 0;
2785
2786 while (val >= POWI_TABLE_SIZE)
2787 {
2788 if (val & 1)
2789 {
2790 digit = val & ((1 << POWI_WINDOW_SIZE) - 1);
2791 result += powi_lookup_cost (digit, cache)
2792 + POWI_WINDOW_SIZE + 1;
2793 val >>= POWI_WINDOW_SIZE;
2794 }
2795 else
2796 {
2797 val >>= 1;
2798 result++;
2799 }
2800 }
0862b7e9 2801
6881dbab 2802 return result + powi_lookup_cost (val, cache);
f1b844c6 2803}
2804
2805/* Recursive subroutine of expand_powi. This function takes the array,
2806 CACHE, of already calculated exponents and an exponent N and returns
2807 an RTX that corresponds to CACHE[1]**N, as calculated in mode MODE. */
2808
2809static rtx
2810expand_powi_1 (enum machine_mode mode, unsigned HOST_WIDE_INT n, rtx *cache)
2811{
2812 unsigned HOST_WIDE_INT digit;
2813 rtx target, result;
2814 rtx op0, op1;
2815
2816 if (n < POWI_TABLE_SIZE)
2817 {
2818 if (cache[n])
a0c938f0 2819 return cache[n];
f1b844c6 2820
2821 target = gen_reg_rtx (mode);
2822 cache[n] = target;
2823
2824 op0 = expand_powi_1 (mode, n - powi_table[n], cache);
2825 op1 = expand_powi_1 (mode, powi_table[n], cache);
2826 }
2827 else if (n & 1)
2828 {
2829 target = gen_reg_rtx (mode);
2830 digit = n & ((1 << POWI_WINDOW_SIZE) - 1);
2831 op0 = expand_powi_1 (mode, n - digit, cache);
2832 op1 = expand_powi_1 (mode, digit, cache);
2833 }
2834 else
2835 {
2836 target = gen_reg_rtx (mode);
2837 op0 = expand_powi_1 (mode, n >> 1, cache);
2838 op1 = op0;
2839 }
2840
2841 result = expand_mult (mode, op0, op1, target, 0);
2842 if (result != target)
2843 emit_move_insn (target, result);
2844 return target;
2845}
2846
2847/* Expand the RTL to evaluate powi(x,n) in mode MODE. X is the
2848 floating point operand in mode MODE, and N is the exponent. This
2849 function needs to be kept in sync with powi_cost above. */
0862b7e9 2850
f1b844c6 2851static rtx
2852expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n)
2853{
2854 unsigned HOST_WIDE_INT val;
2855 rtx cache[POWI_TABLE_SIZE];
2856 rtx result;
2857
2858 if (n == 0)
2859 return CONST1_RTX (mode);
2860
2861 val = (n < 0) ? -n : n;
2862
19bf118a 2863 memset (cache, 0, sizeof (cache));
f1b844c6 2864 cache[1] = x;
2865
2866 result = expand_powi_1 (mode, (n < 0) ? -n : n, cache);
2867
2868 /* If the original exponent was negative, reciprocate the result. */
2869 if (n < 0)
2870 result = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2871 result, NULL_RTX, 0, OPTAB_LIB_WIDEN);
2872
2873 return result;
2874}
2875
c2f47e15 2876/* Expand a call to the pow built-in mathematical function. Return NULL_RTX if
f1b844c6 2877 a normal call should be emitted rather than expanding the function
2878 in-line. EXP is the expression that is a call to the builtin
2879 function; if convenient, the result should be placed in TARGET. */
2880
2881static rtx
2882expand_builtin_pow (tree exp, rtx target, rtx subtarget)
2883{
c2f47e15 2884 tree arg0, arg1;
2885 tree fn, narg0;
1c4709b4 2886 tree type = TREE_TYPE (exp);
2887 REAL_VALUE_TYPE cint, c, c2;
2888 HOST_WIDE_INT n;
2889 rtx op, op2;
2890 enum machine_mode mode = TYPE_MODE (type);
f1b844c6 2891
c2f47e15 2892 if (! validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2893 return NULL_RTX;
f1b844c6 2894
c2f47e15 2895 arg0 = CALL_EXPR_ARG (exp, 0);
2896 arg1 = CALL_EXPR_ARG (exp, 1);
f1b844c6 2897
1c4709b4 2898 if (TREE_CODE (arg1) != REAL_CST
f96bd2bf 2899 || TREE_OVERFLOW (arg1))
1c4709b4 2900 return expand_builtin_mathfn_2 (exp, target, subtarget);
2901
2902 /* Handle constant exponents. */
2903
2904 /* For integer valued exponents we can expand to an optimal multiplication
2905 sequence using expand_powi. */
2906 c = TREE_REAL_CST (arg1);
2907 n = real_to_integer (&c);
2908 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
2909 if (real_identical (&c, &cint)
2910 && ((n >= -1 && n <= 2)
2911 || (flag_unsafe_math_optimizations
2912 && !optimize_size
2913 && powi_cost (n) <= POWI_MAX_MULTS)))
f1b844c6 2914 {
1db6d067 2915 op = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 2916 if (n != 1)
2917 {
2918 op = force_reg (mode, op);
2919 op = expand_powi (op, mode, n);
2920 }
2921 return op;
2922 }
2923
2924 narg0 = builtin_save_expr (arg0);
f1b844c6 2925
1c4709b4 2926 /* If the exponent is not integer valued, check if it is half of an integer.
2927 In this case we can expand to sqrt (x) * x**(n/2). */
2928 fn = mathfn_built_in (type, BUILT_IN_SQRT);
2929 if (fn != NULL_TREE)
2930 {
2931 real_arithmetic (&c2, MULT_EXPR, &c, &dconst2);
2932 n = real_to_integer (&c2);
f1b844c6 2933 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
1c4709b4 2934 if (real_identical (&c2, &cint)
2935 && ((flag_unsafe_math_optimizations
2936 && !optimize_size
2937 && powi_cost (n/2) <= POWI_MAX_MULTS)
2938 || n == 1))
f1b844c6 2939 {
c2f47e15 2940 tree call_expr = build_call_expr (fn, 1, narg0);
8697cf4d 2941 /* Use expand_expr in case the newly built call expression
2942 was folded to a non-call. */
2943 op = expand_expr (call_expr, subtarget, mode, EXPAND_NORMAL);
1c4709b4 2944 if (n != 1)
8c5cac78 2945 {
1db6d067 2946 op2 = expand_expr (narg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 2947 op2 = force_reg (mode, op2);
2948 op2 = expand_powi (op2, mode, abs (n / 2));
2949 op = expand_simple_binop (mode, MULT, op, op2, NULL_RTX,
2950 0, OPTAB_LIB_WIDEN);
2951 /* If the original exponent was negative, reciprocate the
2952 result. */
2953 if (n < 0)
2954 op = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2955 op, NULL_RTX, 0, OPTAB_LIB_WIDEN);
8c5cac78 2956 }
1c4709b4 2957 return op;
f1b844c6 2958 }
2959 }
b613c2a6 2960
1c4709b4 2961 /* Try if the exponent is a third of an integer. In this case
5a84ba55 2962 we can expand to x**(n/3) * cbrt(x)**(n%3). As cbrt (x) is
2963 different from pow (x, 1./3.) due to rounding and behavior
2964 with negative x we need to constrain this transformation to
2965 unsafe math and positive x or finite math. */
1c4709b4 2966 fn = mathfn_built_in (type, BUILT_IN_CBRT);
5a84ba55 2967 if (fn != NULL_TREE
2968 && flag_unsafe_math_optimizations
2969 && (tree_expr_nonnegative_p (arg0)
2970 || !HONOR_NANS (mode)))
1c4709b4 2971 {
2972 real_arithmetic (&c2, MULT_EXPR, &c, &dconst3);
2973 real_round (&c2, mode, &c2);
2974 n = real_to_integer (&c2);
2975 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
2976 real_arithmetic (&c2, RDIV_EXPR, &cint, &dconst3);
2977 real_convert (&c2, mode, &c2);
2978 if (real_identical (&c2, &c)
2979 && ((!optimize_size
1c4709b4 2980 && powi_cost (n/3) <= POWI_MAX_MULTS)
2981 || n == 1))
2982 {
c2f47e15 2983 tree call_expr = build_call_expr (fn, 1,narg0);
1c4709b4 2984 op = expand_builtin (call_expr, NULL_RTX, subtarget, mode, 0);
2985 if (abs (n) % 3 == 2)
2986 op = expand_simple_binop (mode, MULT, op, op, op,
2987 0, OPTAB_LIB_WIDEN);
2988 if (n != 1)
2989 {
1db6d067 2990 op2 = expand_expr (narg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 2991 op2 = force_reg (mode, op2);
2992 op2 = expand_powi (op2, mode, abs (n / 3));
2993 op = expand_simple_binop (mode, MULT, op, op2, NULL_RTX,
2994 0, OPTAB_LIB_WIDEN);
2995 /* If the original exponent was negative, reciprocate the
2996 result. */
2997 if (n < 0)
2998 op = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2999 op, NULL_RTX, 0, OPTAB_LIB_WIDEN);
3000 }
3001 return op;
3002 }
3003 }
3004
3005 /* Fall back to optab expansion. */
b613c2a6 3006 return expand_builtin_mathfn_2 (exp, target, subtarget);
f1b844c6 3007}
3008
c2f47e15 3009/* Expand a call to the powi built-in mathematical function. Return NULL_RTX if
757c219d 3010 a normal call should be emitted rather than expanding the function
3011 in-line. EXP is the expression that is a call to the builtin
3012 function; if convenient, the result should be placed in TARGET. */
3013
3014static rtx
3015expand_builtin_powi (tree exp, rtx target, rtx subtarget)
3016{
757c219d 3017 tree arg0, arg1;
3018 rtx op0, op1;
3019 enum machine_mode mode;
d0405f40 3020 enum machine_mode mode2;
757c219d 3021
c2f47e15 3022 if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
3023 return NULL_RTX;
757c219d 3024
c2f47e15 3025 arg0 = CALL_EXPR_ARG (exp, 0);
3026 arg1 = CALL_EXPR_ARG (exp, 1);
757c219d 3027 mode = TYPE_MODE (TREE_TYPE (exp));
3028
3029 /* Handle constant power. */
3030
3031 if (TREE_CODE (arg1) == INTEGER_CST
f96bd2bf 3032 && !TREE_OVERFLOW (arg1))
757c219d 3033 {
3034 HOST_WIDE_INT n = TREE_INT_CST_LOW (arg1);
3035
3036 /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
3037 Otherwise, check the number of multiplications required. */
3038 if ((TREE_INT_CST_HIGH (arg1) == 0
3039 || TREE_INT_CST_HIGH (arg1) == -1)
3040 && ((n >= -1 && n <= 2)
3041 || (! optimize_size
3042 && powi_cost (n) <= POWI_MAX_MULTS)))
3043 {
1db6d067 3044 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
757c219d 3045 op0 = force_reg (mode, op0);
3046 return expand_powi (op0, mode, n);
3047 }
3048 }
3049
3050 /* Emit a libcall to libgcc. */
3051
c2f47e15 3052 /* Mode of the 2nd argument must match that of an int. */
d0405f40 3053 mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
3054
757c219d 3055 if (target == NULL_RTX)
3056 target = gen_reg_rtx (mode);
3057
1db6d067 3058 op0 = expand_expr (arg0, subtarget, mode, EXPAND_NORMAL);
757c219d 3059 if (GET_MODE (op0) != mode)
3060 op0 = convert_to_mode (mode, op0, 0);
1db6d067 3061 op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
d0405f40 3062 if (GET_MODE (op1) != mode2)
3063 op1 = convert_to_mode (mode2, op1, 0);
757c219d 3064
f36b9f69 3065 target = emit_library_call_value (optab_libfunc (powi_optab, mode),
757c219d 3066 target, LCT_CONST_MAKE_BLOCK, mode, 2,
d0405f40 3067 op0, mode, op1, mode2);
757c219d 3068
3069 return target;
3070}
3071
c2f47e15 3072/* Expand expression EXP which is a call to the strlen builtin. Return
3073 NULL_RTX if we failed the caller should emit a normal call, otherwise
aed0bd19 3074 try to get the result in TARGET, if convenient. */
f7c44134 3075
53800dbe 3076static rtx
c2f47e15 3077expand_builtin_strlen (tree exp, rtx target,
aecda0d6 3078 enum machine_mode target_mode)
53800dbe 3079{
c2f47e15 3080 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
3081 return NULL_RTX;
53800dbe 3082 else
3083 {
911c0150 3084 rtx pat;
c2f47e15 3085 tree len;
3086 tree src = CALL_EXPR_ARG (exp, 0);
911c0150 3087 rtx result, src_reg, char_rtx, before_strlen;
80cd7a5e 3088 enum machine_mode insn_mode = target_mode, char_mode;
ef2c4a29 3089 enum insn_code icode = CODE_FOR_nothing;
6248e345 3090 int align;
3091
3092 /* If the length can be computed at compile-time, return it. */
681fab1e 3093 len = c_strlen (src, 0);
6248e345 3094 if (len)
80cd7a5e 3095 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
6248e345 3096
681fab1e 3097 /* If the length can be computed at compile-time and is constant
3098 integer, but there are side-effects in src, evaluate
3099 src for side-effects, then return len.
3100 E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
3101 can be optimized into: i++; x = 3; */
3102 len = c_strlen (src, 1);
3103 if (len && TREE_CODE (len) == INTEGER_CST)
3104 {
3105 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
3106 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
3107 }
3108
6248e345 3109 align = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
53800dbe 3110
53800dbe 3111 /* If SRC is not a pointer type, don't do this operation inline. */
3112 if (align == 0)
c2f47e15 3113 return NULL_RTX;
53800dbe 3114
911c0150 3115 /* Bail out if we can't compute strlen in the right mode. */
53800dbe 3116 while (insn_mode != VOIDmode)
3117 {
99bdde56 3118 icode = optab_handler (strlen_optab, insn_mode)->insn_code;
53800dbe 3119 if (icode != CODE_FOR_nothing)
c28ae87f 3120 break;
53800dbe 3121
3122 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
3123 }
3124 if (insn_mode == VOIDmode)
c2f47e15 3125 return NULL_RTX;
53800dbe 3126
3127 /* Make a place to write the result of the instruction. */
3128 result = target;
3129 if (! (result != 0
8ad4c111 3130 && REG_P (result)
53800dbe 3131 && GET_MODE (result) == insn_mode
3132 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3133 result = gen_reg_rtx (insn_mode);
3134
911c0150 3135 /* Make a place to hold the source address. We will not expand
3136 the actual source until we are sure that the expansion will
3137 not fail -- there are trees that cannot be expanded twice. */
3138 src_reg = gen_reg_rtx (Pmode);
53800dbe 3139
911c0150 3140 /* Mark the beginning of the strlen sequence so we can emit the
3141 source operand later. */
f0ce3b1f 3142 before_strlen = get_last_insn ();
53800dbe 3143
53800dbe 3144 char_rtx = const0_rtx;
f7c44134 3145 char_mode = insn_data[(int) icode].operand[2].mode;
3146 if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
3147 char_mode))
53800dbe 3148 char_rtx = copy_to_mode_reg (char_mode, char_rtx);
3149
911c0150 3150 pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
3151 char_rtx, GEN_INT (align));
3152 if (! pat)
c2f47e15 3153 return NULL_RTX;
911c0150 3154 emit_insn (pat);
3155
3156 /* Now that we are assured of success, expand the source. */
3157 start_sequence ();
c5aba89c 3158 pat = expand_expr (src, src_reg, ptr_mode, EXPAND_NORMAL);
911c0150 3159 if (pat != src_reg)
3160 emit_move_insn (src_reg, pat);
31d3e01c 3161 pat = get_insns ();
911c0150 3162 end_sequence ();
bceb0d1f 3163
3164 if (before_strlen)
3165 emit_insn_after (pat, before_strlen);
3166 else
3167 emit_insn_before (pat, get_insns ());
53800dbe 3168
3169 /* Return the value in the proper mode for this function. */
80cd7a5e 3170 if (GET_MODE (result) == target_mode)
911c0150 3171 target = result;
53800dbe 3172 else if (target != 0)
911c0150 3173 convert_move (target, result, 0);
53800dbe 3174 else
80cd7a5e 3175 target = convert_to_mode (target_mode, result, 0);
911c0150 3176
3177 return target;
53800dbe 3178 }
3179}
3180
c2f47e15 3181/* Expand a call to the strstr builtin. Return NULL_RTX if we failed the
17f5ea87 3182 caller should emit a normal call, otherwise try to get the result
3183 in TARGET, if convenient (and in mode MODE if that's convenient). */
3184
3185static rtx
c2f47e15 3186expand_builtin_strstr (tree exp, rtx target, enum machine_mode mode)
17f5ea87 3187{
c2f47e15 3188 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
17f5ea87 3189 {
c2f47e15 3190 tree type = TREE_TYPE (exp);
3191 tree result = fold_builtin_strstr (CALL_EXPR_ARG (exp, 0),
3192 CALL_EXPR_ARG (exp, 1), type);
2c84ee37 3193 if (result)
3194 return expand_expr (result, target, mode, EXPAND_NORMAL);
17f5ea87 3195 }
c2f47e15 3196 return NULL_RTX;
17f5ea87 3197}
3198
c2f47e15 3199/* Expand a call to the strchr builtin. Return NULL_RTX if we failed the
46f3a74a 3200 caller should emit a normal call, otherwise try to get the result
3201 in TARGET, if convenient (and in mode MODE if that's convenient). */
3202
3203static rtx
c2f47e15 3204expand_builtin_strchr (tree exp, rtx target, enum machine_mode mode)
46f3a74a 3205{
c2f47e15 3206 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
46f3a74a 3207 {
c2f47e15 3208 tree type = TREE_TYPE (exp);
3209 tree result = fold_builtin_strchr (CALL_EXPR_ARG (exp, 0),
3210 CALL_EXPR_ARG (exp, 1), type);
2c84ee37 3211 if (result)
3212 return expand_expr (result, target, mode, EXPAND_NORMAL);
83d79705 3213
2c84ee37 3214 /* FIXME: Should use strchrM optab so that ports can optimize this. */
83d79705 3215 }
c2f47e15 3216 return NULL_RTX;
83d79705 3217}
3218
c2f47e15 3219/* Expand a call to the strrchr builtin. Return NULL_RTX if we failed the
83d79705 3220 caller should emit a normal call, otherwise try to get the result
3221 in TARGET, if convenient (and in mode MODE if that's convenient). */
3222
3223static rtx
c2f47e15 3224expand_builtin_strrchr (tree exp, rtx target, enum machine_mode mode)
83d79705 3225{
c2f47e15 3226 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
83d79705 3227 {
c2f47e15 3228 tree type = TREE_TYPE (exp);
3229 tree result = fold_builtin_strrchr (CALL_EXPR_ARG (exp, 0),
3230 CALL_EXPR_ARG (exp, 1), type);
2c84ee37 3231 if (result)
3232 return expand_expr (result, target, mode, EXPAND_NORMAL);
83d79705 3233 }
c2f47e15 3234 return NULL_RTX;
83d79705 3235}
3236
c2f47e15 3237/* Expand a call to the strpbrk builtin. Return NULL_RTX if we failed the
83d79705 3238 caller should emit a normal call, otherwise try to get the result
3239 in TARGET, if convenient (and in mode MODE if that's convenient). */
3240
3241static rtx
c2f47e15 3242expand_builtin_strpbrk (tree exp, rtx target, enum machine_mode mode)
83d79705 3243{
c2f47e15 3244 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
83d79705 3245 {
c2f47e15 3246 tree type = TREE_TYPE (exp);
3247 tree result = fold_builtin_strpbrk (CALL_EXPR_ARG (exp, 0),
3248 CALL_EXPR_ARG (exp, 1), type);
2c84ee37 3249 if (result)
3250 return expand_expr (result, target, mode, EXPAND_NORMAL);
46f3a74a 3251 }
c2f47e15 3252 return NULL_RTX;
46f3a74a 3253}
3254
6840589f 3255/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3256 bytes from constant string DATA + OFFSET and return it as target
3257 constant. */
3258
3259static rtx
aecda0d6 3260builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
3261 enum machine_mode mode)
6840589f 3262{
3263 const char *str = (const char *) data;
3264
64db345d 3265 gcc_assert (offset >= 0
3266 && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
3267 <= strlen (str) + 1));
6840589f 3268
3269 return c_readstr (str + offset, mode);
3270}
3271
c2f47e15 3272/* Expand a call EXP to the memcpy 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
9fe0e1b8 3275 mode MODE if that's convenient). */
c2f47e15 3276
53800dbe 3277static rtx
5a0de151 3278expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode)
53800dbe 3279{
8e76ec06 3280 tree fndecl = get_callee_fndecl (exp);
c2f47e15 3281
3282 if (!validate_arglist (exp,
3283 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3284 return NULL_RTX;
53800dbe 3285 else
3286 {
c2f47e15 3287 tree dest = CALL_EXPR_ARG (exp, 0);
3288 tree src = CALL_EXPR_ARG (exp, 1);
3289 tree len = CALL_EXPR_ARG (exp, 2);
6840589f 3290 const char *src_str;
27d0c333 3291 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3292 unsigned int dest_align
3293 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
53800dbe 3294 rtx dest_mem, src_mem, dest_addr, len_rtx;
c2f47e15 3295 tree result = fold_builtin_memory_op (dest, src, len,
3296 TREE_TYPE (TREE_TYPE (fndecl)),
4f46f2b9 3297 false, /*endp=*/0);
162719b3 3298 HOST_WIDE_INT expected_size = -1;
3299 unsigned int expected_align = 0;
5a0de151 3300
3301 if (result)
4f46f2b9 3302 {
3303 while (TREE_CODE (result) == COMPOUND_EXPR)
3304 {
3305 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3306 EXPAND_NORMAL);
3307 result = TREE_OPERAND (result, 1);
3308 }
3309 return expand_expr (result, target, mode, EXPAND_NORMAL);
3310 }
53800dbe 3311
6f428e8b 3312 /* If DEST is not a pointer type, call the normal function. */
3313 if (dest_align == 0)
c2f47e15 3314 return NULL_RTX;
6f428e8b 3315
6f428e8b 3316 /* If either SRC is not a pointer type, don't do this
a0c938f0 3317 operation in-line. */
6f428e8b 3318 if (src_align == 0)
c2f47e15 3319 return NULL_RTX;
162719b3 3320
3321 stringop_block_profile (exp, &expected_align, &expected_size);
3322 if (expected_align < dest_align)
3323 expected_align = dest_align;
d8ae1baa 3324 dest_mem = get_memory_rtx (dest, len);
2a631e19 3325 set_mem_align (dest_mem, dest_align);
8ec3c5c2 3326 len_rtx = expand_normal (len);
6840589f 3327 src_str = c_getstr (src);
3328
3329 /* If SRC is a string constant and block move would be done
3330 by pieces, we can avoid loading the string from memory
3331 and only stored the computed constants. */
3332 if (src_str
6840589f 3333 && GET_CODE (len_rtx) == CONST_INT
3334 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3335 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
4b297e2e 3336 (void *) src_str, dest_align, false))
6840589f 3337 {
9fe0e1b8 3338 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3339 builtin_memcpy_read_str,
4b297e2e 3340 (void *) src_str, dest_align, false, 0);
e5716f7e 3341 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3342 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3343 return dest_mem;
6840589f 3344 }
3345
d8ae1baa 3346 src_mem = get_memory_rtx (src, len);
2a631e19 3347 set_mem_align (src_mem, src_align);
53800dbe 3348
53800dbe 3349 /* Copy word part most expediently. */
162719b3 3350 dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
3351 CALL_EXPR_TAILCALL (exp)
3352 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3353 expected_align, expected_size);
53800dbe 3354
3355 if (dest_addr == 0)
e5716f7e 3356 {
3357 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3358 dest_addr = convert_memory_address (ptr_mode, dest_addr);
e5716f7e 3359 }
9fe0e1b8 3360 return dest_addr;
53800dbe 3361 }
3362}
3363
c2f47e15 3364/* Expand a call EXP to the mempcpy builtin.
3365 Return NULL_RTX if we failed; the caller should emit a normal call,
647661c6 3366 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3367 mode MODE if that's convenient). If ENDP is 0 return the
3368 destination pointer, if ENDP is 1 return the end pointer ala
3369 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3370 stpcpy. */
647661c6 3371
3372static rtx
c2f47e15 3373expand_builtin_mempcpy(tree exp, rtx target, enum machine_mode mode)
647661c6 3374{
c2f47e15 3375 if (!validate_arglist (exp,
3376 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3377 return NULL_RTX;
3378 else
3379 {
3380 tree dest = CALL_EXPR_ARG (exp, 0);
3381 tree src = CALL_EXPR_ARG (exp, 1);
3382 tree len = CALL_EXPR_ARG (exp, 2);
3383 return expand_builtin_mempcpy_args (dest, src, len,
3384 TREE_TYPE (exp),
3385 target, mode, /*endp=*/ 1);
3386 }
3387}
3388
3389/* Helper function to do the actual work for expand_builtin_mempcpy. The
3390 arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out
3391 so that this can also be called without constructing an actual CALL_EXPR.
3392 TYPE is the return type of the call. The other arguments and return value
3393 are the same as for expand_builtin_mempcpy. */
3394
3395static rtx
3396expand_builtin_mempcpy_args (tree dest, tree src, tree len, tree type,
3397 rtx target, enum machine_mode mode, int endp)
3398{
3399 /* If return value is ignored, transform mempcpy into memcpy. */
3400 if (target == const0_rtx)
9fe0e1b8 3401 {
3402 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
3403
3404 if (!fn)
c2f47e15 3405 return NULL_RTX;
9fe0e1b8 3406
c2f47e15 3407 return expand_expr (build_call_expr (fn, 3, dest, src, len),
9fe0e1b8 3408 target, mode, EXPAND_NORMAL);
3409 }
647661c6 3410 else
3411 {
9fe0e1b8 3412 const char *src_str;
3413 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3414 unsigned int dest_align
3415 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3416 rtx dest_mem, src_mem, len_rtx;
c2f47e15 3417 tree result = fold_builtin_memory_op (dest, src, len, type, false, endp);
9fe0e1b8 3418
7da1412b 3419 if (result)
4f46f2b9 3420 {
3421 while (TREE_CODE (result) == COMPOUND_EXPR)
3422 {
3423 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3424 EXPAND_NORMAL);
3425 result = TREE_OPERAND (result, 1);
3426 }
3427 return expand_expr (result, target, mode, EXPAND_NORMAL);
3428 }
a0c938f0 3429
7da1412b 3430 /* If either SRC or DEST is not a pointer type, don't do this
a0c938f0 3431 operation in-line. */
7da1412b 3432 if (dest_align == 0 || src_align == 0)
c2f47e15 3433 return NULL_RTX;
9fe0e1b8 3434
6217c238 3435 /* If LEN is not constant, call the normal function. */
3436 if (! host_integerp (len, 1))
c2f47e15 3437 return NULL_RTX;
0862b7e9 3438
8ec3c5c2 3439 len_rtx = expand_normal (len);
9fe0e1b8 3440 src_str = c_getstr (src);
647661c6 3441
9fe0e1b8 3442 /* If SRC is a string constant and block move would be done
3443 by pieces, we can avoid loading the string from memory
3444 and only stored the computed constants. */
3445 if (src_str
3446 && GET_CODE (len_rtx) == CONST_INT
3447 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3448 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
4b297e2e 3449 (void *) src_str, dest_align, false))
9fe0e1b8 3450 {
d8ae1baa 3451 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3452 set_mem_align (dest_mem, dest_align);
3453 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3454 builtin_memcpy_read_str,
4b297e2e 3455 (void *) src_str, dest_align,
3456 false, endp);
9fe0e1b8 3457 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3458 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3459 return dest_mem;
647661c6 3460 }
3461
9fe0e1b8 3462 if (GET_CODE (len_rtx) == CONST_INT
3463 && can_move_by_pieces (INTVAL (len_rtx),
3464 MIN (dest_align, src_align)))
3465 {
d8ae1baa 3466 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3467 set_mem_align (dest_mem, dest_align);
d8ae1baa 3468 src_mem = get_memory_rtx (src, len);
9fe0e1b8 3469 set_mem_align (src_mem, src_align);
3470 dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
3471 MIN (dest_align, src_align), endp);
3472 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3473 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3474 return dest_mem;
3475 }
3476
c2f47e15 3477 return NULL_RTX;
647661c6 3478 }
3479}
3480
c2f47e15 3481/* Expand expression EXP, which is a call to the memmove builtin. Return
3482 NULL_RTX if we failed; the caller should emit a normal call. */
c4950093 3483
3484static rtx
c2f47e15 3485expand_builtin_memmove (tree exp, rtx target, enum machine_mode mode, int ignore)
c4950093 3486{
c2f47e15 3487 if (!validate_arglist (exp,
3488 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3489 return NULL_RTX;
c4950093 3490 else
3491 {
c2f47e15 3492 tree dest = CALL_EXPR_ARG (exp, 0);
3493 tree src = CALL_EXPR_ARG (exp, 1);
3494 tree len = CALL_EXPR_ARG (exp, 2);
3495 return expand_builtin_memmove_args (dest, src, len, TREE_TYPE (exp),
3496 target, mode, ignore);
3497 }
3498}
7e72af53 3499
c2f47e15 3500/* Helper function to do the actual work for expand_builtin_memmove. The
3501 arguments to the builtin_memmove call DEST, SRC, and LEN are broken out
3502 so that this can also be called without constructing an actual CALL_EXPR.
3503 TYPE is the return type of the call. The other arguments and return value
3504 are the same as for expand_builtin_memmove. */
3505
3506static rtx
3507expand_builtin_memmove_args (tree dest, tree src, tree len,
3508 tree type, rtx target, enum machine_mode mode,
3509 int ignore)
3510{
3511 tree result = fold_builtin_memory_op (dest, src, len, type, ignore, /*endp=*/3);
3512
3513 if (result)
3514 {
05be68f3 3515 STRIP_TYPE_NOPS (result);
c2f47e15 3516 while (TREE_CODE (result) == COMPOUND_EXPR)
4f46f2b9 3517 {
c2f47e15 3518 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3519 EXPAND_NORMAL);
3520 result = TREE_OPERAND (result, 1);
4f46f2b9 3521 }
c2f47e15 3522 return expand_expr (result, target, mode, EXPAND_NORMAL);
3523 }
3524
3525 /* Otherwise, call the normal function. */
3526 return NULL_RTX;
c4950093 3527}
3528
c2f47e15 3529/* Expand expression EXP, which is a call to the bcopy builtin. Return
3530 NULL_RTX if we failed the caller should emit a normal call. */
c4950093 3531
3532static rtx
c2f47e15 3533expand_builtin_bcopy (tree exp, int ignore)
c4950093 3534{
0b25db21 3535 tree type = TREE_TYPE (exp);
c2f47e15 3536 tree src, dest, size;
c4950093 3537
c2f47e15 3538 if (!validate_arglist (exp,
3539 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
c4950093 3540 return NULL_RTX;
3541
c2f47e15 3542 src = CALL_EXPR_ARG (exp, 0);
3543 dest = CALL_EXPR_ARG (exp, 1);
3544 size = CALL_EXPR_ARG (exp, 2);
c4950093 3545
c2f47e15 3546 /* Transform bcopy(ptr x, ptr y, int z) to memmove(ptr y, ptr x, size_t z).
3547 This is done this way so that if it isn't expanded inline, we fall
3548 back to calling bcopy instead of memmove. */
3549 return expand_builtin_memmove_args (dest, src,
3550 fold_convert (sizetype, size),
3551 type, const0_rtx, VOIDmode,
3552 ignore);
c4950093 3553}
3554
727c62dd 3555#ifndef HAVE_movstr
3556# define HAVE_movstr 0
3557# define CODE_FOR_movstr CODE_FOR_nothing
3558#endif
3559
c2f47e15 3560/* Expand into a movstr instruction, if one is available. Return NULL_RTX if
727c62dd 3561 we failed, the caller should emit a normal call, otherwise try to
3562 get the result in TARGET, if convenient. If ENDP is 0 return the
3563 destination pointer, if ENDP is 1 return the end pointer ala
3564 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3565 stpcpy. */
3566
3567static rtx
3568expand_movstr (tree dest, tree src, rtx target, int endp)
3569{
3570 rtx end;
3571 rtx dest_mem;
3572 rtx src_mem;
3573 rtx insn;
3574 const struct insn_data * data;
3575
3576 if (!HAVE_movstr)
c2f47e15 3577 return NULL_RTX;
727c62dd 3578
d8ae1baa 3579 dest_mem = get_memory_rtx (dest, NULL);
3580 src_mem = get_memory_rtx (src, NULL);
727c62dd 3581 if (!endp)
3582 {
3583 target = force_reg (Pmode, XEXP (dest_mem, 0));
3584 dest_mem = replace_equiv_address (dest_mem, target);
3585 end = gen_reg_rtx (Pmode);
3586 }
3587 else
3588 {
3589 if (target == 0 || target == const0_rtx)
3590 {
3591 end = gen_reg_rtx (Pmode);
3592 if (target == 0)
3593 target = end;
3594 }
3595 else
3596 end = target;
3597 }
3598
3599 data = insn_data + CODE_FOR_movstr;
3600
3601 if (data->operand[0].mode != VOIDmode)
3602 end = gen_lowpart (data->operand[0].mode, end);
3603
3604 insn = data->genfun (end, dest_mem, src_mem);
3605
64db345d 3606 gcc_assert (insn);
727c62dd 3607
3608 emit_insn (insn);
3609
3610 /* movstr is supposed to set end to the address of the NUL
3611 terminator. If the caller requested a mempcpy-like return value,
3612 adjust it. */
3613 if (endp == 1 && target != const0_rtx)
c5aba89c 3614 {
3615 rtx tem = plus_constant (gen_lowpart (GET_MODE (target), end), 1);
3616 emit_move_insn (target, force_operand (tem, NULL_RTX));
3617 }
727c62dd 3618
3619 return target;
3620}
3621
c2f47e15 3622/* Expand expression EXP, which is a call to the strcpy builtin. Return
3623 NULL_RTX if we failed the caller should emit a normal call, otherwise
3624 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3625 convenient). */
902de8ed 3626
53800dbe 3627static rtx
c2f47e15 3628expand_builtin_strcpy (tree fndecl, tree exp, rtx target, enum machine_mode mode)
53800dbe 3629{
c2f47e15 3630 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3631 {
3632 tree dest = CALL_EXPR_ARG (exp, 0);
3633 tree src = CALL_EXPR_ARG (exp, 1);
3634 return expand_builtin_strcpy_args (fndecl, dest, src, target, mode);
3635 }
3636 return NULL_RTX;
3637}
3638
3639/* Helper function to do the actual work for expand_builtin_strcpy. The
3640 arguments to the builtin_strcpy call DEST and SRC are broken out
3641 so that this can also be called without constructing an actual CALL_EXPR.
3642 The other arguments and return value are the same as for
3643 expand_builtin_strcpy. */
3644
3645static rtx
3646expand_builtin_strcpy_args (tree fndecl, tree dest, tree src,
3647 rtx target, enum machine_mode mode)
3648{
3649 tree result = fold_builtin_strcpy (fndecl, dest, src, 0);
3650 if (result)
3651 return expand_expr (result, target, mode, EXPAND_NORMAL);
3652 return expand_movstr (dest, src, target, /*endp=*/0);
902de8ed 3653
53800dbe 3654}
3655
c2f47e15 3656/* Expand a call EXP to the stpcpy builtin.
3657 Return NULL_RTX if we failed the caller should emit a normal call,
3b824fa6 3658 otherwise try to get the result in TARGET, if convenient (and in
3659 mode MODE if that's convenient). */
3660
3661static rtx
dc369150 3662expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
3b824fa6 3663{
c2f47e15 3664 tree dst, src;
3665
3666 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3667 return NULL_RTX;
3668
3669 dst = CALL_EXPR_ARG (exp, 0);
3670 src = CALL_EXPR_ARG (exp, 1);
3671
727c62dd 3672 /* If return value is ignored, transform stpcpy into strcpy. */
3673 if (target == const0_rtx)
978836e5 3674 {
3675 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
3676 if (!fn)
c2f47e15 3677 return NULL_RTX;
978836e5 3678
c2f47e15 3679 return expand_expr (build_call_expr (fn, 2, dst, src),
3680 target, mode, EXPAND_NORMAL);
978836e5 3681 }
3b824fa6 3682 else
3683 {
c2f47e15 3684 tree len, lenp1;
727c62dd 3685 rtx ret;
647661c6 3686
9fe0e1b8 3687 /* Ensure we get an actual string whose length can be evaluated at
a0c938f0 3688 compile-time, not an expression containing a string. This is
3689 because the latter will potentially produce pessimized code
3690 when used to produce the return value. */
681fab1e 3691 if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
c2f47e15 3692 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3693
7d705727 3694 lenp1 = size_binop (PLUS_EXPR, len, ssize_int (1));
c2f47e15 3695 ret = expand_builtin_mempcpy_args (dst, src, lenp1, TREE_TYPE (exp),
3696 target, mode, /*endp=*/2);
727c62dd 3697
3698 if (ret)
3699 return ret;
3700
3701 if (TREE_CODE (len) == INTEGER_CST)
3702 {
8ec3c5c2 3703 rtx len_rtx = expand_normal (len);
727c62dd 3704
3705 if (GET_CODE (len_rtx) == CONST_INT)
3706 {
c2f47e15 3707 ret = expand_builtin_strcpy_args (get_callee_fndecl (exp),
3708 dst, src, target, mode);
727c62dd 3709
3710 if (ret)
3711 {
3712 if (! target)
7ac87324 3713 {
3714 if (mode != VOIDmode)
3715 target = gen_reg_rtx (mode);
3716 else
3717 target = gen_reg_rtx (GET_MODE (ret));
3718 }
727c62dd 3719 if (GET_MODE (target) != GET_MODE (ret))
3720 ret = gen_lowpart (GET_MODE (target), ret);
3721
c5aba89c 3722 ret = plus_constant (ret, INTVAL (len_rtx));
3723 ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
64db345d 3724 gcc_assert (ret);
727c62dd 3725
3726 return target;
3727 }
3728 }
3729 }
3730
c2f47e15 3731 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3732 }
3733}
3734
6840589f 3735/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3736 bytes from constant string DATA + OFFSET and return it as target
3737 constant. */
3738
09879952 3739rtx
aecda0d6 3740builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
3741 enum machine_mode mode)
6840589f 3742{
3743 const char *str = (const char *) data;
3744
3745 if ((unsigned HOST_WIDE_INT) offset > strlen (str))
3746 return const0_rtx;
3747
3748 return c_readstr (str + offset, mode);
3749}
3750
c2f47e15 3751/* Expand expression EXP, which is a call to the strncpy builtin. Return
3752 NULL_RTX if we failed the caller should emit a normal call. */
ed09096d 3753
3754static rtx
8ff6a5cd 3755expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode)
ed09096d 3756{
ea726109 3757 tree fndecl = get_callee_fndecl (exp);
c2f47e15 3758
3759 if (validate_arglist (exp,
3760 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
ed09096d 3761 {
c2f47e15 3762 tree dest = CALL_EXPR_ARG (exp, 0);
3763 tree src = CALL_EXPR_ARG (exp, 1);
3764 tree len = CALL_EXPR_ARG (exp, 2);
3765 tree slen = c_strlen (src, 1);
3766 tree result = fold_builtin_strncpy (fndecl, dest, src, len, slen);
a0c938f0 3767
8ff6a5cd 3768 if (result)
4f46f2b9 3769 {
3770 while (TREE_CODE (result) == COMPOUND_EXPR)
3771 {
3772 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3773 EXPAND_NORMAL);
3774 result = TREE_OPERAND (result, 1);
3775 }
3776 return expand_expr (result, target, mode, EXPAND_NORMAL);
3777 }
6840589f 3778
8ff6a5cd 3779 /* We must be passed a constant len and src parameter. */
3780 if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
c2f47e15 3781 return NULL_RTX;
ed09096d 3782
3783 slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
3784
3785 /* We're required to pad with trailing zeros if the requested
a0c938f0 3786 len is greater than strlen(s2)+1. In that case try to
6840589f 3787 use store_by_pieces, if it fails, punt. */
ed09096d 3788 if (tree_int_cst_lt (slen, len))
6840589f 3789 {
27d0c333 3790 unsigned int dest_align
3791 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
c2f47e15 3792 const char *p = c_getstr (src);
6840589f 3793 rtx dest_mem;
3794
27d0c333 3795 if (!p || dest_align == 0 || !host_integerp (len, 1)
3796 || !can_store_by_pieces (tree_low_cst (len, 1),
6840589f 3797 builtin_strncpy_read_str,
4b297e2e 3798 (void *) p, dest_align, false))
c2f47e15 3799 return NULL_RTX;
6840589f 3800
d8ae1baa 3801 dest_mem = get_memory_rtx (dest, len);
27d0c333 3802 store_by_pieces (dest_mem, tree_low_cst (len, 1),
6840589f 3803 builtin_strncpy_read_str,
4b297e2e 3804 (void *) p, dest_align, false, 0);
e5716f7e 3805 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3806 dest_mem = convert_memory_address (ptr_mode, dest_mem);
e5716f7e 3807 return dest_mem;
6840589f 3808 }
ed09096d 3809 }
c2f47e15 3810 return NULL_RTX;
ed09096d 3811}
3812
ecc318ff 3813/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3814 bytes from constant string DATA + OFFSET and return it as target
3815 constant. */
3816
f656b751 3817rtx
aecda0d6 3818builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3819 enum machine_mode mode)
ecc318ff 3820{
3821 const char *c = (const char *) data;
3822 char *p = alloca (GET_MODE_SIZE (mode));
3823
3824 memset (p, *c, GET_MODE_SIZE (mode));
3825
3826 return c_readstr (p, mode);
3827}
3828
a7ec6974 3829/* Callback routine for store_by_pieces. Return the RTL of a register
3830 containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
3831 char value given in the RTL register data. For example, if mode is
3832 4 bytes wide, return the RTL for 0x01010101*data. */
3833
3834static rtx
aecda0d6 3835builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3836 enum machine_mode mode)
a7ec6974 3837{
3838 rtx target, coeff;
3839 size_t size;
3840 char *p;
3841
3842 size = GET_MODE_SIZE (mode);
f0ce3b1f 3843 if (size == 1)
3844 return (rtx) data;
a7ec6974 3845
3846 p = alloca (size);
3847 memset (p, 1, size);
3848 coeff = c_readstr (p, mode);
3849
f0ce3b1f 3850 target = convert_to_mode (mode, (rtx) data, 1);
a7ec6974 3851 target = expand_mult (mode, target, coeff, NULL_RTX, 1);
3852 return force_reg (mode, target);
3853}
3854
c2f47e15 3855/* Expand expression EXP, which is a call to the memset builtin. Return
3856 NULL_RTX if we failed the caller should emit a normal call, otherwise
3857 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3858 convenient). */
902de8ed 3859
53800dbe 3860static rtx
c2f47e15 3861expand_builtin_memset (tree exp, rtx target, enum machine_mode mode)
53800dbe 3862{
c2f47e15 3863 if (!validate_arglist (exp,
3864 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
3865 return NULL_RTX;
53800dbe 3866 else
3867 {
c2f47e15 3868 tree dest = CALL_EXPR_ARG (exp, 0);
3869 tree val = CALL_EXPR_ARG (exp, 1);
3870 tree len = CALL_EXPR_ARG (exp, 2);
3871 return expand_builtin_memset_args (dest, val, len, target, mode, exp);
3872 }
3873}
53800dbe 3874
c2f47e15 3875/* Helper function to do the actual work for expand_builtin_memset. The
3876 arguments to the builtin_memset call DEST, VAL, and LEN are broken out
3877 so that this can also be called without constructing an actual CALL_EXPR.
3878 The other arguments and return value are the same as for
3879 expand_builtin_memset. */
6b961939 3880
c2f47e15 3881static rtx
3882expand_builtin_memset_args (tree dest, tree val, tree len,
3883 rtx target, enum machine_mode mode, tree orig_exp)
3884{
3885 tree fndecl, fn;
3886 enum built_in_function fcode;
3887 char c;
3888 unsigned int dest_align;
3889 rtx dest_mem, dest_addr, len_rtx;
3890 HOST_WIDE_INT expected_size = -1;
3891 unsigned int expected_align = 0;
53800dbe 3892
c2f47e15 3893 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
162719b3 3894
c2f47e15 3895 /* If DEST is not a pointer type, don't do this operation in-line. */
3896 if (dest_align == 0)
3897 return NULL_RTX;
6f428e8b 3898
c2f47e15 3899 stringop_block_profile (orig_exp, &expected_align, &expected_size);
3900 if (expected_align < dest_align)
3901 expected_align = dest_align;
6b961939 3902
c2f47e15 3903 /* If the LEN parameter is zero, return DEST. */
3904 if (integer_zerop (len))
3905 {
3906 /* Evaluate and ignore VAL in case it has side-effects. */
3907 expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
3908 return expand_expr (dest, target, mode, EXPAND_NORMAL);
3909 }
7a3e5564 3910
c2f47e15 3911 /* Stabilize the arguments in case we fail. */
3912 dest = builtin_save_expr (dest);
3913 val = builtin_save_expr (val);
3914 len = builtin_save_expr (len);
a7ec6974 3915
c2f47e15 3916 len_rtx = expand_normal (len);
3917 dest_mem = get_memory_rtx (dest, len);
a7ec6974 3918
c2f47e15 3919 if (TREE_CODE (val) != INTEGER_CST)
3920 {
3921 rtx val_rtx;
a7ec6974 3922
c2f47e15 3923 val_rtx = expand_normal (val);
3924 val_rtx = convert_to_mode (TYPE_MODE (unsigned_char_type_node),
3925 val_rtx, 0);
53800dbe 3926
c2f47e15 3927 /* Assume that we can memset by pieces if we can store
3928 * the coefficients by pieces (in the required modes).
3929 * We can't pass builtin_memset_gen_str as that emits RTL. */
3930 c = 1;
3931 if (host_integerp (len, 1)
c2f47e15 3932 && can_store_by_pieces (tree_low_cst (len, 1),
4b297e2e 3933 builtin_memset_read_str, &c, dest_align,
3934 true))
c2f47e15 3935 {
3936 val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
3937 val_rtx);
3938 store_by_pieces (dest_mem, tree_low_cst (len, 1),
4b297e2e 3939 builtin_memset_gen_str, val_rtx, dest_align,
3940 true, 0);
c2f47e15 3941 }
3942 else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
3943 dest_align, expected_align,
3944 expected_size))
6b961939 3945 goto do_libcall;
c2f47e15 3946
3947 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3948 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3949 return dest_mem;
3950 }
53800dbe 3951
c2f47e15 3952 if (target_char_cast (val, &c))
3953 goto do_libcall;
ecc318ff 3954
c2f47e15 3955 if (c)
3956 {
3957 if (host_integerp (len, 1)
c2f47e15 3958 && can_store_by_pieces (tree_low_cst (len, 1),
4b297e2e 3959 builtin_memset_read_str, &c, dest_align,
3960 true))
c2f47e15 3961 store_by_pieces (dest_mem, tree_low_cst (len, 1),
4b297e2e 3962 builtin_memset_read_str, &c, dest_align, true, 0);
c2f47e15 3963 else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
3964 dest_align, expected_align,
3965 expected_size))
3966 goto do_libcall;
3967
3968 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3969 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3970 return dest_mem;
3971 }
ecc318ff 3972
c2f47e15 3973 set_mem_align (dest_mem, dest_align);
3974 dest_addr = clear_storage_hints (dest_mem, len_rtx,
3975 CALL_EXPR_TAILCALL (orig_exp)
3976 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3977 expected_align, expected_size);
53800dbe 3978
c2f47e15 3979 if (dest_addr == 0)
3980 {
3981 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3982 dest_addr = convert_memory_address (ptr_mode, dest_addr);
3983 }
53800dbe 3984
c2f47e15 3985 return dest_addr;
6b961939 3986
c2f47e15 3987 do_libcall:
3988 fndecl = get_callee_fndecl (orig_exp);
3989 fcode = DECL_FUNCTION_CODE (fndecl);
3990 if (fcode == BUILT_IN_MEMSET)
3991 fn = build_call_expr (fndecl, 3, dest, val, len);
3992 else if (fcode == BUILT_IN_BZERO)
3993 fn = build_call_expr (fndecl, 2, dest, len);
3994 else
3995 gcc_unreachable ();
3996 if (TREE_CODE (fn) == CALL_EXPR)
3997 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
3998 return expand_call (fn, target, target == const0_rtx);
53800dbe 3999}
4000
c2f47e15 4001/* Expand expression EXP, which is a call to the bzero builtin. Return
4002 NULL_RTX if we failed the caller should emit a normal call. */
27d0c333 4003
ffc83088 4004static rtx
0b25db21 4005expand_builtin_bzero (tree exp)
ffc83088 4006{
c2f47e15 4007 tree dest, size;
ffc83088 4008
c2f47e15 4009 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
7369e7ba 4010 return NULL_RTX;
ffc83088 4011
c2f47e15 4012 dest = CALL_EXPR_ARG (exp, 0);
4013 size = CALL_EXPR_ARG (exp, 1);
bf8e3599 4014
7369e7ba 4015 /* New argument list transforming bzero(ptr x, int y) to
6f428e8b 4016 memset(ptr x, int 0, size_t y). This is done this way
4017 so that if it isn't expanded inline, we fallback to
4018 calling bzero instead of memset. */
bf8e3599 4019
c2f47e15 4020 return expand_builtin_memset_args (dest, integer_zero_node,
4021 fold_convert (sizetype, size),
4022 const0_rtx, VOIDmode, exp);
ffc83088 4023}
4024
7959b13b 4025/* Expand a call to the memchr builtin. Return NULL_RTX if we failed the
4026 caller should emit a normal call, otherwise try to get the result
4027 in TARGET, if convenient (and in mode MODE if that's convenient). */
4028
4029static rtx
4030expand_builtin_memchr (tree exp, rtx target, enum machine_mode mode)
4031{
4032 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE,
4033 INTEGER_TYPE, VOID_TYPE))
4034 {
4035 tree type = TREE_TYPE (exp);
4036 tree result = fold_builtin_memchr (CALL_EXPR_ARG (exp, 0),
4037 CALL_EXPR_ARG (exp, 1),
4038 CALL_EXPR_ARG (exp, 2), type);
4039 if (result)
4040 return expand_expr (result, target, mode, EXPAND_NORMAL);
4041 }
4042 return NULL_RTX;
4043}
4044
7a3f89b5 4045/* Expand expression EXP, which is a call to the memcmp built-in function.
c2f47e15 4046 Return NULL_RTX if we failed and the
53800dbe 4047 caller should emit a normal call, otherwise try to get the result in
6f428e8b 4048 TARGET, if convenient (and in mode MODE, if that's convenient). */
27d0c333 4049
53800dbe 4050static rtx
c2f47e15 4051expand_builtin_memcmp (tree exp, rtx target, enum machine_mode mode)
53800dbe 4052{
c2f47e15 4053 if (!validate_arglist (exp,
4054 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4055 return NULL_RTX;
218bc19e 4056 else
6f428e8b 4057 {
c2f47e15 4058 tree result = fold_builtin_memcmp (CALL_EXPR_ARG (exp, 0),
4059 CALL_EXPR_ARG (exp, 1),
4060 CALL_EXPR_ARG (exp, 2));
218bc19e 4061 if (result)
4062 return expand_expr (result, target, mode, EXPAND_NORMAL);
6f428e8b 4063 }
4064
6ac5504b 4065#if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi
53800dbe 4066 {
0cd832f0 4067 rtx arg1_rtx, arg2_rtx, arg3_rtx;
53800dbe 4068 rtx result;
0cd832f0 4069 rtx insn;
c2f47e15 4070 tree arg1 = CALL_EXPR_ARG (exp, 0);
4071 tree arg2 = CALL_EXPR_ARG (exp, 1);
4072 tree len = CALL_EXPR_ARG (exp, 2);
53800dbe 4073
4074 int arg1_align
4075 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4076 int arg2_align
4077 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
b428c0a5 4078 enum machine_mode insn_mode;
4079
4080#ifdef HAVE_cmpmemsi
4081 if (HAVE_cmpmemsi)
4082 insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
4083 else
4084#endif
6ac5504b 4085#ifdef HAVE_cmpstrnsi
4086 if (HAVE_cmpstrnsi)
4087 insn_mode = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
b428c0a5 4088 else
4089#endif
c2f47e15 4090 return NULL_RTX;
53800dbe 4091
4092 /* If we don't have POINTER_TYPE, call the function. */
4093 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4094 return NULL_RTX;
53800dbe 4095
4096 /* Make a place to write the result of the instruction. */
4097 result = target;
4098 if (! (result != 0
8ad4c111 4099 && REG_P (result) && GET_MODE (result) == insn_mode
53800dbe 4100 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4101 result = gen_reg_rtx (insn_mode);
4102
d8ae1baa 4103 arg1_rtx = get_memory_rtx (arg1, len);
4104 arg2_rtx = get_memory_rtx (arg2, len);
8ec3c5c2 4105 arg3_rtx = expand_normal (len);
83f88f8e 4106
4107 /* Set MEM_SIZE as appropriate. */
4108 if (GET_CODE (arg3_rtx) == CONST_INT)
4109 {
4110 set_mem_size (arg1_rtx, arg3_rtx);
4111 set_mem_size (arg2_rtx, arg3_rtx);
4112 }
4113
b428c0a5 4114#ifdef HAVE_cmpmemsi
4115 if (HAVE_cmpmemsi)
4116 insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4117 GEN_INT (MIN (arg1_align, arg2_align)));
0cd832f0 4118 else
b428c0a5 4119#endif
6ac5504b 4120#ifdef HAVE_cmpstrnsi
4121 if (HAVE_cmpstrnsi)
4122 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4123 GEN_INT (MIN (arg1_align, arg2_align)));
b428c0a5 4124 else
4125#endif
64db345d 4126 gcc_unreachable ();
0cd832f0 4127
4128 if (insn)
4129 emit_insn (insn);
4130 else
2c5d421b 4131 emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK,
0cd832f0 4132 TYPE_MODE (integer_type_node), 3,
4133 XEXP (arg1_rtx, 0), Pmode,
4134 XEXP (arg2_rtx, 0), Pmode,
4135 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
78a8ed03 4136 TYPE_UNSIGNED (sizetype)),
0cd832f0 4137 TYPE_MODE (sizetype));
53800dbe 4138
4139 /* Return the value in the proper mode for this function. */
4140 mode = TYPE_MODE (TREE_TYPE (exp));
4141 if (GET_MODE (result) == mode)
4142 return result;
4143 else if (target != 0)
4144 {
4145 convert_move (target, result, 0);
4146 return target;
4147 }
4148 else
4149 return convert_to_mode (mode, result, 0);
4150 }
83d79705 4151#endif
53800dbe 4152
c2f47e15 4153 return NULL_RTX;
6f428e8b 4154}
4155
c2f47e15 4156/* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX
53800dbe 4157 if we failed the caller should emit a normal call, otherwise try to get
4158 the result in TARGET, if convenient. */
902de8ed 4159
53800dbe 4160static rtx
aecda0d6 4161expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
53800dbe 4162{
c2f47e15 4163 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4164 return NULL_RTX;
218bc19e 4165 else
ef6c187e 4166 {
c2f47e15 4167 tree result = fold_builtin_strcmp (CALL_EXPR_ARG (exp, 0),
4168 CALL_EXPR_ARG (exp, 1));
218bc19e 4169 if (result)
4170 return expand_expr (result, target, mode, EXPAND_NORMAL);
ef6c187e 4171 }
bf8e3599 4172
6ac5504b 4173#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
4174 if (cmpstr_optab[SImode] != CODE_FOR_nothing
4175 || cmpstrn_optab[SImode] != CODE_FOR_nothing)
4176 {
4177 rtx arg1_rtx, arg2_rtx;
4178 rtx result, insn = NULL_RTX;
4179 tree fndecl, fn;
c2f47e15 4180 tree arg1 = CALL_EXPR_ARG (exp, 0);
4181 tree arg2 = CALL_EXPR_ARG (exp, 1);
a0c938f0 4182
6ac5504b 4183 int arg1_align
4184 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4185 int arg2_align
4186 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4187
4188 /* If we don't have POINTER_TYPE, call the function. */
4189 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4190 return NULL_RTX;
7a3f89b5 4191
6ac5504b 4192 /* Stabilize the arguments in case gen_cmpstr(n)si fail. */
4193 arg1 = builtin_save_expr (arg1);
4194 arg2 = builtin_save_expr (arg2);
7a3f89b5 4195
d8ae1baa 4196 arg1_rtx = get_memory_rtx (arg1, NULL);
4197 arg2_rtx = get_memory_rtx (arg2, NULL);
53800dbe 4198
6ac5504b 4199#ifdef HAVE_cmpstrsi
4200 /* Try to call cmpstrsi. */
4201 if (HAVE_cmpstrsi)
4202 {
a0c938f0 4203 enum machine_mode insn_mode
6ac5504b 4204 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
4205
4206 /* Make a place to write the result of the instruction. */
4207 result = target;
4208 if (! (result != 0
4209 && REG_P (result) && GET_MODE (result) == insn_mode
4210 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4211 result = gen_reg_rtx (insn_mode);
4212
4213 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
4214 GEN_INT (MIN (arg1_align, arg2_align)));
4215 }
4216#endif
03fd9d2c 4217#ifdef HAVE_cmpstrnsi
6ac5504b 4218 /* Try to determine at least one length and call cmpstrnsi. */
a0c938f0 4219 if (!insn && HAVE_cmpstrnsi)
6ac5504b 4220 {
4221 tree len;
4222 rtx arg3_rtx;
4223
a0c938f0 4224 enum machine_mode insn_mode
6ac5504b 4225 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
4226 tree len1 = c_strlen (arg1, 1);
4227 tree len2 = c_strlen (arg2, 1);
4228
4229 if (len1)
4230 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
4231 if (len2)
4232 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
4233
4234 /* If we don't have a constant length for the first, use the length
4235 of the second, if we know it. We don't require a constant for
4236 this case; some cost analysis could be done if both are available
4237 but neither is constant. For now, assume they're equally cheap,
4238 unless one has side effects. If both strings have constant lengths,
4239 use the smaller. */
4240
4241 if (!len1)
4242 len = len2;
4243 else if (!len2)
4244 len = len1;
4245 else if (TREE_SIDE_EFFECTS (len1))
4246 len = len2;
4247 else if (TREE_SIDE_EFFECTS (len2))
4248 len = len1;
4249 else if (TREE_CODE (len1) != INTEGER_CST)
4250 len = len2;
4251 else if (TREE_CODE (len2) != INTEGER_CST)
4252 len = len1;
4253 else if (tree_int_cst_lt (len1, len2))
4254 len = len1;
4255 else
4256 len = len2;
4257
4258 /* If both arguments have side effects, we cannot optimize. */
4259 if (!len || TREE_SIDE_EFFECTS (len))
6b961939 4260 goto do_libcall;
53800dbe 4261
8ec3c5c2 4262 arg3_rtx = expand_normal (len);
902de8ed 4263
6ac5504b 4264 /* Make a place to write the result of the instruction. */
4265 result = target;
4266 if (! (result != 0
4267 && REG_P (result) && GET_MODE (result) == insn_mode
4268 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4269 result = gen_reg_rtx (insn_mode);
53800dbe 4270
6ac5504b 4271 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4272 GEN_INT (MIN (arg1_align, arg2_align)));
4273 }
4274#endif
3f8aefe2 4275
6ac5504b 4276 if (insn)
4277 {
4278 emit_insn (insn);
3f8aefe2 4279
6ac5504b 4280 /* Return the value in the proper mode for this function. */
4281 mode = TYPE_MODE (TREE_TYPE (exp));
4282 if (GET_MODE (result) == mode)
4283 return result;
4284 if (target == 0)
4285 return convert_to_mode (mode, result, 0);
4286 convert_move (target, result, 0);
4287 return target;
4288 }
902de8ed 4289
6ac5504b 4290 /* Expand the library call ourselves using a stabilized argument
4291 list to avoid re-evaluating the function's arguments twice. */
2694880e 4292#ifdef HAVE_cmpstrnsi
6b961939 4293 do_libcall:
2694880e 4294#endif
6ac5504b 4295 fndecl = get_callee_fndecl (exp);
c2f47e15 4296 fn = build_call_expr (fndecl, 2, arg1, arg2);
6ac5504b 4297 if (TREE_CODE (fn) == CALL_EXPR)
4298 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4299 return expand_call (fn, target, target == const0_rtx);
4300 }
7a3f89b5 4301#endif
c2f47e15 4302 return NULL_RTX;
83d79705 4303}
53800dbe 4304
c2f47e15 4305/* Expand expression EXP, which is a call to the strncmp builtin. Return
4306 NULL_RTX if we failed the caller should emit a normal call, otherwise try to get
ed09096d 4307 the result in TARGET, if convenient. */
27d0c333 4308
ed09096d 4309static rtx
aecda0d6 4310expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
ed09096d 4311{
c2f47e15 4312 if (!validate_arglist (exp,
4313 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4314 return NULL_RTX;
218bc19e 4315 else
ef6c187e 4316 {
c2f47e15 4317 tree result = fold_builtin_strncmp (CALL_EXPR_ARG (exp, 0),
4318 CALL_EXPR_ARG (exp, 1),
4319 CALL_EXPR_ARG (exp, 2));
218bc19e 4320 if (result)
4321 return expand_expr (result, target, mode, EXPAND_NORMAL);
ef6c187e 4322 }
ed09096d 4323
6e34e617 4324 /* If c_strlen can determine an expression for one of the string
6ac5504b 4325 lengths, and it doesn't have side effects, then emit cmpstrnsi
7a3f89b5 4326 using length MIN(strlen(string)+1, arg3). */
6ac5504b 4327#ifdef HAVE_cmpstrnsi
4328 if (HAVE_cmpstrnsi)
7a3f89b5 4329 {
4330 tree len, len1, len2;
4331 rtx arg1_rtx, arg2_rtx, arg3_rtx;
4332 rtx result, insn;
0b25db21 4333 tree fndecl, fn;
c2f47e15 4334 tree arg1 = CALL_EXPR_ARG (exp, 0);
4335 tree arg2 = CALL_EXPR_ARG (exp, 1);
4336 tree arg3 = CALL_EXPR_ARG (exp, 2);
6f428e8b 4337
7a3f89b5 4338 int arg1_align
4339 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4340 int arg2_align
4341 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4342 enum machine_mode insn_mode
6ac5504b 4343 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
bf8e3599 4344
681fab1e 4345 len1 = c_strlen (arg1, 1);
4346 len2 = c_strlen (arg2, 1);
7a3f89b5 4347
4348 if (len1)
4349 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
4350 if (len2)
4351 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
4352
4353 /* If we don't have a constant length for the first, use the length
4354 of the second, if we know it. We don't require a constant for
4355 this case; some cost analysis could be done if both are available
4356 but neither is constant. For now, assume they're equally cheap,
4357 unless one has side effects. If both strings have constant lengths,
4358 use the smaller. */
4359
4360 if (!len1)
4361 len = len2;
4362 else if (!len2)
4363 len = len1;
4364 else if (TREE_SIDE_EFFECTS (len1))
4365 len = len2;
4366 else if (TREE_SIDE_EFFECTS (len2))
4367 len = len1;
4368 else if (TREE_CODE (len1) != INTEGER_CST)
4369 len = len2;
4370 else if (TREE_CODE (len2) != INTEGER_CST)
4371 len = len1;
4372 else if (tree_int_cst_lt (len1, len2))
4373 len = len1;
4374 else
4375 len = len2;
6e34e617 4376
7a3f89b5 4377 /* If both arguments have side effects, we cannot optimize. */
4378 if (!len || TREE_SIDE_EFFECTS (len))
c2f47e15 4379 return NULL_RTX;
bf8e3599 4380
7a3f89b5 4381 /* The actual new length parameter is MIN(len,arg3). */
49d00087 4382 len = fold_build2 (MIN_EXPR, TREE_TYPE (len), len,
4383 fold_convert (TREE_TYPE (len), arg3));
7a3f89b5 4384
4385 /* If we don't have POINTER_TYPE, call the function. */
4386 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4387 return NULL_RTX;
7a3f89b5 4388
4389 /* Make a place to write the result of the instruction. */
4390 result = target;
4391 if (! (result != 0
8ad4c111 4392 && REG_P (result) && GET_MODE (result) == insn_mode
7a3f89b5 4393 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4394 result = gen_reg_rtx (insn_mode);
4395
6ac5504b 4396 /* Stabilize the arguments in case gen_cmpstrnsi fails. */
4ee9c684 4397 arg1 = builtin_save_expr (arg1);
4398 arg2 = builtin_save_expr (arg2);
4399 len = builtin_save_expr (len);
3f8aefe2 4400
d8ae1baa 4401 arg1_rtx = get_memory_rtx (arg1, len);
4402 arg2_rtx = get_memory_rtx (arg2, len);
8ec3c5c2 4403 arg3_rtx = expand_normal (len);
6ac5504b 4404 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4405 GEN_INT (MIN (arg1_align, arg2_align)));
3f8aefe2 4406 if (insn)
4407 {
4408 emit_insn (insn);
4409
4410 /* Return the value in the proper mode for this function. */
4411 mode = TYPE_MODE (TREE_TYPE (exp));
4412 if (GET_MODE (result) == mode)
4413 return result;
4414 if (target == 0)
4415 return convert_to_mode (mode, result, 0);
4416 convert_move (target, result, 0);
4417 return target;
4418 }
7a3f89b5 4419
3f8aefe2 4420 /* Expand the library call ourselves using a stabilized argument
4421 list to avoid re-evaluating the function's arguments twice. */
3f8aefe2 4422 fndecl = get_callee_fndecl (exp);
c2f47e15 4423 fn = build_call_expr (fndecl, 3, arg1, arg2, len);
0b25db21 4424 if (TREE_CODE (fn) == CALL_EXPR)
4425 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4426 return expand_call (fn, target, target == const0_rtx);
7a3f89b5 4427 }
4428#endif
c2f47e15 4429 return NULL_RTX;
ed09096d 4430}
4431
49f0327b 4432/* Expand expression EXP, which is a call to the strcat builtin.
c2f47e15 4433 Return NULL_RTX if we failed the caller should emit a normal call,
49f0327b 4434 otherwise try to get the result in TARGET, if convenient. */
27d0c333 4435
49f0327b 4436static rtx
c2f47e15 4437expand_builtin_strcat (tree fndecl, tree exp, rtx target, enum machine_mode mode)
49f0327b 4438{
c2f47e15 4439 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4440 return NULL_RTX;
49f0327b 4441 else
4442 {
c2f47e15 4443 tree dst = CALL_EXPR_ARG (exp, 0);
4444 tree src = CALL_EXPR_ARG (exp, 1);
49f0327b 4445 const char *p = c_getstr (src);
4446
1d89860b 4447 /* If the string length is zero, return the dst parameter. */
a0c938f0 4448 if (p && *p == '\0')
1d89860b 4449 return expand_expr (dst, target, mode, EXPAND_NORMAL);
a0c938f0 4450
1d89860b 4451 if (!optimize_size)
ca71f89b 4452 {
1d89860b 4453 /* See if we can store by pieces into (dst + strlen(dst)). */
4454 tree newsrc, newdst,
4455 strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
4456 rtx insns;
4457
4458 /* Stabilize the argument list. */
4459 newsrc = builtin_save_expr (src);
1d89860b 4460 dst = builtin_save_expr (dst);
4461
4462 start_sequence ();
4463
4464 /* Create strlen (dst). */
c2f47e15 4465 newdst = build_call_expr (strlen_fn, 1, dst);
0de36bdb 4466 /* Create (dst p+ strlen (dst)). */
1d89860b 4467
0de36bdb 4468 newdst = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
1d89860b 4469 newdst = builtin_save_expr (newdst);
1d89860b 4470
c2f47e15 4471 if (!expand_builtin_strcpy_args (fndecl, newdst, newsrc, target, mode))
ca71f89b 4472 {
1d89860b 4473 end_sequence (); /* Stop sequence. */
c2f47e15 4474 return NULL_RTX;
ca71f89b 4475 }
a0c938f0 4476
1d89860b 4477 /* Output the entire sequence. */
4478 insns = get_insns ();
4479 end_sequence ();
4480 emit_insn (insns);
a0c938f0 4481
1d89860b 4482 return expand_expr (dst, target, mode, EXPAND_NORMAL);
ca71f89b 4483 }
49f0327b 4484
c2f47e15 4485 return NULL_RTX;
49f0327b 4486 }
4487}
4488
4489/* Expand expression EXP, which is a call to the strncat builtin.
c2f47e15 4490 Return NULL_RTX if we failed the caller should emit a normal call,
49f0327b 4491 otherwise try to get the result in TARGET, if convenient. */
27d0c333 4492
49f0327b 4493static rtx
c2f47e15 4494expand_builtin_strncat (tree exp, rtx target, enum machine_mode mode)
49f0327b 4495{
c2f47e15 4496 if (validate_arglist (exp,
4497 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
49f0327b 4498 {
c2f47e15 4499 tree result = fold_builtin_strncat (CALL_EXPR_ARG (exp, 0),
4500 CALL_EXPR_ARG (exp, 1),
4501 CALL_EXPR_ARG (exp, 2));
2c84ee37 4502 if (result)
4503 return expand_expr (result, target, mode, EXPAND_NORMAL);
49f0327b 4504 }
c2f47e15 4505 return NULL_RTX;
49f0327b 4506}
4507
4508/* Expand expression EXP, which is a call to the strspn builtin.
c2f47e15 4509 Return NULL_RTX if we failed the caller should emit a normal call,
49f0327b 4510 otherwise try to get the result in TARGET, if convenient. */
27d0c333 4511
49f0327b 4512static rtx
c2f47e15 4513expand_builtin_strspn (tree exp, rtx target, enum machine_mode mode)
49f0327b 4514{
c2f47e15 4515 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
49f0327b 4516 {
c2f47e15 4517 tree result = fold_builtin_strspn (CALL_EXPR_ARG (exp, 0),
4518 CALL_EXPR_ARG (exp, 1));
2c84ee37 4519 if (result)
4520 return expand_expr (result, target, mode, EXPAND_NORMAL);
49f0327b 4521 }
c2f47e15 4522 return NULL_RTX;
49f0327b 4523}
4524
4525/* Expand expression EXP, which is a call to the strcspn builtin.
c2f47e15 4526 Return NULL_RTX if we failed the caller should emit a normal call,
49f0327b 4527 otherwise try to get the result in TARGET, if convenient. */
27d0c333 4528
49f0327b 4529static rtx
c2f47e15 4530expand_builtin_strcspn (tree exp, rtx target, enum machine_mode mode)
49f0327b 4531{
c2f47e15 4532 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
49f0327b 4533 {
c2f47e15 4534 tree result = fold_builtin_strcspn (CALL_EXPR_ARG (exp, 0),
4535 CALL_EXPR_ARG (exp, 1));
2c84ee37 4536 if (result)
4537 return expand_expr (result, target, mode, EXPAND_NORMAL);
49f0327b 4538 }
c2f47e15 4539 return NULL_RTX;
49f0327b 4540}
4541
a66c9326 4542/* Expand a call to __builtin_saveregs, generating the result in TARGET,
4543 if that's convenient. */
902de8ed 4544
a66c9326 4545rtx
aecda0d6 4546expand_builtin_saveregs (void)
53800dbe 4547{
a66c9326 4548 rtx val, seq;
53800dbe 4549
4550 /* Don't do __builtin_saveregs more than once in a function.
4551 Save the result of the first call and reuse it. */
4552 if (saveregs_value != 0)
4553 return saveregs_value;
53800dbe 4554
a66c9326 4555 /* When this function is called, it means that registers must be
4556 saved on entry to this function. So we migrate the call to the
4557 first insn of this function. */
4558
4559 start_sequence ();
53800dbe 4560
a66c9326 4561 /* Do whatever the machine needs done in this case. */
45550790 4562 val = targetm.calls.expand_builtin_saveregs ();
53800dbe 4563
a66c9326 4564 seq = get_insns ();
4565 end_sequence ();
53800dbe 4566
a66c9326 4567 saveregs_value = val;
53800dbe 4568
31d3e01c 4569 /* Put the insns after the NOTE that starts the function. If this
4570 is inside a start_sequence, make the outer-level insn chain current, so
a66c9326 4571 the code is placed at the start of the function. */
4572 push_topmost_sequence ();
0ec80471 4573 emit_insn_after (seq, entry_of_function ());
a66c9326 4574 pop_topmost_sequence ();
4575
4576 return val;
53800dbe 4577}
4578
4579/* __builtin_args_info (N) returns word N of the arg space info
4580 for the current function. The number and meanings of words
4581 is controlled by the definition of CUMULATIVE_ARGS. */
f7c44134 4582
53800dbe 4583static rtx
c2f47e15 4584expand_builtin_args_info (tree exp)
53800dbe 4585{
53800dbe 4586 int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
4587 int *word_ptr = (int *) &current_function_args_info;
53800dbe 4588
64db345d 4589 gcc_assert (sizeof (CUMULATIVE_ARGS) % sizeof (int) == 0);
53800dbe 4590
c2f47e15 4591 if (call_expr_nargs (exp) != 0)
53800dbe 4592 {
c2f47e15 4593 if (!host_integerp (CALL_EXPR_ARG (exp, 0), 0))
eb586f2c 4594 error ("argument of %<__builtin_args_info%> must be constant");
53800dbe 4595 else
4596 {
c2f47e15 4597 HOST_WIDE_INT wordnum = tree_low_cst (CALL_EXPR_ARG (exp, 0), 0);
53800dbe 4598
27d0c333 4599 if (wordnum < 0 || wordnum >= nwords)
eb586f2c 4600 error ("argument of %<__builtin_args_info%> out of range");
53800dbe 4601 else
4602 return GEN_INT (word_ptr[wordnum]);
4603 }
4604 }
4605 else
eb586f2c 4606 error ("missing argument in %<__builtin_args_info%>");
53800dbe 4607
4608 return const0_rtx;
53800dbe 4609}
4610
79012a9d 4611/* Expand a call to __builtin_next_arg. */
27d0c333 4612
53800dbe 4613static rtx
79012a9d 4614expand_builtin_next_arg (void)
53800dbe 4615{
79012a9d 4616 /* Checking arguments is already done in fold_builtin_next_arg
4617 that must be called before this function. */
940ddc5c 4618 return expand_binop (ptr_mode, add_optab,
53800dbe 4619 current_function_internal_arg_pointer,
4620 current_function_arg_offset_rtx,
4621 NULL_RTX, 0, OPTAB_LIB_WIDEN);
4622}
4623
a66c9326 4624/* Make it easier for the backends by protecting the valist argument
4625 from multiple evaluations. */
4626
4627static tree
aecda0d6 4628stabilize_va_list (tree valist, int needs_lvalue)
a66c9326 4629{
11a61dea 4630 if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
a66c9326 4631 {
2d47cc32 4632 if (TREE_SIDE_EFFECTS (valist))
4633 valist = save_expr (valist);
11a61dea 4634
2d47cc32 4635 /* For this case, the backends will be expecting a pointer to
4636 TREE_TYPE (va_list_type_node), but it's possible we've
4637 actually been given an array (an actual va_list_type_node).
4638 So fix it. */
4639 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
8a15c04a 4640 {
bf8e3599 4641 tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
fcdd3ab3 4642 valist = build_fold_addr_expr_with_type (valist, p1);
8a15c04a 4643 }
a66c9326 4644 }
11a61dea 4645 else
a66c9326 4646 {
2d47cc32 4647 tree pt;
11a61dea 4648
2d47cc32 4649 if (! needs_lvalue)
4650 {
11a61dea 4651 if (! TREE_SIDE_EFFECTS (valist))
4652 return valist;
bf8e3599 4653
11a61dea 4654 pt = build_pointer_type (va_list_type_node);
49d00087 4655 valist = fold_build1 (ADDR_EXPR, pt, valist);
a66c9326 4656 TREE_SIDE_EFFECTS (valist) = 1;
a66c9326 4657 }
2d47cc32 4658
11a61dea 4659 if (TREE_SIDE_EFFECTS (valist))
2d47cc32 4660 valist = save_expr (valist);
fcdd3ab3 4661 valist = build_fold_indirect_ref (valist);
a66c9326 4662 }
4663
4664 return valist;
4665}
4666
2e15d750 4667/* The "standard" definition of va_list is void*. */
4668
4669tree
4670std_build_builtin_va_list (void)
4671{
4672 return ptr_type_node;
4673}
4674
a66c9326 4675/* The "standard" implementation of va_start: just assign `nextarg' to
4676 the variable. */
27d0c333 4677
a66c9326 4678void
aecda0d6 4679std_expand_builtin_va_start (tree valist, rtx nextarg)
a66c9326 4680{
f03c17bc 4681 rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
4682 convert_move (va_r, nextarg, 0);
a66c9326 4683}
4684
c2f47e15 4685/* Expand EXP, a call to __builtin_va_start. */
27d0c333 4686
a66c9326 4687static rtx
c2f47e15 4688expand_builtin_va_start (tree exp)
a66c9326 4689{
4690 rtx nextarg;
c2f47e15 4691 tree valist;
a66c9326 4692
c2f47e15 4693 if (call_expr_nargs (exp) < 2)
cb166087 4694 {
4695 error ("too few arguments to function %<va_start%>");
4696 return const0_rtx;
4697 }
a66c9326 4698
c2f47e15 4699 if (fold_builtin_next_arg (exp, true))
79012a9d 4700 return const0_rtx;
7c2f0500 4701
79012a9d 4702 nextarg = expand_builtin_next_arg ();
c2f47e15 4703 valist = stabilize_va_list (CALL_EXPR_ARG (exp, 0), 1);
a66c9326 4704
4705#ifdef EXPAND_BUILTIN_VA_START
7df226a2 4706 EXPAND_BUILTIN_VA_START (valist, nextarg);
a66c9326 4707#else
7df226a2 4708 std_expand_builtin_va_start (valist, nextarg);
a66c9326 4709#endif
4710
4711 return const0_rtx;
4712}
4713
a66c9326 4714/* The "standard" implementation of va_arg: read the value from the
4715 current (padded) address and increment by the (padded) size. */
f7c44134 4716
e0eca1fa 4717tree
4718std_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
fcdd3ab3 4719{
52cc2eeb 4720 tree addr, t, type_size, rounded_size, valist_tmp;
b8e8e485 4721 unsigned HOST_WIDE_INT align, boundary;
bef380a4 4722 bool indirect;
52cc2eeb 4723
4724#ifdef ARGS_GROW_DOWNWARD
4725 /* All of the alignment and movement below is for args-grow-up machines.
4726 As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
4727 implement their own specialized gimplify_va_arg_expr routines. */
64db345d 4728 gcc_unreachable ();
52cc2eeb 4729#endif
fcdd3ab3 4730
bef380a4 4731 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
4732 if (indirect)
4733 type = build_pointer_type (type);
4734
52cc2eeb 4735 align = PARM_BOUNDARY / BITS_PER_UNIT;
bcff3604 4736 boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type) / BITS_PER_UNIT;
fcdd3ab3 4737
52cc2eeb 4738 /* Hoist the valist value into a temporary for the moment. */
ecdeeb37 4739 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
4740
fcdd3ab3 4741 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
4742 requires greater alignment, we must perform dynamic alignment. */
85c1f587 4743 if (boundary > align
4744 && !integer_zerop (TYPE_SIZE (type)))
fcdd3ab3 4745 {
41076ef6 4746 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
0de36bdb 4747 fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (valist),
4748 valist_tmp, size_int (boundary - 1)));
52cc2eeb 4749 gimplify_and_add (t, pre_p);
4750
0de36bdb 4751 t = fold_convert (sizetype, valist_tmp);
41076ef6 4752 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
0de36bdb 4753 fold_convert (TREE_TYPE (valist),
4754 fold_build2 (BIT_AND_EXPR, sizetype, t,
4755 size_int (-boundary))));
ecdeeb37 4756 gimplify_and_add (t, pre_p);
fcdd3ab3 4757 }
c5dc0c32 4758 else
4759 boundary = align;
4760
4761 /* If the actual alignment is less than the alignment of the type,
4762 adjust the type accordingly so that we don't assume strict alignment
4763 when deferencing the pointer. */
4764 boundary *= BITS_PER_UNIT;
4765 if (boundary < TYPE_ALIGN (type))
4766 {
4767 type = build_variant_type_copy (type);
4768 TYPE_ALIGN (type) = boundary;
4769 }
fcdd3ab3 4770
bcff3604 4771 /* Compute the rounded size of the type. */
52cc2eeb 4772 type_size = size_in_bytes (type);
4773 rounded_size = round_up (type_size, align);
4774
fcdd3ab3 4775 /* Reduce rounded_size so it's sharable with the postqueue. */
4776 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
4777
4778 /* Get AP. */
ecdeeb37 4779 addr = valist_tmp;
52cc2eeb 4780 if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
fcdd3ab3 4781 {
4782 /* Small args are padded downward. */
49d00087 4783 t = fold_build2 (GT_EXPR, sizetype, rounded_size, size_int (align));
4784 t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
4785 size_binop (MINUS_EXPR, rounded_size, type_size));
0de36bdb 4786 addr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (addr), addr, t);
fcdd3ab3 4787 }
4788
fcdd3ab3 4789 /* Compute new value for AP. */
0de36bdb 4790 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (valist), valist_tmp, rounded_size);
41076ef6 4791 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
ecdeeb37 4792 gimplify_and_add (t, pre_p);
e0eca1fa 4793
4794 addr = fold_convert (build_pointer_type (type), addr);
fcdd3ab3 4795
bef380a4 4796 if (indirect)
f2462d6c 4797 addr = build_va_arg_indirect_ref (addr);
4798
4799 return build_va_arg_indirect_ref (addr);
4800}
a0930a69 4801
f2462d6c 4802/* Build an indirect-ref expression over the given TREE, which represents a
4803 piece of a va_arg() expansion. */
4804tree
4805build_va_arg_indirect_ref (tree addr)
4806{
a0930a69 4807 addr = build_fold_indirect_ref (addr);
f2462d6c 4808
a0930a69 4809 if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */
4810 mf_mark (addr);
bef380a4 4811
a0930a69 4812 return addr;
433006a9 4813}
4814
fcdd3ab3 4815/* Return a dummy expression of type TYPE in order to keep going after an
4816 error. */
4817
4818static tree
4819dummy_object (tree type)
4820{
535664e3 4821 tree t = build_int_cst (build_pointer_type (type), 0);
fcdd3ab3 4822 return build1 (INDIRECT_REF, type, t);
4823}
4824
2799a2b7 4825/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
4826 builtin function, but a very special sort of operator. */
fcdd3ab3 4827
4828enum gimplify_status
4829gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p)
4830{
4831 tree promoted_type, want_va_type, have_va_type;
4832 tree valist = TREE_OPERAND (*expr_p, 0);
4833 tree type = TREE_TYPE (*expr_p);
4834 tree t;
4835
4836 /* Verify that valist is of the proper type. */
fcdd3ab3 4837 want_va_type = va_list_type_node;
4838 have_va_type = TREE_TYPE (valist);
f43dda35 4839
4840 if (have_va_type == error_mark_node)
4841 return GS_ERROR;
4842
fcdd3ab3 4843 if (TREE_CODE (want_va_type) == ARRAY_TYPE)
4844 {
4845 /* If va_list is an array type, the argument may have decayed
4846 to a pointer type, e.g. by being passed to another function.
a0c938f0 4847 In that case, unwrap both types so that we can compare the
fcdd3ab3 4848 underlying records. */
4849 if (TREE_CODE (have_va_type) == ARRAY_TYPE
552752f7 4850 || POINTER_TYPE_P (have_va_type))
fcdd3ab3 4851 {
4852 want_va_type = TREE_TYPE (want_va_type);
4853 have_va_type = TREE_TYPE (have_va_type);
4854 }
4855 }
4856
4857 if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
4858 {
eb586f2c 4859 error ("first argument to %<va_arg%> not of type %<va_list%>");
e0eca1fa 4860 return GS_ERROR;
fcdd3ab3 4861 }
4862
4863 /* Generate a diagnostic for requesting data of a type that cannot
4864 be passed through `...' due to type promotion at the call site. */
4865 else if ((promoted_type = lang_hooks.types.type_promotes_to (type))
4866 != type)
4867 {
4868 static bool gave_help;
4869
4870 /* Unfortunately, this is merely undefined, rather than a constraint
4871 violation, so we cannot make this an error. If this call is never
4872 executed, the program is still strictly conforming. */
c3ceba8e 4873 warning (0, "%qT is promoted to %qT when passed through %<...%>",
fcdd3ab3 4874 type, promoted_type);
4875 if (! gave_help)
4876 {
4877 gave_help = true;
2006d7dc 4878 inform ("(so you should pass %qT not %qT to %<va_arg%>)",
fcdd3ab3 4879 promoted_type, type);
4880 }
4881
4882 /* We can, however, treat "undefined" any way we please.
4883 Call abort to encourage the user to fix the program. */
4884 inform ("if this code is reached, the program will abort");
c2f47e15 4885 t = build_call_expr (implicit_built_in_decls[BUILT_IN_TRAP], 0);
fcdd3ab3 4886 append_to_statement_list (t, pre_p);
4887
4888 /* This is dead code, but go ahead and finish so that the
4889 mode of the result comes out right. */
4890 *expr_p = dummy_object (type);
4891 return GS_ALL_DONE;
4892 }
4893 else
4894 {
4895 /* Make it easier for the backends by protecting the valist argument
a0c938f0 4896 from multiple evaluations. */
e0eca1fa 4897 if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
4898 {
4899 /* For this case, the backends will be expecting a pointer to
4900 TREE_TYPE (va_list_type_node), but it's possible we've
4901 actually been given an array (an actual va_list_type_node).
4902 So fix it. */
4903 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
4904 {
4905 tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
4906 valist = build_fold_addr_expr_with_type (valist, p1);
4907 }
4908 gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
4909 }
4910 else
4911 gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
fcdd3ab3 4912
17a6380d 4913 if (!targetm.gimplify_va_arg_expr)
89f18f73 4914 /* FIXME:Once most targets are converted we should merely
4915 assert this is non-null. */
fcdd3ab3 4916 return GS_ALL_DONE;
4917
17a6380d 4918 *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
fcdd3ab3 4919 return GS_OK;
4920 }
4921}
4922
c2f47e15 4923/* Expand EXP, a call to __builtin_va_end. */
f7c44134 4924
a66c9326 4925static rtx
c2f47e15 4926expand_builtin_va_end (tree exp)
a66c9326 4927{
c2f47e15 4928 tree valist = CALL_EXPR_ARG (exp, 0);
8a15c04a 4929
8a15c04a 4930 /* Evaluate for side effects, if needed. I hate macros that don't
4931 do that. */
4932 if (TREE_SIDE_EFFECTS (valist))
4933 expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
a66c9326 4934
4935 return const0_rtx;
4936}
4937
c2f47e15 4938/* Expand EXP, a call to __builtin_va_copy. We do this as a
a66c9326 4939 builtin rather than just as an assignment in stdarg.h because of the
4940 nastiness of array-type va_list types. */
f7c44134 4941
a66c9326 4942static rtx
c2f47e15 4943expand_builtin_va_copy (tree exp)
a66c9326 4944{
4945 tree dst, src, t;
4946
c2f47e15 4947 dst = CALL_EXPR_ARG (exp, 0);
4948 src = CALL_EXPR_ARG (exp, 1);
a66c9326 4949
4950 dst = stabilize_va_list (dst, 1);
4951 src = stabilize_va_list (src, 0);
4952
4953 if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
4954 {
41076ef6 4955 t = build2 (MODIFY_EXPR, va_list_type_node, dst, src);
a66c9326 4956 TREE_SIDE_EFFECTS (t) = 1;
4957 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4958 }
4959 else
4960 {
11a61dea 4961 rtx dstb, srcb, size;
4962
4963 /* Evaluate to pointers. */
4964 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
4965 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
4966 size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
4967 VOIDmode, EXPAND_NORMAL);
4968
85d654dd 4969 dstb = convert_memory_address (Pmode, dstb);
4970 srcb = convert_memory_address (Pmode, srcb);
726ec87c 4971
11a61dea 4972 /* "Dereference" to BLKmode memories. */
4973 dstb = gen_rtx_MEM (BLKmode, dstb);
ab6ab77e 4974 set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
2a631e19 4975 set_mem_align (dstb, TYPE_ALIGN (va_list_type_node));
11a61dea 4976 srcb = gen_rtx_MEM (BLKmode, srcb);
ab6ab77e 4977 set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
2a631e19 4978 set_mem_align (srcb, TYPE_ALIGN (va_list_type_node));
11a61dea 4979
4980 /* Copy. */
0378dbdc 4981 emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
a66c9326 4982 }
4983
4984 return const0_rtx;
4985}
4986
53800dbe 4987/* Expand a call to one of the builtin functions __builtin_frame_address or
4988 __builtin_return_address. */
27d0c333 4989
53800dbe 4990static rtx
c2f47e15 4991expand_builtin_frame_address (tree fndecl, tree exp)
53800dbe 4992{
53800dbe 4993 /* The argument must be a nonnegative integer constant.
4994 It counts the number of frames to scan up the stack.
4995 The value is the return address saved in that frame. */
c2f47e15 4996 if (call_expr_nargs (exp) == 0)
53800dbe 4997 /* Warning about missing arg was already issued. */
4998 return const0_rtx;
c2f47e15 4999 else if (! host_integerp (CALL_EXPR_ARG (exp, 0), 1))
53800dbe 5000 {
5001 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
07e3a3d2 5002 error ("invalid argument to %<__builtin_frame_address%>");
53800dbe 5003 else
07e3a3d2 5004 error ("invalid argument to %<__builtin_return_address%>");
53800dbe 5005 return const0_rtx;
5006 }
5007 else
5008 {
27d0c333 5009 rtx tem
5010 = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
c2f47e15 5011 tree_low_cst (CALL_EXPR_ARG (exp, 0), 1));
53800dbe 5012
5013 /* Some ports cannot access arbitrary stack frames. */
5014 if (tem == NULL)
5015 {
5016 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
c3ceba8e 5017 warning (0, "unsupported argument to %<__builtin_frame_address%>");
53800dbe 5018 else
c3ceba8e 5019 warning (0, "unsupported argument to %<__builtin_return_address%>");
53800dbe 5020 return const0_rtx;
5021 }
5022
5023 /* For __builtin_frame_address, return what we've got. */
5024 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
5025 return tem;
5026
8ad4c111 5027 if (!REG_P (tem)
53800dbe 5028 && ! CONSTANT_P (tem))
5029 tem = copy_to_mode_reg (Pmode, tem);
5030 return tem;
5031 }
5032}
5033
c2f47e15 5034/* Expand EXP, a call to the alloca builtin. Return NULL_RTX if
53800dbe 5035 we failed and the caller should emit a normal call, otherwise try to get
5036 the result in TARGET, if convenient. */
15c6cf6b 5037
53800dbe 5038static rtx
c2f47e15 5039expand_builtin_alloca (tree exp, rtx target)
53800dbe 5040{
5041 rtx op0;
15c6cf6b 5042 rtx result;
53800dbe 5043
4ee9c684 5044 /* In -fmudflap-instrumented code, alloca() and __builtin_alloca()
5045 should always expand to function calls. These can be intercepted
5046 in libmudflap. */
5047 if (flag_mudflap)
c2f47e15 5048 return NULL_RTX;
4ee9c684 5049
c2f47e15 5050 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
5051 return NULL_RTX;
53800dbe 5052
5053 /* Compute the argument. */
c2f47e15 5054 op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
53800dbe 5055
5056 /* Allocate the desired space. */
15c6cf6b 5057 result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
85d654dd 5058 result = convert_memory_address (ptr_mode, result);
15c6cf6b 5059
5060 return result;
53800dbe 5061}
5062
c2f47e15 5063/* Expand a call to a bswap builtin with argument ARG0. MODE
42791117 5064 is the mode to expand with. */
5065
5066static rtx
c2f47e15 5067expand_builtin_bswap (tree exp, rtx target, rtx subtarget)
42791117 5068{
5069 enum machine_mode mode;
5070 tree arg;
5071 rtx op0;
5072
c2f47e15 5073 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
5074 return NULL_RTX;
42791117 5075
c2f47e15 5076 arg = CALL_EXPR_ARG (exp, 0);
42791117 5077 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 5078 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
42791117 5079
5080 target = expand_unop (mode, bswap_optab, op0, target, 1);
5081
5082 gcc_assert (target);
5083
5084 return convert_to_mode (mode, target, 0);
5085}
5086
c2f47e15 5087/* Expand a call to a unary builtin in EXP.
5088 Return NULL_RTX if a normal call should be emitted rather than expanding the
53800dbe 5089 function in-line. If convenient, the result should be placed in TARGET.
5090 SUBTARGET may be used as the target for computing one of EXP's operands. */
15c6cf6b 5091
53800dbe 5092static rtx
c2f47e15 5093expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target,
aecda0d6 5094 rtx subtarget, optab op_optab)
53800dbe 5095{
5096 rtx op0;
c2f47e15 5097
5098 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
5099 return NULL_RTX;
53800dbe 5100
5101 /* Compute the argument. */
1db6d067 5102 op0 = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
5103 VOIDmode, EXPAND_NORMAL);
6a08d0ab 5104 /* Compute op, into TARGET if possible.
53800dbe 5105 Set TARGET to wherever the result comes back. */
c2f47e15 5106 target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
6a08d0ab 5107 op_optab, op0, target, 1);
64db345d 5108 gcc_assert (target);
7d3f6cc7 5109
efb070c8 5110 return convert_to_mode (target_mode, target, 0);
53800dbe 5111}
89cfe6e5 5112
df94cd3b 5113/* If the string passed to fputs is a constant and is one character
2c0e001b 5114 long, we attempt to transform this call into __builtin_fputc(). */
15c6cf6b 5115
df94cd3b 5116static rtx
c2f47e15 5117expand_builtin_fputs (tree exp, rtx target, bool unlocked)
df94cd3b 5118{
2c0e001b 5119 /* Verify the arguments in the original call. */
c2f47e15 5120 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
ce1b14f4 5121 {
c2f47e15 5122 tree result = fold_builtin_fputs (CALL_EXPR_ARG (exp, 0),
5123 CALL_EXPR_ARG (exp, 1),
5124 (target == const0_rtx),
2c84ee37 5125 unlocked, NULL_TREE);
5126 if (result)
5127 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
ce1b14f4 5128 }
c2f47e15 5129 return NULL_RTX;
3311f67b 5130}
5131
5a74f77e 5132/* Expand a call to __builtin_expect. We just return our argument
5133 as the builtin_expect semantic should've been already executed by
5134 tree branch prediction pass. */
89cfe6e5 5135
5136static rtx
c2f47e15 5137expand_builtin_expect (tree exp, rtx target)
89cfe6e5 5138{
c2f47e15 5139 tree arg, c;
89cfe6e5 5140
c2f47e15 5141 if (call_expr_nargs (exp) < 2)
89cfe6e5 5142 return const0_rtx;
c2f47e15 5143 arg = CALL_EXPR_ARG (exp, 0);
5144 c = CALL_EXPR_ARG (exp, 1);
89cfe6e5 5145
c2f47e15 5146 target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5a74f77e 5147 /* When guessing was done, the hints should be already stripped away. */
07311427 5148 gcc_assert (!flag_guess_branch_prob
5149 || optimize == 0 || errorcount || sorrycount);
89cfe6e5 5150 return target;
5151}
689df48e 5152
c22de3f0 5153void
aecda0d6 5154expand_builtin_trap (void)
a0ef1725 5155{
5156#ifdef HAVE_trap
5157 if (HAVE_trap)
5158 emit_insn (gen_trap ());
5159 else
5160#endif
5161 emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
5162 emit_barrier ();
5163}
78a74442 5164
c2f47e15 5165/* Expand EXP, a call to fabs, fabsf or fabsl.
5166 Return NULL_RTX if a normal call should be emitted rather than expanding
78a74442 5167 the function inline. If convenient, the result should be placed
5168 in TARGET. SUBTARGET may be used as the target for computing
5169 the operand. */
5170
5171static rtx
c2f47e15 5172expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
78a74442 5173{
5174 enum machine_mode mode;
5175 tree arg;
5176 rtx op0;
5177
c2f47e15 5178 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
5179 return NULL_RTX;
78a74442 5180
c2f47e15 5181 arg = CALL_EXPR_ARG (exp, 0);
78a74442 5182 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 5183 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
78a74442 5184 return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
5185}
5186
c2f47e15 5187/* Expand EXP, a call to copysign, copysignf, or copysignl.
270436f3 5188 Return NULL is a normal call should be emitted rather than expanding the
5189 function inline. If convenient, the result should be placed in TARGET.
5190 SUBTARGET may be used as the target for computing the operand. */
5191
5192static rtx
c2f47e15 5193expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
270436f3 5194{
5195 rtx op0, op1;
5196 tree arg;
5197
c2f47e15 5198 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
5199 return NULL_RTX;
270436f3 5200
c2f47e15 5201 arg = CALL_EXPR_ARG (exp, 0);
8ec3c5c2 5202 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
270436f3 5203
c2f47e15 5204 arg = CALL_EXPR_ARG (exp, 1);
8ec3c5c2 5205 op1 = expand_normal (arg);
270436f3 5206
5207 return expand_copysign (op0, op1, target);
5208}
5209
19bf118a 5210/* Create a new constant string literal and return a char* pointer to it.
5211 The STRING_CST value is the LEN characters at STR. */
1e8e9920 5212tree
19bf118a 5213build_string_literal (int len, const char *str)
5214{
5215 tree t, elem, index, type;
5216
5217 t = build_string (len, str);
5218 elem = build_type_variant (char_type_node, 1, 0);
7016c612 5219 index = build_index_type (build_int_cst (NULL_TREE, len - 1));
19bf118a 5220 type = build_array_type (elem, index);
5221 TREE_TYPE (t) = type;
5222 TREE_CONSTANT (t) = 1;
4ee9c684 5223 TREE_INVARIANT (t) = 1;
19bf118a 5224 TREE_READONLY (t) = 1;
5225 TREE_STATIC (t) = 1;
5226
5227 type = build_pointer_type (type);
5228 t = build1 (ADDR_EXPR, type, t);
5229
5230 type = build_pointer_type (elem);
5231 t = build1 (NOP_EXPR, type, t);
5232 return t;
5233}
5234
0b25db21 5235/* Expand EXP, a call to printf or printf_unlocked.
c2f47e15 5236 Return NULL_RTX if a normal call should be emitted rather than transforming
19bf118a 5237 the function inline. If convenient, the result should be placed in
0862b7e9 5238 TARGET with mode MODE. UNLOCKED indicates this is a printf_unlocked
19bf118a 5239 call. */
5240static rtx
0b25db21 5241expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
19bf118a 5242 bool unlocked)
5243{
6d77ed92 5244 /* If we're using an unlocked function, assume the other unlocked
5245 functions exist explicitly. */
5246 tree const fn_putchar = unlocked ? built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
5247 : implicit_built_in_decls[BUILT_IN_PUTCHAR];
5248 tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED]
5249 : implicit_built_in_decls[BUILT_IN_PUTS];
19bf118a 5250 const char *fmt_str;
c2f47e15 5251 tree fn = 0;
5252 tree fmt, arg;
5253 int nargs = call_expr_nargs (exp);
19bf118a 5254
5255 /* If the return value is used, don't do the transformation. */
5256 if (target != const0_rtx)
c2f47e15 5257 return NULL_RTX;
19bf118a 5258
5259 /* Verify the required arguments in the original call. */
c2f47e15 5260 if (nargs == 0)
5261 return NULL_RTX;
5262 fmt = CALL_EXPR_ARG (exp, 0);
552752f7 5263 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
c2f47e15 5264 return NULL_RTX;
19bf118a 5265
5266 /* Check whether the format is a literal string constant. */
5267 fmt_str = c_getstr (fmt);
5268 if (fmt_str == NULL)
c2f47e15 5269 return NULL_RTX;
19bf118a 5270
d4473c84 5271 if (!init_target_chars ())
c2f47e15 5272 return NULL_RTX;
a0c938f0 5273
19bf118a 5274 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
99eabcc1 5275 if (strcmp (fmt_str, target_percent_s_newline) == 0)
19bf118a 5276 {
c2f47e15 5277 if ((nargs != 2)
5278 || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (exp, 1))))
5279 return NULL_RTX;
5280 if (fn_puts)
5281 fn = build_call_expr (fn_puts, 1, CALL_EXPR_ARG (exp, 1));
19bf118a 5282 }
5283 /* If the format specifier was "%c", call __builtin_putchar(arg). */
99eabcc1 5284 else if (strcmp (fmt_str, target_percent_c) == 0)
19bf118a 5285 {
c2f47e15 5286 if ((nargs != 2)
5287 || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1))) != INTEGER_TYPE)
5288 return NULL_RTX;
5289 if (fn_putchar)
5290 fn = build_call_expr (fn_putchar, 1, CALL_EXPR_ARG (exp, 1));
19bf118a 5291 }
5292 else
5293 {
5294 /* We can't handle anything else with % args or %% ... yet. */
99eabcc1 5295 if (strchr (fmt_str, target_percent))
c2f47e15 5296 return NULL_RTX;
19bf118a 5297
c2f47e15 5298 if (nargs > 1)
5299 return NULL_RTX;
19bf118a 5300
5301 /* If the format specifier was "", printf does nothing. */
5302 if (fmt_str[0] == '\0')
5303 return const0_rtx;
5304 /* If the format specifier has length of 1, call putchar. */
5305 if (fmt_str[1] == '\0')
5306 {
5307 /* Given printf("c"), (where c is any one character,)
5308 convert "c"[0] to an int and pass that to the replacement
5309 function. */
7016c612 5310 arg = build_int_cst (NULL_TREE, fmt_str[0]);
c2f47e15 5311 if (fn_putchar)
5312 fn = build_call_expr (fn_putchar, 1, arg);
19bf118a 5313 }
5314 else
5315 {
5316 /* If the format specifier was "string\n", call puts("string"). */
5317 size_t len = strlen (fmt_str);
99eabcc1 5318 if ((unsigned char)fmt_str[len - 1] == target_newline)
19bf118a 5319 {
91c82c20 5320 /* Create a NUL-terminated string that's one char shorter
19bf118a 5321 than the original, stripping off the trailing '\n'. */
4acc30e5 5322 char *newstr = alloca (len);
19bf118a 5323 memcpy (newstr, fmt_str, len - 1);
5324 newstr[len - 1] = 0;
19bf118a 5325 arg = build_string_literal (len, newstr);
c2f47e15 5326 if (fn_puts)
5327 fn = build_call_expr (fn_puts, 1, arg);
19bf118a 5328 }
5329 else
5330 /* We'd like to arrange to call fputs(string,stdout) here,
5331 but we need stdout and don't have a way to get it yet. */
c2f47e15 5332 return NULL_RTX;
19bf118a 5333 }
5334 }
5335
5336 if (!fn)
c2f47e15 5337 return NULL_RTX;
0b25db21 5338 if (TREE_CODE (fn) == CALL_EXPR)
5339 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
5340 return expand_expr (fn, target, mode, EXPAND_NORMAL);
19bf118a 5341}
5342
0b25db21 5343/* Expand EXP, a call to fprintf or fprintf_unlocked.
c2f47e15 5344 Return NULL_RTX if a normal call should be emitted rather than transforming
19bf118a 5345 the function inline. If convenient, the result should be placed in
0862b7e9 5346 TARGET with mode MODE. UNLOCKED indicates this is a fprintf_unlocked
19bf118a 5347 call. */
5348static rtx
0b25db21 5349expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
a0c938f0 5350 bool unlocked)
19bf118a 5351{
6d77ed92 5352 /* If we're using an unlocked function, assume the other unlocked
5353 functions exist explicitly. */
5354 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
5355 : implicit_built_in_decls[BUILT_IN_FPUTC];
5356 tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
5357 : implicit_built_in_decls[BUILT_IN_FPUTS];
19bf118a 5358 const char *fmt_str;
c2f47e15 5359 tree fn = 0;
5360 tree fmt, fp, arg;
5361 int nargs = call_expr_nargs (exp);
19bf118a 5362
5363 /* If the return value is used, don't do the transformation. */
5364 if (target != const0_rtx)
c2f47e15 5365 return NULL_RTX;
19bf118a 5366
5367 /* Verify the required arguments in the original call. */
c2f47e15 5368 if (nargs < 2)
5369 return NULL_RTX;
5370 fp = CALL_EXPR_ARG (exp, 0);
552752f7 5371 if (! POINTER_TYPE_P (TREE_TYPE (fp)))
c2f47e15 5372 return NULL_RTX;
5373 fmt = CALL_EXPR_ARG (exp, 1);
552752f7 5374 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
c2f47e15 5375 return NULL_RTX;
19bf118a 5376
5377 /* Check whether the format is a literal string constant. */
5378 fmt_str = c_getstr (fmt);
5379 if (fmt_str == NULL)
c2f47e15 5380 return NULL_RTX;
19bf118a 5381
d4473c84 5382 if (!init_target_chars ())
c2f47e15 5383 return NULL_RTX;
a0c938f0 5384
19bf118a 5385 /* If the format specifier was "%s", call __builtin_fputs(arg,fp). */
99eabcc1 5386 if (strcmp (fmt_str, target_percent_s) == 0)
19bf118a 5387 {
c2f47e15 5388 if ((nargs != 3)
5389 || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (exp, 2))))
5390 return NULL_RTX;
5391 arg = CALL_EXPR_ARG (exp, 2);
5392 if (fn_fputs)
5393 fn = build_call_expr (fn_fputs, 2, arg, fp);
19bf118a 5394 }
5395 /* If the format specifier was "%c", call __builtin_fputc(arg,fp). */
99eabcc1 5396 else if (strcmp (fmt_str, target_percent_c) == 0)
19bf118a 5397 {
c2f47e15 5398 if ((nargs != 3)
5399 || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2))) != INTEGER_TYPE)
5400 return NULL_RTX;
5401 arg = CALL_EXPR_ARG (exp, 2);
5402 if (fn_fputc)
5403 fn = build_call_expr (fn_fputc, 2, arg, fp);
19bf118a 5404 }
5405 else
5406 {
5407 /* We can't handle anything else with % args or %% ... yet. */
99eabcc1 5408 if (strchr (fmt_str, target_percent))
c2f47e15 5409 return NULL_RTX;
19bf118a 5410
c2f47e15 5411 if (nargs > 2)
5412 return NULL_RTX;
19bf118a 5413
5414 /* If the format specifier was "", fprintf does nothing. */
5415 if (fmt_str[0] == '\0')
5416 {
5417 /* Evaluate and ignore FILE* argument for side-effects. */
5418 expand_expr (fp, const0_rtx, VOIDmode, EXPAND_NORMAL);
5419 return const0_rtx;
5420 }
5421
5422 /* When "string" doesn't contain %, replace all cases of
5423 fprintf(stream,string) with fputs(string,stream). The fputs
5424 builtin will take care of special cases like length == 1. */
c2f47e15 5425 if (fn_fputs)
5426 fn = build_call_expr (fn_fputs, 2, fmt, fp);
19bf118a 5427 }
5428
5429 if (!fn)
c2f47e15 5430 return NULL_RTX;
0b25db21 5431 if (TREE_CODE (fn) == CALL_EXPR)
5432 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
5433 return expand_expr (fn, target, mode, EXPAND_NORMAL);
19bf118a 5434}
5435
c2f47e15 5436/* Expand a call EXP to sprintf. Return NULL_RTX if
6411575e 5437 a normal call should be emitted rather than expanding the function
5438 inline. If convenient, the result should be placed in TARGET with
5439 mode MODE. */
5440
5441static rtx
c2f47e15 5442expand_builtin_sprintf (tree exp, rtx target, enum machine_mode mode)
6411575e 5443{
c2f47e15 5444 tree dest, fmt;
a7a723f0 5445 const char *fmt_str;
c2f47e15 5446 int nargs = call_expr_nargs (exp);
6411575e 5447
5448 /* Verify the required arguments in the original call. */
c2f47e15 5449 if (nargs < 2)
5450 return NULL_RTX;
5451 dest = CALL_EXPR_ARG (exp, 0);
552752f7 5452 if (! POINTER_TYPE_P (TREE_TYPE (dest)))
c2f47e15 5453 return NULL_RTX;
5454 fmt = CALL_EXPR_ARG (exp, 0);
552752f7 5455 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
c2f47e15 5456 return NULL_RTX;
6411575e 5457
5458 /* Check whether the format is a literal string constant. */
a7a723f0 5459 fmt_str = c_getstr (fmt);
5460 if (fmt_str == NULL)
c2f47e15 5461 return NULL_RTX;
6411575e 5462
d4473c84 5463 if (!init_target_chars ())
c2f47e15 5464 return NULL_RTX;
99eabcc1 5465
6411575e 5466 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 5467 if (strchr (fmt_str, target_percent) == 0)
6411575e 5468 {
5469 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
5470 tree exp;
5471
c2f47e15 5472 if ((nargs > 2) || ! fn)
5473 return NULL_RTX;
5474 expand_expr (build_call_expr (fn, 2, dest, fmt),
6411575e 5475 const0_rtx, VOIDmode, EXPAND_NORMAL);
5476 if (target == const0_rtx)
5477 return const0_rtx;
7016c612 5478 exp = build_int_cst (NULL_TREE, strlen (fmt_str));
6411575e 5479 return expand_expr (exp, target, mode, EXPAND_NORMAL);
5480 }
a7a723f0 5481 /* If the format is "%s", use strcpy if the result isn't used. */
99eabcc1 5482 else if (strcmp (fmt_str, target_percent_s) == 0)
6411575e 5483 {
a7a723f0 5484 tree fn, arg, len;
5485 fn = implicit_built_in_decls[BUILT_IN_STRCPY];
6411575e 5486
a7a723f0 5487 if (! fn)
c2f47e15 5488 return NULL_RTX;
5489 if (nargs != 3)
5490 return NULL_RTX;
5491 arg = CALL_EXPR_ARG (exp, 2);
552752f7 5492 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
c2f47e15 5493 return NULL_RTX;
6411575e 5494
5495 if (target != const0_rtx)
5496 {
681fab1e 5497 len = c_strlen (arg, 1);
a7a723f0 5498 if (! len || TREE_CODE (len) != INTEGER_CST)
c2f47e15 5499 return NULL_RTX;
6411575e 5500 }
5501 else
a7a723f0 5502 len = NULL_TREE;
6411575e 5503
c2f47e15 5504 expand_expr (build_call_expr (fn, 2, dest, arg),
6411575e 5505 const0_rtx, VOIDmode, EXPAND_NORMAL);
5506
5507 if (target == const0_rtx)
5508 return const0_rtx;
a7a723f0 5509 return expand_expr (len, target, mode, EXPAND_NORMAL);
6411575e 5510 }
5511
c2f47e15 5512 return NULL_RTX;
6411575e 5513}
27f261ef 5514
4ee9c684 5515/* Expand a call to either the entry or exit function profiler. */
5516
5517static rtx
5518expand_builtin_profile_func (bool exitp)
5519{
5520 rtx this, which;
5521
5522 this = DECL_RTL (current_function_decl);
64db345d 5523 gcc_assert (MEM_P (this));
5524 this = XEXP (this, 0);
4ee9c684 5525
5526 if (exitp)
5527 which = profile_function_exit_libfunc;
5528 else
5529 which = profile_function_entry_libfunc;
5530
5531 emit_library_call (which, LCT_NORMAL, VOIDmode, 2, this, Pmode,
5532 expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
869d0ef0 5533 0),
4ee9c684 5534 Pmode);
5535
5536 return const0_rtx;
5537}
5538
ac8fb6db 5539/* Expand a call to __builtin___clear_cache. */
5540
5541static rtx
5542expand_builtin___clear_cache (tree exp ATTRIBUTE_UNUSED)
5543{
5544#ifndef HAVE_clear_cache
5545#ifdef CLEAR_INSN_CACHE
5546 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
5547 does something. Just do the default expansion to a call to
5548 __clear_cache(). */
5549 return NULL_RTX;
5550#else
5551 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
5552 does nothing. There is no need to call it. Do nothing. */
5553 return const0_rtx;
5554#endif /* CLEAR_INSN_CACHE */
5555#else
5556 /* We have a "clear_cache" insn, and it will handle everything. */
5557 tree begin, end;
5558 rtx begin_rtx, end_rtx;
5559 enum insn_code icode;
5560
5561 /* We must not expand to a library call. If we did, any
5562 fallback library function in libgcc that might contain a call to
5563 __builtin___clear_cache() would recurse infinitely. */
5564 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
5565 {
5566 error ("both arguments to %<__builtin___clear_cache%> must be pointers");
5567 return const0_rtx;
5568 }
5569
5570 if (HAVE_clear_cache)
5571 {
5572 icode = CODE_FOR_clear_cache;
5573
5574 begin = CALL_EXPR_ARG (exp, 0);
5575 begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
5576 begin_rtx = convert_memory_address (Pmode, begin_rtx);
5577 if (!insn_data[icode].operand[0].predicate (begin_rtx, Pmode))
5578 begin_rtx = copy_to_mode_reg (Pmode, begin_rtx);
5579
5580 end = CALL_EXPR_ARG (exp, 1);
5581 end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
5582 end_rtx = convert_memory_address (Pmode, end_rtx);
5583 if (!insn_data[icode].operand[1].predicate (end_rtx, Pmode))
5584 end_rtx = copy_to_mode_reg (Pmode, end_rtx);
5585
5586 emit_insn (gen_clear_cache (begin_rtx, end_rtx));
5587 }
5588 return const0_rtx;
5589#endif /* HAVE_clear_cache */
5590}
5591
4ee9c684 5592/* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
5593
5594static rtx
5595round_trampoline_addr (rtx tramp)
5596{
5597 rtx temp, addend, mask;
5598
5599 /* If we don't need too much alignment, we'll have been guaranteed
5600 proper alignment by get_trampoline_type. */
5601 if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
5602 return tramp;
5603
5604 /* Round address up to desired boundary. */
5605 temp = gen_reg_rtx (Pmode);
5606 addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
5607 mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
5608
5609 temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
5610 temp, 0, OPTAB_LIB_WIDEN);
5611 tramp = expand_simple_binop (Pmode, AND, temp, mask,
5612 temp, 0, OPTAB_LIB_WIDEN);
5613
5614 return tramp;
5615}
5616
5617static rtx
c2f47e15 5618expand_builtin_init_trampoline (tree exp)
4ee9c684 5619{
5620 tree t_tramp, t_func, t_chain;
5621 rtx r_tramp, r_func, r_chain;
5622#ifdef TRAMPOLINE_TEMPLATE
5623 rtx blktramp;
5624#endif
5625
c2f47e15 5626 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
4ee9c684 5627 POINTER_TYPE, VOID_TYPE))
5628 return NULL_RTX;
5629
c2f47e15 5630 t_tramp = CALL_EXPR_ARG (exp, 0);
5631 t_func = CALL_EXPR_ARG (exp, 1);
5632 t_chain = CALL_EXPR_ARG (exp, 2);
4ee9c684 5633
8ec3c5c2 5634 r_tramp = expand_normal (t_tramp);
5635 r_func = expand_normal (t_func);
5636 r_chain = expand_normal (t_chain);
4ee9c684 5637
5638 /* Generate insns to initialize the trampoline. */
5639 r_tramp = round_trampoline_addr (r_tramp);
5640#ifdef TRAMPOLINE_TEMPLATE
5641 blktramp = gen_rtx_MEM (BLKmode, r_tramp);
5642 set_mem_align (blktramp, TRAMPOLINE_ALIGNMENT);
5643 emit_block_move (blktramp, assemble_trampoline_template (),
5644 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
5645#endif
5646 trampolines_created = 1;
5647 INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain);
5648
5649 return const0_rtx;
5650}
5651
5652static rtx
c2f47e15 5653expand_builtin_adjust_trampoline (tree exp)
4ee9c684 5654{
5655 rtx tramp;
5656
c2f47e15 5657 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
4ee9c684 5658 return NULL_RTX;
5659
c2f47e15 5660 tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
4ee9c684 5661 tramp = round_trampoline_addr (tramp);
5662#ifdef TRAMPOLINE_ADJUST_ADDRESS
5663 TRAMPOLINE_ADJUST_ADDRESS (tramp);
5664#endif
5665
5666 return tramp;
5667}
5668
93f564d6 5669/* Expand the call EXP to the built-in signbit, signbitf or signbitl
5670 function. The function first checks whether the back end provides
5671 an insn to implement signbit for the respective mode. If not, it
5672 checks whether the floating point format of the value is such that
5673 the sign bit can be extracted. If that is not the case, the
5674 function returns NULL_RTX to indicate that a normal call should be
5675 emitted rather than expanding the function in-line. EXP is the
5676 expression that is a call to the builtin function; if convenient,
5677 the result should be placed in TARGET. */
27f261ef 5678static rtx
5679expand_builtin_signbit (tree exp, rtx target)
5680{
5681 const struct real_format *fmt;
5682 enum machine_mode fmode, imode, rmode;
5683 HOST_WIDE_INT hi, lo;
c2f47e15 5684 tree arg;
ca4f1f5b 5685 int word, bitpos;
27eda240 5686 enum insn_code icode;
27f261ef 5687 rtx temp;
5688
c2f47e15 5689 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
5690 return NULL_RTX;
27f261ef 5691
c2f47e15 5692 arg = CALL_EXPR_ARG (exp, 0);
27f261ef 5693 fmode = TYPE_MODE (TREE_TYPE (arg));
5694 rmode = TYPE_MODE (TREE_TYPE (exp));
5695 fmt = REAL_MODE_FORMAT (fmode);
5696
93f564d6 5697 arg = builtin_save_expr (arg);
5698
5699 /* Expand the argument yielding a RTX expression. */
5700 temp = expand_normal (arg);
5701
5702 /* Check if the back end provides an insn that handles signbit for the
5703 argument's mode. */
27eda240 5704 icode = signbit_optab->handlers [(int) fmode].insn_code;
5705 if (icode != CODE_FOR_nothing)
93f564d6 5706 {
5707 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
27eda240 5708 emit_unop_insn (icode, target, temp, UNKNOWN);
93f564d6 5709 return target;
5710 }
5711
27f261ef 5712 /* For floating point formats without a sign bit, implement signbit
5713 as "ARG < 0.0". */
8d564692 5714 bitpos = fmt->signbit_ro;
ca4f1f5b 5715 if (bitpos < 0)
27f261ef 5716 {
5717 /* But we can't do this if the format supports signed zero. */
5718 if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
c2f47e15 5719 return NULL_RTX;
27f261ef 5720
49d00087 5721 arg = fold_build2 (LT_EXPR, TREE_TYPE (exp), arg,
5722 build_real (TREE_TYPE (arg), dconst0));
27f261ef 5723 return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5724 }
5725
ca4f1f5b 5726 if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
27f261ef 5727 {
ca4f1f5b 5728 imode = int_mode_for_mode (fmode);
5729 if (imode == BLKmode)
c2f47e15 5730 return NULL_RTX;
ca4f1f5b 5731 temp = gen_lowpart (imode, temp);
24fd4260 5732 }
5733 else
5734 {
ca4f1f5b 5735 imode = word_mode;
5736 /* Handle targets with different FP word orders. */
5737 if (FLOAT_WORDS_BIG_ENDIAN)
a0c938f0 5738 word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
ca4f1f5b 5739 else
a0c938f0 5740 word = bitpos / BITS_PER_WORD;
ca4f1f5b 5741 temp = operand_subword_force (temp, word, fmode);
5742 bitpos = bitpos % BITS_PER_WORD;
5743 }
5744
44b0f1d0 5745 /* Force the intermediate word_mode (or narrower) result into a
5746 register. This avoids attempting to create paradoxical SUBREGs
5747 of floating point modes below. */
5748 temp = force_reg (imode, temp);
5749
ca4f1f5b 5750 /* If the bitpos is within the "result mode" lowpart, the operation
5751 can be implement with a single bitwise AND. Otherwise, we need
5752 a right shift and an AND. */
5753
5754 if (bitpos < GET_MODE_BITSIZE (rmode))
5755 {
24fd4260 5756 if (bitpos < HOST_BITS_PER_WIDE_INT)
27f261ef 5757 {
24fd4260 5758 hi = 0;
5759 lo = (HOST_WIDE_INT) 1 << bitpos;
27f261ef 5760 }
5761 else
24fd4260 5762 {
5763 hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
5764 lo = 0;
5765 }
27f261ef 5766
ca4f1f5b 5767 if (imode != rmode)
5768 temp = gen_lowpart (rmode, temp);
24fd4260 5769 temp = expand_binop (rmode, and_optab, temp,
5770 immed_double_const (lo, hi, rmode),
ca4f1f5b 5771 NULL_RTX, 1, OPTAB_LIB_WIDEN);
27f261ef 5772 }
ca4f1f5b 5773 else
5774 {
5775 /* Perform a logical right shift to place the signbit in the least
a0c938f0 5776 significant bit, then truncate the result to the desired mode
ca4f1f5b 5777 and mask just this bit. */
5778 temp = expand_shift (RSHIFT_EXPR, imode, temp,
5779 build_int_cst (NULL_TREE, bitpos), NULL_RTX, 1);
5780 temp = gen_lowpart (rmode, temp);
5781 temp = expand_binop (rmode, and_optab, temp, const1_rtx,
5782 NULL_RTX, 1, OPTAB_LIB_WIDEN);
5783 }
5784
27f261ef 5785 return temp;
5786}
73673831 5787
5788/* Expand fork or exec calls. TARGET is the desired target of the
c2f47e15 5789 call. EXP is the call. FN is the
73673831 5790 identificator of the actual function. IGNORE is nonzero if the
5791 value is to be ignored. */
5792
5793static rtx
c2f47e15 5794expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
73673831 5795{
5796 tree id, decl;
5797 tree call;
5798
5799 /* If we are not profiling, just call the function. */
5800 if (!profile_arc_flag)
5801 return NULL_RTX;
5802
5803 /* Otherwise call the wrapper. This should be equivalent for the rest of
5804 compiler, so the code does not diverge, and the wrapper may run the
9c9bad97 5805 code necessary for keeping the profiling sane. */
73673831 5806
5807 switch (DECL_FUNCTION_CODE (fn))
5808 {
5809 case BUILT_IN_FORK:
5810 id = get_identifier ("__gcov_fork");
5811 break;
5812
5813 case BUILT_IN_EXECL:
5814 id = get_identifier ("__gcov_execl");
5815 break;
5816
5817 case BUILT_IN_EXECV:
5818 id = get_identifier ("__gcov_execv");
5819 break;
5820
5821 case BUILT_IN_EXECLP:
5822 id = get_identifier ("__gcov_execlp");
5823 break;
5824
5825 case BUILT_IN_EXECLE:
5826 id = get_identifier ("__gcov_execle");
5827 break;
5828
5829 case BUILT_IN_EXECVP:
5830 id = get_identifier ("__gcov_execvp");
5831 break;
5832
5833 case BUILT_IN_EXECVE:
5834 id = get_identifier ("__gcov_execve");
5835 break;
5836
5837 default:
64db345d 5838 gcc_unreachable ();
73673831 5839 }
5840
5841 decl = build_decl (FUNCTION_DECL, id, TREE_TYPE (fn));
5842 DECL_EXTERNAL (decl) = 1;
5843 TREE_PUBLIC (decl) = 1;
5844 DECL_ARTIFICIAL (decl) = 1;
5845 TREE_NOTHROW (decl) = 1;
e82d310b 5846 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
5847 DECL_VISIBILITY_SPECIFIED (decl) = 1;
c2f47e15 5848 call = rewrite_call_expr (exp, 0, decl, 0);
73673831 5849 return expand_call (call, target, ignore);
c2f47e15 5850 }
5851
b6a5fc45 5852
5853\f
3e272de8 5854/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
5855 the pointer in these functions is void*, the tree optimizers may remove
5856 casts. The mode computed in expand_builtin isn't reliable either, due
5857 to __sync_bool_compare_and_swap.
5858
5859 FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
5860 group of builtins. This gives us log2 of the mode size. */
5861
5862static inline enum machine_mode
5863get_builtin_sync_mode (int fcode_diff)
5864{
ad3a13b5 5865 /* The size is not negotiable, so ask not to get BLKmode in return
5866 if the target indicates that a smaller size would be better. */
5867 return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
3e272de8 5868}
5869
041e0215 5870/* Expand the memory expression LOC and return the appropriate memory operand
5871 for the builtin_sync operations. */
5872
5873static rtx
5874get_builtin_sync_mem (tree loc, enum machine_mode mode)
5875{
5876 rtx addr, mem;
5877
1db6d067 5878 addr = expand_expr (loc, NULL_RTX, Pmode, EXPAND_SUM);
041e0215 5879
5880 /* Note that we explicitly do not want any alias information for this
5881 memory, so that we kill all other live memories. Otherwise we don't
5882 satisfy the full barrier semantics of the intrinsic. */
5883 mem = validize_mem (gen_rtx_MEM (mode, addr));
5884
5885 set_mem_align (mem, get_pointer_alignment (loc, BIGGEST_ALIGNMENT));
c94cfd1c 5886 set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
041e0215 5887 MEM_VOLATILE_P (mem) = 1;
5888
5889 return mem;
5890}
5891
b6a5fc45 5892/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
c2f47e15 5893 EXP is the CALL_EXPR. CODE is the rtx code
b6a5fc45 5894 that corresponds to the arithmetic or logical operation from the name;
5895 an exception here is that NOT actually means NAND. TARGET is an optional
5896 place for us to store the results; AFTER is true if this is the
5897 fetch_and_xxx form. IGNORE is true if we don't actually care about
5898 the result of the operation at all. */
5899
5900static rtx
c2f47e15 5901expand_builtin_sync_operation (enum machine_mode mode, tree exp,
3e272de8 5902 enum rtx_code code, bool after,
b6a5fc45 5903 rtx target, bool ignore)
5904{
041e0215 5905 rtx val, mem;
a8bb7059 5906 enum machine_mode old_mode;
b6a5fc45 5907
5908 /* Expand the operands. */
c2f47e15 5909 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5910
1db6d067 5911 val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
a8bb7059 5912 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5913 of CONST_INTs, where we know the old_mode only from the call argument. */
5914 old_mode = GET_MODE (val);
5915 if (old_mode == VOIDmode)
5916 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5917 val = convert_modes (mode, old_mode, val, 1);
b6a5fc45 5918
b6a5fc45 5919 if (ignore)
5920 return expand_sync_operation (mem, val, code);
5921 else
5922 return expand_sync_fetch_operation (mem, val, code, after, target);
5923}
5924
5925/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
c2f47e15 5926 intrinsics. EXP is the CALL_EXPR. IS_BOOL is
b6a5fc45 5927 true if this is the boolean form. TARGET is a place for us to store the
5928 results; this is NOT optional if IS_BOOL is true. */
5929
5930static rtx
c2f47e15 5931expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
3e272de8 5932 bool is_bool, rtx target)
b6a5fc45 5933{
041e0215 5934 rtx old_val, new_val, mem;
a8bb7059 5935 enum machine_mode old_mode;
b6a5fc45 5936
5937 /* Expand the operands. */
c2f47e15 5938 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5939
c2f47e15 5940
1db6d067 5941 old_val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX,
5942 mode, EXPAND_NORMAL);
a8bb7059 5943 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5944 of CONST_INTs, where we know the old_mode only from the call argument. */
5945 old_mode = GET_MODE (old_val);
5946 if (old_mode == VOIDmode)
5947 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5948 old_val = convert_modes (mode, old_mode, old_val, 1);
b6a5fc45 5949
1db6d067 5950 new_val = expand_expr (CALL_EXPR_ARG (exp, 2), NULL_RTX,
5951 mode, EXPAND_NORMAL);
a8bb7059 5952 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5953 of CONST_INTs, where we know the old_mode only from the call argument. */
5954 old_mode = GET_MODE (new_val);
5955 if (old_mode == VOIDmode)
5956 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2)));
5957 new_val = convert_modes (mode, old_mode, new_val, 1);
b6a5fc45 5958
b6a5fc45 5959 if (is_bool)
5960 return expand_bool_compare_and_swap (mem, old_val, new_val, target);
5961 else
5962 return expand_val_compare_and_swap (mem, old_val, new_val, target);
5963}
5964
5965/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
5966 general form is actually an atomic exchange, and some targets only
5967 support a reduced form with the second argument being a constant 1.
c2f47e15 5968 EXP is the CALL_EXPR; TARGET is an optional place for us to store
5969 the results. */
b6a5fc45 5970
5971static rtx
c2f47e15 5972expand_builtin_lock_test_and_set (enum machine_mode mode, tree exp,
3e272de8 5973 rtx target)
b6a5fc45 5974{
041e0215 5975 rtx val, mem;
a8bb7059 5976 enum machine_mode old_mode;
b6a5fc45 5977
5978 /* Expand the operands. */
c2f47e15 5979 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1db6d067 5980 val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
a8bb7059 5981 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5982 of CONST_INTs, where we know the old_mode only from the call argument. */
5983 old_mode = GET_MODE (val);
5984 if (old_mode == VOIDmode)
5985 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5986 val = convert_modes (mode, old_mode, val, 1);
b6a5fc45 5987
b6a5fc45 5988 return expand_sync_lock_test_and_set (mem, val, target);
5989}
5990
5991/* Expand the __sync_synchronize intrinsic. */
5992
5993static void
5994expand_builtin_synchronize (void)
5995{
82e58396 5996 tree x;
b6a5fc45 5997
5998#ifdef HAVE_memory_barrier
5999 if (HAVE_memory_barrier)
6000 {
6001 emit_insn (gen_memory_barrier ());
6002 return;
6003 }
6004#endif
6005
82e58396 6006 /* If no explicit memory barrier instruction is available, create an
6007 empty asm stmt with a memory clobber. */
6008 x = build4 (ASM_EXPR, void_type_node, build_string (0, ""), NULL, NULL,
6009 tree_cons (NULL, build_string (6, "memory"), NULL));
6010 ASM_VOLATILE_P (x) = 1;
6011 expand_asm_expr (x);
b6a5fc45 6012}
6013
c2f47e15 6014/* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */
b6a5fc45 6015
6016static void
c2f47e15 6017expand_builtin_lock_release (enum machine_mode mode, tree exp)
b6a5fc45 6018{
b6a5fc45 6019 enum insn_code icode;
041e0215 6020 rtx mem, insn;
3e272de8 6021 rtx val = const0_rtx;
b6a5fc45 6022
6023 /* Expand the operands. */
c2f47e15 6024 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 6025
6026 /* If there is an explicit operation in the md file, use it. */
6027 icode = sync_lock_release[mode];
6028 if (icode != CODE_FOR_nothing)
6029 {
6030 if (!insn_data[icode].operand[1].predicate (val, mode))
6031 val = force_reg (mode, val);
6032
6033 insn = GEN_FCN (icode) (mem, val);
6034 if (insn)
6035 {
6036 emit_insn (insn);
6037 return;
6038 }
6039 }
6040
6041 /* Otherwise we can implement this operation by emitting a barrier
6042 followed by a store of zero. */
6043 expand_builtin_synchronize ();
6044 emit_move_insn (mem, val);
6045}
53800dbe 6046\f
6047/* Expand an expression EXP that calls a built-in function,
6048 with result going to TARGET if that's convenient
6049 (and in mode MODE if that's convenient).
6050 SUBTARGET may be used as the target for computing one of EXP's operands.
6051 IGNORE is nonzero if the value is to be ignored. */
6052
6053rtx
aecda0d6 6054expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
6055 int ignore)
53800dbe 6056{
c6e6ecb1 6057 tree fndecl = get_callee_fndecl (exp);
53800dbe 6058 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
efb070c8 6059 enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
53800dbe 6060
8305149e 6061 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
883b2e73 6062 return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
bf8e3599 6063
53800dbe 6064 /* When not optimizing, generate calls to library functions for a certain
6065 set of builtins. */
cd9ff771 6066 if (!optimize
b6a5fc45 6067 && !called_as_built_in (fndecl)
cd9ff771 6068 && DECL_ASSEMBLER_NAME_SET_P (fndecl)
6069 && fcode != BUILT_IN_ALLOCA)
6070 return expand_call (exp, target, ignore);
53800dbe 6071
8d6d7930 6072 /* The built-in function expanders test for target == const0_rtx
6073 to determine whether the function's result will be ignored. */
6074 if (ignore)
6075 target = const0_rtx;
6076
6077 /* If the result of a pure or const built-in function is ignored, and
6078 none of its arguments are volatile, we can avoid expanding the
6079 built-in call and just evaluate the arguments for side-effects. */
6080 if (target == const0_rtx
6081 && (DECL_IS_PURE (fndecl) || TREE_READONLY (fndecl)))
6082 {
6083 bool volatilep = false;
6084 tree arg;
c2f47e15 6085 call_expr_arg_iterator iter;
8d6d7930 6086
c2f47e15 6087 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
6088 if (TREE_THIS_VOLATILE (arg))
8d6d7930 6089 {
6090 volatilep = true;
6091 break;
6092 }
6093
6094 if (! volatilep)
6095 {
c2f47e15 6096 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
6097 expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
8d6d7930 6098 return const0_rtx;
6099 }
6100 }
6101
53800dbe 6102 switch (fcode)
6103 {
4f35b1fc 6104 CASE_FLT_FN (BUILT_IN_FABS):
c2f47e15 6105 target = expand_builtin_fabs (exp, target, subtarget);
78a74442 6106 if (target)
a0c938f0 6107 return target;
78a74442 6108 break;
6109
4f35b1fc 6110 CASE_FLT_FN (BUILT_IN_COPYSIGN):
c2f47e15 6111 target = expand_builtin_copysign (exp, target, subtarget);
270436f3 6112 if (target)
6113 return target;
6114 break;
6115
7d3f6cc7 6116 /* Just do a normal library call if we were unable to fold
6117 the values. */
4f35b1fc 6118 CASE_FLT_FN (BUILT_IN_CABS):
78a74442 6119 break;
53800dbe 6120
4f35b1fc 6121 CASE_FLT_FN (BUILT_IN_EXP):
6122 CASE_FLT_FN (BUILT_IN_EXP10):
6123 CASE_FLT_FN (BUILT_IN_POW10):
6124 CASE_FLT_FN (BUILT_IN_EXP2):
6125 CASE_FLT_FN (BUILT_IN_EXPM1):
6126 CASE_FLT_FN (BUILT_IN_LOGB):
4f35b1fc 6127 CASE_FLT_FN (BUILT_IN_LOG):
6128 CASE_FLT_FN (BUILT_IN_LOG10):
6129 CASE_FLT_FN (BUILT_IN_LOG2):
6130 CASE_FLT_FN (BUILT_IN_LOG1P):
6131 CASE_FLT_FN (BUILT_IN_TAN):
6132 CASE_FLT_FN (BUILT_IN_ASIN):
6133 CASE_FLT_FN (BUILT_IN_ACOS):
6134 CASE_FLT_FN (BUILT_IN_ATAN):
7f3be425 6135 /* Treat these like sqrt only if unsafe math optimizations are allowed,
6136 because of possible accuracy problems. */
6137 if (! flag_unsafe_math_optimizations)
53800dbe 6138 break;
4f35b1fc 6139 CASE_FLT_FN (BUILT_IN_SQRT):
6140 CASE_FLT_FN (BUILT_IN_FLOOR):
6141 CASE_FLT_FN (BUILT_IN_CEIL):
6142 CASE_FLT_FN (BUILT_IN_TRUNC):
6143 CASE_FLT_FN (BUILT_IN_ROUND):
6144 CASE_FLT_FN (BUILT_IN_NEARBYINT):
6145 CASE_FLT_FN (BUILT_IN_RINT):
53800dbe 6146 target = expand_builtin_mathfn (exp, target, subtarget);
6147 if (target)
6148 return target;
6149 break;
6150
a67a90e5 6151 CASE_FLT_FN (BUILT_IN_ILOGB):
6152 if (! flag_unsafe_math_optimizations)
6153 break;
69b779ea 6154 CASE_FLT_FN (BUILT_IN_ISINF):
cde061c1 6155 CASE_FLT_FN (BUILT_IN_FINITE):
6156 case BUILT_IN_ISFINITE:
8a1a9cb7 6157 case BUILT_IN_ISNORMAL:
a67a90e5 6158 target = expand_builtin_interclass_mathfn (exp, target, subtarget);
6159 if (target)
6160 return target;
6161 break;
6162
4f35b1fc 6163 CASE_FLT_FN (BUILT_IN_LCEIL):
6164 CASE_FLT_FN (BUILT_IN_LLCEIL):
6165 CASE_FLT_FN (BUILT_IN_LFLOOR):
6166 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 6167 target = expand_builtin_int_roundingfn (exp, target, subtarget);
6168 if (target)
6169 return target;
6170 break;
6171
7d3afc77 6172 CASE_FLT_FN (BUILT_IN_LRINT):
6173 CASE_FLT_FN (BUILT_IN_LLRINT):
ef2f1a10 6174 CASE_FLT_FN (BUILT_IN_LROUND):
6175 CASE_FLT_FN (BUILT_IN_LLROUND):
7d3afc77 6176 target = expand_builtin_int_roundingfn_2 (exp, target, subtarget);
6177 if (target)
6178 return target;
6179 break;
6180
4f35b1fc 6181 CASE_FLT_FN (BUILT_IN_POW):
f1b844c6 6182 target = expand_builtin_pow (exp, target, subtarget);
6183 if (target)
6184 return target;
6185 break;
6186
4f35b1fc 6187 CASE_FLT_FN (BUILT_IN_POWI):
757c219d 6188 target = expand_builtin_powi (exp, target, subtarget);
6189 if (target)
6190 return target;
6191 break;
6192
4f35b1fc 6193 CASE_FLT_FN (BUILT_IN_ATAN2):
6194 CASE_FLT_FN (BUILT_IN_LDEXP):
73a954a1 6195 CASE_FLT_FN (BUILT_IN_SCALB):
6196 CASE_FLT_FN (BUILT_IN_SCALBN):
6197 CASE_FLT_FN (BUILT_IN_SCALBLN):
0fd605a5 6198 if (! flag_unsafe_math_optimizations)
6199 break;
ef722005 6200
6201 CASE_FLT_FN (BUILT_IN_FMOD):
6202 CASE_FLT_FN (BUILT_IN_REMAINDER):
6203 CASE_FLT_FN (BUILT_IN_DREM):
0fd605a5 6204 target = expand_builtin_mathfn_2 (exp, target, subtarget);
6205 if (target)
6206 return target;
6207 break;
6208
d735c391 6209 CASE_FLT_FN (BUILT_IN_CEXPI):
6210 target = expand_builtin_cexpi (exp, target, subtarget);
6211 gcc_assert (target);
6212 return target;
6213
4f35b1fc 6214 CASE_FLT_FN (BUILT_IN_SIN):
6215 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 6216 if (! flag_unsafe_math_optimizations)
6217 break;
6218 target = expand_builtin_mathfn_3 (exp, target, subtarget);
6219 if (target)
6220 return target;
6221 break;
6222
c3147c1a 6223 CASE_FLT_FN (BUILT_IN_SINCOS):
6224 if (! flag_unsafe_math_optimizations)
6225 break;
6226 target = expand_builtin_sincos (exp);
6227 if (target)
6228 return target;
6229 break;
6230
53800dbe 6231 case BUILT_IN_APPLY_ARGS:
6232 return expand_builtin_apply_args ();
6233
6234 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
6235 FUNCTION with a copy of the parameters described by
6236 ARGUMENTS, and ARGSIZE. It returns a block of memory
6237 allocated on the stack into which is stored all the registers
6238 that might possibly be used for returning the result of a
6239 function. ARGUMENTS is the value returned by
6240 __builtin_apply_args. ARGSIZE is the number of bytes of
6241 arguments that must be copied. ??? How should this value be
6242 computed? We'll also need a safe worst case value for varargs
6243 functions. */
6244 case BUILT_IN_APPLY:
c2f47e15 6245 if (!validate_arglist (exp, POINTER_TYPE,
0eb671f7 6246 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
c2f47e15 6247 && !validate_arglist (exp, REFERENCE_TYPE,
0eb671f7 6248 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 6249 return const0_rtx;
6250 else
6251 {
53800dbe 6252 rtx ops[3];
6253
c2f47e15 6254 ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
6255 ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
6256 ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
53800dbe 6257
6258 return expand_builtin_apply (ops[0], ops[1], ops[2]);
6259 }
6260
6261 /* __builtin_return (RESULT) causes the function to return the
6262 value described by RESULT. RESULT is address of the block of
6263 memory returned by __builtin_apply. */
6264 case BUILT_IN_RETURN:
c2f47e15 6265 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
6266 expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
53800dbe 6267 return const0_rtx;
6268
6269 case BUILT_IN_SAVEREGS:
a66c9326 6270 return expand_builtin_saveregs ();
53800dbe 6271
6272 case BUILT_IN_ARGS_INFO:
c2f47e15 6273 return expand_builtin_args_info (exp);
53800dbe 6274
48dc2227 6275 case BUILT_IN_VA_ARG_PACK:
6276 /* All valid uses of __builtin_va_arg_pack () are removed during
6277 inlining. */
b8c23db3 6278 error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
48dc2227 6279 return const0_rtx;
6280
4e1d7ea4 6281 case BUILT_IN_VA_ARG_PACK_LEN:
6282 /* All valid uses of __builtin_va_arg_pack_len () are removed during
6283 inlining. */
b8c23db3 6284 error ("%Kinvalid use of %<__builtin_va_arg_pack_len ()%>", exp);
4e1d7ea4 6285 return const0_rtx;
6286
53800dbe 6287 /* Return the address of the first anonymous stack arg. */
6288 case BUILT_IN_NEXT_ARG:
c2f47e15 6289 if (fold_builtin_next_arg (exp, false))
a0c938f0 6290 return const0_rtx;
79012a9d 6291 return expand_builtin_next_arg ();
53800dbe 6292
ac8fb6db 6293 case BUILT_IN_CLEAR_CACHE:
6294 target = expand_builtin___clear_cache (exp);
6295 if (target)
6296 return target;
6297 break;
6298
53800dbe 6299 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 6300 return expand_builtin_classify_type (exp);
53800dbe 6301
6302 case BUILT_IN_CONSTANT_P:
4ee9c684 6303 return const0_rtx;
53800dbe 6304
6305 case BUILT_IN_FRAME_ADDRESS:
6306 case BUILT_IN_RETURN_ADDRESS:
c2f47e15 6307 return expand_builtin_frame_address (fndecl, exp);
53800dbe 6308
6309 /* Returns the address of the area where the structure is returned.
6310 0 otherwise. */
6311 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
c2f47e15 6312 if (call_expr_nargs (exp) != 0
9342ee68 6313 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
e16ceb8e 6314 || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
9342ee68 6315 return const0_rtx;
53800dbe 6316 else
9342ee68 6317 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
53800dbe 6318
6319 case BUILT_IN_ALLOCA:
c2f47e15 6320 target = expand_builtin_alloca (exp, target);
53800dbe 6321 if (target)
6322 return target;
6323 break;
6324
4ee9c684 6325 case BUILT_IN_STACK_SAVE:
6326 return expand_stack_save ();
6327
6328 case BUILT_IN_STACK_RESTORE:
c2f47e15 6329 expand_stack_restore (CALL_EXPR_ARG (exp, 0));
4ee9c684 6330 return const0_rtx;
6331
42791117 6332 case BUILT_IN_BSWAP32:
6333 case BUILT_IN_BSWAP64:
c2f47e15 6334 target = expand_builtin_bswap (exp, target, subtarget);
42791117 6335
6336 if (target)
6337 return target;
6338 break;
6339
4f35b1fc 6340 CASE_INT_FN (BUILT_IN_FFS):
5053259b 6341 case BUILT_IN_FFSIMAX:
c2f47e15 6342 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6343 subtarget, ffs_optab);
6a08d0ab 6344 if (target)
6345 return target;
6346 break;
6347
4f35b1fc 6348 CASE_INT_FN (BUILT_IN_CLZ):
5053259b 6349 case BUILT_IN_CLZIMAX:
c2f47e15 6350 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6351 subtarget, clz_optab);
6a08d0ab 6352 if (target)
6353 return target;
6354 break;
6355
4f35b1fc 6356 CASE_INT_FN (BUILT_IN_CTZ):
5053259b 6357 case BUILT_IN_CTZIMAX:
c2f47e15 6358 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6359 subtarget, ctz_optab);
6a08d0ab 6360 if (target)
6361 return target;
6362 break;
6363
4f35b1fc 6364 CASE_INT_FN (BUILT_IN_POPCOUNT):
5053259b 6365 case BUILT_IN_POPCOUNTIMAX:
c2f47e15 6366 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6367 subtarget, popcount_optab);
6a08d0ab 6368 if (target)
6369 return target;
6370 break;
6371
4f35b1fc 6372 CASE_INT_FN (BUILT_IN_PARITY):
5053259b 6373 case BUILT_IN_PARITYIMAX:
c2f47e15 6374 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6375 subtarget, parity_optab);
53800dbe 6376 if (target)
6377 return target;
6378 break;
6379
6380 case BUILT_IN_STRLEN:
c2f47e15 6381 target = expand_builtin_strlen (exp, target, target_mode);
53800dbe 6382 if (target)
6383 return target;
6384 break;
6385
6386 case BUILT_IN_STRCPY:
c2f47e15 6387 target = expand_builtin_strcpy (fndecl, exp, target, mode);
53800dbe 6388 if (target)
6389 return target;
6390 break;
bf8e3599 6391
ed09096d 6392 case BUILT_IN_STRNCPY:
8ff6a5cd 6393 target = expand_builtin_strncpy (exp, target, mode);
ed09096d 6394 if (target)
6395 return target;
6396 break;
bf8e3599 6397
3b824fa6 6398 case BUILT_IN_STPCPY:
dc369150 6399 target = expand_builtin_stpcpy (exp, target, mode);
3b824fa6 6400 if (target)
6401 return target;
6402 break;
6403
49f0327b 6404 case BUILT_IN_STRCAT:
c2f47e15 6405 target = expand_builtin_strcat (fndecl, exp, target, mode);
49f0327b 6406 if (target)
6407 return target;
6408 break;
bf8e3599 6409
49f0327b 6410 case BUILT_IN_STRNCAT:
c2f47e15 6411 target = expand_builtin_strncat (exp, target, mode);
49f0327b 6412 if (target)
6413 return target;
6414 break;
bf8e3599 6415
49f0327b 6416 case BUILT_IN_STRSPN:
c2f47e15 6417 target = expand_builtin_strspn (exp, target, mode);
49f0327b 6418 if (target)
6419 return target;
6420 break;
bf8e3599 6421
49f0327b 6422 case BUILT_IN_STRCSPN:
c2f47e15 6423 target = expand_builtin_strcspn (exp, target, mode);
49f0327b 6424 if (target)
6425 return target;
6426 break;
bf8e3599 6427
17f5ea87 6428 case BUILT_IN_STRSTR:
c2f47e15 6429 target = expand_builtin_strstr (exp, target, mode);
17f5ea87 6430 if (target)
6431 return target;
6432 break;
bf8e3599 6433
46f3a74a 6434 case BUILT_IN_STRPBRK:
c2f47e15 6435 target = expand_builtin_strpbrk (exp, target, mode);
46f3a74a 6436 if (target)
6437 return target;
6438 break;
bf8e3599 6439
398aae36 6440 case BUILT_IN_INDEX:
83d79705 6441 case BUILT_IN_STRCHR:
c2f47e15 6442 target = expand_builtin_strchr (exp, target, mode);
83d79705 6443 if (target)
6444 return target;
6445 break;
6446
398aae36 6447 case BUILT_IN_RINDEX:
83d79705 6448 case BUILT_IN_STRRCHR:
c2f47e15 6449 target = expand_builtin_strrchr (exp, target, mode);
83d79705 6450 if (target)
6451 return target;
6452 break;
6453
53800dbe 6454 case BUILT_IN_MEMCPY:
5a0de151 6455 target = expand_builtin_memcpy (exp, target, mode);
3b824fa6 6456 if (target)
6457 return target;
6458 break;
6459
6460 case BUILT_IN_MEMPCPY:
c2f47e15 6461 target = expand_builtin_mempcpy (exp, target, mode);
53800dbe 6462 if (target)
6463 return target;
6464 break;
6465
c4950093 6466 case BUILT_IN_MEMMOVE:
c2f47e15 6467 target = expand_builtin_memmove (exp, target, mode, ignore);
c4950093 6468 if (target)
6469 return target;
6470 break;
6471
6472 case BUILT_IN_BCOPY:
c2f47e15 6473 target = expand_builtin_bcopy (exp, ignore);
c4950093 6474 if (target)
6475 return target;
6476 break;
6477
53800dbe 6478 case BUILT_IN_MEMSET:
c2f47e15 6479 target = expand_builtin_memset (exp, target, mode);
53800dbe 6480 if (target)
6481 return target;
6482 break;
6483
ffc83088 6484 case BUILT_IN_BZERO:
0b25db21 6485 target = expand_builtin_bzero (exp);
ffc83088 6486 if (target)
6487 return target;
6488 break;
6489
53800dbe 6490 case BUILT_IN_STRCMP:
83d79705 6491 target = expand_builtin_strcmp (exp, target, mode);
53800dbe 6492 if (target)
6493 return target;
6494 break;
6495
ed09096d 6496 case BUILT_IN_STRNCMP:
6497 target = expand_builtin_strncmp (exp, target, mode);
6498 if (target)
6499 return target;
6500 break;
6501
7959b13b 6502 case BUILT_IN_MEMCHR:
6503 target = expand_builtin_memchr (exp, target, mode);
6504 if (target)
6505 return target;
6506 break;
6507
071f1696 6508 case BUILT_IN_BCMP:
53800dbe 6509 case BUILT_IN_MEMCMP:
c2f47e15 6510 target = expand_builtin_memcmp (exp, target, mode);
53800dbe 6511 if (target)
6512 return target;
6513 break;
53800dbe 6514
6515 case BUILT_IN_SETJMP:
2c8a1497 6516 /* This should have been lowered to the builtins below. */
6517 gcc_unreachable ();
6518
6519 case BUILT_IN_SETJMP_SETUP:
6520 /* __builtin_setjmp_setup is passed a pointer to an array of five words
6521 and the receiver label. */
c2f47e15 6522 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2c8a1497 6523 {
c2f47e15 6524 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
2c8a1497 6525 VOIDmode, EXPAND_NORMAL);
c2f47e15 6526 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
2c8a1497 6527 rtx label_r = label_rtx (label);
6528
6529 /* This is copied from the handling of non-local gotos. */
6530 expand_builtin_setjmp_setup (buf_addr, label_r);
6531 nonlocal_goto_handler_labels
6532 = gen_rtx_EXPR_LIST (VOIDmode, label_r,
6533 nonlocal_goto_handler_labels);
6534 /* ??? Do not let expand_label treat us as such since we would
6535 not want to be both on the list of non-local labels and on
6536 the list of forced labels. */
6537 FORCED_LABEL (label) = 0;
6538 return const0_rtx;
6539 }
6540 break;
6541
6542 case BUILT_IN_SETJMP_DISPATCHER:
6543 /* __builtin_setjmp_dispatcher is passed the dispatcher label. */
c2f47e15 6544 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6545 {
c2f47e15 6546 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6547 rtx label_r = label_rtx (label);
6548
6549 /* Remove the dispatcher label from the list of non-local labels
6550 since the receiver labels have been added to it above. */
6551 remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels);
6552 return const0_rtx;
6553 }
6554 break;
6555
6556 case BUILT_IN_SETJMP_RECEIVER:
6557 /* __builtin_setjmp_receiver is passed the receiver label. */
c2f47e15 6558 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6559 {
c2f47e15 6560 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6561 rtx label_r = label_rtx (label);
6562
6563 expand_builtin_setjmp_receiver (label_r);
6564 return const0_rtx;
6565 }
6b7f6858 6566 break;
53800dbe 6567
6568 /* __builtin_longjmp is passed a pointer to an array of five words.
6569 It's similar to the C library longjmp function but works with
6570 __builtin_setjmp above. */
6571 case BUILT_IN_LONGJMP:
c2f47e15 6572 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 6573 {
c2f47e15 6574 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
8ec3c5c2 6575 VOIDmode, EXPAND_NORMAL);
c2f47e15 6576 rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
53800dbe 6577
6578 if (value != const1_rtx)
6579 {
1e5fcbe2 6580 error ("%<__builtin_longjmp%> second argument must be 1");
53800dbe 6581 return const0_rtx;
6582 }
6583
6584 expand_builtin_longjmp (buf_addr, value);
6585 return const0_rtx;
6586 }
2c8a1497 6587 break;
53800dbe 6588
4ee9c684 6589 case BUILT_IN_NONLOCAL_GOTO:
c2f47e15 6590 target = expand_builtin_nonlocal_goto (exp);
4ee9c684 6591 if (target)
6592 return target;
6593 break;
6594
843d08a9 6595 /* This updates the setjmp buffer that is its argument with the value
6596 of the current stack pointer. */
6597 case BUILT_IN_UPDATE_SETJMP_BUF:
c2f47e15 6598 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
843d08a9 6599 {
6600 rtx buf_addr
c2f47e15 6601 = expand_normal (CALL_EXPR_ARG (exp, 0));
843d08a9 6602
6603 expand_builtin_update_setjmp_buf (buf_addr);
6604 return const0_rtx;
6605 }
6606 break;
6607
53800dbe 6608 case BUILT_IN_TRAP:
a0ef1725 6609 expand_builtin_trap ();
53800dbe 6610 return const0_rtx;
6611
19bf118a 6612 case BUILT_IN_PRINTF:
0b25db21 6613 target = expand_builtin_printf (exp, target, mode, false);
19bf118a 6614 if (target)
6615 return target;
6616 break;
6617
6618 case BUILT_IN_PRINTF_UNLOCKED:
0b25db21 6619 target = expand_builtin_printf (exp, target, mode, true);
19bf118a 6620 if (target)
6621 return target;
6622 break;
6623
df94cd3b 6624 case BUILT_IN_FPUTS:
c2f47e15 6625 target = expand_builtin_fputs (exp, target, false);
c013a46e 6626 if (target)
6627 return target;
6628 break;
6629 case BUILT_IN_FPUTS_UNLOCKED:
c2f47e15 6630 target = expand_builtin_fputs (exp, target, true);
19bf118a 6631 if (target)
6632 return target;
6633 break;
6634
6635 case BUILT_IN_FPRINTF:
0b25db21 6636 target = expand_builtin_fprintf (exp, target, mode, false);
19bf118a 6637 if (target)
6638 return target;
6639 break;
6640
6641 case BUILT_IN_FPRINTF_UNLOCKED:
0b25db21 6642 target = expand_builtin_fprintf (exp, target, mode, true);
df94cd3b 6643 if (target)
6644 return target;
6645 break;
bf8e3599 6646
6411575e 6647 case BUILT_IN_SPRINTF:
c2f47e15 6648 target = expand_builtin_sprintf (exp, target, mode);
6411575e 6649 if (target)
6650 return target;
6651 break;
6652
4f35b1fc 6653 CASE_FLT_FN (BUILT_IN_SIGNBIT):
004e23c4 6654 case BUILT_IN_SIGNBITD32:
6655 case BUILT_IN_SIGNBITD64:
6656 case BUILT_IN_SIGNBITD128:
27f261ef 6657 target = expand_builtin_signbit (exp, target);
6658 if (target)
6659 return target;
6660 break;
6661
53800dbe 6662 /* Various hooks for the DWARF 2 __throw routine. */
6663 case BUILT_IN_UNWIND_INIT:
6664 expand_builtin_unwind_init ();
6665 return const0_rtx;
6666 case BUILT_IN_DWARF_CFA:
6667 return virtual_cfa_rtx;
6668#ifdef DWARF2_UNWIND_INFO
f8f023a5 6669 case BUILT_IN_DWARF_SP_COLUMN:
6670 return expand_builtin_dwarf_sp_column ();
695e919b 6671 case BUILT_IN_INIT_DWARF_REG_SIZES:
c2f47e15 6672 expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
695e919b 6673 return const0_rtx;
53800dbe 6674#endif
6675 case BUILT_IN_FROB_RETURN_ADDR:
c2f47e15 6676 return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6677 case BUILT_IN_EXTRACT_RETURN_ADDR:
c2f47e15 6678 return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6679 case BUILT_IN_EH_RETURN:
c2f47e15 6680 expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
6681 CALL_EXPR_ARG (exp, 1));
53800dbe 6682 return const0_rtx;
df4b504c 6683#ifdef EH_RETURN_DATA_REGNO
6684 case BUILT_IN_EH_RETURN_DATA_REGNO:
c2f47e15 6685 return expand_builtin_eh_return_data_regno (exp);
df4b504c 6686#endif
26093bf4 6687 case BUILT_IN_EXTEND_POINTER:
c2f47e15 6688 return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
26093bf4 6689
7ccc713a 6690 case BUILT_IN_VA_START:
a66c9326 6691 case BUILT_IN_STDARG_START:
c2f47e15 6692 return expand_builtin_va_start (exp);
a66c9326 6693 case BUILT_IN_VA_END:
c2f47e15 6694 return expand_builtin_va_end (exp);
a66c9326 6695 case BUILT_IN_VA_COPY:
c2f47e15 6696 return expand_builtin_va_copy (exp);
89cfe6e5 6697 case BUILT_IN_EXPECT:
c2f47e15 6698 return expand_builtin_expect (exp, target);
5e3608d8 6699 case BUILT_IN_PREFETCH:
c2f47e15 6700 expand_builtin_prefetch (exp);
5e3608d8 6701 return const0_rtx;
6702
4ee9c684 6703 case BUILT_IN_PROFILE_FUNC_ENTER:
6704 return expand_builtin_profile_func (false);
6705 case BUILT_IN_PROFILE_FUNC_EXIT:
6706 return expand_builtin_profile_func (true);
6707
6708 case BUILT_IN_INIT_TRAMPOLINE:
c2f47e15 6709 return expand_builtin_init_trampoline (exp);
4ee9c684 6710 case BUILT_IN_ADJUST_TRAMPOLINE:
c2f47e15 6711 return expand_builtin_adjust_trampoline (exp);
4ee9c684 6712
73673831 6713 case BUILT_IN_FORK:
6714 case BUILT_IN_EXECL:
6715 case BUILT_IN_EXECV:
6716 case BUILT_IN_EXECLP:
6717 case BUILT_IN_EXECLE:
6718 case BUILT_IN_EXECVP:
6719 case BUILT_IN_EXECVE:
c2f47e15 6720 target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
73673831 6721 if (target)
6722 return target;
6723 break;
53800dbe 6724
b6a5fc45 6725 case BUILT_IN_FETCH_AND_ADD_1:
6726 case BUILT_IN_FETCH_AND_ADD_2:
6727 case BUILT_IN_FETCH_AND_ADD_4:
6728 case BUILT_IN_FETCH_AND_ADD_8:
27213ba3 6729 case BUILT_IN_FETCH_AND_ADD_16:
3e272de8 6730 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_ADD_1);
c2f47e15 6731 target = expand_builtin_sync_operation (mode, exp, PLUS,
b6a5fc45 6732 false, target, ignore);
6733 if (target)
6734 return target;
6735 break;
6736
6737 case BUILT_IN_FETCH_AND_SUB_1:
6738 case BUILT_IN_FETCH_AND_SUB_2:
6739 case BUILT_IN_FETCH_AND_SUB_4:
6740 case BUILT_IN_FETCH_AND_SUB_8:
27213ba3 6741 case BUILT_IN_FETCH_AND_SUB_16:
3e272de8 6742 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_SUB_1);
c2f47e15 6743 target = expand_builtin_sync_operation (mode, exp, MINUS,
b6a5fc45 6744 false, target, ignore);
6745 if (target)
6746 return target;
6747 break;
6748
6749 case BUILT_IN_FETCH_AND_OR_1:
6750 case BUILT_IN_FETCH_AND_OR_2:
6751 case BUILT_IN_FETCH_AND_OR_4:
6752 case BUILT_IN_FETCH_AND_OR_8:
27213ba3 6753 case BUILT_IN_FETCH_AND_OR_16:
3e272de8 6754 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_OR_1);
c2f47e15 6755 target = expand_builtin_sync_operation (mode, exp, IOR,
b6a5fc45 6756 false, target, ignore);
6757 if (target)
6758 return target;
6759 break;
6760
6761 case BUILT_IN_FETCH_AND_AND_1:
6762 case BUILT_IN_FETCH_AND_AND_2:
6763 case BUILT_IN_FETCH_AND_AND_4:
6764 case BUILT_IN_FETCH_AND_AND_8:
27213ba3 6765 case BUILT_IN_FETCH_AND_AND_16:
3e272de8 6766 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_AND_1);
c2f47e15 6767 target = expand_builtin_sync_operation (mode, exp, AND,
b6a5fc45 6768 false, target, ignore);
6769 if (target)
6770 return target;
6771 break;
6772
6773 case BUILT_IN_FETCH_AND_XOR_1:
6774 case BUILT_IN_FETCH_AND_XOR_2:
6775 case BUILT_IN_FETCH_AND_XOR_4:
6776 case BUILT_IN_FETCH_AND_XOR_8:
27213ba3 6777 case BUILT_IN_FETCH_AND_XOR_16:
3e272de8 6778 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_XOR_1);
c2f47e15 6779 target = expand_builtin_sync_operation (mode, exp, XOR,
b6a5fc45 6780 false, target, ignore);
6781 if (target)
6782 return target;
6783 break;
6784
6785 case BUILT_IN_FETCH_AND_NAND_1:
6786 case BUILT_IN_FETCH_AND_NAND_2:
6787 case BUILT_IN_FETCH_AND_NAND_4:
6788 case BUILT_IN_FETCH_AND_NAND_8:
27213ba3 6789 case BUILT_IN_FETCH_AND_NAND_16:
3e272de8 6790 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_NAND_1);
c2f47e15 6791 target = expand_builtin_sync_operation (mode, exp, NOT,
b6a5fc45 6792 false, target, ignore);
6793 if (target)
6794 return target;
6795 break;
6796
6797 case BUILT_IN_ADD_AND_FETCH_1:
6798 case BUILT_IN_ADD_AND_FETCH_2:
6799 case BUILT_IN_ADD_AND_FETCH_4:
6800 case BUILT_IN_ADD_AND_FETCH_8:
27213ba3 6801 case BUILT_IN_ADD_AND_FETCH_16:
3e272de8 6802 mode = get_builtin_sync_mode (fcode - BUILT_IN_ADD_AND_FETCH_1);
c2f47e15 6803 target = expand_builtin_sync_operation (mode, exp, PLUS,
b6a5fc45 6804 true, target, ignore);
6805 if (target)
6806 return target;
6807 break;
6808
6809 case BUILT_IN_SUB_AND_FETCH_1:
6810 case BUILT_IN_SUB_AND_FETCH_2:
6811 case BUILT_IN_SUB_AND_FETCH_4:
6812 case BUILT_IN_SUB_AND_FETCH_8:
27213ba3 6813 case BUILT_IN_SUB_AND_FETCH_16:
3e272de8 6814 mode = get_builtin_sync_mode (fcode - BUILT_IN_SUB_AND_FETCH_1);
c2f47e15 6815 target = expand_builtin_sync_operation (mode, exp, MINUS,
b6a5fc45 6816 true, target, ignore);
6817 if (target)
6818 return target;
6819 break;
6820
6821 case BUILT_IN_OR_AND_FETCH_1:
6822 case BUILT_IN_OR_AND_FETCH_2:
6823 case BUILT_IN_OR_AND_FETCH_4:
6824 case BUILT_IN_OR_AND_FETCH_8:
27213ba3 6825 case BUILT_IN_OR_AND_FETCH_16:
3e272de8 6826 mode = get_builtin_sync_mode (fcode - BUILT_IN_OR_AND_FETCH_1);
c2f47e15 6827 target = expand_builtin_sync_operation (mode, exp, IOR,
b6a5fc45 6828 true, target, ignore);
6829 if (target)
6830 return target;
6831 break;
6832
6833 case BUILT_IN_AND_AND_FETCH_1:
6834 case BUILT_IN_AND_AND_FETCH_2:
6835 case BUILT_IN_AND_AND_FETCH_4:
6836 case BUILT_IN_AND_AND_FETCH_8:
27213ba3 6837 case BUILT_IN_AND_AND_FETCH_16:
3e272de8 6838 mode = get_builtin_sync_mode (fcode - BUILT_IN_AND_AND_FETCH_1);
c2f47e15 6839 target = expand_builtin_sync_operation (mode, exp, AND,
b6a5fc45 6840 true, target, ignore);
6841 if (target)
6842 return target;
6843 break;
6844
6845 case BUILT_IN_XOR_AND_FETCH_1:
6846 case BUILT_IN_XOR_AND_FETCH_2:
6847 case BUILT_IN_XOR_AND_FETCH_4:
6848 case BUILT_IN_XOR_AND_FETCH_8:
27213ba3 6849 case BUILT_IN_XOR_AND_FETCH_16:
3e272de8 6850 mode = get_builtin_sync_mode (fcode - BUILT_IN_XOR_AND_FETCH_1);
c2f47e15 6851 target = expand_builtin_sync_operation (mode, exp, XOR,
b6a5fc45 6852 true, target, ignore);
6853 if (target)
6854 return target;
6855 break;
6856
6857 case BUILT_IN_NAND_AND_FETCH_1:
6858 case BUILT_IN_NAND_AND_FETCH_2:
6859 case BUILT_IN_NAND_AND_FETCH_4:
6860 case BUILT_IN_NAND_AND_FETCH_8:
27213ba3 6861 case BUILT_IN_NAND_AND_FETCH_16:
3e272de8 6862 mode = get_builtin_sync_mode (fcode - BUILT_IN_NAND_AND_FETCH_1);
c2f47e15 6863 target = expand_builtin_sync_operation (mode, exp, NOT,
b6a5fc45 6864 true, target, ignore);
6865 if (target)
6866 return target;
6867 break;
6868
6869 case BUILT_IN_BOOL_COMPARE_AND_SWAP_1:
6870 case BUILT_IN_BOOL_COMPARE_AND_SWAP_2:
6871 case BUILT_IN_BOOL_COMPARE_AND_SWAP_4:
6872 case BUILT_IN_BOOL_COMPARE_AND_SWAP_8:
27213ba3 6873 case BUILT_IN_BOOL_COMPARE_AND_SWAP_16:
a601d32a 6874 if (mode == VOIDmode)
6875 mode = TYPE_MODE (boolean_type_node);
b6a5fc45 6876 if (!target || !register_operand (target, mode))
6877 target = gen_reg_rtx (mode);
3e272de8 6878
6879 mode = get_builtin_sync_mode (fcode - BUILT_IN_BOOL_COMPARE_AND_SWAP_1);
c2f47e15 6880 target = expand_builtin_compare_and_swap (mode, exp, true, target);
b6a5fc45 6881 if (target)
6882 return target;
6883 break;
6884
6885 case BUILT_IN_VAL_COMPARE_AND_SWAP_1:
6886 case BUILT_IN_VAL_COMPARE_AND_SWAP_2:
6887 case BUILT_IN_VAL_COMPARE_AND_SWAP_4:
6888 case BUILT_IN_VAL_COMPARE_AND_SWAP_8:
27213ba3 6889 case BUILT_IN_VAL_COMPARE_AND_SWAP_16:
3e272de8 6890 mode = get_builtin_sync_mode (fcode - BUILT_IN_VAL_COMPARE_AND_SWAP_1);
c2f47e15 6891 target = expand_builtin_compare_and_swap (mode, exp, false, target);
b6a5fc45 6892 if (target)
6893 return target;
6894 break;
6895
6896 case BUILT_IN_LOCK_TEST_AND_SET_1:
6897 case BUILT_IN_LOCK_TEST_AND_SET_2:
6898 case BUILT_IN_LOCK_TEST_AND_SET_4:
6899 case BUILT_IN_LOCK_TEST_AND_SET_8:
27213ba3 6900 case BUILT_IN_LOCK_TEST_AND_SET_16:
3e272de8 6901 mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_TEST_AND_SET_1);
c2f47e15 6902 target = expand_builtin_lock_test_and_set (mode, exp, target);
b6a5fc45 6903 if (target)
6904 return target;
6905 break;
6906
6907 case BUILT_IN_LOCK_RELEASE_1:
6908 case BUILT_IN_LOCK_RELEASE_2:
6909 case BUILT_IN_LOCK_RELEASE_4:
6910 case BUILT_IN_LOCK_RELEASE_8:
27213ba3 6911 case BUILT_IN_LOCK_RELEASE_16:
3e272de8 6912 mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_RELEASE_1);
c2f47e15 6913 expand_builtin_lock_release (mode, exp);
b6a5fc45 6914 return const0_rtx;
6915
6916 case BUILT_IN_SYNCHRONIZE:
6917 expand_builtin_synchronize ();
6918 return const0_rtx;
6919
0a39fd54 6920 case BUILT_IN_OBJECT_SIZE:
6921 return expand_builtin_object_size (exp);
6922
6923 case BUILT_IN_MEMCPY_CHK:
6924 case BUILT_IN_MEMPCPY_CHK:
6925 case BUILT_IN_MEMMOVE_CHK:
6926 case BUILT_IN_MEMSET_CHK:
6927 target = expand_builtin_memory_chk (exp, target, mode, fcode);
6928 if (target)
6929 return target;
6930 break;
6931
6932 case BUILT_IN_STRCPY_CHK:
6933 case BUILT_IN_STPCPY_CHK:
6934 case BUILT_IN_STRNCPY_CHK:
6935 case BUILT_IN_STRCAT_CHK:
b356dfef 6936 case BUILT_IN_STRNCAT_CHK:
0a39fd54 6937 case BUILT_IN_SNPRINTF_CHK:
6938 case BUILT_IN_VSNPRINTF_CHK:
6939 maybe_emit_chk_warning (exp, fcode);
6940 break;
6941
6942 case BUILT_IN_SPRINTF_CHK:
6943 case BUILT_IN_VSPRINTF_CHK:
6944 maybe_emit_sprintf_chk_warning (exp, fcode);
6945 break;
6946
92482ee0 6947 default: /* just do library call, if unknown builtin */
146c1b4f 6948 break;
53800dbe 6949 }
6950
6951 /* The switch statement above can drop through to cause the function
6952 to be called normally. */
6953 return expand_call (exp, target, ignore);
6954}
650e4c94 6955
805e22b2 6956/* Determine whether a tree node represents a call to a built-in
52203a9d 6957 function. If the tree T is a call to a built-in function with
6958 the right number of arguments of the appropriate types, return
6959 the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
6960 Otherwise the return value is END_BUILTINS. */
aecda0d6 6961
805e22b2 6962enum built_in_function
b7bf20db 6963builtin_mathfn_code (const_tree t)
805e22b2 6964{
b7bf20db 6965 const_tree fndecl, arg, parmlist;
6966 const_tree argtype, parmtype;
6967 const_call_expr_arg_iterator iter;
805e22b2 6968
6969 if (TREE_CODE (t) != CALL_EXPR
c2f47e15 6970 || TREE_CODE (CALL_EXPR_FN (t)) != ADDR_EXPR)
805e22b2 6971 return END_BUILTINS;
6972
c6e6ecb1 6973 fndecl = get_callee_fndecl (t);
6974 if (fndecl == NULL_TREE
52203a9d 6975 || TREE_CODE (fndecl) != FUNCTION_DECL
805e22b2 6976 || ! DECL_BUILT_IN (fndecl)
6977 || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
6978 return END_BUILTINS;
6979
52203a9d 6980 parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
b7bf20db 6981 init_const_call_expr_arg_iterator (t, &iter);
52203a9d 6982 for (; parmlist; parmlist = TREE_CHAIN (parmlist))
e9f80ff5 6983 {
52203a9d 6984 /* If a function doesn't take a variable number of arguments,
6985 the last element in the list will have type `void'. */
6986 parmtype = TREE_VALUE (parmlist);
6987 if (VOID_TYPE_P (parmtype))
6988 {
b7bf20db 6989 if (more_const_call_expr_args_p (&iter))
52203a9d 6990 return END_BUILTINS;
6991 return DECL_FUNCTION_CODE (fndecl);
6992 }
6993
b7bf20db 6994 if (! more_const_call_expr_args_p (&iter))
e9f80ff5 6995 return END_BUILTINS;
c2f47e15 6996
b7bf20db 6997 arg = next_const_call_expr_arg (&iter);
c2f47e15 6998 argtype = TREE_TYPE (arg);
52203a9d 6999
7000 if (SCALAR_FLOAT_TYPE_P (parmtype))
7001 {
7002 if (! SCALAR_FLOAT_TYPE_P (argtype))
7003 return END_BUILTINS;
7004 }
7005 else if (COMPLEX_FLOAT_TYPE_P (parmtype))
7006 {
7007 if (! COMPLEX_FLOAT_TYPE_P (argtype))
7008 return END_BUILTINS;
7009 }
7010 else if (POINTER_TYPE_P (parmtype))
7011 {
7012 if (! POINTER_TYPE_P (argtype))
7013 return END_BUILTINS;
7014 }
7015 else if (INTEGRAL_TYPE_P (parmtype))
7016 {
7017 if (! INTEGRAL_TYPE_P (argtype))
7018 return END_BUILTINS;
7019 }
7020 else
e9f80ff5 7021 return END_BUILTINS;
e9f80ff5 7022 }
7023
52203a9d 7024 /* Variable-length argument list. */
805e22b2 7025 return DECL_FUNCTION_CODE (fndecl);
7026}
7027
c2f47e15 7028/* Fold a call to __builtin_constant_p, if we know its argument ARG will
7029 evaluate to a constant. */
650e4c94 7030
7031static tree
c2f47e15 7032fold_builtin_constant_p (tree arg)
650e4c94 7033{
650e4c94 7034 /* We return 1 for a numeric type that's known to be a constant
7035 value at compile-time or for an aggregate type that's a
7036 literal constant. */
c2f47e15 7037 STRIP_NOPS (arg);
650e4c94 7038
7039 /* If we know this is a constant, emit the constant of one. */
c2f47e15 7040 if (CONSTANT_CLASS_P (arg)
7041 || (TREE_CODE (arg) == CONSTRUCTOR
7042 && TREE_CONSTANT (arg)))
650e4c94 7043 return integer_one_node;
c2f47e15 7044 if (TREE_CODE (arg) == ADDR_EXPR)
adcfa3a3 7045 {
c2f47e15 7046 tree op = TREE_OPERAND (arg, 0);
adcfa3a3 7047 if (TREE_CODE (op) == STRING_CST
7048 || (TREE_CODE (op) == ARRAY_REF
7049 && integer_zerop (TREE_OPERAND (op, 1))
7050 && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
7051 return integer_one_node;
7052 }
650e4c94 7053
1fb4300c 7054 /* If this expression has side effects, show we don't know it to be a
7055 constant. Likewise if it's a pointer or aggregate type since in
7056 those case we only want literals, since those are only optimized
f97c71a1 7057 when generating RTL, not later.
7058 And finally, if we are compiling an initializer, not code, we
7059 need to return a definite result now; there's not going to be any
7060 more optimization done. */
c2f47e15 7061 if (TREE_SIDE_EFFECTS (arg)
7062 || AGGREGATE_TYPE_P (TREE_TYPE (arg))
7063 || POINTER_TYPE_P (TREE_TYPE (arg))
47be647d 7064 || cfun == 0
7065 || folding_initializer)
650e4c94 7066 return integer_zero_node;
7067
c2f47e15 7068 return NULL_TREE;
650e4c94 7069}
7070
76f5a783 7071/* Create builtin_expect with PRED and EXPECTED as its arguments and
7072 return it as a truthvalue. */
4ee9c684 7073
7074static tree
76f5a783 7075build_builtin_expect_predicate (tree pred, tree expected)
4ee9c684 7076{
76f5a783 7077 tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
4ee9c684 7078
76f5a783 7079 fn = built_in_decls[BUILT_IN_EXPECT];
7080 arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
7081 ret_type = TREE_TYPE (TREE_TYPE (fn));
7082 pred_type = TREE_VALUE (arg_types);
7083 expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
7084
7085 pred = fold_convert (pred_type, pred);
7086 expected = fold_convert (expected_type, expected);
7087 call_expr = build_call_expr (fn, 2, pred, expected);
7088
7089 return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
7090 build_int_cst (ret_type, 0));
7091}
7092
7093/* Fold a call to builtin_expect with arguments ARG0 and ARG1. Return
7094 NULL_TREE if no simplification is possible. */
7095
7096static tree
7097fold_builtin_expect (tree arg0, tree arg1)
7098{
7099 tree inner, fndecl;
7100 enum tree_code code;
7101
7102 /* If this is a builtin_expect within a builtin_expect keep the
7103 inner one. See through a comparison against a constant. It
7104 might have been added to create a thruthvalue. */
7105 inner = arg0;
7106 if (COMPARISON_CLASS_P (inner)
7107 && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST)
7108 inner = TREE_OPERAND (inner, 0);
7109
7110 if (TREE_CODE (inner) == CALL_EXPR
7111 && (fndecl = get_callee_fndecl (inner))
7112 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
7113 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT)
7114 return arg0;
7115
7116 /* Distribute the expected value over short-circuiting operators.
7117 See through the cast from truthvalue_type_node to long. */
7118 inner = arg0;
7119 while (TREE_CODE (inner) == NOP_EXPR
7120 && INTEGRAL_TYPE_P (TREE_TYPE (inner))
7121 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner, 0))))
7122 inner = TREE_OPERAND (inner, 0);
7123
7124 code = TREE_CODE (inner);
7125 if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
7126 {
7127 tree op0 = TREE_OPERAND (inner, 0);
7128 tree op1 = TREE_OPERAND (inner, 1);
7129
7130 op0 = build_builtin_expect_predicate (op0, arg1);
7131 op1 = build_builtin_expect_predicate (op1, arg1);
7132 inner = build2 (code, TREE_TYPE (inner), op0, op1);
7133
7134 return fold_convert (TREE_TYPE (arg0), inner);
7135 }
7136
7137 /* If the argument isn't invariant then there's nothing else we can do. */
7138 if (!TREE_INVARIANT (arg0))
c2f47e15 7139 return NULL_TREE;
4ee9c684 7140
76f5a783 7141 /* If we expect that a comparison against the argument will fold to
7142 a constant return the constant. In practice, this means a true
7143 constant or the address of a non-weak symbol. */
7144 inner = arg0;
4ee9c684 7145 STRIP_NOPS (inner);
7146 if (TREE_CODE (inner) == ADDR_EXPR)
7147 {
7148 do
7149 {
7150 inner = TREE_OPERAND (inner, 0);
7151 }
7152 while (TREE_CODE (inner) == COMPONENT_REF
7153 || TREE_CODE (inner) == ARRAY_REF);
7154 if (DECL_P (inner) && DECL_WEAK (inner))
c2f47e15 7155 return NULL_TREE;
4ee9c684 7156 }
7157
76f5a783 7158 /* Otherwise, ARG0 already has the proper type for the return value. */
7159 return arg0;
4ee9c684 7160}
7161
c2f47e15 7162/* Fold a call to __builtin_classify_type with argument ARG. */
27d0c333 7163
539a3a92 7164static tree
c2f47e15 7165fold_builtin_classify_type (tree arg)
539a3a92 7166{
c2f47e15 7167 if (arg == 0)
7016c612 7168 return build_int_cst (NULL_TREE, no_type_class);
539a3a92 7169
c2f47e15 7170 return build_int_cst (NULL_TREE, type_to_class (TREE_TYPE (arg)));
539a3a92 7171}
7172
c2f47e15 7173/* Fold a call to __builtin_strlen with argument ARG. */
e6e27594 7174
7175static tree
c2f47e15 7176fold_builtin_strlen (tree arg)
e6e27594 7177{
c2f47e15 7178 if (!validate_arg (arg, POINTER_TYPE))
e6e27594 7179 return NULL_TREE;
7180 else
7181 {
c2f47e15 7182 tree len = c_strlen (arg, 0);
e6e27594 7183
7184 if (len)
7185 {
7186 /* Convert from the internal "sizetype" type to "size_t". */
7187 if (size_type_node)
7188 len = fold_convert (size_type_node, len);
7189 return len;
7190 }
7191
7192 return NULL_TREE;
7193 }
7194}
7195
92c43e3c 7196/* Fold a call to __builtin_inf or __builtin_huge_val. */
7197
7198static tree
aecda0d6 7199fold_builtin_inf (tree type, int warn)
92c43e3c 7200{
aa870c1b 7201 REAL_VALUE_TYPE real;
7202
40f4dbd5 7203 /* __builtin_inff is intended to be usable to define INFINITY on all
7204 targets. If an infinity is not available, INFINITY expands "to a
7205 positive constant of type float that overflows at translation
7206 time", footnote "In this case, using INFINITY will violate the
7207 constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
7208 Thus we pedwarn to ensure this constraint violation is
7209 diagnosed. */
92c43e3c 7210 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
40f4dbd5 7211 pedwarn ("target format does not support infinity");
92c43e3c 7212
aa870c1b 7213 real_inf (&real);
7214 return build_real (type, real);
92c43e3c 7215}
7216
c2f47e15 7217/* Fold a call to __builtin_nan or __builtin_nans with argument ARG. */
b0db7939 7218
7219static tree
c2f47e15 7220fold_builtin_nan (tree arg, tree type, int quiet)
b0db7939 7221{
7222 REAL_VALUE_TYPE real;
7223 const char *str;
7224
c2f47e15 7225 if (!validate_arg (arg, POINTER_TYPE))
7226 return NULL_TREE;
7227 str = c_getstr (arg);
b0db7939 7228 if (!str)
c2f47e15 7229 return NULL_TREE;
b0db7939 7230
7231 if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
c2f47e15 7232 return NULL_TREE;
b0db7939 7233
7234 return build_real (type, real);
7235}
7236
277f8dd2 7237/* Return true if the floating point expression T has an integer value.
7238 We also allow +Inf, -Inf and NaN to be considered integer values. */
7239
7240static bool
7241integer_valued_real_p (tree t)
7242{
7243 switch (TREE_CODE (t))
7244 {
7245 case FLOAT_EXPR:
7246 return true;
7247
7248 case ABS_EXPR:
7249 case SAVE_EXPR:
7250 case NON_LVALUE_EXPR:
7251 return integer_valued_real_p (TREE_OPERAND (t, 0));
7252
7253 case COMPOUND_EXPR:
41076ef6 7254 case MODIFY_EXPR:
277f8dd2 7255 case BIND_EXPR:
35cc02b5 7256 return integer_valued_real_p (GENERIC_TREE_OPERAND (t, 1));
277f8dd2 7257
7258 case PLUS_EXPR:
7259 case MINUS_EXPR:
7260 case MULT_EXPR:
7261 case MIN_EXPR:
7262 case MAX_EXPR:
7263 return integer_valued_real_p (TREE_OPERAND (t, 0))
7264 && integer_valued_real_p (TREE_OPERAND (t, 1));
7265
7266 case COND_EXPR:
7267 return integer_valued_real_p (TREE_OPERAND (t, 1))
7268 && integer_valued_real_p (TREE_OPERAND (t, 2));
7269
7270 case REAL_CST:
0570334c 7271 return real_isinteger (TREE_REAL_CST_PTR (t), TYPE_MODE (TREE_TYPE (t)));
277f8dd2 7272
7273 case NOP_EXPR:
7274 {
7275 tree type = TREE_TYPE (TREE_OPERAND (t, 0));
7276 if (TREE_CODE (type) == INTEGER_TYPE)
7277 return true;
7278 if (TREE_CODE (type) == REAL_TYPE)
7279 return integer_valued_real_p (TREE_OPERAND (t, 0));
7280 break;
7281 }
7282
7283 case CALL_EXPR:
7284 switch (builtin_mathfn_code (t))
7285 {
4f35b1fc 7286 CASE_FLT_FN (BUILT_IN_CEIL):
7287 CASE_FLT_FN (BUILT_IN_FLOOR):
7288 CASE_FLT_FN (BUILT_IN_NEARBYINT):
7289 CASE_FLT_FN (BUILT_IN_RINT):
7290 CASE_FLT_FN (BUILT_IN_ROUND):
7291 CASE_FLT_FN (BUILT_IN_TRUNC):
277f8dd2 7292 return true;
7293
d4a43a03 7294 CASE_FLT_FN (BUILT_IN_FMIN):
7295 CASE_FLT_FN (BUILT_IN_FMAX):
c2f47e15 7296 return integer_valued_real_p (CALL_EXPR_ARG (t, 0))
7297 && integer_valued_real_p (CALL_EXPR_ARG (t, 1));
d4a43a03 7298
277f8dd2 7299 default:
7300 break;
7301 }
7302 break;
7303
7304 default:
7305 break;
7306 }
7307 return false;
7308}
7309
c2f47e15 7310/* FNDECL is assumed to be a builtin where truncation can be propagated
6528f4f4 7311 across (for instance floor((double)f) == (double)floorf (f).
c2f47e15 7312 Do the transformation for a call with argument ARG. */
277f8dd2 7313
6528f4f4 7314static tree
c2f47e15 7315fold_trunc_transparent_mathfn (tree fndecl, tree arg)
6528f4f4 7316{
6528f4f4 7317 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
277f8dd2 7318
c2f47e15 7319 if (!validate_arg (arg, REAL_TYPE))
7320 return NULL_TREE;
6528f4f4 7321
277f8dd2 7322 /* Integer rounding functions are idempotent. */
7323 if (fcode == builtin_mathfn_code (arg))
7324 return arg;
7325
7326 /* If argument is already integer valued, and we don't need to worry
7327 about setting errno, there's no need to perform rounding. */
7328 if (! flag_errno_math && integer_valued_real_p (arg))
7329 return arg;
7330
7331 if (optimize)
6528f4f4 7332 {
277f8dd2 7333 tree arg0 = strip_float_extensions (arg);
2426241c 7334 tree ftype = TREE_TYPE (TREE_TYPE (fndecl));
6528f4f4 7335 tree newtype = TREE_TYPE (arg0);
7336 tree decl;
7337
7338 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7339 && (decl = mathfn_built_in (newtype, fcode)))
c2f47e15 7340 return fold_convert (ftype,
7341 build_call_expr (decl, 1,
7342 fold_convert (newtype, arg0)));
6528f4f4 7343 }
c2f47e15 7344 return NULL_TREE;
6528f4f4 7345}
7346
c2f47e15 7347/* FNDECL is assumed to be builtin which can narrow the FP type of
7348 the argument, for instance lround((double)f) -> lroundf (f).
7349 Do the transformation for a call with argument ARG. */
9ed65c7f 7350
7351static tree
c2f47e15 7352fold_fixed_mathfn (tree fndecl, tree arg)
9ed65c7f 7353{
9ed65c7f 7354 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9ed65c7f 7355
c2f47e15 7356 if (!validate_arg (arg, REAL_TYPE))
7357 return NULL_TREE;
9ed65c7f 7358
7359 /* If argument is already integer valued, and we don't need to worry
7360 about setting errno, there's no need to perform rounding. */
7361 if (! flag_errno_math && integer_valued_real_p (arg))
49d00087 7362 return fold_build1 (FIX_TRUNC_EXPR, TREE_TYPE (TREE_TYPE (fndecl)), arg);
9ed65c7f 7363
7364 if (optimize)
7365 {
7366 tree ftype = TREE_TYPE (arg);
7367 tree arg0 = strip_float_extensions (arg);
7368 tree newtype = TREE_TYPE (arg0);
7369 tree decl;
7370
7371 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7372 && (decl = mathfn_built_in (newtype, fcode)))
c2f47e15 7373 return build_call_expr (decl, 1, fold_convert (newtype, arg0));
9ed65c7f 7374 }
73a0da56 7375
7376 /* Canonicalize llround (x) to lround (x) on LP64 targets where
7377 sizeof (long long) == sizeof (long). */
7378 if (TYPE_PRECISION (long_long_integer_type_node)
7379 == TYPE_PRECISION (long_integer_type_node))
7380 {
7381 tree newfn = NULL_TREE;
7382 switch (fcode)
7383 {
7384 CASE_FLT_FN (BUILT_IN_LLCEIL):
7385 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
7386 break;
7387
7388 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7389 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
7390 break;
7391
7392 CASE_FLT_FN (BUILT_IN_LLROUND):
7393 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
7394 break;
7395
7396 CASE_FLT_FN (BUILT_IN_LLRINT):
7397 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
7398 break;
7399
7400 default:
7401 break;
7402 }
7403
7404 if (newfn)
7405 {
c2f47e15 7406 tree newcall = build_call_expr(newfn, 1, arg);
73a0da56 7407 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), newcall);
7408 }
7409 }
7410
c2f47e15 7411 return NULL_TREE;
9ed65c7f 7412}
7413
c2f47e15 7414/* Fold call to builtin cabs, cabsf or cabsl with argument ARG. TYPE is the
7415 return type. Return NULL_TREE if no simplification can be made. */
c63f4ad3 7416
7417static tree
c2f47e15 7418fold_builtin_cabs (tree arg, tree type, tree fndecl)
c63f4ad3 7419{
c2f47e15 7420 tree res;
c63f4ad3 7421
c63f4ad3 7422 if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
7423 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
7424 return NULL_TREE;
7425
b4725390 7426 /* Calculate the result when the argument is a constant. */
7427 if (TREE_CODE (arg) == COMPLEX_CST
7428 && (res = do_mpfr_arg2 (TREE_REALPART (arg), TREE_IMAGPART (arg),
7429 type, mpfr_hypot)))
7430 return res;
7431
1af0d139 7432 if (TREE_CODE (arg) == COMPLEX_EXPR)
7433 {
7434 tree real = TREE_OPERAND (arg, 0);
7435 tree imag = TREE_OPERAND (arg, 1);
7436
7437 /* If either part is zero, cabs is fabs of the other. */
7438 if (real_zerop (real))
7439 return fold_build1 (ABS_EXPR, type, imag);
7440 if (real_zerop (imag))
7441 return fold_build1 (ABS_EXPR, type, real);
7442
7443 /* cabs(x+xi) -> fabs(x)*sqrt(2). */
7444 if (flag_unsafe_math_optimizations
7445 && operand_equal_p (real, imag, OEP_PURE_SAME))
7446 {
2e7ca27b 7447 const REAL_VALUE_TYPE sqrt2_trunc
7448 = real_value_truncate (TYPE_MODE (type), dconstsqrt2);
1af0d139 7449 STRIP_NOPS (real);
7450 return fold_build2 (MULT_EXPR, type,
7451 fold_build1 (ABS_EXPR, type, real),
2e7ca27b 7452 build_real (type, sqrt2_trunc));
1af0d139 7453 }
7454 }
c63f4ad3 7455
749891b2 7456 /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */
7457 if (TREE_CODE (arg) == NEGATE_EXPR
7458 || TREE_CODE (arg) == CONJ_EXPR)
c2f47e15 7459 return build_call_expr (fndecl, 1, TREE_OPERAND (arg, 0));
749891b2 7460
7d3f6cc7 7461 /* Don't do this when optimizing for size. */
7462 if (flag_unsafe_math_optimizations
7463 && optimize && !optimize_size)
c63f4ad3 7464 {
0da0dbfa 7465 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
c63f4ad3 7466
7467 if (sqrtfn != NULL_TREE)
7468 {
c2f47e15 7469 tree rpart, ipart, result;
c63f4ad3 7470
4ee9c684 7471 arg = builtin_save_expr (arg);
29a6518e 7472
49d00087 7473 rpart = fold_build1 (REALPART_EXPR, type, arg);
7474 ipart = fold_build1 (IMAGPART_EXPR, type, arg);
c63f4ad3 7475
4ee9c684 7476 rpart = builtin_save_expr (rpart);
7477 ipart = builtin_save_expr (ipart);
c63f4ad3 7478
49d00087 7479 result = fold_build2 (PLUS_EXPR, type,
7480 fold_build2 (MULT_EXPR, type,
7481 rpart, rpart),
7482 fold_build2 (MULT_EXPR, type,
7483 ipart, ipart));
c63f4ad3 7484
c2f47e15 7485 return build_call_expr (sqrtfn, 1, result);
c63f4ad3 7486 }
7487 }
7488
7489 return NULL_TREE;
7490}
7491
c2f47e15 7492/* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG.
7493 Return NULL_TREE if no simplification can be made. */
e6e27594 7494
7495static tree
c2f47e15 7496fold_builtin_sqrt (tree arg, tree type)
e6e27594 7497{
7498
7499 enum built_in_function fcode;
b4e8ab0c 7500 tree res;
c2f47e15 7501
7502 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7503 return NULL_TREE;
7504
b4e8ab0c 7505 /* Calculate the result when the argument is a constant. */
7506 if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
7507 return res;
7508
e6e27594 7509 /* Optimize sqrt(expN(x)) = expN(x*0.5). */
7510 fcode = builtin_mathfn_code (arg);
7511 if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
7512 {
c2f47e15 7513 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
49d00087 7514 arg = fold_build2 (MULT_EXPR, type,
c2f47e15 7515 CALL_EXPR_ARG (arg, 0),
49d00087 7516 build_real (type, dconsthalf));
c2f47e15 7517 return build_call_expr (expfn, 1, arg);
e6e27594 7518 }
7519
7520 /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */
7521 if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
7522 {
7523 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7524
7525 if (powfn)
7526 {
c2f47e15 7527 tree arg0 = CALL_EXPR_ARG (arg, 0);
e6e27594 7528 tree tree_root;
7529 /* The inner root was either sqrt or cbrt. */
7530 REAL_VALUE_TYPE dconstroot =
7531 BUILTIN_SQRT_P (fcode) ? dconsthalf : dconstthird;
7532
7533 /* Adjust for the outer root. */
7534 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7535 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7536 tree_root = build_real (type, dconstroot);
c2f47e15 7537 return build_call_expr (powfn, 2, arg0, tree_root);
e6e27594 7538 }
7539 }
7540
bc33117f 7541 /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
e6e27594 7542 if (flag_unsafe_math_optimizations
7543 && (fcode == BUILT_IN_POW
7544 || fcode == BUILT_IN_POWF
7545 || fcode == BUILT_IN_POWL))
7546 {
c2f47e15 7547 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
7548 tree arg0 = CALL_EXPR_ARG (arg, 0);
7549 tree arg1 = CALL_EXPR_ARG (arg, 1);
bc33117f 7550 tree narg1;
7551 if (!tree_expr_nonnegative_p (arg0))
7552 arg0 = build1 (ABS_EXPR, type, arg0);
49d00087 7553 narg1 = fold_build2 (MULT_EXPR, type, arg1,
7554 build_real (type, dconsthalf));
c2f47e15 7555 return build_call_expr (powfn, 2, arg0, narg1);
e6e27594 7556 }
7557
7558 return NULL_TREE;
7559}
7560
c2f47e15 7561/* Fold a builtin function call to cbrt, cbrtf, or cbrtl with argument ARG.
7562 Return NULL_TREE if no simplification can be made. */
7563
e6e27594 7564static tree
c2f47e15 7565fold_builtin_cbrt (tree arg, tree type)
e6e27594 7566{
e6e27594 7567 const enum built_in_function fcode = builtin_mathfn_code (arg);
29f4cd78 7568 tree res;
e6e27594 7569
c2f47e15 7570 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7571 return NULL_TREE;
7572
29f4cd78 7573 /* Calculate the result when the argument is a constant. */
7574 if ((res = do_mpfr_arg1 (arg, type, mpfr_cbrt, NULL, NULL, 0)))
7575 return res;
e6e27594 7576
cdfeb715 7577 if (flag_unsafe_math_optimizations)
e6e27594 7578 {
cdfeb715 7579 /* Optimize cbrt(expN(x)) -> expN(x/3). */
7580 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 7581 {
c2f47e15 7582 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7583 const REAL_VALUE_TYPE third_trunc =
7584 real_value_truncate (TYPE_MODE (type), dconstthird);
49d00087 7585 arg = fold_build2 (MULT_EXPR, type,
c2f47e15 7586 CALL_EXPR_ARG (arg, 0),
49d00087 7587 build_real (type, third_trunc));
c2f47e15 7588 return build_call_expr (expfn, 1, arg);
cdfeb715 7589 }
e6e27594 7590
cdfeb715 7591 /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */
7592 if (BUILTIN_SQRT_P (fcode))
a0c938f0 7593 {
cdfeb715 7594 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
e6e27594 7595
cdfeb715 7596 if (powfn)
7597 {
c2f47e15 7598 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7599 tree tree_root;
7600 REAL_VALUE_TYPE dconstroot = dconstthird;
7601
7602 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7603 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7604 tree_root = build_real (type, dconstroot);
c2f47e15 7605 return build_call_expr (powfn, 2, arg0, tree_root);
cdfeb715 7606 }
e6e27594 7607 }
7608
cdfeb715 7609 /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */
7610 if (BUILTIN_CBRT_P (fcode))
a0c938f0 7611 {
c2f47e15 7612 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7613 if (tree_expr_nonnegative_p (arg0))
7614 {
7615 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7616
7617 if (powfn)
a0c938f0 7618 {
cdfeb715 7619 tree tree_root;
7620 REAL_VALUE_TYPE dconstroot;
a0c938f0 7621
cdfeb715 7622 real_arithmetic (&dconstroot, MULT_EXPR, &dconstthird, &dconstthird);
7623 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7624 tree_root = build_real (type, dconstroot);
c2f47e15 7625 return build_call_expr (powfn, 2, arg0, tree_root);
cdfeb715 7626 }
7627 }
7628 }
a0c938f0 7629
cdfeb715 7630 /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */
c2f47e15 7631 if (fcode == BUILT_IN_POW
7632 || fcode == BUILT_IN_POWF
cdfeb715 7633 || fcode == BUILT_IN_POWL)
a0c938f0 7634 {
c2f47e15 7635 tree arg00 = CALL_EXPR_ARG (arg, 0);
7636 tree arg01 = CALL_EXPR_ARG (arg, 1);
cdfeb715 7637 if (tree_expr_nonnegative_p (arg00))
7638 {
c2f47e15 7639 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7640 const REAL_VALUE_TYPE dconstroot
7641 = real_value_truncate (TYPE_MODE (type), dconstthird);
49d00087 7642 tree narg01 = fold_build2 (MULT_EXPR, type, arg01,
7643 build_real (type, dconstroot));
c2f47e15 7644 return build_call_expr (powfn, 2, arg00, narg01);
cdfeb715 7645 }
7646 }
e6e27594 7647 }
7648 return NULL_TREE;
7649}
7650
c2f47e15 7651/* Fold function call to builtin cos, cosf, or cosl with argument ARG.
7652 TYPE is the type of the return value. Return NULL_TREE if no
7653 simplification can be made. */
7654
e6e27594 7655static tree
c2f47e15 7656fold_builtin_cos (tree arg, tree type, tree fndecl)
e6e27594 7657{
e6ab33d8 7658 tree res, narg;
e6e27594 7659
c2f47e15 7660 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7661 return NULL_TREE;
7662
bffb7645 7663 /* Calculate the result when the argument is a constant. */
728bac60 7664 if ((res = do_mpfr_arg1 (arg, type, mpfr_cos, NULL, NULL, 0)))
bffb7645 7665 return res;
7666
e6e27594 7667 /* Optimize cos(-x) into cos (x). */
e6ab33d8 7668 if ((narg = fold_strip_sign_ops (arg)))
c2f47e15 7669 return build_call_expr (fndecl, 1, narg);
e6e27594 7670
7671 return NULL_TREE;
7672}
7673
c2f47e15 7674/* Fold function call to builtin cosh, coshf, or coshl with argument ARG.
7675 Return NULL_TREE if no simplification can be made. */
7676
cacdc1af 7677static tree
c2f47e15 7678fold_builtin_cosh (tree arg, tree type, tree fndecl)
cacdc1af 7679{
c2f47e15 7680 if (validate_arg (arg, REAL_TYPE))
cacdc1af 7681 {
cacdc1af 7682 tree res, narg;
7683
7684 /* Calculate the result when the argument is a constant. */
7685 if ((res = do_mpfr_arg1 (arg, type, mpfr_cosh, NULL, NULL, 0)))
7686 return res;
7687
7688 /* Optimize cosh(-x) into cosh (x). */
7689 if ((narg = fold_strip_sign_ops (arg)))
c2f47e15 7690 return build_call_expr (fndecl, 1, narg);
cacdc1af 7691 }
7692
7693 return NULL_TREE;
7694}
7695
c2f47e15 7696/* Fold function call to builtin tan, tanf, or tanl with argument ARG.
7697 Return NULL_TREE if no simplification can be made. */
7698
e6e27594 7699static tree
c2f47e15 7700fold_builtin_tan (tree arg, tree type)
e6e27594 7701{
7702 enum built_in_function fcode;
29f4cd78 7703 tree res;
e6e27594 7704
c2f47e15 7705 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7706 return NULL_TREE;
7707
bffb7645 7708 /* Calculate the result when the argument is a constant. */
728bac60 7709 if ((res = do_mpfr_arg1 (arg, type, mpfr_tan, NULL, NULL, 0)))
bffb7645 7710 return res;
7711
e6e27594 7712 /* Optimize tan(atan(x)) = x. */
7713 fcode = builtin_mathfn_code (arg);
7714 if (flag_unsafe_math_optimizations
7715 && (fcode == BUILT_IN_ATAN
7716 || fcode == BUILT_IN_ATANF
7717 || fcode == BUILT_IN_ATANL))
c2f47e15 7718 return CALL_EXPR_ARG (arg, 0);
e6e27594 7719
7720 return NULL_TREE;
7721}
7722
d735c391 7723/* Fold function call to builtin sincos, sincosf, or sincosl. Return
7724 NULL_TREE if no simplification can be made. */
7725
7726static tree
c2f47e15 7727fold_builtin_sincos (tree arg0, tree arg1, tree arg2)
d735c391 7728{
c2f47e15 7729 tree type;
d735c391 7730 tree res, fn, call;
7731
c2f47e15 7732 if (!validate_arg (arg0, REAL_TYPE)
7733 || !validate_arg (arg1, POINTER_TYPE)
7734 || !validate_arg (arg2, POINTER_TYPE))
d735c391 7735 return NULL_TREE;
7736
d735c391 7737 type = TREE_TYPE (arg0);
d735c391 7738
7739 /* Calculate the result when the argument is a constant. */
7740 if ((res = do_mpfr_sincos (arg0, arg1, arg2)))
7741 return res;
7742
7743 /* Canonicalize sincos to cexpi. */
2a6b4c77 7744 if (!TARGET_C99_FUNCTIONS)
7745 return NULL_TREE;
d735c391 7746 fn = mathfn_built_in (type, BUILT_IN_CEXPI);
7747 if (!fn)
7748 return NULL_TREE;
7749
c2f47e15 7750 call = build_call_expr (fn, 1, arg0);
d735c391 7751 call = builtin_save_expr (call);
7752
7753 return build2 (COMPOUND_EXPR, type,
7754 build2 (MODIFY_EXPR, void_type_node,
7755 build_fold_indirect_ref (arg1),
7756 build1 (IMAGPART_EXPR, type, call)),
7757 build2 (MODIFY_EXPR, void_type_node,
7758 build_fold_indirect_ref (arg2),
7759 build1 (REALPART_EXPR, type, call)));
7760}
7761
c5bb2c4b 7762/* Fold function call to builtin cexp, cexpf, or cexpl. Return
7763 NULL_TREE if no simplification can be made. */
7764
7765static tree
c2f47e15 7766fold_builtin_cexp (tree arg0, tree type)
c5bb2c4b 7767{
c2f47e15 7768 tree rtype;
c5bb2c4b 7769 tree realp, imagp, ifn;
7770
c2f47e15 7771 if (!validate_arg (arg0, COMPLEX_TYPE))
c5bb2c4b 7772 return NULL_TREE;
7773
c5bb2c4b 7774 rtype = TREE_TYPE (TREE_TYPE (arg0));
7775
7776 /* In case we can figure out the real part of arg0 and it is constant zero
7777 fold to cexpi. */
2a6b4c77 7778 if (!TARGET_C99_FUNCTIONS)
7779 return NULL_TREE;
c5bb2c4b 7780 ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI);
7781 if (!ifn)
7782 return NULL_TREE;
7783
7784 if ((realp = fold_unary (REALPART_EXPR, rtype, arg0))
7785 && real_zerop (realp))
7786 {
7787 tree narg = fold_build1 (IMAGPART_EXPR, rtype, arg0);
c2f47e15 7788 return build_call_expr (ifn, 1, narg);
c5bb2c4b 7789 }
7790
7791 /* In case we can easily decompose real and imaginary parts split cexp
7792 to exp (r) * cexpi (i). */
7793 if (flag_unsafe_math_optimizations
7794 && realp)
7795 {
7796 tree rfn, rcall, icall;
7797
7798 rfn = mathfn_built_in (rtype, BUILT_IN_EXP);
7799 if (!rfn)
7800 return NULL_TREE;
7801
7802 imagp = fold_unary (IMAGPART_EXPR, rtype, arg0);
7803 if (!imagp)
7804 return NULL_TREE;
7805
c2f47e15 7806 icall = build_call_expr (ifn, 1, imagp);
c5bb2c4b 7807 icall = builtin_save_expr (icall);
c2f47e15 7808 rcall = build_call_expr (rfn, 1, realp);
c5bb2c4b 7809 rcall = builtin_save_expr (rcall);
71bf42bb 7810 return fold_build2 (COMPLEX_EXPR, type,
7811 fold_build2 (MULT_EXPR, rtype,
7812 rcall,
7813 fold_build1 (REALPART_EXPR, rtype, icall)),
7814 fold_build2 (MULT_EXPR, rtype,
7815 rcall,
7816 fold_build1 (IMAGPART_EXPR, rtype, icall)));
c5bb2c4b 7817 }
7818
7819 return NULL_TREE;
7820}
7821
c2f47e15 7822/* Fold function call to builtin trunc, truncf or truncl with argument ARG.
7823 Return NULL_TREE if no simplification can be made. */
277f8dd2 7824
7825static tree
c2f47e15 7826fold_builtin_trunc (tree fndecl, tree arg)
277f8dd2 7827{
c2f47e15 7828 if (!validate_arg (arg, REAL_TYPE))
7829 return NULL_TREE;
277f8dd2 7830
7831 /* Optimize trunc of constant value. */
f96bd2bf 7832 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7833 {
7834 REAL_VALUE_TYPE r, x;
2426241c 7835 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7836
7837 x = TREE_REAL_CST (arg);
7838 real_trunc (&r, TYPE_MODE (type), &x);
7839 return build_real (type, r);
7840 }
7841
c2f47e15 7842 return fold_trunc_transparent_mathfn (fndecl, arg);
277f8dd2 7843}
7844
c2f47e15 7845/* Fold function call to builtin floor, floorf or floorl with argument ARG.
7846 Return NULL_TREE if no simplification can be made. */
277f8dd2 7847
7848static tree
c2f47e15 7849fold_builtin_floor (tree fndecl, tree arg)
277f8dd2 7850{
c2f47e15 7851 if (!validate_arg (arg, REAL_TYPE))
7852 return NULL_TREE;
277f8dd2 7853
7854 /* Optimize floor of constant value. */
f96bd2bf 7855 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7856 {
7857 REAL_VALUE_TYPE x;
7858
7859 x = TREE_REAL_CST (arg);
7860 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7861 {
2426241c 7862 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7863 REAL_VALUE_TYPE r;
7864
7865 real_floor (&r, TYPE_MODE (type), &x);
7866 return build_real (type, r);
7867 }
7868 }
7869
acc2b92e 7870 /* Fold floor (x) where x is nonnegative to trunc (x). */
7871 if (tree_expr_nonnegative_p (arg))
30fe8286 7872 {
7873 tree truncfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_TRUNC);
7874 if (truncfn)
c2f47e15 7875 return build_call_expr (truncfn, 1, arg);
30fe8286 7876 }
acc2b92e 7877
c2f47e15 7878 return fold_trunc_transparent_mathfn (fndecl, arg);
277f8dd2 7879}
7880
c2f47e15 7881/* Fold function call to builtin ceil, ceilf or ceill with argument ARG.
7882 Return NULL_TREE if no simplification can be made. */
277f8dd2 7883
7884static tree
c2f47e15 7885fold_builtin_ceil (tree fndecl, tree arg)
277f8dd2 7886{
c2f47e15 7887 if (!validate_arg (arg, REAL_TYPE))
7888 return NULL_TREE;
277f8dd2 7889
7890 /* Optimize ceil of constant value. */
f96bd2bf 7891 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7892 {
7893 REAL_VALUE_TYPE x;
7894
7895 x = TREE_REAL_CST (arg);
7896 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7897 {
2426241c 7898 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7899 REAL_VALUE_TYPE r;
7900
7901 real_ceil (&r, TYPE_MODE (type), &x);
7902 return build_real (type, r);
7903 }
7904 }
7905
c2f47e15 7906 return fold_trunc_transparent_mathfn (fndecl, arg);
277f8dd2 7907}
7908
c2f47e15 7909/* Fold function call to builtin round, roundf or roundl with argument ARG.
7910 Return NULL_TREE if no simplification can be made. */
89ab3887 7911
7912static tree
c2f47e15 7913fold_builtin_round (tree fndecl, tree arg)
89ab3887 7914{
c2f47e15 7915 if (!validate_arg (arg, REAL_TYPE))
7916 return NULL_TREE;
89ab3887 7917
34f17811 7918 /* Optimize round of constant value. */
f96bd2bf 7919 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
89ab3887 7920 {
7921 REAL_VALUE_TYPE x;
7922
7923 x = TREE_REAL_CST (arg);
7924 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7925 {
2426241c 7926 tree type = TREE_TYPE (TREE_TYPE (fndecl));
89ab3887 7927 REAL_VALUE_TYPE r;
7928
7929 real_round (&r, TYPE_MODE (type), &x);
7930 return build_real (type, r);
7931 }
7932 }
7933
c2f47e15 7934 return fold_trunc_transparent_mathfn (fndecl, arg);
89ab3887 7935}
7936
34f17811 7937/* Fold function call to builtin lround, lroundf or lroundl (or the
c2f47e15 7938 corresponding long long versions) and other rounding functions. ARG
7939 is the argument to the call. Return NULL_TREE if no simplification
7940 can be made. */
34f17811 7941
7942static tree
c2f47e15 7943fold_builtin_int_roundingfn (tree fndecl, tree arg)
34f17811 7944{
c2f47e15 7945 if (!validate_arg (arg, REAL_TYPE))
7946 return NULL_TREE;
34f17811 7947
7948 /* Optimize lround of constant value. */
f96bd2bf 7949 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
34f17811 7950 {
7951 const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
7952
776a7bab 7953 if (real_isfinite (&x))
34f17811 7954 {
2426241c 7955 tree itype = TREE_TYPE (TREE_TYPE (fndecl));
ca9b061d 7956 tree ftype = TREE_TYPE (arg);
7957 unsigned HOST_WIDE_INT lo2;
34f17811 7958 HOST_WIDE_INT hi, lo;
7959 REAL_VALUE_TYPE r;
7960
ad52b9b7 7961 switch (DECL_FUNCTION_CODE (fndecl))
7962 {
4f35b1fc 7963 CASE_FLT_FN (BUILT_IN_LFLOOR):
7964 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 7965 real_floor (&r, TYPE_MODE (ftype), &x);
7966 break;
7967
4f35b1fc 7968 CASE_FLT_FN (BUILT_IN_LCEIL):
7969 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 7970 real_ceil (&r, TYPE_MODE (ftype), &x);
7971 break;
7972
4f35b1fc 7973 CASE_FLT_FN (BUILT_IN_LROUND):
7974 CASE_FLT_FN (BUILT_IN_LLROUND):
ad52b9b7 7975 real_round (&r, TYPE_MODE (ftype), &x);
7976 break;
7977
7978 default:
7979 gcc_unreachable ();
7980 }
7981
34f17811 7982 REAL_VALUE_TO_INT (&lo, &hi, r);
ca9b061d 7983 if (!fit_double_type (lo, hi, &lo2, &hi, itype))
7984 return build_int_cst_wide (itype, lo2, hi);
34f17811 7985 }
7986 }
7987
acc2b92e 7988 switch (DECL_FUNCTION_CODE (fndecl))
7989 {
7990 CASE_FLT_FN (BUILT_IN_LFLOOR):
7991 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7992 /* Fold lfloor (x) where x is nonnegative to FIX_TRUNC (x). */
7993 if (tree_expr_nonnegative_p (arg))
7994 return fold_build1 (FIX_TRUNC_EXPR, TREE_TYPE (TREE_TYPE (fndecl)),
7995 arg);
7996 break;
7997 default:;
7998 }
7999
c2f47e15 8000 return fold_fixed_mathfn (fndecl, arg);
34f17811 8001}
8002
70fb4c07 8003/* Fold function call to builtin ffs, clz, ctz, popcount and parity
c2f47e15 8004 and their long and long long variants (i.e. ffsl and ffsll). ARG is
8005 the argument to the call. Return NULL_TREE if no simplification can
8006 be made. */
70fb4c07 8007
8008static tree
c2f47e15 8009fold_builtin_bitop (tree fndecl, tree arg)
70fb4c07 8010{
c2f47e15 8011 if (!validate_arg (arg, INTEGER_TYPE))
70fb4c07 8012 return NULL_TREE;
8013
8014 /* Optimize for constant argument. */
f96bd2bf 8015 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
70fb4c07 8016 {
8017 HOST_WIDE_INT hi, width, result;
8018 unsigned HOST_WIDE_INT lo;
7c446c95 8019 tree type;
70fb4c07 8020
8021 type = TREE_TYPE (arg);
8022 width = TYPE_PRECISION (type);
8023 lo = TREE_INT_CST_LOW (arg);
8024
8025 /* Clear all the bits that are beyond the type's precision. */
8026 if (width > HOST_BITS_PER_WIDE_INT)
8027 {
8028 hi = TREE_INT_CST_HIGH (arg);
8029 if (width < 2 * HOST_BITS_PER_WIDE_INT)
8030 hi &= ~((HOST_WIDE_INT) (-1) >> (width - HOST_BITS_PER_WIDE_INT));
8031 }
8032 else
8033 {
8034 hi = 0;
8035 if (width < HOST_BITS_PER_WIDE_INT)
8036 lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
8037 }
8038
8039 switch (DECL_FUNCTION_CODE (fndecl))
8040 {
4f35b1fc 8041 CASE_INT_FN (BUILT_IN_FFS):
70fb4c07 8042 if (lo != 0)
8043 result = exact_log2 (lo & -lo) + 1;
8044 else if (hi != 0)
8045 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi) + 1;
8046 else
8047 result = 0;
8048 break;
8049
4f35b1fc 8050 CASE_INT_FN (BUILT_IN_CLZ):
70fb4c07 8051 if (hi != 0)
8052 result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
8053 else if (lo != 0)
8054 result = width - floor_log2 (lo) - 1;
8055 else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
8056 result = width;
8057 break;
8058
4f35b1fc 8059 CASE_INT_FN (BUILT_IN_CTZ):
70fb4c07 8060 if (lo != 0)
8061 result = exact_log2 (lo & -lo);
8062 else if (hi != 0)
8063 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi);
8064 else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
8065 result = width;
8066 break;
8067
4f35b1fc 8068 CASE_INT_FN (BUILT_IN_POPCOUNT):
70fb4c07 8069 result = 0;
8070 while (lo)
8071 result++, lo &= lo - 1;
8072 while (hi)
8073 result++, hi &= hi - 1;
8074 break;
8075
4f35b1fc 8076 CASE_INT_FN (BUILT_IN_PARITY):
70fb4c07 8077 result = 0;
8078 while (lo)
8079 result++, lo &= lo - 1;
8080 while (hi)
8081 result++, hi &= hi - 1;
8082 result &= 1;
8083 break;
8084
8085 default:
64db345d 8086 gcc_unreachable ();
70fb4c07 8087 }
8088
2426241c 8089 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
70fb4c07 8090 }
8091
8092 return NULL_TREE;
8093}
8094
42791117 8095/* Fold function call to builtin_bswap and the long and long long
8096 variants. Return NULL_TREE if no simplification can be made. */
8097static tree
c2f47e15 8098fold_builtin_bswap (tree fndecl, tree arg)
42791117 8099{
c2f47e15 8100 if (! validate_arg (arg, INTEGER_TYPE))
8101 return NULL_TREE;
42791117 8102
8103 /* Optimize constant value. */
f96bd2bf 8104 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
42791117 8105 {
8106 HOST_WIDE_INT hi, width, r_hi = 0;
8107 unsigned HOST_WIDE_INT lo, r_lo = 0;
8108 tree type;
8109
8110 type = TREE_TYPE (arg);
8111 width = TYPE_PRECISION (type);
8112 lo = TREE_INT_CST_LOW (arg);
8113 hi = TREE_INT_CST_HIGH (arg);
8114
8115 switch (DECL_FUNCTION_CODE (fndecl))
8116 {
8117 case BUILT_IN_BSWAP32:
8118 case BUILT_IN_BSWAP64:
8119 {
8120 int s;
8121
8122 for (s = 0; s < width; s += 8)
8123 {
8124 int d = width - s - 8;
8125 unsigned HOST_WIDE_INT byte;
8126
8127 if (s < HOST_BITS_PER_WIDE_INT)
8128 byte = (lo >> s) & 0xff;
8129 else
8130 byte = (hi >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff;
8131
8132 if (d < HOST_BITS_PER_WIDE_INT)
8133 r_lo |= byte << d;
8134 else
8135 r_hi |= byte << (d - HOST_BITS_PER_WIDE_INT);
8136 }
8137 }
8138
8139 break;
8140
8141 default:
8142 gcc_unreachable ();
8143 }
8144
8145 if (width < HOST_BITS_PER_WIDE_INT)
8146 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), r_lo);
8147 else
8148 return build_int_cst_wide (TREE_TYPE (TREE_TYPE (fndecl)), r_lo, r_hi);
8149 }
8150
8151 return NULL_TREE;
8152}
c2f47e15 8153
8918c507 8154/* Return true if EXPR is the real constant contained in VALUE. */
8155
8156static bool
8157real_dconstp (tree expr, const REAL_VALUE_TYPE *value)
8158{
8159 STRIP_NOPS (expr);
8160
8161 return ((TREE_CODE (expr) == REAL_CST
f96bd2bf 8162 && !TREE_OVERFLOW (expr)
a0c938f0 8163 && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), *value))
8164 || (TREE_CODE (expr) == COMPLEX_CST
8165 && real_dconstp (TREE_REALPART (expr), value)
8166 && real_zerop (TREE_IMAGPART (expr))));
8918c507 8167}
8168
8169/* A subroutine of fold_builtin to fold the various logarithmic
29f4cd78 8170 functions. Return NULL_TREE if no simplification can me made.
8171 FUNC is the corresponding MPFR logarithm function. */
8918c507 8172
8173static tree
c2f47e15 8174fold_builtin_logarithm (tree fndecl, tree arg,
29f4cd78 8175 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8176{
c2f47e15 8177 if (validate_arg (arg, REAL_TYPE))
8918c507 8178 {
8918c507 8179 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8180 tree res;
8918c507 8181 const enum built_in_function fcode = builtin_mathfn_code (arg);
0862b7e9 8182
29f4cd78 8183 /* Optimize log(e) = 1.0. We're never passed an exact 'e',
8184 instead we'll look for 'e' truncated to MODE. So only do
8185 this if flag_unsafe_math_optimizations is set. */
8186 if (flag_unsafe_math_optimizations && func == mpfr_log)
8187 {
8188 const REAL_VALUE_TYPE e_truncated =
8189 real_value_truncate (TYPE_MODE (type), dconste);
8190 if (real_dconstp (arg, &e_truncated))
1f5cb383 8191 return build_real (type, dconst1);
8192 }
0862b7e9 8193
29f4cd78 8194 /* Calculate the result when the argument is a constant. */
8195 if ((res = do_mpfr_arg1 (arg, type, func, &dconst0, NULL, false)))
8196 return res;
8197
8918c507 8198 /* Special case, optimize logN(expN(x)) = x. */
8199 if (flag_unsafe_math_optimizations
29f4cd78 8200 && ((func == mpfr_log
8918c507 8201 && (fcode == BUILT_IN_EXP
8202 || fcode == BUILT_IN_EXPF
8203 || fcode == BUILT_IN_EXPL))
29f4cd78 8204 || (func == mpfr_log2
8918c507 8205 && (fcode == BUILT_IN_EXP2
8206 || fcode == BUILT_IN_EXP2F
8207 || fcode == BUILT_IN_EXP2L))
29f4cd78 8208 || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode)))))
c2f47e15 8209 return fold_convert (type, CALL_EXPR_ARG (arg, 0));
8918c507 8210
ca273d4a 8211 /* Optimize logN(func()) for various exponential functions. We
a0c938f0 8212 want to determine the value "x" and the power "exponent" in
8213 order to transform logN(x**exponent) into exponent*logN(x). */
8918c507 8214 if (flag_unsafe_math_optimizations)
a0c938f0 8215 {
8918c507 8216 tree exponent = 0, x = 0;
0862b7e9 8217
8918c507 8218 switch (fcode)
8219 {
4f35b1fc 8220 CASE_FLT_FN (BUILT_IN_EXP):
8918c507 8221 /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
8918c507 8222 x = build_real (type,
8223 real_value_truncate (TYPE_MODE (type), dconste));
c2f47e15 8224 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8225 break;
4f35b1fc 8226 CASE_FLT_FN (BUILT_IN_EXP2):
8918c507 8227 /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */
8228 x = build_real (type, dconst2);
c2f47e15 8229 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8230 break;
4f35b1fc 8231 CASE_FLT_FN (BUILT_IN_EXP10):
8232 CASE_FLT_FN (BUILT_IN_POW10):
8918c507 8233 /* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */
8234 x = build_real (type, dconst10);
c2f47e15 8235 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8236 break;
4f35b1fc 8237 CASE_FLT_FN (BUILT_IN_SQRT):
8918c507 8238 /* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */
c2f47e15 8239 x = CALL_EXPR_ARG (arg, 0);
8918c507 8240 exponent = build_real (type, dconsthalf);
8241 break;
4f35b1fc 8242 CASE_FLT_FN (BUILT_IN_CBRT):
8918c507 8243 /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */
c2f47e15 8244 x = CALL_EXPR_ARG (arg, 0);
8918c507 8245 exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
8246 dconstthird));
8247 break;
4f35b1fc 8248 CASE_FLT_FN (BUILT_IN_POW):
8918c507 8249 /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x). */
c2f47e15 8250 x = CALL_EXPR_ARG (arg, 0);
8251 exponent = CALL_EXPR_ARG (arg, 1);
8918c507 8252 break;
8253 default:
8254 break;
8255 }
8256
8257 /* Now perform the optimization. */
8258 if (x && exponent)
8259 {
c2f47e15 8260 tree logfn = build_call_expr (fndecl, 1, x);
49d00087 8261 return fold_build2 (MULT_EXPR, type, exponent, logfn);
8918c507 8262 }
8263 }
8264 }
8265
c2f47e15 8266 return NULL_TREE;
8918c507 8267}
0862b7e9 8268
f0c477f2 8269/* Fold a builtin function call to hypot, hypotf, or hypotl. Return
8270 NULL_TREE if no simplification can be made. */
8271
8272static tree
c2f47e15 8273fold_builtin_hypot (tree fndecl, tree arg0, tree arg1, tree type)
f0c477f2 8274{
e6ab33d8 8275 tree res, narg0, narg1;
f0c477f2 8276
c2f47e15 8277 if (!validate_arg (arg0, REAL_TYPE)
8278 || !validate_arg (arg1, REAL_TYPE))
f0c477f2 8279 return NULL_TREE;
8280
8281 /* Calculate the result when the argument is a constant. */
8282 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot)))
8283 return res;
8284
6c95f21c 8285 /* If either argument to hypot has a negate or abs, strip that off.
8286 E.g. hypot(-x,fabs(y)) -> hypot(x,y). */
e6ab33d8 8287 narg0 = fold_strip_sign_ops (arg0);
8288 narg1 = fold_strip_sign_ops (arg1);
8289 if (narg0 || narg1)
8290 {
c2f47e15 8291 return build_call_expr (fndecl, 2, narg0 ? narg0 : arg0,
8292 narg1 ? narg1 : arg1);
6c95f21c 8293 }
8294
f0c477f2 8295 /* If either argument is zero, hypot is fabs of the other. */
8296 if (real_zerop (arg0))
8297 return fold_build1 (ABS_EXPR, type, arg1);
8298 else if (real_zerop (arg1))
8299 return fold_build1 (ABS_EXPR, type, arg0);
8300
6c95f21c 8301 /* hypot(x,x) -> fabs(x)*sqrt(2). */
8302 if (flag_unsafe_math_optimizations
8303 && operand_equal_p (arg0, arg1, OEP_PURE_SAME))
f0c477f2 8304 {
2e7ca27b 8305 const REAL_VALUE_TYPE sqrt2_trunc
8306 = real_value_truncate (TYPE_MODE (type), dconstsqrt2);
6c95f21c 8307 return fold_build2 (MULT_EXPR, type,
8308 fold_build1 (ABS_EXPR, type, arg0),
2e7ca27b 8309 build_real (type, sqrt2_trunc));
f0c477f2 8310 }
8311
f0c477f2 8312 return NULL_TREE;
8313}
8314
8315
e6e27594 8316/* Fold a builtin function call to pow, powf, or powl. Return
8317 NULL_TREE if no simplification can be made. */
8318static tree
c2f47e15 8319fold_builtin_pow (tree fndecl, tree arg0, tree arg1, tree type)
e6e27594 8320{
f0c477f2 8321 tree res;
e6e27594 8322
c2f47e15 8323 if (!validate_arg (arg0, REAL_TYPE)
8324 || !validate_arg (arg1, REAL_TYPE))
e6e27594 8325 return NULL_TREE;
8326
f0c477f2 8327 /* Calculate the result when the argument is a constant. */
8328 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_pow)))
8329 return res;
8330
e6e27594 8331 /* Optimize pow(1.0,y) = 1.0. */
8332 if (real_onep (arg0))
8333 return omit_one_operand (type, build_real (type, dconst1), arg1);
8334
8335 if (TREE_CODE (arg1) == REAL_CST
f96bd2bf 8336 && !TREE_OVERFLOW (arg1))
e6e27594 8337 {
198d9bbe 8338 REAL_VALUE_TYPE cint;
e6e27594 8339 REAL_VALUE_TYPE c;
198d9bbe 8340 HOST_WIDE_INT n;
8341
e6e27594 8342 c = TREE_REAL_CST (arg1);
8343
8344 /* Optimize pow(x,0.0) = 1.0. */
8345 if (REAL_VALUES_EQUAL (c, dconst0))
8346 return omit_one_operand (type, build_real (type, dconst1),
8347 arg0);
8348
8349 /* Optimize pow(x,1.0) = x. */
8350 if (REAL_VALUES_EQUAL (c, dconst1))
8351 return arg0;
8352
8353 /* Optimize pow(x,-1.0) = 1.0/x. */
8354 if (REAL_VALUES_EQUAL (c, dconstm1))
49d00087 8355 return fold_build2 (RDIV_EXPR, type,
8356 build_real (type, dconst1), arg0);
e6e27594 8357
8358 /* Optimize pow(x,0.5) = sqrt(x). */
8359 if (flag_unsafe_math_optimizations
8360 && REAL_VALUES_EQUAL (c, dconsthalf))
8361 {
8362 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
8363
8364 if (sqrtfn != NULL_TREE)
c2f47e15 8365 return build_call_expr (sqrtfn, 1, arg0);
e6e27594 8366 }
8367
feb5b3eb 8368 /* Optimize pow(x,1.0/3.0) = cbrt(x). */
8369 if (flag_unsafe_math_optimizations)
8370 {
8371 const REAL_VALUE_TYPE dconstroot
8372 = real_value_truncate (TYPE_MODE (type), dconstthird);
8373
8374 if (REAL_VALUES_EQUAL (c, dconstroot))
8375 {
8376 tree cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT);
8377 if (cbrtfn != NULL_TREE)
c2f47e15 8378 return build_call_expr (cbrtfn, 1, arg0);
feb5b3eb 8379 }
8380 }
8381
198d9bbe 8382 /* Check for an integer exponent. */
8383 n = real_to_integer (&c);
8384 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
8385 if (real_identical (&c, &cint))
e6e27594 8386 {
198d9bbe 8387 /* Attempt to evaluate pow at compile-time. */
8388 if (TREE_CODE (arg0) == REAL_CST
f96bd2bf 8389 && !TREE_OVERFLOW (arg0))
e6e27594 8390 {
8391 REAL_VALUE_TYPE x;
8392 bool inexact;
8393
8394 x = TREE_REAL_CST (arg0);
8395 inexact = real_powi (&x, TYPE_MODE (type), &x, n);
8396 if (flag_unsafe_math_optimizations || !inexact)
8397 return build_real (type, x);
8398 }
198d9bbe 8399
8400 /* Strip sign ops from even integer powers. */
8401 if ((n & 1) == 0 && flag_unsafe_math_optimizations)
8402 {
8403 tree narg0 = fold_strip_sign_ops (arg0);
8404 if (narg0)
c2f47e15 8405 return build_call_expr (fndecl, 2, narg0, arg1);
198d9bbe 8406 }
e6e27594 8407 }
8408 }
8409
cdfeb715 8410 if (flag_unsafe_math_optimizations)
e6e27594 8411 {
cdfeb715 8412 const enum built_in_function fcode = builtin_mathfn_code (arg0);
e6e27594 8413
cdfeb715 8414 /* Optimize pow(expN(x),y) = expN(x*y). */
8415 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 8416 {
c2f47e15 8417 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
8418 tree arg = CALL_EXPR_ARG (arg0, 0);
49d00087 8419 arg = fold_build2 (MULT_EXPR, type, arg, arg1);
c2f47e15 8420 return build_call_expr (expfn, 1, arg);
cdfeb715 8421 }
e6e27594 8422
cdfeb715 8423 /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
8424 if (BUILTIN_SQRT_P (fcode))
a0c938f0 8425 {
c2f47e15 8426 tree narg0 = CALL_EXPR_ARG (arg0, 0);
49d00087 8427 tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
8428 build_real (type, dconsthalf));
c2f47e15 8429 return build_call_expr (fndecl, 2, narg0, narg1);
cdfeb715 8430 }
8431
8432 /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */
8433 if (BUILTIN_CBRT_P (fcode))
a0c938f0 8434 {
c2f47e15 8435 tree arg = CALL_EXPR_ARG (arg0, 0);
cdfeb715 8436 if (tree_expr_nonnegative_p (arg))
8437 {
8438 const REAL_VALUE_TYPE dconstroot
8439 = real_value_truncate (TYPE_MODE (type), dconstthird);
49d00087 8440 tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
8441 build_real (type, dconstroot));
c2f47e15 8442 return build_call_expr (fndecl, 2, arg, narg1);
cdfeb715 8443 }
8444 }
a0c938f0 8445
cdfeb715 8446 /* Optimize pow(pow(x,y),z) = pow(x,y*z). */
c2f47e15 8447 if (fcode == BUILT_IN_POW
8448 || fcode == BUILT_IN_POWF
8449 || fcode == BUILT_IN_POWL)
a0c938f0 8450 {
c2f47e15 8451 tree arg00 = CALL_EXPR_ARG (arg0, 0);
8452 tree arg01 = CALL_EXPR_ARG (arg0, 1);
49d00087 8453 tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1);
c2f47e15 8454 return build_call_expr (fndecl, 2, arg00, narg1);
cdfeb715 8455 }
e6e27594 8456 }
cdfeb715 8457
e6e27594 8458 return NULL_TREE;
8459}
8460
c2f47e15 8461/* Fold a builtin function call to powi, powif, or powil with argument ARG.
8462 Return NULL_TREE if no simplification can be made. */
b4d0c20c 8463static tree
c2f47e15 8464fold_builtin_powi (tree fndecl ATTRIBUTE_UNUSED,
8465 tree arg0, tree arg1, tree type)
b4d0c20c 8466{
c2f47e15 8467 if (!validate_arg (arg0, REAL_TYPE)
8468 || !validate_arg (arg1, INTEGER_TYPE))
b4d0c20c 8469 return NULL_TREE;
8470
8471 /* Optimize pow(1.0,y) = 1.0. */
8472 if (real_onep (arg0))
8473 return omit_one_operand (type, build_real (type, dconst1), arg1);
8474
8475 if (host_integerp (arg1, 0))
8476 {
8477 HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
8478
8479 /* Evaluate powi at compile-time. */
8480 if (TREE_CODE (arg0) == REAL_CST
f96bd2bf 8481 && !TREE_OVERFLOW (arg0))
b4d0c20c 8482 {
8483 REAL_VALUE_TYPE x;
8484 x = TREE_REAL_CST (arg0);
8485 real_powi (&x, TYPE_MODE (type), &x, c);
8486 return build_real (type, x);
8487 }
8488
8489 /* Optimize pow(x,0) = 1.0. */
8490 if (c == 0)
8491 return omit_one_operand (type, build_real (type, dconst1),
8492 arg0);
8493
8494 /* Optimize pow(x,1) = x. */
8495 if (c == 1)
8496 return arg0;
8497
8498 /* Optimize pow(x,-1) = 1.0/x. */
8499 if (c == -1)
49d00087 8500 return fold_build2 (RDIV_EXPR, type,
8501 build_real (type, dconst1), arg0);
b4d0c20c 8502 }
8503
8504 return NULL_TREE;
8505}
8506
8918c507 8507/* A subroutine of fold_builtin to fold the various exponent
c2f47e15 8508 functions. Return NULL_TREE if no simplification can be made.
debf9994 8509 FUNC is the corresponding MPFR exponent function. */
8918c507 8510
8511static tree
c2f47e15 8512fold_builtin_exponent (tree fndecl, tree arg,
debf9994 8513 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8514{
c2f47e15 8515 if (validate_arg (arg, REAL_TYPE))
8918c507 8516 {
8918c507 8517 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8518 tree res;
debf9994 8519
8520 /* Calculate the result when the argument is a constant. */
728bac60 8521 if ((res = do_mpfr_arg1 (arg, type, func, NULL, NULL, 0)))
debf9994 8522 return res;
8918c507 8523
8524 /* Optimize expN(logN(x)) = x. */
8525 if (flag_unsafe_math_optimizations)
a0c938f0 8526 {
8918c507 8527 const enum built_in_function fcode = builtin_mathfn_code (arg);
8528
debf9994 8529 if ((func == mpfr_exp
8918c507 8530 && (fcode == BUILT_IN_LOG
8531 || fcode == BUILT_IN_LOGF
8532 || fcode == BUILT_IN_LOGL))
debf9994 8533 || (func == mpfr_exp2
8918c507 8534 && (fcode == BUILT_IN_LOG2
8535 || fcode == BUILT_IN_LOG2F
8536 || fcode == BUILT_IN_LOG2L))
debf9994 8537 || (func == mpfr_exp10
8918c507 8538 && (fcode == BUILT_IN_LOG10
8539 || fcode == BUILT_IN_LOG10F
8540 || fcode == BUILT_IN_LOG10L)))
c2f47e15 8541 return fold_convert (type, CALL_EXPR_ARG (arg, 0));
8918c507 8542 }
8543 }
8544
c2f47e15 8545 return NULL_TREE;
8918c507 8546}
8547
e973ffcc 8548/* Return true if VAR is a VAR_DECL or a component thereof. */
8549
8550static bool
8551var_decl_component_p (tree var)
8552{
8553 tree inner = var;
8554 while (handled_component_p (inner))
8555 inner = TREE_OPERAND (inner, 0);
8556 return SSA_VAR_P (inner);
8557}
8558
4f46f2b9 8559/* Fold function call to builtin memset. Return
9c8a1629 8560 NULL_TREE if no simplification can be made. */
8561
8562static tree
c2f47e15 8563fold_builtin_memset (tree dest, tree c, tree len, tree type, bool ignore)
9c8a1629 8564{
c2f47e15 8565 tree var, ret;
4f46f2b9 8566 unsigned HOST_WIDE_INT length, cval;
9c8a1629 8567
c2f47e15 8568 if (! validate_arg (dest, POINTER_TYPE)
8569 || ! validate_arg (c, INTEGER_TYPE)
8570 || ! validate_arg (len, INTEGER_TYPE))
8571 return NULL_TREE;
9c8a1629 8572
4f46f2b9 8573 if (! host_integerp (len, 1))
c2f47e15 8574 return NULL_TREE;
4f46f2b9 8575
9c8a1629 8576 /* If the LEN parameter is zero, return DEST. */
8577 if (integer_zerop (len))
4f46f2b9 8578 return omit_one_operand (type, dest, c);
9c8a1629 8579
4f46f2b9 8580 if (! host_integerp (c, 1) || TREE_SIDE_EFFECTS (dest))
c2f47e15 8581 return NULL_TREE;
9c8a1629 8582
4f46f2b9 8583 var = dest;
8584 STRIP_NOPS (var);
8585 if (TREE_CODE (var) != ADDR_EXPR)
c2f47e15 8586 return NULL_TREE;
4f46f2b9 8587
8588 var = TREE_OPERAND (var, 0);
8589 if (TREE_THIS_VOLATILE (var))
c2f47e15 8590 return NULL_TREE;
4f46f2b9 8591
8592 if (!INTEGRAL_TYPE_P (TREE_TYPE (var))
8593 && !POINTER_TYPE_P (TREE_TYPE (var)))
c2f47e15 8594 return NULL_TREE;
4f46f2b9 8595
e973ffcc 8596 if (! var_decl_component_p (var))
c2f47e15 8597 return NULL_TREE;
e973ffcc 8598
4f46f2b9 8599 length = tree_low_cst (len, 1);
8600 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (var))) != length
8601 || get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
8602 < (int) length)
c2f47e15 8603 return NULL_TREE;
4f46f2b9 8604
8605 if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT)
c2f47e15 8606 return NULL_TREE;
4f46f2b9 8607
8608 if (integer_zerop (c))
8609 cval = 0;
8610 else
8611 {
8612 if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64)
c2f47e15 8613 return NULL_TREE;
4f46f2b9 8614
8615 cval = tree_low_cst (c, 1);
8616 cval &= 0xff;
8617 cval |= cval << 8;
8618 cval |= cval << 16;
8619 cval |= (cval << 31) << 1;
8620 }
8621
8622 ret = build_int_cst_type (TREE_TYPE (var), cval);
41076ef6 8623 ret = build2 (MODIFY_EXPR, TREE_TYPE (var), var, ret);
4f46f2b9 8624 if (ignore)
8625 return ret;
8626
8627 return omit_one_operand (type, dest, ret);
9c8a1629 8628}
8629
4f46f2b9 8630/* Fold function call to builtin memset. Return
9c8a1629 8631 NULL_TREE if no simplification can be made. */
8632
8633static tree
c2f47e15 8634fold_builtin_bzero (tree dest, tree size, bool ignore)
9c8a1629 8635{
c2f47e15 8636 if (! validate_arg (dest, POINTER_TYPE)
8637 || ! validate_arg (size, INTEGER_TYPE))
8638 return NULL_TREE;
9c8a1629 8639
4f46f2b9 8640 if (!ignore)
c2f47e15 8641 return NULL_TREE;
a0c938f0 8642
4f46f2b9 8643 /* New argument list transforming bzero(ptr x, int y) to
8644 memset(ptr x, int 0, size_t y). This is done this way
8645 so that if it isn't expanded inline, we fallback to
8646 calling bzero instead of memset. */
8647
c2f47e15 8648 return fold_builtin_memset (dest, integer_zero_node,
8649 fold_convert (sizetype, size),
8650 void_type_node, ignore);
9c8a1629 8651}
8652
4f46f2b9 8653/* Fold function call to builtin mem{{,p}cpy,move}. Return
8654 NULL_TREE if no simplification can be made.
8655 If ENDP is 0, return DEST (like memcpy).
8656 If ENDP is 1, return DEST+LEN (like mempcpy).
8657 If ENDP is 2, return DEST+LEN-1 (like stpcpy).
8658 If ENDP is 3, return DEST, additionally *SRC and *DEST may overlap
8659 (memmove). */
9c8a1629 8660
8661static tree
c2f47e15 8662fold_builtin_memory_op (tree dest, tree src, tree len, tree type, bool ignore, int endp)
9c8a1629 8663{
c2f47e15 8664 tree destvar, srcvar, expr;
9c8a1629 8665
c2f47e15 8666 if (! validate_arg (dest, POINTER_TYPE)
8667 || ! validate_arg (src, POINTER_TYPE)
8668 || ! validate_arg (len, INTEGER_TYPE))
8669 return NULL_TREE;
9c8a1629 8670
8671 /* If the LEN parameter is zero, return DEST. */
8672 if (integer_zerop (len))
7e72af53 8673 return omit_one_operand (type, dest, src);
9c8a1629 8674
4f46f2b9 8675 /* If SRC and DEST are the same (and not volatile), return
8676 DEST{,+LEN,+LEN-1}. */
9c8a1629 8677 if (operand_equal_p (src, dest, 0))
4f46f2b9 8678 expr = len;
8679 else
8680 {
5a84fdd6 8681 tree srctype, desttype;
3b1757a2 8682 if (endp == 3)
8683 {
5a84fdd6 8684 int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
8685 int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
8686
3b1757a2 8687 /* Both DEST and SRC must be pointer types.
8688 ??? This is what old code did. Is the testing for pointer types
8689 really mandatory?
8690
8691 If either SRC is readonly or length is 1, we can use memcpy. */
8692 if (dest_align && src_align
8693 && (readonly_data_expr (src)
5a84fdd6 8694 || (host_integerp (len, 1)
b4fc673b 8695 && (MIN (src_align, dest_align) / BITS_PER_UNIT >=
5a84fdd6 8696 tree_low_cst (len, 1)))))
3b1757a2 8697 {
8698 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8699 if (!fn)
c2f47e15 8700 return NULL_TREE;
8701 return build_call_expr (fn, 3, dest, src, len);
3b1757a2 8702 }
c2f47e15 8703 return NULL_TREE;
3b1757a2 8704 }
4f46f2b9 8705
5a84fdd6 8706 if (!host_integerp (len, 0))
c2f47e15 8707 return NULL_TREE;
5a84fdd6 8708 /* FIXME:
8709 This logic lose for arguments like (type *)malloc (sizeof (type)),
8710 since we strip the casts of up to VOID return value from malloc.
8711 Perhaps we ought to inherit type from non-VOID argument here? */
8712 STRIP_NOPS (src);
8713 STRIP_NOPS (dest);
8714 srctype = TREE_TYPE (TREE_TYPE (src));
8715 desttype = TREE_TYPE (TREE_TYPE (dest));
8716 if (!srctype || !desttype
8717 || !TYPE_SIZE_UNIT (srctype)
8718 || !TYPE_SIZE_UNIT (desttype)
8719 || TREE_CODE (TYPE_SIZE_UNIT (srctype)) != INTEGER_CST
8720 || TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST
92552a26 8721 || !tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len)
8722 || !tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
c2f47e15 8723 return NULL_TREE;
4f46f2b9 8724
5a84fdd6 8725 if (get_pointer_alignment (dest, BIGGEST_ALIGNMENT)
8726 < (int) TYPE_ALIGN (desttype)
8727 || (get_pointer_alignment (src, BIGGEST_ALIGNMENT)
8728 < (int) TYPE_ALIGN (srctype)))
c2f47e15 8729 return NULL_TREE;
e973ffcc 8730
5a84fdd6 8731 if (!ignore)
8732 dest = builtin_save_expr (dest);
4f46f2b9 8733
5a84fdd6 8734 srcvar = build_fold_indirect_ref (src);
4f46f2b9 8735 if (TREE_THIS_VOLATILE (srcvar))
c2f47e15 8736 return NULL_TREE;
92552a26 8737 if (!tree_int_cst_equal (lang_hooks.expr_size (srcvar), len))
c2f47e15 8738 return NULL_TREE;
5a84fdd6 8739 /* With memcpy, it is possible to bypass aliasing rules, so without
8740 this check i. e. execute/20060930-2.c would be misoptimized, because
8741 it use conflicting alias set to hold argument for the memcpy call.
8742 This check is probably unnecesary with -fno-strict-aliasing.
8743 Similarly for destvar. See also PR29286. */
8744 if (!var_decl_component_p (srcvar)
8745 /* Accept: memcpy (*char_var, "test", 1); that simplify
8746 to char_var='t'; */
8747 || is_gimple_min_invariant (srcvar)
8748 || readonly_data_expr (src))
c2f47e15 8749 return NULL_TREE;
4f46f2b9 8750
5a84fdd6 8751 destvar = build_fold_indirect_ref (dest);
8752 if (TREE_THIS_VOLATILE (destvar))
c2f47e15 8753 return NULL_TREE;
92552a26 8754 if (!tree_int_cst_equal (lang_hooks.expr_size (destvar), len))
c2f47e15 8755 return NULL_TREE;
5a84fdd6 8756 if (!var_decl_component_p (destvar))
c2f47e15 8757 return NULL_TREE;
4f46f2b9 8758
5a84fdd6 8759 if (srctype == desttype
2d04fd8d 8760 || (gimple_in_ssa_p (cfun)
548044d8 8761 && useless_type_conversion_p (desttype, srctype)))
5a84fdd6 8762 expr = srcvar;
8763 else if ((INTEGRAL_TYPE_P (TREE_TYPE (srcvar))
4f46f2b9 8764 || POINTER_TYPE_P (TREE_TYPE (srcvar)))
8765 && (INTEGRAL_TYPE_P (TREE_TYPE (destvar))
8766 || POINTER_TYPE_P (TREE_TYPE (destvar))))
8767 expr = fold_convert (TREE_TYPE (destvar), srcvar);
8768 else
8769 expr = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (destvar), srcvar);
41076ef6 8770 expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, expr);
4f46f2b9 8771 }
8772
8773 if (ignore)
8774 return expr;
8775
8776 if (endp == 0 || endp == 3)
8777 return omit_one_operand (type, dest, expr);
8778
8779 if (expr == len)
c2f47e15 8780 expr = NULL_TREE;
4f46f2b9 8781
8782 if (endp == 2)
8783 len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len,
8784 ssize_int (1));
8785
0de36bdb 8786 dest = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
4f46f2b9 8787 dest = fold_convert (type, dest);
8788 if (expr)
8789 dest = omit_one_operand (type, dest, expr);
8790 return dest;
8791}
8792
c2f47e15 8793/* Fold function call to builtin strcpy with arguments DEST and SRC.
8794 If LEN is not NULL, it represents the length of the string to be
8795 copied. Return NULL_TREE if no simplification can be made. */
9c8a1629 8796
f0613857 8797tree
c2f47e15 8798fold_builtin_strcpy (tree fndecl, tree dest, tree src, tree len)
9c8a1629 8799{
c2f47e15 8800 tree fn;
9c8a1629 8801
c2f47e15 8802 if (!validate_arg (dest, POINTER_TYPE)
8803 || !validate_arg (src, POINTER_TYPE))
8804 return NULL_TREE;
9c8a1629 8805
8806 /* If SRC and DEST are the same (and not volatile), return DEST. */
8807 if (operand_equal_p (src, dest, 0))
2426241c 8808 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
9c8a1629 8809
f0613857 8810 if (optimize_size)
c2f47e15 8811 return NULL_TREE;
f0613857 8812
8813 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8814 if (!fn)
c2f47e15 8815 return NULL_TREE;
f0613857 8816
8817 if (!len)
8818 {
8819 len = c_strlen (src, 1);
8820 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 8821 return NULL_TREE;
f0613857 8822 }
8823
8824 len = size_binop (PLUS_EXPR, len, ssize_int (1));
2426241c 8825 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
c2f47e15 8826 build_call_expr (fn, 3, dest, src, len));
9c8a1629 8827}
8828
c2f47e15 8829/* Fold function call to builtin strncpy with arguments DEST, SRC, and LEN.
8830 If SLEN is not NULL, it represents the length of the source string.
8831 Return NULL_TREE if no simplification can be made. */
9c8a1629 8832
f0613857 8833tree
c2f47e15 8834fold_builtin_strncpy (tree fndecl, tree dest, tree src, tree len, tree slen)
9c8a1629 8835{
c2f47e15 8836 tree fn;
9c8a1629 8837
c2f47e15 8838 if (!validate_arg (dest, POINTER_TYPE)
8839 || !validate_arg (src, POINTER_TYPE)
8840 || !validate_arg (len, INTEGER_TYPE))
8841 return NULL_TREE;
9c8a1629 8842
8843 /* If the LEN parameter is zero, return DEST. */
8844 if (integer_zerop (len))
2426241c 8845 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
9c8a1629 8846
19226313 8847 /* We can't compare slen with len as constants below if len is not a
8848 constant. */
8849 if (len == 0 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 8850 return NULL_TREE;
19226313 8851
f0613857 8852 if (!slen)
8853 slen = c_strlen (src, 1);
8854
8855 /* Now, we must be passed a constant src ptr parameter. */
8856 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
c2f47e15 8857 return NULL_TREE;
f0613857 8858
8859 slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
8860
8861 /* We do not support simplification of this case, though we do
8862 support it when expanding trees into RTL. */
8863 /* FIXME: generate a call to __builtin_memset. */
8864 if (tree_int_cst_lt (slen, len))
c2f47e15 8865 return NULL_TREE;
f0613857 8866
8867 /* OK transform into builtin memcpy. */
8868 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8869 if (!fn)
c2f47e15 8870 return NULL_TREE;
2426241c 8871 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
c2f47e15 8872 build_call_expr (fn, 3, dest, src, len));
9c8a1629 8873}
8874
7959b13b 8875/* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the
8876 arguments to the call, and TYPE is its return type.
8877 Return NULL_TREE if no simplification can be made. */
8878
8879static tree
8880fold_builtin_memchr (tree arg1, tree arg2, tree len, tree type)
8881{
8882 if (!validate_arg (arg1, POINTER_TYPE)
8883 || !validate_arg (arg2, INTEGER_TYPE)
8884 || !validate_arg (len, INTEGER_TYPE))
8885 return NULL_TREE;
8886 else
8887 {
8888 const char *p1;
8889
8890 if (TREE_CODE (arg2) != INTEGER_CST
8891 || !host_integerp (len, 1))
8892 return NULL_TREE;
8893
8894 p1 = c_getstr (arg1);
8895 if (p1 && compare_tree_int (len, strlen (p1) + 1) <= 0)
8896 {
8897 char c;
8898 const char *r;
8899 tree tem;
8900
8901 if (target_char_cast (arg2, &c))
8902 return NULL_TREE;
8903
8904 r = memchr (p1, c, tree_low_cst (len, 1));
8905
8906 if (r == NULL)
8907 return build_int_cst (TREE_TYPE (arg1), 0);
8908
0de36bdb 8909 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (arg1), arg1,
8910 size_int (r - p1));
7959b13b 8911 return fold_convert (type, tem);
8912 }
8913 return NULL_TREE;
8914 }
8915}
8916
c2f47e15 8917/* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
8918 Return NULL_TREE if no simplification can be made. */
9c8a1629 8919
8920static tree
c2f47e15 8921fold_builtin_memcmp (tree arg1, tree arg2, tree len)
9c8a1629 8922{
c4fef134 8923 const char *p1, *p2;
9c8a1629 8924
c2f47e15 8925 if (!validate_arg (arg1, POINTER_TYPE)
8926 || !validate_arg (arg2, POINTER_TYPE)
8927 || !validate_arg (len, INTEGER_TYPE))
8928 return NULL_TREE;
9c8a1629 8929
8930 /* If the LEN parameter is zero, return zero. */
8931 if (integer_zerop (len))
c4fef134 8932 return omit_two_operands (integer_type_node, integer_zero_node,
8933 arg1, arg2);
9c8a1629 8934
8935 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8936 if (operand_equal_p (arg1, arg2, 0))
c4fef134 8937 return omit_one_operand (integer_type_node, integer_zero_node, len);
8938
8939 p1 = c_getstr (arg1);
8940 p2 = c_getstr (arg2);
8941
8942 /* If all arguments are constant, and the value of len is not greater
8943 than the lengths of arg1 and arg2, evaluate at compile-time. */
8944 if (host_integerp (len, 1) && p1 && p2
8945 && compare_tree_int (len, strlen (p1) + 1) <= 0
8946 && compare_tree_int (len, strlen (p2) + 1) <= 0)
8947 {
8948 const int r = memcmp (p1, p2, tree_low_cst (len, 1));
8949
8950 if (r > 0)
8951 return integer_one_node;
8952 else if (r < 0)
8953 return integer_minus_one_node;
8954 else
8955 return integer_zero_node;
8956 }
8957
8958 /* If len parameter is one, return an expression corresponding to
8959 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
8960 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
8961 {
8962 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8963 tree cst_uchar_ptr_node
8964 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8965
c4fef134 8966 tree ind1 = fold_convert (integer_type_node,
8967 build1 (INDIRECT_REF, cst_uchar_node,
8968 fold_convert (cst_uchar_ptr_node,
8969 arg1)));
8970 tree ind2 = fold_convert (integer_type_node,
8971 build1 (INDIRECT_REF, cst_uchar_node,
8972 fold_convert (cst_uchar_ptr_node,
8973 arg2)));
49d00087 8974 return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
c4fef134 8975 }
9c8a1629 8976
c2f47e15 8977 return NULL_TREE;
9c8a1629 8978}
8979
c2f47e15 8980/* Fold function call to builtin strcmp with arguments ARG1 and ARG2.
8981 Return NULL_TREE if no simplification can be made. */
9c8a1629 8982
8983static tree
c2f47e15 8984fold_builtin_strcmp (tree arg1, tree arg2)
9c8a1629 8985{
9c8a1629 8986 const char *p1, *p2;
8987
c2f47e15 8988 if (!validate_arg (arg1, POINTER_TYPE)
8989 || !validate_arg (arg2, POINTER_TYPE))
8990 return NULL_TREE;
9c8a1629 8991
8992 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8993 if (operand_equal_p (arg1, arg2, 0))
c4fef134 8994 return integer_zero_node;
9c8a1629 8995
8996 p1 = c_getstr (arg1);
8997 p2 = c_getstr (arg2);
8998
8999 if (p1 && p2)
9000 {
9c8a1629 9001 const int i = strcmp (p1, p2);
9002 if (i < 0)
c4fef134 9003 return integer_minus_one_node;
9c8a1629 9004 else if (i > 0)
c4fef134 9005 return integer_one_node;
9c8a1629 9006 else
c4fef134 9007 return integer_zero_node;
9008 }
9009
9010 /* If the second arg is "", return *(const unsigned char*)arg1. */
9011 if (p2 && *p2 == '\0')
9012 {
9013 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9014 tree cst_uchar_ptr_node
9015 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9016
c4fef134 9017 return fold_convert (integer_type_node,
9018 build1 (INDIRECT_REF, cst_uchar_node,
9019 fold_convert (cst_uchar_ptr_node,
9020 arg1)));
9021 }
9022
9023 /* If the first arg is "", return -*(const unsigned char*)arg2. */
9024 if (p1 && *p1 == '\0')
9025 {
9026 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9027 tree cst_uchar_ptr_node
9028 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9029
c4fef134 9030 tree temp = fold_convert (integer_type_node,
9031 build1 (INDIRECT_REF, cst_uchar_node,
9032 fold_convert (cst_uchar_ptr_node,
9033 arg2)));
49d00087 9034 return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
9c8a1629 9035 }
9036
c2f47e15 9037 return NULL_TREE;
9c8a1629 9038}
9039
c2f47e15 9040/* Fold function call to builtin strncmp with arguments ARG1, ARG2, and LEN.
9041 Return NULL_TREE if no simplification can be made. */
9c8a1629 9042
9043static tree
c2f47e15 9044fold_builtin_strncmp (tree arg1, tree arg2, tree len)
9c8a1629 9045{
9c8a1629 9046 const char *p1, *p2;
9047
c2f47e15 9048 if (!validate_arg (arg1, POINTER_TYPE)
9049 || !validate_arg (arg2, POINTER_TYPE)
9050 || !validate_arg (len, INTEGER_TYPE))
9051 return NULL_TREE;
9c8a1629 9052
9053 /* If the LEN parameter is zero, return zero. */
9054 if (integer_zerop (len))
c4fef134 9055 return omit_two_operands (integer_type_node, integer_zero_node,
9056 arg1, arg2);
9c8a1629 9057
9058 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9059 if (operand_equal_p (arg1, arg2, 0))
c4fef134 9060 return omit_one_operand (integer_type_node, integer_zero_node, len);
9c8a1629 9061
9062 p1 = c_getstr (arg1);
9063 p2 = c_getstr (arg2);
9064
9065 if (host_integerp (len, 1) && p1 && p2)
9066 {
9c8a1629 9067 const int i = strncmp (p1, p2, tree_low_cst (len, 1));
c4fef134 9068 if (i > 0)
9069 return integer_one_node;
9070 else if (i < 0)
9071 return integer_minus_one_node;
9c8a1629 9072 else
c4fef134 9073 return integer_zero_node;
9074 }
9075
9076 /* If the second arg is "", and the length is greater than zero,
9077 return *(const unsigned char*)arg1. */
9078 if (p2 && *p2 == '\0'
9079 && TREE_CODE (len) == INTEGER_CST
9080 && tree_int_cst_sgn (len) == 1)
9081 {
9082 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9083 tree cst_uchar_ptr_node
9084 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9085
c4fef134 9086 return fold_convert (integer_type_node,
9087 build1 (INDIRECT_REF, cst_uchar_node,
9088 fold_convert (cst_uchar_ptr_node,
9089 arg1)));
9090 }
9091
9092 /* If the first arg is "", and the length is greater than zero,
9093 return -*(const unsigned char*)arg2. */
9094 if (p1 && *p1 == '\0'
9095 && TREE_CODE (len) == INTEGER_CST
9096 && tree_int_cst_sgn (len) == 1)
9097 {
9098 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9099 tree cst_uchar_ptr_node
9100 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9101
c4fef134 9102 tree temp = fold_convert (integer_type_node,
9103 build1 (INDIRECT_REF, cst_uchar_node,
9104 fold_convert (cst_uchar_ptr_node,
9105 arg2)));
49d00087 9106 return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
c4fef134 9107 }
9108
9109 /* If len parameter is one, return an expression corresponding to
9110 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
9111 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
9112 {
9113 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9114 tree cst_uchar_ptr_node
9115 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9116
c4fef134 9117 tree ind1 = fold_convert (integer_type_node,
9118 build1 (INDIRECT_REF, cst_uchar_node,
9119 fold_convert (cst_uchar_ptr_node,
9120 arg1)));
9121 tree ind2 = fold_convert (integer_type_node,
9122 build1 (INDIRECT_REF, cst_uchar_node,
9123 fold_convert (cst_uchar_ptr_node,
9124 arg2)));
49d00087 9125 return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
9c8a1629 9126 }
9127
c2f47e15 9128 return NULL_TREE;
9c8a1629 9129}
9130
c2f47e15 9131/* Fold function call to builtin signbit, signbitf or signbitl with argument
9132 ARG. Return NULL_TREE if no simplification can be made. */
27f261ef 9133
9134static tree
c2f47e15 9135fold_builtin_signbit (tree arg, tree type)
27f261ef 9136{
c2f47e15 9137 tree temp;
27f261ef 9138
c2f47e15 9139 if (!validate_arg (arg, REAL_TYPE))
27f261ef 9140 return NULL_TREE;
9141
27f261ef 9142 /* If ARG is a compile-time constant, determine the result. */
9143 if (TREE_CODE (arg) == REAL_CST
f96bd2bf 9144 && !TREE_OVERFLOW (arg))
27f261ef 9145 {
9146 REAL_VALUE_TYPE c;
9147
9148 c = TREE_REAL_CST (arg);
9149 temp = REAL_VALUE_NEGATIVE (c) ? integer_one_node : integer_zero_node;
2426241c 9150 return fold_convert (type, temp);
27f261ef 9151 }
9152
9153 /* If ARG is non-negative, the result is always zero. */
9154 if (tree_expr_nonnegative_p (arg))
2426241c 9155 return omit_one_operand (type, integer_zero_node, arg);
27f261ef 9156
9157 /* If ARG's format doesn't have signed zeros, return "arg < 0.0". */
9158 if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
49d00087 9159 return fold_build2 (LT_EXPR, type, arg,
9160 build_real (TREE_TYPE (arg), dconst0));
27f261ef 9161
9162 return NULL_TREE;
9163}
9164
c2f47e15 9165/* Fold function call to builtin copysign, copysignf or copysignl with
9166 arguments ARG1 and ARG2. Return NULL_TREE if no simplification can
9167 be made. */
467214fd 9168
9169static tree
c2f47e15 9170fold_builtin_copysign (tree fndecl, tree arg1, tree arg2, tree type)
467214fd 9171{
c2f47e15 9172 tree tem;
467214fd 9173
c2f47e15 9174 if (!validate_arg (arg1, REAL_TYPE)
9175 || !validate_arg (arg2, REAL_TYPE))
467214fd 9176 return NULL_TREE;
9177
467214fd 9178 /* copysign(X,X) is X. */
9179 if (operand_equal_p (arg1, arg2, 0))
9180 return fold_convert (type, arg1);
9181
9182 /* If ARG1 and ARG2 are compile-time constants, determine the result. */
9183 if (TREE_CODE (arg1) == REAL_CST
9184 && TREE_CODE (arg2) == REAL_CST
f96bd2bf 9185 && !TREE_OVERFLOW (arg1)
9186 && !TREE_OVERFLOW (arg2))
467214fd 9187 {
9188 REAL_VALUE_TYPE c1, c2;
9189
9190 c1 = TREE_REAL_CST (arg1);
9191 c2 = TREE_REAL_CST (arg2);
749680e2 9192 /* c1.sign := c2.sign. */
467214fd 9193 real_copysign (&c1, &c2);
9194 return build_real (type, c1);
467214fd 9195 }
9196
9197 /* copysign(X, Y) is fabs(X) when Y is always non-negative.
9198 Remember to evaluate Y for side-effects. */
9199 if (tree_expr_nonnegative_p (arg2))
9200 return omit_one_operand (type,
49d00087 9201 fold_build1 (ABS_EXPR, type, arg1),
467214fd 9202 arg2);
9203
198d9bbe 9204 /* Strip sign changing operations for the first argument. */
9205 tem = fold_strip_sign_ops (arg1);
9206 if (tem)
c2f47e15 9207 return build_call_expr (fndecl, 2, tem, arg2);
198d9bbe 9208
467214fd 9209 return NULL_TREE;
9210}
9211
c2f47e15 9212/* Fold a call to builtin isascii with argument ARG. */
d49367d4 9213
9214static tree
c2f47e15 9215fold_builtin_isascii (tree arg)
d49367d4 9216{
c2f47e15 9217 if (!validate_arg (arg, INTEGER_TYPE))
9218 return NULL_TREE;
d49367d4 9219 else
9220 {
9221 /* Transform isascii(c) -> ((c & ~0x7f) == 0). */
7c446c95 9222 arg = build2 (BIT_AND_EXPR, integer_type_node, arg,
9223 build_int_cst (NULL_TREE,
7016c612 9224 ~ (unsigned HOST_WIDE_INT) 0x7f));
f2532264 9225 return fold_build2 (EQ_EXPR, integer_type_node,
9226 arg, integer_zero_node);
d49367d4 9227 }
9228}
9229
c2f47e15 9230/* Fold a call to builtin toascii with argument ARG. */
d49367d4 9231
9232static tree
c2f47e15 9233fold_builtin_toascii (tree arg)
d49367d4 9234{
c2f47e15 9235 if (!validate_arg (arg, INTEGER_TYPE))
9236 return NULL_TREE;
9237
9238 /* Transform toascii(c) -> (c & 0x7f). */
9239 return fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
9240 build_int_cst (NULL_TREE, 0x7f));
d49367d4 9241}
9242
c2f47e15 9243/* Fold a call to builtin isdigit with argument ARG. */
df1cf42e 9244
9245static tree
c2f47e15 9246fold_builtin_isdigit (tree arg)
df1cf42e 9247{
c2f47e15 9248 if (!validate_arg (arg, INTEGER_TYPE))
9249 return NULL_TREE;
df1cf42e 9250 else
9251 {
9252 /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */
624d37a6 9253 /* According to the C standard, isdigit is unaffected by locale.
9254 However, it definitely is affected by the target character set. */
624d37a6 9255 unsigned HOST_WIDE_INT target_digit0
9256 = lang_hooks.to_target_charset ('0');
9257
9258 if (target_digit0 == 0)
9259 return NULL_TREE;
9260
c2f47e15 9261 arg = fold_convert (unsigned_type_node, arg);
05abc81b 9262 arg = build2 (MINUS_EXPR, unsigned_type_node, arg,
624d37a6 9263 build_int_cst (unsigned_type_node, target_digit0));
f2532264 9264 return fold_build2 (LE_EXPR, integer_type_node, arg,
9265 build_int_cst (unsigned_type_node, 9));
df1cf42e 9266 }
9267}
27f261ef 9268
c2f47e15 9269/* Fold a call to fabs, fabsf or fabsl with argument ARG. */
d1aade50 9270
9271static tree
c2f47e15 9272fold_builtin_fabs (tree arg, tree type)
d1aade50 9273{
c2f47e15 9274 if (!validate_arg (arg, REAL_TYPE))
9275 return NULL_TREE;
d1aade50 9276
9829e110 9277 arg = fold_convert (type, arg);
d1aade50 9278 if (TREE_CODE (arg) == REAL_CST)
9279 return fold_abs_const (arg, type);
49d00087 9280 return fold_build1 (ABS_EXPR, type, arg);
d1aade50 9281}
9282
c2f47e15 9283/* Fold a call to abs, labs, llabs or imaxabs with argument ARG. */
d1aade50 9284
9285static tree
c2f47e15 9286fold_builtin_abs (tree arg, tree type)
d1aade50 9287{
c2f47e15 9288 if (!validate_arg (arg, INTEGER_TYPE))
9289 return NULL_TREE;
d1aade50 9290
9829e110 9291 arg = fold_convert (type, arg);
d1aade50 9292 if (TREE_CODE (arg) == INTEGER_CST)
9293 return fold_abs_const (arg, type);
49d00087 9294 return fold_build1 (ABS_EXPR, type, arg);
d1aade50 9295}
9296
d4a43a03 9297/* Fold a call to builtin fmin or fmax. */
9298
9299static tree
c2f47e15 9300fold_builtin_fmin_fmax (tree arg0, tree arg1, tree type, bool max)
d4a43a03 9301{
c2f47e15 9302 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, REAL_TYPE))
d4a43a03 9303 {
d4a43a03 9304 /* Calculate the result when the argument is a constant. */
9305 tree res = do_mpfr_arg2 (arg0, arg1, type, (max ? mpfr_max : mpfr_min));
9306
9307 if (res)
9308 return res;
9309
61fe3555 9310 /* If either argument is NaN, return the other one. Avoid the
9311 transformation if we get (and honor) a signalling NaN. Using
9312 omit_one_operand() ensures we create a non-lvalue. */
9313 if (TREE_CODE (arg0) == REAL_CST
9314 && real_isnan (&TREE_REAL_CST (arg0))
9315 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
9316 || ! TREE_REAL_CST (arg0).signalling))
9317 return omit_one_operand (type, arg1, arg0);
9318 if (TREE_CODE (arg1) == REAL_CST
9319 && real_isnan (&TREE_REAL_CST (arg1))
9320 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
9321 || ! TREE_REAL_CST (arg1).signalling))
9322 return omit_one_operand (type, arg0, arg1);
9323
d4a43a03 9324 /* Transform fmin/fmax(x,x) -> x. */
9325 if (operand_equal_p (arg0, arg1, OEP_PURE_SAME))
9326 return omit_one_operand (type, arg0, arg1);
9327
9328 /* Convert fmin/fmax to MIN_EXPR/MAX_EXPR. C99 requires these
9329 functions to return the numeric arg if the other one is NaN.
9330 These tree codes don't honor that, so only transform if
9331 -ffinite-math-only is set. C99 doesn't require -0.0 to be
9332 handled, so we don't have to worry about it either. */
9333 if (flag_finite_math_only)
9334 return fold_build2 ((max ? MAX_EXPR : MIN_EXPR), type,
9335 fold_convert (type, arg0),
9336 fold_convert (type, arg1));
9337 }
9338 return NULL_TREE;
9339}
9340
abe4dcf6 9341/* Fold a call to builtin carg(a+bi) -> atan2(b,a). */
9342
9343static tree
c2f47e15 9344fold_builtin_carg (tree arg, tree type)
abe4dcf6 9345{
c2f47e15 9346 if (validate_arg (arg, COMPLEX_TYPE))
abe4dcf6 9347 {
9348 tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
9349
9350 if (atan2_fn)
9351 {
c2f47e15 9352 tree new_arg = builtin_save_expr (arg);
9353 tree r_arg = fold_build1 (REALPART_EXPR, type, new_arg);
9354 tree i_arg = fold_build1 (IMAGPART_EXPR, type, new_arg);
9355 return build_call_expr (atan2_fn, 2, i_arg, r_arg);
abe4dcf6 9356 }
9357 }
9358
9359 return NULL_TREE;
9360}
9361
cb2b9385 9362/* Fold a call to builtin logb/ilogb. */
9363
9364static tree
9365fold_builtin_logb (tree arg, tree rettype)
9366{
9367 if (! validate_arg (arg, REAL_TYPE))
9368 return NULL_TREE;
9369
9370 STRIP_NOPS (arg);
9371
9372 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9373 {
9374 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
9375
9376 switch (value->cl)
9377 {
9378 case rvc_nan:
9379 case rvc_inf:
9380 /* If arg is Inf or NaN and we're logb, return it. */
9381 if (TREE_CODE (rettype) == REAL_TYPE)
9382 return fold_convert (rettype, arg);
9383 /* Fall through... */
9384 case rvc_zero:
9385 /* Zero may set errno and/or raise an exception for logb, also
9386 for ilogb we don't know FP_ILOGB0. */
9387 return NULL_TREE;
9388 case rvc_normal:
9389 /* For normal numbers, proceed iff radix == 2. In GCC,
9390 normalized significands are in the range [0.5, 1.0). We
9391 want the exponent as if they were [1.0, 2.0) so get the
9392 exponent and subtract 1. */
9393 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
9394 return fold_convert (rettype, build_int_cst (NULL_TREE,
9395 REAL_EXP (value)-1));
9396 break;
9397 }
9398 }
9399
9400 return NULL_TREE;
9401}
9402
9403/* Fold a call to builtin significand, if radix == 2. */
9404
9405static tree
9406fold_builtin_significand (tree arg, tree rettype)
9407{
9408 if (! validate_arg (arg, REAL_TYPE))
9409 return NULL_TREE;
9410
9411 STRIP_NOPS (arg);
9412
9413 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9414 {
9415 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
9416
9417 switch (value->cl)
9418 {
9419 case rvc_zero:
9420 case rvc_nan:
9421 case rvc_inf:
9422 /* If arg is +-0, +-Inf or +-NaN, then return it. */
9423 return fold_convert (rettype, arg);
9424 case rvc_normal:
9425 /* For normal numbers, proceed iff radix == 2. */
9426 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
9427 {
9428 REAL_VALUE_TYPE result = *value;
9429 /* In GCC, normalized significands are in the range [0.5,
9430 1.0). We want them to be [1.0, 2.0) so set the
9431 exponent to 1. */
9432 SET_REAL_EXP (&result, 1);
9433 return build_real (rettype, result);
9434 }
9435 break;
9436 }
9437 }
9438
9439 return NULL_TREE;
9440}
9441
3838b9ae 9442/* Fold a call to builtin frexp, we can assume the base is 2. */
9443
9444static tree
9445fold_builtin_frexp (tree arg0, tree arg1, tree rettype)
9446{
9447 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9448 return NULL_TREE;
9449
9450 STRIP_NOPS (arg0);
9451
9452 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9453 return NULL_TREE;
9454
9455 arg1 = build_fold_indirect_ref (arg1);
9456
9457 /* Proceed if a valid pointer type was passed in. */
9458 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
9459 {
9460 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9461 tree frac, exp;
9462
9463 switch (value->cl)
9464 {
9465 case rvc_zero:
9466 /* For +-0, return (*exp = 0, +-0). */
9467 exp = integer_zero_node;
9468 frac = arg0;
9469 break;
9470 case rvc_nan:
9471 case rvc_inf:
9472 /* For +-NaN or +-Inf, *exp is unspecified, return arg0. */
9473 return omit_one_operand (rettype, arg0, arg1);
9474 case rvc_normal:
9475 {
9476 /* Since the frexp function always expects base 2, and in
9477 GCC normalized significands are already in the range
9478 [0.5, 1.0), we have exactly what frexp wants. */
9479 REAL_VALUE_TYPE frac_rvt = *value;
9480 SET_REAL_EXP (&frac_rvt, 0);
9481 frac = build_real (rettype, frac_rvt);
9482 exp = build_int_cst (NULL_TREE, REAL_EXP (value));
9483 }
9484 break;
9485 default:
9486 gcc_unreachable ();
9487 }
9488
9489 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
9490 arg1 = fold_build2 (MODIFY_EXPR, rettype, arg1, exp);
9491 TREE_SIDE_EFFECTS (arg1) = 1;
9492 return fold_build2 (COMPOUND_EXPR, rettype, arg1, frac);
9493 }
9494
9495 return NULL_TREE;
9496}
9497
7587301b 9498/* Fold a call to builtin ldexp or scalbn/scalbln. If LDEXP is true
9499 then we can assume the base is two. If it's false, then we have to
9500 check the mode of the TYPE parameter in certain cases. */
9501
9502static tree
9503fold_builtin_load_exponent (tree arg0, tree arg1, tree type, bool ldexp)
9504{
9505 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, INTEGER_TYPE))
9506 {
9507 STRIP_NOPS (arg0);
9508 STRIP_NOPS (arg1);
9509
9510 /* If arg0 is 0, Inf or NaN, or if arg1 is 0, then return arg0. */
9511 if (real_zerop (arg0) || integer_zerop (arg1)
9512 || (TREE_CODE (arg0) == REAL_CST
776a7bab 9513 && !real_isfinite (&TREE_REAL_CST (arg0))))
7587301b 9514 return omit_one_operand (type, arg0, arg1);
9515
9516 /* If both arguments are constant, then try to evaluate it. */
9517 if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2)
9518 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
9519 && host_integerp (arg1, 0))
9520 {
9521 /* Bound the maximum adjustment to twice the range of the
9522 mode's valid exponents. Use abs to ensure the range is
9523 positive as a sanity check. */
9524 const long max_exp_adj = 2 *
9525 labs (REAL_MODE_FORMAT (TYPE_MODE (type))->emax
9526 - REAL_MODE_FORMAT (TYPE_MODE (type))->emin);
9527
9528 /* Get the user-requested adjustment. */
9529 const HOST_WIDE_INT req_exp_adj = tree_low_cst (arg1, 0);
9530
9531 /* The requested adjustment must be inside this range. This
9532 is a preliminary cap to avoid things like overflow, we
9533 may still fail to compute the result for other reasons. */
9534 if (-max_exp_adj < req_exp_adj && req_exp_adj < max_exp_adj)
9535 {
9536 REAL_VALUE_TYPE initial_result;
9537
9538 real_ldexp (&initial_result, &TREE_REAL_CST (arg0), req_exp_adj);
9539
9540 /* Ensure we didn't overflow. */
9541 if (! real_isinf (&initial_result))
9542 {
9543 const REAL_VALUE_TYPE trunc_result
9544 = real_value_truncate (TYPE_MODE (type), initial_result);
9545
9546 /* Only proceed if the target mode can hold the
9547 resulting value. */
9548 if (REAL_VALUES_EQUAL (initial_result, trunc_result))
9549 return build_real (type, trunc_result);
9550 }
9551 }
9552 }
9553 }
9554
9555 return NULL_TREE;
9556}
9557
ebf8b4f5 9558/* Fold a call to builtin modf. */
9559
9560static tree
9561fold_builtin_modf (tree arg0, tree arg1, tree rettype)
9562{
9563 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9564 return NULL_TREE;
9565
9566 STRIP_NOPS (arg0);
9567
9568 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9569 return NULL_TREE;
9570
9571 arg1 = build_fold_indirect_ref (arg1);
9572
9573 /* Proceed if a valid pointer type was passed in. */
9574 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
9575 {
9576 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9577 REAL_VALUE_TYPE trunc, frac;
9578
9579 switch (value->cl)
9580 {
9581 case rvc_nan:
9582 case rvc_zero:
9583 /* For +-NaN or +-0, return (*arg1 = arg0, arg0). */
9584 trunc = frac = *value;
9585 break;
9586 case rvc_inf:
9587 /* For +-Inf, return (*arg1 = arg0, +-0). */
9588 frac = dconst0;
9589 frac.sign = value->sign;
9590 trunc = *value;
9591 break;
9592 case rvc_normal:
9593 /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)). */
9594 real_trunc (&trunc, VOIDmode, value);
9595 real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
9596 /* If the original number was negative and already
9597 integral, then the fractional part is -0.0. */
9598 if (value->sign && frac.cl == rvc_zero)
9599 frac.sign = value->sign;
9600 break;
9601 }
9602
9603 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
9604 arg1 = fold_build2 (MODIFY_EXPR, rettype, arg1,
9605 build_real (rettype, trunc));
9606 TREE_SIDE_EFFECTS (arg1) = 1;
9607 return fold_build2 (COMPOUND_EXPR, rettype, arg1,
9608 build_real (rettype, frac));
9609 }
9610
9611 return NULL_TREE;
9612}
9613
726069ba 9614/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
c2f47e15 9615 ARG is the argument for the call. */
726069ba 9616
9617static tree
c2f47e15 9618fold_builtin_classify (tree fndecl, tree arg, int builtin_index)
726069ba 9619{
726069ba 9620 tree type = TREE_TYPE (TREE_TYPE (fndecl));
726069ba 9621 REAL_VALUE_TYPE r;
9622
c2f47e15 9623 if (!validate_arg (arg, REAL_TYPE))
726069ba 9624 {
c2f47e15 9625 error ("non-floating-point argument to function %qs",
9626 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
9627 return error_mark_node;
726069ba 9628 }
9629
726069ba 9630 switch (builtin_index)
9631 {
9632 case BUILT_IN_ISINF:
b70bfd00 9633 if (!HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
a0c938f0 9634 return omit_one_operand (type, integer_zero_node, arg);
726069ba 9635
9636 if (TREE_CODE (arg) == REAL_CST)
9637 {
9638 r = TREE_REAL_CST (arg);
9639 if (real_isinf (&r))
9640 return real_compare (GT_EXPR, &r, &dconst0)
9641 ? integer_one_node : integer_minus_one_node;
9642 else
9643 return integer_zero_node;
9644 }
9645
9646 return NULL_TREE;
9647
cde061c1 9648 case BUILT_IN_ISFINITE:
b70bfd00 9649 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
9650 && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
34709e02 9651 return omit_one_operand (type, integer_one_node, arg);
726069ba 9652
9653 if (TREE_CODE (arg) == REAL_CST)
9654 {
9655 r = TREE_REAL_CST (arg);
776a7bab 9656 return real_isfinite (&r) ? integer_one_node : integer_zero_node;
726069ba 9657 }
9658
9659 return NULL_TREE;
9660
9661 case BUILT_IN_ISNAN:
b70bfd00 9662 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))))
a0c938f0 9663 return omit_one_operand (type, integer_zero_node, arg);
726069ba 9664
9665 if (TREE_CODE (arg) == REAL_CST)
9666 {
9667 r = TREE_REAL_CST (arg);
9668 return real_isnan (&r) ? integer_one_node : integer_zero_node;
9669 }
9670
9671 arg = builtin_save_expr (arg);
49d00087 9672 return fold_build2 (UNORDERED_EXPR, type, arg, arg);
726069ba 9673
9674 default:
64db345d 9675 gcc_unreachable ();
726069ba 9676 }
9677}
9678
9bc9f15f 9679/* Fold a call to an unordered comparison function such as
d5019fe8 9680 __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function
c2f47e15 9681 being called and ARG0 and ARG1 are the arguments for the call.
726069ba 9682 UNORDERED_CODE and ORDERED_CODE are comparison codes that give
9683 the opposite of the desired result. UNORDERED_CODE is used
9684 for modes that can hold NaNs and ORDERED_CODE is used for
9685 the rest. */
9bc9f15f 9686
9687static tree
c2f47e15 9688fold_builtin_unordered_cmp (tree fndecl, tree arg0, tree arg1,
9bc9f15f 9689 enum tree_code unordered_code,
9690 enum tree_code ordered_code)
9691{
859f903a 9692 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9bc9f15f 9693 enum tree_code code;
6978db0d 9694 tree type0, type1;
9695 enum tree_code code0, code1;
9696 tree cmp_type = NULL_TREE;
9bc9f15f 9697
6978db0d 9698 type0 = TREE_TYPE (arg0);
9699 type1 = TREE_TYPE (arg1);
a0c938f0 9700
6978db0d 9701 code0 = TREE_CODE (type0);
9702 code1 = TREE_CODE (type1);
a0c938f0 9703
6978db0d 9704 if (code0 == REAL_TYPE && code1 == REAL_TYPE)
9705 /* Choose the wider of two real types. */
9706 cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
9707 ? type0 : type1;
9708 else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
9709 cmp_type = type0;
9710 else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
9711 cmp_type = type1;
859f903a 9712 else
9713 {
6978db0d 9714 error ("non-floating-point argument to function %qs",
9715 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
9716 return error_mark_node;
859f903a 9717 }
a0c938f0 9718
6978db0d 9719 arg0 = fold_convert (cmp_type, arg0);
9720 arg1 = fold_convert (cmp_type, arg1);
859f903a 9721
9722 if (unordered_code == UNORDERED_EXPR)
9723 {
b70bfd00 9724 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
859f903a 9725 return omit_two_operands (type, integer_zero_node, arg0, arg1);
49d00087 9726 return fold_build2 (UNORDERED_EXPR, type, arg0, arg1);
859f903a 9727 }
9bc9f15f 9728
b70bfd00 9729 code = HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
9730 : ordered_code;
49d00087 9731 return fold_build1 (TRUTH_NOT_EXPR, type,
9732 fold_build2 (code, type, arg0, arg1));
9bc9f15f 9733}
9734
c2f47e15 9735/* Fold a call to built-in function FNDECL with 0 arguments.
9736 IGNORE is true if the result of the function call is ignored. This
9737 function returns NULL_TREE if no simplification was possible. */
650e4c94 9738
4ee9c684 9739static tree
c2f47e15 9740fold_builtin_0 (tree fndecl, bool ignore ATTRIBUTE_UNUSED)
650e4c94 9741{
e9f80ff5 9742 tree type = TREE_TYPE (TREE_TYPE (fndecl));
c2f47e15 9743 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
189b3398 9744 switch (fcode)
650e4c94 9745 {
c2f47e15 9746 CASE_FLT_FN (BUILT_IN_INF):
9747 case BUILT_IN_INFD32:
9748 case BUILT_IN_INFD64:
9749 case BUILT_IN_INFD128:
9750 return fold_builtin_inf (type, true);
7c2f0500 9751
c2f47e15 9752 CASE_FLT_FN (BUILT_IN_HUGE_VAL):
9753 return fold_builtin_inf (type, false);
7c2f0500 9754
c2f47e15 9755 case BUILT_IN_CLASSIFY_TYPE:
9756 return fold_builtin_classify_type (NULL_TREE);
7c2f0500 9757
c2f47e15 9758 default:
9759 break;
9760 }
9761 return NULL_TREE;
9762}
7c2f0500 9763
c2f47e15 9764/* Fold a call to built-in function FNDECL with 1 argument, ARG0.
9765 IGNORE is true if the result of the function call is ignored. This
9766 function returns NULL_TREE if no simplification was possible. */
7c2f0500 9767
c2f47e15 9768static tree
9769fold_builtin_1 (tree fndecl, tree arg0, bool ignore)
9770{
9771 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9772 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9773 switch (fcode)
9774 {
7c2f0500 9775
650e4c94 9776 case BUILT_IN_CONSTANT_P:
7c2f0500 9777 {
c2f47e15 9778 tree val = fold_builtin_constant_p (arg0);
7c2f0500 9779
7c2f0500 9780 /* Gimplification will pull the CALL_EXPR for the builtin out of
9781 an if condition. When not optimizing, we'll not CSE it back.
9782 To avoid link error types of regressions, return false now. */
9783 if (!val && !optimize)
9784 val = integer_zero_node;
9785
9786 return val;
9787 }
650e4c94 9788
539a3a92 9789 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 9790 return fold_builtin_classify_type (arg0);
539a3a92 9791
650e4c94 9792 case BUILT_IN_STRLEN:
c2f47e15 9793 return fold_builtin_strlen (arg0);
650e4c94 9794
4f35b1fc 9795 CASE_FLT_FN (BUILT_IN_FABS):
c2f47e15 9796 return fold_builtin_fabs (arg0, type);
d1aade50 9797
9798 case BUILT_IN_ABS:
9799 case BUILT_IN_LABS:
9800 case BUILT_IN_LLABS:
9801 case BUILT_IN_IMAXABS:
c2f47e15 9802 return fold_builtin_abs (arg0, type);
c63f4ad3 9803
4f35b1fc 9804 CASE_FLT_FN (BUILT_IN_CONJ):
c2f47e15 9805 if (validate_arg (arg0, COMPLEX_TYPE))
9806 return fold_build1 (CONJ_EXPR, type, arg0);
9807 break;
36d3581d 9808
4f35b1fc 9809 CASE_FLT_FN (BUILT_IN_CREAL):
c2f47e15 9810 if (validate_arg (arg0, COMPLEX_TYPE))
9811 return non_lvalue (fold_build1 (REALPART_EXPR, type, arg0));;
9812 break;
36d3581d 9813
4f35b1fc 9814 CASE_FLT_FN (BUILT_IN_CIMAG):
c2f47e15 9815 if (validate_arg (arg0, COMPLEX_TYPE))
9816 return non_lvalue (fold_build1 (IMAGPART_EXPR, type, arg0));
9817 break;
36d3581d 9818
503733d5 9819 CASE_FLT_FN (BUILT_IN_CCOS):
9820 CASE_FLT_FN (BUILT_IN_CCOSH):
9821 /* These functions are "even", i.e. f(x) == f(-x). */
c2f47e15 9822 if (validate_arg (arg0, COMPLEX_TYPE))
9823 {
9824 tree narg = fold_strip_sign_ops (arg0);
503733d5 9825 if (narg)
c2f47e15 9826 return build_call_expr (fndecl, 1, narg);
503733d5 9827 }
c2f47e15 9828 break;
503733d5 9829
4f35b1fc 9830 CASE_FLT_FN (BUILT_IN_CABS):
c2f47e15 9831 return fold_builtin_cabs (arg0, type, fndecl);
c63f4ad3 9832
abe4dcf6 9833 CASE_FLT_FN (BUILT_IN_CARG):
c2f47e15 9834 return fold_builtin_carg (arg0, type);
abe4dcf6 9835
4f35b1fc 9836 CASE_FLT_FN (BUILT_IN_SQRT):
c2f47e15 9837 return fold_builtin_sqrt (arg0, type);
805e22b2 9838
4f35b1fc 9839 CASE_FLT_FN (BUILT_IN_CBRT):
c2f47e15 9840 return fold_builtin_cbrt (arg0, type);
3bc5c41b 9841
728bac60 9842 CASE_FLT_FN (BUILT_IN_ASIN):
c2f47e15 9843 if (validate_arg (arg0, REAL_TYPE))
9844 return do_mpfr_arg1 (arg0, type, mpfr_asin,
728bac60 9845 &dconstm1, &dconst1, true);
9846 break;
9847
9848 CASE_FLT_FN (BUILT_IN_ACOS):
c2f47e15 9849 if (validate_arg (arg0, REAL_TYPE))
9850 return do_mpfr_arg1 (arg0, type, mpfr_acos,
728bac60 9851 &dconstm1, &dconst1, true);
9852 break;
9853
9854 CASE_FLT_FN (BUILT_IN_ATAN):
c2f47e15 9855 if (validate_arg (arg0, REAL_TYPE))
9856 return do_mpfr_arg1 (arg0, type, mpfr_atan, NULL, NULL, 0);
728bac60 9857 break;
9858
9859 CASE_FLT_FN (BUILT_IN_ASINH):
c2f47e15 9860 if (validate_arg (arg0, REAL_TYPE))
9861 return do_mpfr_arg1 (arg0, type, mpfr_asinh, NULL, NULL, 0);
728bac60 9862 break;
9863
9864 CASE_FLT_FN (BUILT_IN_ACOSH):
c2f47e15 9865 if (validate_arg (arg0, REAL_TYPE))
9866 return do_mpfr_arg1 (arg0, type, mpfr_acosh,
728bac60 9867 &dconst1, NULL, true);
9868 break;
9869
9870 CASE_FLT_FN (BUILT_IN_ATANH):
c2f47e15 9871 if (validate_arg (arg0, REAL_TYPE))
9872 return do_mpfr_arg1 (arg0, type, mpfr_atanh,
728bac60 9873 &dconstm1, &dconst1, false);
9874 break;
9875
4f35b1fc 9876 CASE_FLT_FN (BUILT_IN_SIN):
c2f47e15 9877 if (validate_arg (arg0, REAL_TYPE))
9878 return do_mpfr_arg1 (arg0, type, mpfr_sin, NULL, NULL, 0);
728bac60 9879 break;
77e89269 9880
4f35b1fc 9881 CASE_FLT_FN (BUILT_IN_COS):
c2f47e15 9882 return fold_builtin_cos (arg0, type, fndecl);
9883 break;
77e89269 9884
728bac60 9885 CASE_FLT_FN (BUILT_IN_TAN):
c2f47e15 9886 return fold_builtin_tan (arg0, type);
d735c391 9887
c5bb2c4b 9888 CASE_FLT_FN (BUILT_IN_CEXP):
c2f47e15 9889 return fold_builtin_cexp (arg0, type);
c5bb2c4b 9890
d735c391 9891 CASE_FLT_FN (BUILT_IN_CEXPI):
c2f47e15 9892 if (validate_arg (arg0, REAL_TYPE))
9893 return do_mpfr_sincos (arg0, NULL_TREE, NULL_TREE);
9894 break;
d92f994c 9895
728bac60 9896 CASE_FLT_FN (BUILT_IN_SINH):
c2f47e15 9897 if (validate_arg (arg0, REAL_TYPE))
9898 return do_mpfr_arg1 (arg0, type, mpfr_sinh, NULL, NULL, 0);
728bac60 9899 break;
9900
9901 CASE_FLT_FN (BUILT_IN_COSH):
c2f47e15 9902 return fold_builtin_cosh (arg0, type, fndecl);
728bac60 9903
9904 CASE_FLT_FN (BUILT_IN_TANH):
c2f47e15 9905 if (validate_arg (arg0, REAL_TYPE))
9906 return do_mpfr_arg1 (arg0, type, mpfr_tanh, NULL, NULL, 0);
728bac60 9907 break;
9908
29f4cd78 9909 CASE_FLT_FN (BUILT_IN_ERF):
c2f47e15 9910 if (validate_arg (arg0, REAL_TYPE))
9911 return do_mpfr_arg1 (arg0, type, mpfr_erf, NULL, NULL, 0);
29f4cd78 9912 break;
9913
9914 CASE_FLT_FN (BUILT_IN_ERFC):
c2f47e15 9915 if (validate_arg (arg0, REAL_TYPE))
9916 return do_mpfr_arg1 (arg0, type, mpfr_erfc, NULL, NULL, 0);
29f4cd78 9917 break;
9918
32dba52b 9919 CASE_FLT_FN (BUILT_IN_TGAMMA):
c2f47e15 9920 if (validate_arg (arg0, REAL_TYPE))
9921 return do_mpfr_arg1 (arg0, type, mpfr_gamma, NULL, NULL, 0);
32dba52b 9922 break;
9923
4f35b1fc 9924 CASE_FLT_FN (BUILT_IN_EXP):
c2f47e15 9925 return fold_builtin_exponent (fndecl, arg0, mpfr_exp);
467214fd 9926
4f35b1fc 9927 CASE_FLT_FN (BUILT_IN_EXP2):
c2f47e15 9928 return fold_builtin_exponent (fndecl, arg0, mpfr_exp2);
467214fd 9929
4f35b1fc 9930 CASE_FLT_FN (BUILT_IN_EXP10):
9931 CASE_FLT_FN (BUILT_IN_POW10):
c2f47e15 9932 return fold_builtin_exponent (fndecl, arg0, mpfr_exp10);
467214fd 9933
29f4cd78 9934 CASE_FLT_FN (BUILT_IN_EXPM1):
c2f47e15 9935 if (validate_arg (arg0, REAL_TYPE))
9936 return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0);
29f4cd78 9937 break;
9938
4f35b1fc 9939 CASE_FLT_FN (BUILT_IN_LOG):
c2f47e15 9940 return fold_builtin_logarithm (fndecl, arg0, mpfr_log);
467214fd 9941
4f35b1fc 9942 CASE_FLT_FN (BUILT_IN_LOG2):
c2f47e15 9943 return fold_builtin_logarithm (fndecl, arg0, mpfr_log2);
467214fd 9944
4f35b1fc 9945 CASE_FLT_FN (BUILT_IN_LOG10):
c2f47e15 9946 return fold_builtin_logarithm (fndecl, arg0, mpfr_log10);
29f4cd78 9947
9948 CASE_FLT_FN (BUILT_IN_LOG1P):
c2f47e15 9949 if (validate_arg (arg0, REAL_TYPE))
9950 return do_mpfr_arg1 (arg0, type, mpfr_log1p,
29f4cd78 9951 &dconstm1, NULL, false);
9952 break;
805e22b2 9953
65dd1378 9954#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
9955 CASE_FLT_FN (BUILT_IN_J0):
9956 if (validate_arg (arg0, REAL_TYPE))
9957 return do_mpfr_arg1 (arg0, type, mpfr_j0,
9958 NULL, NULL, 0);
9959 break;
9960
9961 CASE_FLT_FN (BUILT_IN_J1):
9962 if (validate_arg (arg0, REAL_TYPE))
9963 return do_mpfr_arg1 (arg0, type, mpfr_j1,
9964 NULL, NULL, 0);
9965 break;
6ff9eeff 9966
9967 CASE_FLT_FN (BUILT_IN_Y0):
9968 if (validate_arg (arg0, REAL_TYPE))
9969 return do_mpfr_arg1 (arg0, type, mpfr_y0,
9970 &dconst0, NULL, false);
9971 break;
9972
9973 CASE_FLT_FN (BUILT_IN_Y1):
9974 if (validate_arg (arg0, REAL_TYPE))
9975 return do_mpfr_arg1 (arg0, type, mpfr_y1,
9976 &dconst0, NULL, false);
9977 break;
65dd1378 9978#endif
9979
4f35b1fc 9980 CASE_FLT_FN (BUILT_IN_NAN):
c4503c0a 9981 case BUILT_IN_NAND32:
9982 case BUILT_IN_NAND64:
9983 case BUILT_IN_NAND128:
c2f47e15 9984 return fold_builtin_nan (arg0, type, true);
b0db7939 9985
4f35b1fc 9986 CASE_FLT_FN (BUILT_IN_NANS):
c2f47e15 9987 return fold_builtin_nan (arg0, type, false);
b0db7939 9988
4f35b1fc 9989 CASE_FLT_FN (BUILT_IN_FLOOR):
c2f47e15 9990 return fold_builtin_floor (fndecl, arg0);
277f8dd2 9991
4f35b1fc 9992 CASE_FLT_FN (BUILT_IN_CEIL):
c2f47e15 9993 return fold_builtin_ceil (fndecl, arg0);
277f8dd2 9994
4f35b1fc 9995 CASE_FLT_FN (BUILT_IN_TRUNC):
c2f47e15 9996 return fold_builtin_trunc (fndecl, arg0);
277f8dd2 9997
4f35b1fc 9998 CASE_FLT_FN (BUILT_IN_ROUND):
c2f47e15 9999 return fold_builtin_round (fndecl, arg0);
89ab3887 10000
4f35b1fc 10001 CASE_FLT_FN (BUILT_IN_NEARBYINT):
10002 CASE_FLT_FN (BUILT_IN_RINT):
c2f47e15 10003 return fold_trunc_transparent_mathfn (fndecl, arg0);
6528f4f4 10004
4f35b1fc 10005 CASE_FLT_FN (BUILT_IN_LCEIL):
10006 CASE_FLT_FN (BUILT_IN_LLCEIL):
10007 CASE_FLT_FN (BUILT_IN_LFLOOR):
10008 CASE_FLT_FN (BUILT_IN_LLFLOOR):
a0c938f0 10009 CASE_FLT_FN (BUILT_IN_LROUND):
4f35b1fc 10010 CASE_FLT_FN (BUILT_IN_LLROUND):
c2f47e15 10011 return fold_builtin_int_roundingfn (fndecl, arg0);
34f17811 10012
4f35b1fc 10013 CASE_FLT_FN (BUILT_IN_LRINT):
10014 CASE_FLT_FN (BUILT_IN_LLRINT):
c2f47e15 10015 return fold_fixed_mathfn (fndecl, arg0);
9ed65c7f 10016
42791117 10017 case BUILT_IN_BSWAP32:
10018 case BUILT_IN_BSWAP64:
c2f47e15 10019 return fold_builtin_bswap (fndecl, arg0);
42791117 10020
4f35b1fc 10021 CASE_INT_FN (BUILT_IN_FFS):
10022 CASE_INT_FN (BUILT_IN_CLZ):
10023 CASE_INT_FN (BUILT_IN_CTZ):
10024 CASE_INT_FN (BUILT_IN_POPCOUNT):
10025 CASE_INT_FN (BUILT_IN_PARITY):
c2f47e15 10026 return fold_builtin_bitop (fndecl, arg0);
9c8a1629 10027
4f35b1fc 10028 CASE_FLT_FN (BUILT_IN_SIGNBIT):
c2f47e15 10029 return fold_builtin_signbit (arg0, type);
27f261ef 10030
cb2b9385 10031 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
10032 return fold_builtin_significand (arg0, type);
10033
10034 CASE_FLT_FN (BUILT_IN_ILOGB):
10035 CASE_FLT_FN (BUILT_IN_LOGB):
10036 return fold_builtin_logb (arg0, type);
10037
d49367d4 10038 case BUILT_IN_ISASCII:
c2f47e15 10039 return fold_builtin_isascii (arg0);
d49367d4 10040
10041 case BUILT_IN_TOASCII:
c2f47e15 10042 return fold_builtin_toascii (arg0);
d49367d4 10043
df1cf42e 10044 case BUILT_IN_ISDIGIT:
c2f47e15 10045 return fold_builtin_isdigit (arg0);
467214fd 10046
4f35b1fc 10047 CASE_FLT_FN (BUILT_IN_FINITE):
c4503c0a 10048 case BUILT_IN_FINITED32:
10049 case BUILT_IN_FINITED64:
10050 case BUILT_IN_FINITED128:
cde061c1 10051 case BUILT_IN_ISFINITE:
10052 return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISFINITE);
726069ba 10053
4f35b1fc 10054 CASE_FLT_FN (BUILT_IN_ISINF):
c4503c0a 10055 case BUILT_IN_ISINFD32:
10056 case BUILT_IN_ISINFD64:
10057 case BUILT_IN_ISINFD128:
c2f47e15 10058 return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISINF);
726069ba 10059
4f35b1fc 10060 CASE_FLT_FN (BUILT_IN_ISNAN):
c4503c0a 10061 case BUILT_IN_ISNAND32:
10062 case BUILT_IN_ISNAND64:
10063 case BUILT_IN_ISNAND128:
c2f47e15 10064 return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISNAN);
10065
a7f5bb2d 10066 case BUILT_IN_ISNORMAL:
10067 if (!validate_arg (arg0, REAL_TYPE))
10068 {
10069 error ("non-floating-point argument to function %qs",
10070 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
10071 return error_mark_node;
10072 }
10073 break;
10074
c2f47e15 10075 case BUILT_IN_PRINTF:
10076 case BUILT_IN_PRINTF_UNLOCKED:
10077 case BUILT_IN_VPRINTF:
10078 return fold_builtin_printf (fndecl, arg0, NULL_TREE, ignore, fcode);
10079
10080 default:
10081 break;
10082 }
10083
10084 return NULL_TREE;
10085
10086}
10087
10088/* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1.
10089 IGNORE is true if the result of the function call is ignored. This
10090 function returns NULL_TREE if no simplification was possible. */
10091
10092static tree
10093fold_builtin_2 (tree fndecl, tree arg0, tree arg1, bool ignore)
10094{
10095 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10096 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10097
10098 switch (fcode)
10099 {
65dd1378 10100#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
10101 CASE_FLT_FN (BUILT_IN_JN):
10102 if (validate_arg (arg0, INTEGER_TYPE)
10103 && validate_arg (arg1, REAL_TYPE))
10104 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_jn, NULL, 0);
10105 break;
6ff9eeff 10106
10107 CASE_FLT_FN (BUILT_IN_YN):
10108 if (validate_arg (arg0, INTEGER_TYPE)
10109 && validate_arg (arg1, REAL_TYPE))
10110 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_yn,
10111 &dconst0, false);
10112 break;
e5407ca6 10113
10114 CASE_FLT_FN (BUILT_IN_DREM):
10115 CASE_FLT_FN (BUILT_IN_REMAINDER):
10116 if (validate_arg (arg0, REAL_TYPE)
10117 && validate_arg(arg1, REAL_TYPE))
10118 return do_mpfr_arg2 (arg0, arg1, type, mpfr_remainder);
10119 break;
e84da7c1 10120
10121 CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
10122 CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
10123 if (validate_arg (arg0, REAL_TYPE)
10124 && validate_arg(arg1, POINTER_TYPE))
10125 return do_mpfr_lgamma_r (arg0, arg1, type);
10126 break;
65dd1378 10127#endif
c2f47e15 10128
10129 CASE_FLT_FN (BUILT_IN_ATAN2):
10130 if (validate_arg (arg0, REAL_TYPE)
10131 && validate_arg(arg1, REAL_TYPE))
10132 return do_mpfr_arg2 (arg0, arg1, type, mpfr_atan2);
10133 break;
10134
10135 CASE_FLT_FN (BUILT_IN_FDIM):
10136 if (validate_arg (arg0, REAL_TYPE)
10137 && validate_arg(arg1, REAL_TYPE))
10138 return do_mpfr_arg2 (arg0, arg1, type, mpfr_dim);
10139 break;
10140
10141 CASE_FLT_FN (BUILT_IN_HYPOT):
10142 return fold_builtin_hypot (fndecl, arg0, arg1, type);
10143
7587301b 10144 CASE_FLT_FN (BUILT_IN_LDEXP):
10145 return fold_builtin_load_exponent (arg0, arg1, type, /*ldexp=*/true);
10146 CASE_FLT_FN (BUILT_IN_SCALBN):
10147 CASE_FLT_FN (BUILT_IN_SCALBLN):
10148 return fold_builtin_load_exponent (arg0, arg1, type, /*ldexp=*/false);
10149
3838b9ae 10150 CASE_FLT_FN (BUILT_IN_FREXP):
10151 return fold_builtin_frexp (arg0, arg1, type);
10152
ebf8b4f5 10153 CASE_FLT_FN (BUILT_IN_MODF):
10154 return fold_builtin_modf (arg0, arg1, type);
10155
c2f47e15 10156 case BUILT_IN_BZERO:
10157 return fold_builtin_bzero (arg0, arg1, ignore);
10158
10159 case BUILT_IN_FPUTS:
10160 return fold_builtin_fputs (arg0, arg1, ignore, false, NULL_TREE);
10161
10162 case BUILT_IN_FPUTS_UNLOCKED:
10163 return fold_builtin_fputs (arg0, arg1, ignore, true, NULL_TREE);
10164
10165 case BUILT_IN_STRSTR:
10166 return fold_builtin_strstr (arg0, arg1, type);
10167
10168 case BUILT_IN_STRCAT:
10169 return fold_builtin_strcat (arg0, arg1);
10170
10171 case BUILT_IN_STRSPN:
10172 return fold_builtin_strspn (arg0, arg1);
10173
10174 case BUILT_IN_STRCSPN:
10175 return fold_builtin_strcspn (arg0, arg1);
10176
10177 case BUILT_IN_STRCHR:
10178 case BUILT_IN_INDEX:
10179 return fold_builtin_strchr (arg0, arg1, type);
10180
10181 case BUILT_IN_STRRCHR:
10182 case BUILT_IN_RINDEX:
10183 return fold_builtin_strrchr (arg0, arg1, type);
10184
10185 case BUILT_IN_STRCPY:
10186 return fold_builtin_strcpy (fndecl, arg0, arg1, NULL_TREE);
10187
10188 case BUILT_IN_STRCMP:
10189 return fold_builtin_strcmp (arg0, arg1);
10190
10191 case BUILT_IN_STRPBRK:
10192 return fold_builtin_strpbrk (arg0, arg1, type);
10193
10194 case BUILT_IN_EXPECT:
76f5a783 10195 return fold_builtin_expect (arg0, arg1);
c2f47e15 10196
10197 CASE_FLT_FN (BUILT_IN_POW):
10198 return fold_builtin_pow (fndecl, arg0, arg1, type);
10199
10200 CASE_FLT_FN (BUILT_IN_POWI):
10201 return fold_builtin_powi (fndecl, arg0, arg1, type);
10202
10203 CASE_FLT_FN (BUILT_IN_COPYSIGN):
10204 return fold_builtin_copysign (fndecl, arg0, arg1, type);
10205
10206 CASE_FLT_FN (BUILT_IN_FMIN):
10207 return fold_builtin_fmin_fmax (arg0, arg1, type, /*max=*/false);
10208
10209 CASE_FLT_FN (BUILT_IN_FMAX):
10210 return fold_builtin_fmin_fmax (arg0, arg1, type, /*max=*/true);
726069ba 10211
9bc9f15f 10212 case BUILT_IN_ISGREATER:
c2f47e15 10213 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNLE_EXPR, LE_EXPR);
9bc9f15f 10214 case BUILT_IN_ISGREATEREQUAL:
c2f47e15 10215 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNLT_EXPR, LT_EXPR);
9bc9f15f 10216 case BUILT_IN_ISLESS:
c2f47e15 10217 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNGE_EXPR, GE_EXPR);
9bc9f15f 10218 case BUILT_IN_ISLESSEQUAL:
c2f47e15 10219 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNGT_EXPR, GT_EXPR);
9bc9f15f 10220 case BUILT_IN_ISLESSGREATER:
c2f47e15 10221 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNEQ_EXPR, EQ_EXPR);
9bc9f15f 10222 case BUILT_IN_ISUNORDERED:
c2f47e15 10223 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNORDERED_EXPR,
d5019fe8 10224 NOP_EXPR);
9bc9f15f 10225
7c2f0500 10226 /* We do the folding for va_start in the expander. */
10227 case BUILT_IN_VA_START:
10228 break;
f0613857 10229
c2f47e15 10230 case BUILT_IN_SPRINTF:
10231 return fold_builtin_sprintf (arg0, arg1, NULL_TREE, ignore);
10232
0a39fd54 10233 case BUILT_IN_OBJECT_SIZE:
c2f47e15 10234 return fold_builtin_object_size (arg0, arg1);
0a39fd54 10235
10236 case BUILT_IN_PRINTF:
10237 case BUILT_IN_PRINTF_UNLOCKED:
10238 case BUILT_IN_VPRINTF:
c2f47e15 10239 return fold_builtin_printf (fndecl, arg0, arg1, ignore, fcode);
10240
0a39fd54 10241 case BUILT_IN_PRINTF_CHK:
10242 case BUILT_IN_VPRINTF_CHK:
c2f47e15 10243 if (!validate_arg (arg0, INTEGER_TYPE)
10244 || TREE_SIDE_EFFECTS (arg0))
10245 return NULL_TREE;
10246 else
10247 return fold_builtin_printf (fndecl, arg1, NULL_TREE, ignore, fcode);
10248 break;
0a39fd54 10249
10250 case BUILT_IN_FPRINTF:
10251 case BUILT_IN_FPRINTF_UNLOCKED:
10252 case BUILT_IN_VFPRINTF:
c2f47e15 10253 return fold_builtin_fprintf (fndecl, arg0, arg1, NULL_TREE,
10254 ignore, fcode);
10255
10256 default:
10257 break;
10258 }
10259 return NULL_TREE;
10260}
10261
10262/* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
10263 and ARG2. IGNORE is true if the result of the function call is ignored.
10264 This function returns NULL_TREE if no simplification was possible. */
10265
10266static tree
10267fold_builtin_3 (tree fndecl, tree arg0, tree arg1, tree arg2, bool ignore)
10268{
10269 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10270 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10271 switch (fcode)
10272 {
10273
10274 CASE_FLT_FN (BUILT_IN_SINCOS):
10275 return fold_builtin_sincos (arg0, arg1, arg2);
10276
10277 CASE_FLT_FN (BUILT_IN_FMA):
10278 if (validate_arg (arg0, REAL_TYPE)
10279 && validate_arg(arg1, REAL_TYPE)
10280 && validate_arg(arg2, REAL_TYPE))
10281 return do_mpfr_arg3 (arg0, arg1, arg2, type, mpfr_fma);
10282 break;
10283
e5407ca6 10284#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
10285 CASE_FLT_FN (BUILT_IN_REMQUO):
10286 if (validate_arg (arg0, REAL_TYPE)
10287 && validate_arg(arg1, REAL_TYPE)
10288 && validate_arg(arg2, POINTER_TYPE))
10289 return do_mpfr_remquo (arg0, arg1, arg2);
10290 break;
10291#endif
10292
c2f47e15 10293 case BUILT_IN_MEMSET:
10294 return fold_builtin_memset (arg0, arg1, arg2, type, ignore);
10295
10296 case BUILT_IN_BCOPY:
10297 return fold_builtin_memory_op (arg1, arg0, arg2, void_type_node, true, /*endp=*/3);
10298
10299 case BUILT_IN_MEMCPY:
10300 return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/0);
10301
10302 case BUILT_IN_MEMPCPY:
10303 return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/1);
10304
10305 case BUILT_IN_MEMMOVE:
10306 return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/3);
10307
10308 case BUILT_IN_STRNCAT:
10309 return fold_builtin_strncat (arg0, arg1, arg2);
10310
10311 case BUILT_IN_STRNCPY:
10312 return fold_builtin_strncpy (fndecl, arg0, arg1, arg2, NULL_TREE);
10313
10314 case BUILT_IN_STRNCMP:
10315 return fold_builtin_strncmp (arg0, arg1, arg2);
10316
7959b13b 10317 case BUILT_IN_MEMCHR:
10318 return fold_builtin_memchr (arg0, arg1, arg2, type);
10319
c2f47e15 10320 case BUILT_IN_BCMP:
10321 case BUILT_IN_MEMCMP:
10322 return fold_builtin_memcmp (arg0, arg1, arg2);;
10323
10324 case BUILT_IN_SPRINTF:
10325 return fold_builtin_sprintf (arg0, arg1, arg2, ignore);
10326
10327 case BUILT_IN_STRCPY_CHK:
10328 case BUILT_IN_STPCPY_CHK:
10329 return fold_builtin_stxcpy_chk (fndecl, arg0, arg1, arg2, NULL_TREE,
10330 ignore, fcode);
10331
10332 case BUILT_IN_STRCAT_CHK:
10333 return fold_builtin_strcat_chk (fndecl, arg0, arg1, arg2);
10334
10335 case BUILT_IN_PRINTF_CHK:
10336 case BUILT_IN_VPRINTF_CHK:
10337 if (!validate_arg (arg0, INTEGER_TYPE)
10338 || TREE_SIDE_EFFECTS (arg0))
10339 return NULL_TREE;
10340 else
10341 return fold_builtin_printf (fndecl, arg1, arg2, ignore, fcode);
10342 break;
10343
10344 case BUILT_IN_FPRINTF:
10345 case BUILT_IN_FPRINTF_UNLOCKED:
10346 case BUILT_IN_VFPRINTF:
10347 return fold_builtin_fprintf (fndecl, arg0, arg1, arg2, ignore, fcode);
10348
0a39fd54 10349 case BUILT_IN_FPRINTF_CHK:
10350 case BUILT_IN_VFPRINTF_CHK:
c2f47e15 10351 if (!validate_arg (arg1, INTEGER_TYPE)
10352 || TREE_SIDE_EFFECTS (arg1))
10353 return NULL_TREE;
10354 else
10355 return fold_builtin_fprintf (fndecl, arg0, arg2, NULL_TREE,
10356 ignore, fcode);
0a39fd54 10357
650e4c94 10358 default:
10359 break;
10360 }
c2f47e15 10361 return NULL_TREE;
10362}
650e4c94 10363
c2f47e15 10364/* Fold a call to built-in function FNDECL with 4 arguments, ARG0, ARG1,
10365 ARG2, and ARG3. IGNORE is true if the result of the function call is
10366 ignored. This function returns NULL_TREE if no simplification was
10367 possible. */
10368
10369static tree
10370fold_builtin_4 (tree fndecl, tree arg0, tree arg1, tree arg2, tree arg3,
10371 bool ignore)
10372{
10373 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10374
10375 switch (fcode)
10376 {
10377 case BUILT_IN_MEMCPY_CHK:
10378 case BUILT_IN_MEMPCPY_CHK:
10379 case BUILT_IN_MEMMOVE_CHK:
10380 case BUILT_IN_MEMSET_CHK:
10381 return fold_builtin_memory_chk (fndecl, arg0, arg1, arg2, arg3,
10382 NULL_TREE, ignore,
10383 DECL_FUNCTION_CODE (fndecl));
10384
10385 case BUILT_IN_STRNCPY_CHK:
10386 return fold_builtin_strncpy_chk (arg0, arg1, arg2, arg3, NULL_TREE);
10387
10388 case BUILT_IN_STRNCAT_CHK:
10389 return fold_builtin_strncat_chk (fndecl, arg0, arg1, arg2, arg3);
10390
10391 case BUILT_IN_FPRINTF_CHK:
10392 case BUILT_IN_VFPRINTF_CHK:
10393 if (!validate_arg (arg1, INTEGER_TYPE)
10394 || TREE_SIDE_EFFECTS (arg1))
10395 return NULL_TREE;
10396 else
10397 return fold_builtin_fprintf (fndecl, arg0, arg2, arg3,
10398 ignore, fcode);
10399 break;
10400
10401 default:
10402 break;
10403 }
10404 return NULL_TREE;
10405}
10406
10407/* Fold a call to built-in function FNDECL. ARGS is an array of NARGS
10408 arguments, where NARGS <= 4. IGNORE is true if the result of the
10409 function call is ignored. This function returns NULL_TREE if no
10410 simplification was possible. Note that this only folds builtins with
10411 fixed argument patterns. Foldings that do varargs-to-varargs
10412 transformations, or that match calls with more than 4 arguments,
10413 need to be handled with fold_builtin_varargs instead. */
10414
10415#define MAX_ARGS_TO_FOLD_BUILTIN 4
10416
10417static tree
10418fold_builtin_n (tree fndecl, tree *args, int nargs, bool ignore)
10419{
a7f5bb2d 10420 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
c2f47e15 10421 tree ret = NULL_TREE;
a7f5bb2d 10422
10423 /* Verify the number of arguments for type-generic and thus variadic
10424 builtins. */
10425 switch (fcode)
10426 {
10427 case BUILT_IN_ISFINITE:
10428 case BUILT_IN_ISINF:
10429 case BUILT_IN_ISNAN:
10430 case BUILT_IN_ISNORMAL:
10431 if (nargs < 1)
10432 {
10433 error ("too few arguments to function %qs",
10434 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
10435 return error_mark_node;
10436 }
10437 else if (nargs > 1)
10438 {
10439 error ("too many arguments to function %qs",
10440 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
10441 return error_mark_node;
10442 }
10443 break;
10444
10445 case BUILT_IN_ISGREATER:
10446 case BUILT_IN_ISGREATEREQUAL:
10447 case BUILT_IN_ISLESS:
10448 case BUILT_IN_ISLESSEQUAL:
10449 case BUILT_IN_ISLESSGREATER:
10450 case BUILT_IN_ISUNORDERED:
10451 if (nargs < 2)
10452 {
10453 error ("too few arguments to function %qs",
10454 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
10455 return error_mark_node;
10456 }
10457 else if (nargs > 2)
10458 {
10459 error ("too many arguments to function %qs",
10460 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
10461 return error_mark_node;
10462 }
10463 break;
10464
10465 default:
10466 break;
10467 }
10468
c2f47e15 10469 switch (nargs)
10470 {
10471 case 0:
10472 ret = fold_builtin_0 (fndecl, ignore);
10473 break;
10474 case 1:
10475 ret = fold_builtin_1 (fndecl, args[0], ignore);
10476 break;
10477 case 2:
10478 ret = fold_builtin_2 (fndecl, args[0], args[1], ignore);
10479 break;
10480 case 3:
10481 ret = fold_builtin_3 (fndecl, args[0], args[1], args[2], ignore);
10482 break;
10483 case 4:
10484 ret = fold_builtin_4 (fndecl, args[0], args[1], args[2], args[3],
10485 ignore);
10486 break;
10487 default:
10488 break;
10489 }
10490 if (ret)
10491 {
10492 ret = build1 (NOP_EXPR, GENERIC_TREE_TYPE (ret), ret);
10493 TREE_NO_WARNING (ret) = 1;
10494 return ret;
10495 }
10496 return NULL_TREE;
10497}
10498
10499/* Builtins with folding operations that operate on "..." arguments
10500 need special handling; we need to store the arguments in a convenient
10501 data structure before attempting any folding. Fortunately there are
10502 only a few builtins that fall into this category. FNDECL is the
10503 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
10504 result of the function call is ignored. */
10505
10506static tree
10507fold_builtin_varargs (tree fndecl, tree exp, bool ignore ATTRIBUTE_UNUSED)
10508{
10509 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10510 tree ret = NULL_TREE;
10511
10512 switch (fcode)
10513 {
10514 case BUILT_IN_SPRINTF_CHK:
10515 case BUILT_IN_VSPRINTF_CHK:
10516 ret = fold_builtin_sprintf_chk (exp, fcode);
10517 break;
10518
10519 case BUILT_IN_SNPRINTF_CHK:
10520 case BUILT_IN_VSNPRINTF_CHK:
10521 ret = fold_builtin_snprintf_chk (exp, NULL_TREE, fcode);
10522
10523 default:
10524 break;
10525 }
10526 if (ret)
10527 {
10528 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
10529 TREE_NO_WARNING (ret) = 1;
10530 return ret;
10531 }
10532 return NULL_TREE;
650e4c94 10533}
7e15618b 10534
4ee9c684 10535/* A wrapper function for builtin folding that prevents warnings for
491e04ef 10536 "statement without effect" and the like, caused by removing the
4ee9c684 10537 call node earlier than the warning is generated. */
10538
10539tree
c2f47e15 10540fold_call_expr (tree exp, bool ignore)
4ee9c684 10541{
c2f47e15 10542 tree ret = NULL_TREE;
10543 tree fndecl = get_callee_fndecl (exp);
10544 if (fndecl
10545 && TREE_CODE (fndecl) == FUNCTION_DECL
48dc2227 10546 && DECL_BUILT_IN (fndecl)
10547 /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
10548 yet. Defer folding until we see all the arguments
10549 (after inlining). */
10550 && !CALL_EXPR_VA_ARG_PACK (exp))
10551 {
10552 int nargs = call_expr_nargs (exp);
10553
10554 /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
10555 instead last argument is __builtin_va_arg_pack (). Defer folding
10556 even in that case, until arguments are finalized. */
10557 if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
10558 {
10559 tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1));
10560 if (fndecl2
10561 && TREE_CODE (fndecl2) == FUNCTION_DECL
10562 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
10563 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
10564 return NULL_TREE;
10565 }
10566
c2f47e15 10567 /* FIXME: Don't use a list in this interface. */
10568 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
10569 return targetm.fold_builtin (fndecl, CALL_EXPR_ARGS (exp), ignore);
10570 else
10571 {
c2f47e15 10572 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
10573 {
10574 tree *args = CALL_EXPR_ARGP (exp);
10575 ret = fold_builtin_n (fndecl, args, nargs, ignore);
10576 }
10577 if (!ret)
10578 ret = fold_builtin_varargs (fndecl, exp, ignore);
10579 if (ret)
10580 {
10581 /* Propagate location information from original call to
10582 expansion of builtin. Otherwise things like
10583 maybe_emit_chk_warning, that operate on the expansion
10584 of a builtin, will use the wrong location information. */
10585 if (CAN_HAVE_LOCATION_P (exp) && EXPR_HAS_LOCATION (exp))
10586 {
10587 tree realret = ret;
10588 if (TREE_CODE (ret) == NOP_EXPR)
10589 realret = TREE_OPERAND (ret, 0);
10590 if (CAN_HAVE_LOCATION_P (realret)
10591 && !EXPR_HAS_LOCATION (realret))
10592 SET_EXPR_LOCATION (realret, EXPR_LOCATION (exp));
10593 }
10594 return ret;
10595 }
10596 }
4ee9c684 10597 }
c2f47e15 10598 return NULL_TREE;
10599}
10600
10601/* Conveniently construct a function call expression. FNDECL names the
10602 function to be called and ARGLIST is a TREE_LIST of arguments. */
10603
10604tree
10605build_function_call_expr (tree fndecl, tree arglist)
10606{
10607 tree fntype = TREE_TYPE (fndecl);
10608 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
d01f58f9 10609 int n = list_length (arglist);
10610 tree *argarray = (tree *) alloca (n * sizeof (tree));
10611 int i;
10612
10613 for (i = 0; i < n; i++, arglist = TREE_CHAIN (arglist))
10614 argarray[i] = TREE_VALUE (arglist);
10615 return fold_builtin_call_array (TREE_TYPE (fntype), fn, n, argarray);
c2f47e15 10616}
10617
10618/* Conveniently construct a function call expression. FNDECL names the
10619 function to be called, N is the number of arguments, and the "..."
10620 parameters are the argument expressions. */
10621
10622tree
10623build_call_expr (tree fndecl, int n, ...)
10624{
10625 va_list ap;
c2f47e15 10626 tree fntype = TREE_TYPE (fndecl);
10627 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
d01f58f9 10628 tree *argarray = (tree *) alloca (n * sizeof (tree));
10629 int i;
c2f47e15 10630
10631 va_start (ap, n);
d01f58f9 10632 for (i = 0; i < n; i++)
10633 argarray[i] = va_arg (ap, tree);
c2f47e15 10634 va_end (ap);
d01f58f9 10635 return fold_builtin_call_array (TREE_TYPE (fntype), fn, n, argarray);
4ee9c684 10636}
10637
c2f47e15 10638/* Construct a CALL_EXPR with type TYPE with FN as the function expression.
d01f58f9 10639 N arguments are passed in the array ARGARRAY. */
805e22b2 10640
10641tree
d01f58f9 10642fold_builtin_call_array (tree type,
10643 tree fn,
10644 int n,
10645 tree *argarray)
7e15618b 10646{
c2f47e15 10647 tree ret = NULL_TREE;
10648 int i;
10649 tree exp;
10650
10651 if (TREE_CODE (fn) == ADDR_EXPR)
10652 {
10653 tree fndecl = TREE_OPERAND (fn, 0);
10654 if (TREE_CODE (fndecl) == FUNCTION_DECL
10655 && DECL_BUILT_IN (fndecl))
10656 {
48dc2227 10657 /* If last argument is __builtin_va_arg_pack (), arguments to this
10658 function are not finalized yet. Defer folding until they are. */
10659 if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
10660 {
10661 tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
10662 if (fndecl2
10663 && TREE_CODE (fndecl2) == FUNCTION_DECL
10664 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
10665 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
10666 return build_call_array (type, fn, n, argarray);
10667 }
c2f47e15 10668 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
10669 {
10670 tree arglist = NULL_TREE;
d01f58f9 10671 for (i = n - 1; i >= 0; i--)
10672 arglist = tree_cons (NULL_TREE, argarray[i], arglist);
c2f47e15 10673 ret = targetm.fold_builtin (fndecl, arglist, false);
10674 if (ret)
10675 return ret;
10676 }
10677 else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
10678 {
10679 /* First try the transformations that don't require consing up
10680 an exp. */
d01f58f9 10681 ret = fold_builtin_n (fndecl, argarray, n, false);
c2f47e15 10682 if (ret)
10683 return ret;
10684 }
10685
10686 /* If we got this far, we need to build an exp. */
d01f58f9 10687 exp = build_call_array (type, fn, n, argarray);
c2f47e15 10688 ret = fold_builtin_varargs (fndecl, exp, false);
10689 return ret ? ret : exp;
10690 }
10691 }
10692
d01f58f9 10693 return build_call_array (type, fn, n, argarray);
c2f47e15 10694}
10695
10696/* Construct a new CALL_EXPR using the tail of the argument list of EXP
10697 along with N new arguments specified as the "..." parameters. SKIP
10698 is the number of arguments in EXP to be omitted. This function is used
10699 to do varargs-to-varargs transformations. */
10700
10701static tree
10702rewrite_call_expr (tree exp, int skip, tree fndecl, int n, ...)
10703{
10704 int oldnargs = call_expr_nargs (exp);
10705 int nargs = oldnargs - skip + n;
10706 tree fntype = TREE_TYPE (fndecl);
10707 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
10708 tree *buffer;
10709
10710 if (n > 0)
10711 {
10712 int i, j;
10713 va_list ap;
7e15618b 10714
c2f47e15 10715 buffer = alloca (nargs * sizeof (tree));
10716 va_start (ap, n);
10717 for (i = 0; i < n; i++)
10718 buffer[i] = va_arg (ap, tree);
10719 va_end (ap);
10720 for (j = skip; j < oldnargs; j++, i++)
10721 buffer[i] = CALL_EXPR_ARG (exp, j);
10722 }
10723 else
10724 buffer = CALL_EXPR_ARGP (exp) + skip;
10725
10726 return fold (build_call_array (TREE_TYPE (exp), fn, nargs, buffer));
10727}
10728
10729/* Validate a single argument ARG against a tree code CODE representing
10730 a type. */
10731
10732static bool
b7bf20db 10733validate_arg (const_tree arg, enum tree_code code)
c2f47e15 10734{
10735 if (!arg)
10736 return false;
10737 else if (code == POINTER_TYPE)
10738 return POINTER_TYPE_P (TREE_TYPE (arg));
10739 return code == TREE_CODE (TREE_TYPE (arg));
7e15618b 10740}
0eb671f7 10741
10742/* This function validates the types of a function call argument list
c2f47e15 10743 against a specified list of tree_codes. If the last specifier is a 0,
10744 that represents an ellipses, otherwise the last specifier must be a
10745 VOID_TYPE. */
27d0c333 10746
c2f47e15 10747bool
b7bf20db 10748validate_arglist (const_tree callexpr, ...)
0eb671f7 10749{
0eb671f7 10750 enum tree_code code;
c2f47e15 10751 bool res = 0;
ee582a61 10752 va_list ap;
b7bf20db 10753 const_call_expr_arg_iterator iter;
10754 const_tree arg;
aecda0d6 10755
c2f47e15 10756 va_start (ap, callexpr);
b7bf20db 10757 init_const_call_expr_arg_iterator (callexpr, &iter);
0eb671f7 10758
f0ce3b1f 10759 do
0eb671f7 10760 {
f0ce3b1f 10761 code = va_arg (ap, enum tree_code);
10762 switch (code)
10763 {
10764 case 0:
10765 /* This signifies an ellipses, any further arguments are all ok. */
c2f47e15 10766 res = true;
f0ce3b1f 10767 goto end;
10768 case VOID_TYPE:
10769 /* This signifies an endlink, if no arguments remain, return
10770 true, otherwise return false. */
b7bf20db 10771 res = !more_const_call_expr_args_p (&iter);
f0ce3b1f 10772 goto end;
10773 default:
10774 /* If no parameters remain or the parameter's code does not
10775 match the specified code, return false. Otherwise continue
10776 checking any remaining arguments. */
b7bf20db 10777 arg = next_const_call_expr_arg (&iter);
c2f47e15 10778 if (!validate_arg (arg, code))
f0ce3b1f 10779 goto end;
10780 break;
10781 }
0eb671f7 10782 }
f0ce3b1f 10783 while (1);
0903457a 10784
10785 /* We need gotos here since we can only have one VA_CLOSE in a
10786 function. */
10787 end: ;
ee582a61 10788 va_end (ap);
0903457a 10789
10790 return res;
0eb671f7 10791}
fc2a2dcb 10792
fc2a2dcb 10793/* Default target-specific builtin expander that does nothing. */
10794
10795rtx
aecda0d6 10796default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
10797 rtx target ATTRIBUTE_UNUSED,
10798 rtx subtarget ATTRIBUTE_UNUSED,
10799 enum machine_mode mode ATTRIBUTE_UNUSED,
10800 int ignore ATTRIBUTE_UNUSED)
fc2a2dcb 10801{
10802 return NULL_RTX;
10803}
c7926a82 10804
01537105 10805/* Returns true is EXP represents data that would potentially reside
10806 in a readonly section. */
10807
10808static bool
10809readonly_data_expr (tree exp)
10810{
10811 STRIP_NOPS (exp);
10812
9ff0637e 10813 if (TREE_CODE (exp) != ADDR_EXPR)
10814 return false;
10815
10816 exp = get_base_address (TREE_OPERAND (exp, 0));
10817 if (!exp)
10818 return false;
10819
10820 /* Make sure we call decl_readonly_section only for trees it
10821 can handle (since it returns true for everything it doesn't
10822 understand). */
491e04ef 10823 if (TREE_CODE (exp) == STRING_CST
9ff0637e 10824 || TREE_CODE (exp) == CONSTRUCTOR
10825 || (TREE_CODE (exp) == VAR_DECL && TREE_STATIC (exp)))
10826 return decl_readonly_section (exp, 0);
01537105 10827 else
10828 return false;
10829}
4ee9c684 10830
c2f47e15 10831/* Simplify a call to the strstr builtin. S1 and S2 are the arguments
10832 to the call, and TYPE is its return type.
4ee9c684 10833
c2f47e15 10834 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10835 simplified form of the call as a tree.
10836
10837 The simplified form may be a constant or other expression which
10838 computes the same value, but in a more efficient manner (including
10839 calls to other builtin functions).
10840
10841 The call may contain arguments which need to be evaluated, but
10842 which are not useful to determine the result of the call. In
10843 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10844 COMPOUND_EXPR will be an argument which must be evaluated.
10845 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10846 COMPOUND_EXPR in the chain will contain the tree for the simplified
10847 form of the builtin function call. */
10848
10849static tree
c2f47e15 10850fold_builtin_strstr (tree s1, tree s2, tree type)
4ee9c684 10851{
c2f47e15 10852 if (!validate_arg (s1, POINTER_TYPE)
10853 || !validate_arg (s2, POINTER_TYPE))
10854 return NULL_TREE;
4ee9c684 10855 else
10856 {
4ee9c684 10857 tree fn;
10858 const char *p1, *p2;
10859
10860 p2 = c_getstr (s2);
10861 if (p2 == NULL)
c2f47e15 10862 return NULL_TREE;
4ee9c684 10863
10864 p1 = c_getstr (s1);
10865 if (p1 != NULL)
10866 {
10867 const char *r = strstr (p1, p2);
daa1d5f5 10868 tree tem;
4ee9c684 10869
4ee9c684 10870 if (r == NULL)
779b4c41 10871 return build_int_cst (TREE_TYPE (s1), 0);
c0c67e38 10872
10873 /* Return an offset into the constant string argument. */
0de36bdb 10874 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
10875 s1, size_int (r - p1));
daa1d5f5 10876 return fold_convert (type, tem);
4ee9c684 10877 }
10878
7efa231c 10879 /* The argument is const char *, and the result is char *, so we need
10880 a type conversion here to avoid a warning. */
4ee9c684 10881 if (p2[0] == '\0')
7efa231c 10882 return fold_convert (type, s1);
4ee9c684 10883
10884 if (p2[1] != '\0')
c2f47e15 10885 return NULL_TREE;
4ee9c684 10886
10887 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
10888 if (!fn)
c2f47e15 10889 return NULL_TREE;
4ee9c684 10890
10891 /* New argument list transforming strstr(s1, s2) to
10892 strchr(s1, s2[0]). */
c2f47e15 10893 return build_call_expr (fn, 2, s1, build_int_cst (NULL_TREE, p2[0]));
4ee9c684 10894 }
10895}
10896
c2f47e15 10897/* Simplify a call to the strchr builtin. S1 and S2 are the arguments to
10898 the call, and TYPE is its return type.
4ee9c684 10899
c2f47e15 10900 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10901 simplified form of the call as a tree.
10902
10903 The simplified form may be a constant or other expression which
10904 computes the same value, but in a more efficient manner (including
10905 calls to other builtin functions).
10906
10907 The call may contain arguments which need to be evaluated, but
10908 which are not useful to determine the result of the call. In
10909 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10910 COMPOUND_EXPR will be an argument which must be evaluated.
10911 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10912 COMPOUND_EXPR in the chain will contain the tree for the simplified
10913 form of the builtin function call. */
10914
10915static tree
c2f47e15 10916fold_builtin_strchr (tree s1, tree s2, tree type)
4ee9c684 10917{
c2f47e15 10918 if (!validate_arg (s1, POINTER_TYPE)
10919 || !validate_arg (s2, INTEGER_TYPE))
10920 return NULL_TREE;
4ee9c684 10921 else
10922 {
4ee9c684 10923 const char *p1;
10924
10925 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 10926 return NULL_TREE;
4ee9c684 10927
10928 p1 = c_getstr (s1);
10929 if (p1 != NULL)
10930 {
10931 char c;
10932 const char *r;
daa1d5f5 10933 tree tem;
4ee9c684 10934
10935 if (target_char_cast (s2, &c))
c2f47e15 10936 return NULL_TREE;
4ee9c684 10937
10938 r = strchr (p1, c);
10939
10940 if (r == NULL)
779b4c41 10941 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 10942
10943 /* Return an offset into the constant string argument. */
0de36bdb 10944 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
10945 s1, size_int (r - p1));
daa1d5f5 10946 return fold_convert (type, tem);
4ee9c684 10947 }
c2f47e15 10948 return NULL_TREE;
4ee9c684 10949 }
10950}
10951
c2f47e15 10952/* Simplify a call to the strrchr builtin. S1 and S2 are the arguments to
10953 the call, and TYPE is its return type.
4ee9c684 10954
c2f47e15 10955 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10956 simplified form of the call as a tree.
10957
10958 The simplified form may be a constant or other expression which
10959 computes the same value, but in a more efficient manner (including
10960 calls to other builtin functions).
10961
10962 The call may contain arguments which need to be evaluated, but
10963 which are not useful to determine the result of the call. In
10964 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10965 COMPOUND_EXPR will be an argument which must be evaluated.
10966 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10967 COMPOUND_EXPR in the chain will contain the tree for the simplified
10968 form of the builtin function call. */
10969
10970static tree
c2f47e15 10971fold_builtin_strrchr (tree s1, tree s2, tree type)
4ee9c684 10972{
c2f47e15 10973 if (!validate_arg (s1, POINTER_TYPE)
10974 || !validate_arg (s2, INTEGER_TYPE))
10975 return NULL_TREE;
4ee9c684 10976 else
10977 {
4ee9c684 10978 tree fn;
10979 const char *p1;
10980
10981 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 10982 return NULL_TREE;
4ee9c684 10983
10984 p1 = c_getstr (s1);
10985 if (p1 != NULL)
10986 {
10987 char c;
10988 const char *r;
daa1d5f5 10989 tree tem;
4ee9c684 10990
10991 if (target_char_cast (s2, &c))
c2f47e15 10992 return NULL_TREE;
4ee9c684 10993
10994 r = strrchr (p1, c);
10995
10996 if (r == NULL)
779b4c41 10997 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 10998
10999 /* Return an offset into the constant string argument. */
0de36bdb 11000 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
11001 s1, size_int (r - p1));
daa1d5f5 11002 return fold_convert (type, tem);
4ee9c684 11003 }
11004
11005 if (! integer_zerop (s2))
c2f47e15 11006 return NULL_TREE;
4ee9c684 11007
11008 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
11009 if (!fn)
c2f47e15 11010 return NULL_TREE;
4ee9c684 11011
11012 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
c2f47e15 11013 return build_call_expr (fn, 2, s1, s2);
4ee9c684 11014 }
11015}
11016
c2f47e15 11017/* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments
11018 to the call, and TYPE is its return type.
4ee9c684 11019
c2f47e15 11020 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11021 simplified form of the call as a tree.
11022
11023 The simplified form may be a constant or other expression which
11024 computes the same value, but in a more efficient manner (including
11025 calls to other builtin functions).
11026
11027 The call may contain arguments which need to be evaluated, but
11028 which are not useful to determine the result of the call. In
11029 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11030 COMPOUND_EXPR will be an argument which must be evaluated.
11031 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11032 COMPOUND_EXPR in the chain will contain the tree for the simplified
11033 form of the builtin function call. */
11034
11035static tree
c2f47e15 11036fold_builtin_strpbrk (tree s1, tree s2, tree type)
4ee9c684 11037{
c2f47e15 11038 if (!validate_arg (s1, POINTER_TYPE)
11039 || !validate_arg (s2, POINTER_TYPE))
11040 return NULL_TREE;
4ee9c684 11041 else
11042 {
4ee9c684 11043 tree fn;
11044 const char *p1, *p2;
11045
11046 p2 = c_getstr (s2);
11047 if (p2 == NULL)
c2f47e15 11048 return NULL_TREE;
4ee9c684 11049
11050 p1 = c_getstr (s1);
11051 if (p1 != NULL)
11052 {
11053 const char *r = strpbrk (p1, p2);
daa1d5f5 11054 tree tem;
4ee9c684 11055
11056 if (r == NULL)
779b4c41 11057 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11058
11059 /* Return an offset into the constant string argument. */
0de36bdb 11060 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
11061 s1, size_int (r - p1));
daa1d5f5 11062 return fold_convert (type, tem);
4ee9c684 11063 }
11064
11065 if (p2[0] == '\0')
05abc81b 11066 /* strpbrk(x, "") == NULL.
11067 Evaluate and ignore s1 in case it had side-effects. */
11068 return omit_one_operand (TREE_TYPE (s1), integer_zero_node, s1);
4ee9c684 11069
11070 if (p2[1] != '\0')
c2f47e15 11071 return NULL_TREE; /* Really call strpbrk. */
4ee9c684 11072
11073 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
11074 if (!fn)
c2f47e15 11075 return NULL_TREE;
4ee9c684 11076
11077 /* New argument list transforming strpbrk(s1, s2) to
11078 strchr(s1, s2[0]). */
c2f47e15 11079 return build_call_expr (fn, 2, s1, build_int_cst (NULL_TREE, p2[0]));
4ee9c684 11080 }
11081}
11082
c2f47e15 11083/* Simplify a call to the strcat builtin. DST and SRC are the arguments
11084 to the call.
4ee9c684 11085
c2f47e15 11086 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11087 simplified form of the call as a tree.
11088
11089 The simplified form may be a constant or other expression which
11090 computes the same value, but in a more efficient manner (including
11091 calls to other builtin functions).
11092
11093 The call may contain arguments which need to be evaluated, but
11094 which are not useful to determine the result of the call. In
11095 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11096 COMPOUND_EXPR will be an argument which must be evaluated.
11097 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11098 COMPOUND_EXPR in the chain will contain the tree for the simplified
11099 form of the builtin function call. */
11100
11101static tree
c2f47e15 11102fold_builtin_strcat (tree dst, tree src)
4ee9c684 11103{
c2f47e15 11104 if (!validate_arg (dst, POINTER_TYPE)
11105 || !validate_arg (src, POINTER_TYPE))
11106 return NULL_TREE;
4ee9c684 11107 else
11108 {
4ee9c684 11109 const char *p = c_getstr (src);
11110
11111 /* If the string length is zero, return the dst parameter. */
11112 if (p && *p == '\0')
11113 return dst;
11114
c2f47e15 11115 return NULL_TREE;
4ee9c684 11116 }
11117}
11118
c2f47e15 11119/* Simplify a call to the strncat builtin. DST, SRC, and LEN are the
11120 arguments to the call.
4ee9c684 11121
c2f47e15 11122 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11123 simplified form of the call as a tree.
11124
11125 The simplified form may be a constant or other expression which
11126 computes the same value, but in a more efficient manner (including
11127 calls to other builtin functions).
11128
11129 The call may contain arguments which need to be evaluated, but
11130 which are not useful to determine the result of the call. In
11131 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11132 COMPOUND_EXPR will be an argument which must be evaluated.
11133 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11134 COMPOUND_EXPR in the chain will contain the tree for the simplified
11135 form of the builtin function call. */
11136
11137static tree
c2f47e15 11138fold_builtin_strncat (tree dst, tree src, tree len)
4ee9c684 11139{
c2f47e15 11140 if (!validate_arg (dst, POINTER_TYPE)
11141 || !validate_arg (src, POINTER_TYPE)
11142 || !validate_arg (len, INTEGER_TYPE))
11143 return NULL_TREE;
4ee9c684 11144 else
11145 {
4ee9c684 11146 const char *p = c_getstr (src);
11147
11148 /* If the requested length is zero, or the src parameter string
0a39fd54 11149 length is zero, return the dst parameter. */
4ee9c684 11150 if (integer_zerop (len) || (p && *p == '\0'))
a0c938f0 11151 return omit_two_operands (TREE_TYPE (dst), dst, src, len);
4ee9c684 11152
11153 /* If the requested len is greater than or equal to the string
a0c938f0 11154 length, call strcat. */
4ee9c684 11155 if (TREE_CODE (len) == INTEGER_CST && p
11156 && compare_tree_int (len, strlen (p)) >= 0)
11157 {
4ee9c684 11158 tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
11159
11160 /* If the replacement _DECL isn't initialized, don't do the
11161 transformation. */
11162 if (!fn)
c2f47e15 11163 return NULL_TREE;
4ee9c684 11164
c2f47e15 11165 return build_call_expr (fn, 2, dst, src);
4ee9c684 11166 }
c2f47e15 11167 return NULL_TREE;
4ee9c684 11168 }
11169}
11170
c2f47e15 11171/* Simplify a call to the strspn builtin. S1 and S2 are the arguments
11172 to the call.
4ee9c684 11173
c2f47e15 11174 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11175 simplified form of the call as a tree.
11176
11177 The simplified form may be a constant or other expression which
11178 computes the same value, but in a more efficient manner (including
11179 calls to other builtin functions).
11180
11181 The call may contain arguments which need to be evaluated, but
11182 which are not useful to determine the result of the call. In
11183 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11184 COMPOUND_EXPR will be an argument which must be evaluated.
11185 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11186 COMPOUND_EXPR in the chain will contain the tree for the simplified
11187 form of the builtin function call. */
11188
11189static tree
c2f47e15 11190fold_builtin_strspn (tree s1, tree s2)
4ee9c684 11191{
c2f47e15 11192 if (!validate_arg (s1, POINTER_TYPE)
11193 || !validate_arg (s2, POINTER_TYPE))
11194 return NULL_TREE;
4ee9c684 11195 else
11196 {
4ee9c684 11197 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11198
11199 /* If both arguments are constants, evaluate at compile-time. */
11200 if (p1 && p2)
11201 {
11202 const size_t r = strspn (p1, p2);
11203 return size_int (r);
11204 }
11205
c2f47e15 11206 /* If either argument is "", return NULL_TREE. */
4ee9c684 11207 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9bc9f15f 11208 /* Evaluate and ignore both arguments in case either one has
11209 side-effects. */
11210 return omit_two_operands (integer_type_node, integer_zero_node,
11211 s1, s2);
c2f47e15 11212 return NULL_TREE;
4ee9c684 11213 }
11214}
11215
c2f47e15 11216/* Simplify a call to the strcspn builtin. S1 and S2 are the arguments
11217 to the call.
4ee9c684 11218
c2f47e15 11219 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11220 simplified form of the call as a tree.
11221
11222 The simplified form may be a constant or other expression which
11223 computes the same value, but in a more efficient manner (including
11224 calls to other builtin functions).
11225
11226 The call may contain arguments which need to be evaluated, but
11227 which are not useful to determine the result of the call. In
11228 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11229 COMPOUND_EXPR will be an argument which must be evaluated.
11230 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11231 COMPOUND_EXPR in the chain will contain the tree for the simplified
11232 form of the builtin function call. */
11233
11234static tree
c2f47e15 11235fold_builtin_strcspn (tree s1, tree s2)
4ee9c684 11236{
c2f47e15 11237 if (!validate_arg (s1, POINTER_TYPE)
11238 || !validate_arg (s2, POINTER_TYPE))
11239 return NULL_TREE;
4ee9c684 11240 else
11241 {
4ee9c684 11242 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11243
11244 /* If both arguments are constants, evaluate at compile-time. */
11245 if (p1 && p2)
11246 {
11247 const size_t r = strcspn (p1, p2);
11248 return size_int (r);
11249 }
11250
c2f47e15 11251 /* If the first argument is "", return NULL_TREE. */
4ee9c684 11252 if (p1 && *p1 == '\0')
11253 {
11254 /* Evaluate and ignore argument s2 in case it has
11255 side-effects. */
05abc81b 11256 return omit_one_operand (integer_type_node,
11257 integer_zero_node, s2);
4ee9c684 11258 }
11259
11260 /* If the second argument is "", return __builtin_strlen(s1). */
11261 if (p2 && *p2 == '\0')
11262 {
c2f47e15 11263 tree fn = implicit_built_in_decls[BUILT_IN_STRLEN];
4ee9c684 11264
11265 /* If the replacement _DECL isn't initialized, don't do the
11266 transformation. */
11267 if (!fn)
c2f47e15 11268 return NULL_TREE;
4ee9c684 11269
c2f47e15 11270 return build_call_expr (fn, 1, s1);
4ee9c684 11271 }
c2f47e15 11272 return NULL_TREE;
4ee9c684 11273 }
11274}
11275
c2f47e15 11276/* Fold a call to the fputs builtin. ARG0 and ARG1 are the arguments
11277 to the call. IGNORE is true if the value returned
f0613857 11278 by the builtin will be ignored. UNLOCKED is true is true if this
11279 actually a call to fputs_unlocked. If LEN in non-NULL, it represents
11280 the known length of the string. Return NULL_TREE if no simplification
11281 was possible. */
4ee9c684 11282
11283tree
c2f47e15 11284fold_builtin_fputs (tree arg0, tree arg1, bool ignore, bool unlocked, tree len)
4ee9c684 11285{
6d77ed92 11286 /* If we're using an unlocked function, assume the other unlocked
11287 functions exist explicitly. */
11288 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
4ee9c684 11289 : implicit_built_in_decls[BUILT_IN_FPUTC];
6d77ed92 11290 tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
4ee9c684 11291 : implicit_built_in_decls[BUILT_IN_FWRITE];
11292
c403edd4 11293 /* If the return value is used, don't do the transformation. */
11294 if (!ignore)
c2f47e15 11295 return NULL_TREE;
4ee9c684 11296
11297 /* Verify the arguments in the original call. */
c2f47e15 11298 if (!validate_arg (arg0, POINTER_TYPE)
11299 || !validate_arg (arg1, POINTER_TYPE))
11300 return NULL_TREE;
4ee9c684 11301
f0613857 11302 if (! len)
c2f47e15 11303 len = c_strlen (arg0, 0);
4ee9c684 11304
11305 /* Get the length of the string passed to fputs. If the length
11306 can't be determined, punt. */
11307 if (!len
11308 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 11309 return NULL_TREE;
4ee9c684 11310
11311 switch (compare_tree_int (len, 1))
11312 {
11313 case -1: /* length is 0, delete the call entirely . */
c2f47e15 11314 return omit_one_operand (integer_type_node, integer_zero_node, arg1);;
05abc81b 11315
4ee9c684 11316 case 0: /* length is 1, call fputc. */
11317 {
c2f47e15 11318 const char *p = c_getstr (arg0);
4ee9c684 11319
11320 if (p != NULL)
11321 {
c2f47e15 11322 if (fn_fputc)
11323 return build_call_expr (fn_fputc, 2,
11324 build_int_cst (NULL_TREE, p[0]), arg1);
11325 else
11326 return NULL_TREE;
4ee9c684 11327 }
11328 }
11329 /* FALLTHROUGH */
11330 case 1: /* length is greater than 1, call fwrite. */
11331 {
0bed3869 11332 /* If optimizing for size keep fputs. */
4ee9c684 11333 if (optimize_size)
c2f47e15 11334 return NULL_TREE;
4ee9c684 11335 /* New argument list transforming fputs(string, stream) to
11336 fwrite(string, 1, len, stream). */
c2f47e15 11337 if (fn_fwrite)
11338 return build_call_expr (fn_fwrite, 4, arg0, size_one_node, len, arg1);
11339 else
11340 return NULL_TREE;
4ee9c684 11341 }
11342 default:
64db345d 11343 gcc_unreachable ();
4ee9c684 11344 }
c2f47e15 11345 return NULL_TREE;
4ee9c684 11346}
11347
c2f47e15 11348/* Fold the next_arg or va_start call EXP. Returns true if there was an error
743b0c6a 11349 produced. False otherwise. This is done so that we don't output the error
11350 or warning twice or three times. */
11351bool
c2f47e15 11352fold_builtin_next_arg (tree exp, bool va_start_p)
4ee9c684 11353{
11354 tree fntype = TREE_TYPE (current_function_decl);
c2f47e15 11355 int nargs = call_expr_nargs (exp);
11356 tree arg;
4ee9c684 11357
11358 if (TYPE_ARG_TYPES (fntype) == 0
11359 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
11360 == void_type_node))
743b0c6a 11361 {
11362 error ("%<va_start%> used in function with fixed args");
11363 return true;
11364 }
c2f47e15 11365
11366 if (va_start_p)
79012a9d 11367 {
c2f47e15 11368 if (va_start_p && (nargs != 2))
11369 {
11370 error ("wrong number of arguments to function %<va_start%>");
11371 return true;
11372 }
11373 arg = CALL_EXPR_ARG (exp, 1);
79012a9d 11374 }
11375 /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
11376 when we checked the arguments and if needed issued a warning. */
c2f47e15 11377 else
4ee9c684 11378 {
c2f47e15 11379 if (nargs == 0)
11380 {
11381 /* Evidently an out of date version of <stdarg.h>; can't validate
11382 va_start's second argument, but can still work as intended. */
11383 warning (0, "%<__builtin_next_arg%> called without an argument");
11384 return true;
11385 }
11386 else if (nargs > 1)
a0c938f0 11387 {
c2f47e15 11388 error ("wrong number of arguments to function %<__builtin_next_arg%>");
a0c938f0 11389 return true;
11390 }
c2f47e15 11391 arg = CALL_EXPR_ARG (exp, 0);
11392 }
11393
11394 /* We destructively modify the call to be __builtin_va_start (ap, 0)
11395 or __builtin_next_arg (0) the first time we see it, after checking
11396 the arguments and if needed issuing a warning. */
11397 if (!integer_zerop (arg))
11398 {
11399 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
79012a9d 11400
4ee9c684 11401 /* Strip off all nops for the sake of the comparison. This
11402 is not quite the same as STRIP_NOPS. It does more.
11403 We must also strip off INDIRECT_EXPR for C++ reference
11404 parameters. */
11405 while (TREE_CODE (arg) == NOP_EXPR
11406 || TREE_CODE (arg) == CONVERT_EXPR
11407 || TREE_CODE (arg) == NON_LVALUE_EXPR
11408 || TREE_CODE (arg) == INDIRECT_REF)
11409 arg = TREE_OPERAND (arg, 0);
11410 if (arg != last_parm)
a0c938f0 11411 {
b08cf617 11412 /* FIXME: Sometimes with the tree optimizers we can get the
11413 not the last argument even though the user used the last
11414 argument. We just warn and set the arg to be the last
11415 argument so that we will get wrong-code because of
11416 it. */
c3ceba8e 11417 warning (0, "second parameter of %<va_start%> not last named argument");
743b0c6a 11418 }
79012a9d 11419 /* We want to verify the second parameter just once before the tree
a0c938f0 11420 optimizers are run and then avoid keeping it in the tree,
11421 as otherwise we could warn even for correct code like:
11422 void foo (int i, ...)
11423 { va_list ap; i++; va_start (ap, i); va_end (ap); } */
c2f47e15 11424 if (va_start_p)
11425 CALL_EXPR_ARG (exp, 1) = integer_zero_node;
11426 else
11427 CALL_EXPR_ARG (exp, 0) = integer_zero_node;
743b0c6a 11428 }
11429 return false;
4ee9c684 11430}
11431
11432
c2f47e15 11433/* Simplify a call to the sprintf builtin with arguments DEST, FMT, and ORIG.
11434 ORIG may be null if this is a 2-argument call. We don't attempt to
11435 simplify calls with more than 3 arguments.
4ee9c684 11436
c2f47e15 11437 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11438 simplified form of the call as a tree. If IGNORED is true, it means that
11439 the caller does not use the returned value of the function. */
11440
11441static tree
c2f47e15 11442fold_builtin_sprintf (tree dest, tree fmt, tree orig, int ignored)
4ee9c684 11443{
c2f47e15 11444 tree call, retval;
4ee9c684 11445 const char *fmt_str = NULL;
11446
11447 /* Verify the required arguments in the original call. We deal with two
11448 types of sprintf() calls: 'sprintf (str, fmt)' and
11449 'sprintf (dest, "%s", orig)'. */
c2f47e15 11450 if (!validate_arg (dest, POINTER_TYPE)
11451 || !validate_arg (fmt, POINTER_TYPE))
11452 return NULL_TREE;
11453 if (orig && !validate_arg (orig, POINTER_TYPE))
4ee9c684 11454 return NULL_TREE;
4ee9c684 11455
11456 /* Check whether the format is a literal string constant. */
11457 fmt_str = c_getstr (fmt);
11458 if (fmt_str == NULL)
11459 return NULL_TREE;
11460
11461 call = NULL_TREE;
11462 retval = NULL_TREE;
11463
d4473c84 11464 if (!init_target_chars ())
c2f47e15 11465 return NULL_TREE;
99eabcc1 11466
4ee9c684 11467 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 11468 if (strchr (fmt_str, target_percent) == NULL)
4ee9c684 11469 {
11470 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11471
11472 if (!fn)
11473 return NULL_TREE;
11474
72dfb3f2 11475 /* Don't optimize sprintf (buf, "abc", ptr++). */
c2f47e15 11476 if (orig)
72dfb3f2 11477 return NULL_TREE;
11478
4ee9c684 11479 /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
11480 'format' is known to contain no % formats. */
c2f47e15 11481 call = build_call_expr (fn, 2, dest, fmt);
4ee9c684 11482 if (!ignored)
7016c612 11483 retval = build_int_cst (NULL_TREE, strlen (fmt_str));
4ee9c684 11484 }
11485
11486 /* If the format is "%s", use strcpy if the result isn't used. */
99eabcc1 11487 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
4ee9c684 11488 {
c2f47e15 11489 tree fn;
4ee9c684 11490 fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11491
11492 if (!fn)
11493 return NULL_TREE;
11494
72dfb3f2 11495 /* Don't crash on sprintf (str1, "%s"). */
c2f47e15 11496 if (!orig)
72dfb3f2 11497 return NULL_TREE;
11498
4ee9c684 11499 /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2). */
4ee9c684 11500 if (!ignored)
11501 {
11502 retval = c_strlen (orig, 1);
11503 if (!retval || TREE_CODE (retval) != INTEGER_CST)
11504 return NULL_TREE;
11505 }
c2f47e15 11506 call = build_call_expr (fn, 2, dest, orig);
4ee9c684 11507 }
11508
11509 if (call && retval)
11510 {
e3b560a6 11511 retval = fold_convert
4ee9c684 11512 (TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])),
11513 retval);
05abc81b 11514 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
4ee9c684 11515 }
11516 else
11517 return call;
11518}
0a39fd54 11519
c2f47e15 11520/* Expand a call EXP to __builtin_object_size. */
0a39fd54 11521
11522rtx
11523expand_builtin_object_size (tree exp)
11524{
11525 tree ost;
11526 int object_size_type;
11527 tree fndecl = get_callee_fndecl (exp);
0a39fd54 11528
c2f47e15 11529 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
0a39fd54 11530 {
b8c23db3 11531 error ("%Kfirst argument of %D must be a pointer, second integer constant",
11532 exp, fndecl);
0a39fd54 11533 expand_builtin_trap ();
11534 return const0_rtx;
11535 }
11536
c2f47e15 11537 ost = CALL_EXPR_ARG (exp, 1);
0a39fd54 11538 STRIP_NOPS (ost);
11539
11540 if (TREE_CODE (ost) != INTEGER_CST
11541 || tree_int_cst_sgn (ost) < 0
11542 || compare_tree_int (ost, 3) > 0)
11543 {
b8c23db3 11544 error ("%Klast argument of %D is not integer constant between 0 and 3",
11545 exp, fndecl);
0a39fd54 11546 expand_builtin_trap ();
11547 return const0_rtx;
11548 }
11549
11550 object_size_type = tree_low_cst (ost, 0);
11551
11552 return object_size_type < 2 ? constm1_rtx : const0_rtx;
11553}
11554
11555/* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
11556 FCODE is the BUILT_IN_* to use.
c2f47e15 11557 Return NULL_RTX if we failed; the caller should emit a normal call,
0a39fd54 11558 otherwise try to get the result in TARGET, if convenient (and in
11559 mode MODE if that's convenient). */
11560
11561static rtx
11562expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
11563 enum built_in_function fcode)
11564{
0a39fd54 11565 tree dest, src, len, size;
11566
c2f47e15 11567 if (!validate_arglist (exp,
0a39fd54 11568 POINTER_TYPE,
11569 fcode == BUILT_IN_MEMSET_CHK
11570 ? INTEGER_TYPE : POINTER_TYPE,
11571 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
c2f47e15 11572 return NULL_RTX;
0a39fd54 11573
c2f47e15 11574 dest = CALL_EXPR_ARG (exp, 0);
11575 src = CALL_EXPR_ARG (exp, 1);
11576 len = CALL_EXPR_ARG (exp, 2);
11577 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11578
11579 if (! host_integerp (size, 1))
c2f47e15 11580 return NULL_RTX;
0a39fd54 11581
11582 if (host_integerp (len, 1) || integer_all_onesp (size))
11583 {
11584 tree fn;
11585
11586 if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
11587 {
b8c23db3 11588 warning (0, "%Kcall to %D will always overflow destination buffer",
11589 exp, get_callee_fndecl (exp));
c2f47e15 11590 return NULL_RTX;
0a39fd54 11591 }
11592
0a39fd54 11593 fn = NULL_TREE;
11594 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
11595 mem{cpy,pcpy,move,set} is available. */
11596 switch (fcode)
11597 {
11598 case BUILT_IN_MEMCPY_CHK:
11599 fn = built_in_decls[BUILT_IN_MEMCPY];
11600 break;
11601 case BUILT_IN_MEMPCPY_CHK:
11602 fn = built_in_decls[BUILT_IN_MEMPCPY];
11603 break;
11604 case BUILT_IN_MEMMOVE_CHK:
11605 fn = built_in_decls[BUILT_IN_MEMMOVE];
11606 break;
11607 case BUILT_IN_MEMSET_CHK:
11608 fn = built_in_decls[BUILT_IN_MEMSET];
11609 break;
11610 default:
11611 break;
11612 }
11613
11614 if (! fn)
c2f47e15 11615 return NULL_RTX;
0a39fd54 11616
c2f47e15 11617 fn = build_call_expr (fn, 3, dest, src, len);
6d54e886 11618 STRIP_TYPE_NOPS (fn);
11619 while (TREE_CODE (fn) == COMPOUND_EXPR)
11620 {
11621 expand_expr (TREE_OPERAND (fn, 0), const0_rtx, VOIDmode,
11622 EXPAND_NORMAL);
11623 fn = TREE_OPERAND (fn, 1);
11624 }
0a39fd54 11625 if (TREE_CODE (fn) == CALL_EXPR)
11626 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
11627 return expand_expr (fn, target, mode, EXPAND_NORMAL);
11628 }
11629 else if (fcode == BUILT_IN_MEMSET_CHK)
c2f47e15 11630 return NULL_RTX;
0a39fd54 11631 else
11632 {
11633 unsigned int dest_align
11634 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
11635
11636 /* If DEST is not a pointer type, call the normal function. */
11637 if (dest_align == 0)
c2f47e15 11638 return NULL_RTX;
0a39fd54 11639
11640 /* If SRC and DEST are the same (and not volatile), do nothing. */
11641 if (operand_equal_p (src, dest, 0))
11642 {
11643 tree expr;
11644
11645 if (fcode != BUILT_IN_MEMPCPY_CHK)
11646 {
11647 /* Evaluate and ignore LEN in case it has side-effects. */
11648 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
11649 return expand_expr (dest, target, mode, EXPAND_NORMAL);
11650 }
11651
0de36bdb 11652 expr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
0a39fd54 11653 return expand_expr (expr, target, mode, EXPAND_NORMAL);
11654 }
11655
11656 /* __memmove_chk special case. */
11657 if (fcode == BUILT_IN_MEMMOVE_CHK)
11658 {
11659 unsigned int src_align
11660 = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
11661
11662 if (src_align == 0)
c2f47e15 11663 return NULL_RTX;
0a39fd54 11664
11665 /* If src is categorized for a readonly section we can use
11666 normal __memcpy_chk. */
11667 if (readonly_data_expr (src))
11668 {
11669 tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
11670 if (!fn)
c2f47e15 11671 return NULL_RTX;
11672 fn = build_call_expr (fn, 4, dest, src, len, size);
6d54e886 11673 STRIP_TYPE_NOPS (fn);
11674 while (TREE_CODE (fn) == COMPOUND_EXPR)
11675 {
11676 expand_expr (TREE_OPERAND (fn, 0), const0_rtx, VOIDmode,
11677 EXPAND_NORMAL);
11678 fn = TREE_OPERAND (fn, 1);
11679 }
0a39fd54 11680 if (TREE_CODE (fn) == CALL_EXPR)
11681 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
11682 return expand_expr (fn, target, mode, EXPAND_NORMAL);
11683 }
11684 }
c2f47e15 11685 return NULL_RTX;
0a39fd54 11686 }
11687}
11688
11689/* Emit warning if a buffer overflow is detected at compile time. */
11690
11691static void
11692maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
11693{
c2f47e15 11694 int is_strlen = 0;
0a39fd54 11695 tree len, size;
0a39fd54 11696
11697 switch (fcode)
11698 {
11699 case BUILT_IN_STRCPY_CHK:
11700 case BUILT_IN_STPCPY_CHK:
11701 /* For __strcat_chk the warning will be emitted only if overflowing
11702 by at least strlen (dest) + 1 bytes. */
11703 case BUILT_IN_STRCAT_CHK:
c2f47e15 11704 len = CALL_EXPR_ARG (exp, 1);
11705 size = CALL_EXPR_ARG (exp, 2);
0a39fd54 11706 is_strlen = 1;
11707 break;
b356dfef 11708 case BUILT_IN_STRNCAT_CHK:
0a39fd54 11709 case BUILT_IN_STRNCPY_CHK:
c2f47e15 11710 len = CALL_EXPR_ARG (exp, 2);
11711 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11712 break;
11713 case BUILT_IN_SNPRINTF_CHK:
11714 case BUILT_IN_VSNPRINTF_CHK:
c2f47e15 11715 len = CALL_EXPR_ARG (exp, 1);
11716 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11717 break;
11718 default:
11719 gcc_unreachable ();
11720 }
11721
0a39fd54 11722 if (!len || !size)
11723 return;
11724
0a39fd54 11725 if (! host_integerp (size, 1) || integer_all_onesp (size))
11726 return;
11727
11728 if (is_strlen)
11729 {
11730 len = c_strlen (len, 1);
11731 if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
11732 return;
11733 }
b356dfef 11734 else if (fcode == BUILT_IN_STRNCAT_CHK)
11735 {
c2f47e15 11736 tree src = CALL_EXPR_ARG (exp, 1);
b356dfef 11737 if (! src || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
11738 return;
11739 src = c_strlen (src, 1);
11740 if (! src || ! host_integerp (src, 1))
11741 {
b8c23db3 11742 warning (0, "%Kcall to %D might overflow destination buffer",
11743 exp, get_callee_fndecl (exp));
b356dfef 11744 return;
11745 }
11746 else if (tree_int_cst_lt (src, size))
11747 return;
11748 }
0a39fd54 11749 else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
11750 return;
11751
b8c23db3 11752 warning (0, "%Kcall to %D will always overflow destination buffer",
11753 exp, get_callee_fndecl (exp));
0a39fd54 11754}
11755
11756/* Emit warning if a buffer overflow is detected at compile time
11757 in __sprintf_chk/__vsprintf_chk calls. */
11758
11759static void
11760maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
11761{
0a39fd54 11762 tree dest, size, len, fmt, flag;
11763 const char *fmt_str;
c2f47e15 11764 int nargs = call_expr_nargs (exp);
0a39fd54 11765
11766 /* Verify the required arguments in the original call. */
c2f47e15 11767
11768 if (nargs < 4)
0a39fd54 11769 return;
c2f47e15 11770 dest = CALL_EXPR_ARG (exp, 0);
11771 flag = CALL_EXPR_ARG (exp, 1);
11772 size = CALL_EXPR_ARG (exp, 2);
11773 fmt = CALL_EXPR_ARG (exp, 3);
0a39fd54 11774
11775 if (! host_integerp (size, 1) || integer_all_onesp (size))
11776 return;
11777
11778 /* Check whether the format is a literal string constant. */
11779 fmt_str = c_getstr (fmt);
11780 if (fmt_str == NULL)
11781 return;
11782
d4473c84 11783 if (!init_target_chars ())
99eabcc1 11784 return;
11785
0a39fd54 11786 /* If the format doesn't contain % args or %%, we know its size. */
99eabcc1 11787 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 11788 len = build_int_cstu (size_type_node, strlen (fmt_str));
11789 /* If the format is "%s" and first ... argument is a string literal,
11790 we know it too. */
c2f47e15 11791 else if (fcode == BUILT_IN_SPRINTF_CHK
11792 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 11793 {
11794 tree arg;
11795
c2f47e15 11796 if (nargs < 5)
0a39fd54 11797 return;
c2f47e15 11798 arg = CALL_EXPR_ARG (exp, 4);
0a39fd54 11799 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
11800 return;
11801
11802 len = c_strlen (arg, 1);
11803 if (!len || ! host_integerp (len, 1))
11804 return;
11805 }
11806 else
11807 return;
11808
11809 if (! tree_int_cst_lt (len, size))
11810 {
b8c23db3 11811 warning (0, "%Kcall to %D will always overflow destination buffer",
11812 exp, get_callee_fndecl (exp));
0a39fd54 11813 }
11814}
11815
c2f47e15 11816/* Fold a call to __builtin_object_size with arguments PTR and OST,
11817 if possible. */
0a39fd54 11818
11819tree
c2f47e15 11820fold_builtin_object_size (tree ptr, tree ost)
0a39fd54 11821{
c2f47e15 11822 tree ret = NULL_TREE;
0a39fd54 11823 int object_size_type;
11824
c2f47e15 11825 if (!validate_arg (ptr, POINTER_TYPE)
11826 || !validate_arg (ost, INTEGER_TYPE))
11827 return NULL_TREE;
0a39fd54 11828
0a39fd54 11829 STRIP_NOPS (ost);
11830
11831 if (TREE_CODE (ost) != INTEGER_CST
11832 || tree_int_cst_sgn (ost) < 0
11833 || compare_tree_int (ost, 3) > 0)
c2f47e15 11834 return NULL_TREE;
0a39fd54 11835
11836 object_size_type = tree_low_cst (ost, 0);
11837
11838 /* __builtin_object_size doesn't evaluate side-effects in its arguments;
11839 if there are any side-effects, it returns (size_t) -1 for types 0 and 1
11840 and (size_t) 0 for types 2 and 3. */
11841 if (TREE_SIDE_EFFECTS (ptr))
697bbc3f 11842 return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
0a39fd54 11843
11844 if (TREE_CODE (ptr) == ADDR_EXPR)
11845 ret = build_int_cstu (size_type_node,
697bbc3f 11846 compute_builtin_object_size (ptr, object_size_type));
0a39fd54 11847
11848 else if (TREE_CODE (ptr) == SSA_NAME)
11849 {
11850 unsigned HOST_WIDE_INT bytes;
11851
11852 /* If object size is not known yet, delay folding until
11853 later. Maybe subsequent passes will help determining
11854 it. */
11855 bytes = compute_builtin_object_size (ptr, object_size_type);
11856 if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2
11857 ? -1 : 0))
11858 ret = build_int_cstu (size_type_node, bytes);
11859 }
11860
11861 if (ret)
11862 {
697bbc3f 11863 unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (ret);
11864 HOST_WIDE_INT high = TREE_INT_CST_HIGH (ret);
11865 if (fit_double_type (low, high, &low, &high, TREE_TYPE (ret)))
11866 ret = NULL_TREE;
0a39fd54 11867 }
11868
11869 return ret;
11870}
11871
11872/* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
c2f47e15 11873 DEST, SRC, LEN, and SIZE are the arguments to the call.
0a39fd54 11874 IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_*
11875 code of the builtin. If MAXLEN is not NULL, it is maximum length
11876 passed as third argument. */
11877
11878tree
c2f47e15 11879fold_builtin_memory_chk (tree fndecl,
11880 tree dest, tree src, tree len, tree size,
11881 tree maxlen, bool ignore,
0a39fd54 11882 enum built_in_function fcode)
11883{
c2f47e15 11884 tree fn;
0a39fd54 11885
c2f47e15 11886 if (!validate_arg (dest, POINTER_TYPE)
11887 || !validate_arg (src,
11888 (fcode == BUILT_IN_MEMSET_CHK
11889 ? INTEGER_TYPE : POINTER_TYPE))
11890 || !validate_arg (len, INTEGER_TYPE)
11891 || !validate_arg (size, INTEGER_TYPE))
11892 return NULL_TREE;
0a39fd54 11893
11894 /* If SRC and DEST are the same (and not volatile), return DEST
11895 (resp. DEST+LEN for __mempcpy_chk). */
11896 if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
11897 {
11898 if (fcode != BUILT_IN_MEMPCPY_CHK)
11899 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
11900 else
11901 {
0de36bdb 11902 tree temp = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
0a39fd54 11903 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), temp);
11904 }
11905 }
11906
11907 if (! host_integerp (size, 1))
c2f47e15 11908 return NULL_TREE;
0a39fd54 11909
11910 if (! integer_all_onesp (size))
11911 {
11912 if (! host_integerp (len, 1))
11913 {
11914 /* If LEN is not constant, try MAXLEN too.
11915 For MAXLEN only allow optimizing into non-_ocs function
11916 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
11917 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
11918 {
11919 if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
11920 {
11921 /* (void) __mempcpy_chk () can be optimized into
11922 (void) __memcpy_chk (). */
11923 fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
11924 if (!fn)
c2f47e15 11925 return NULL_TREE;
0a39fd54 11926
c2f47e15 11927 return build_call_expr (fn, 4, dest, src, len, size);
0a39fd54 11928 }
c2f47e15 11929 return NULL_TREE;
0a39fd54 11930 }
0a39fd54 11931 }
ad89623c 11932 else
11933 maxlen = len;
0a39fd54 11934
ad89623c 11935 if (tree_int_cst_lt (size, maxlen))
c2f47e15 11936 return NULL_TREE;
0a39fd54 11937 }
11938
0a39fd54 11939 fn = NULL_TREE;
11940 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
11941 mem{cpy,pcpy,move,set} is available. */
11942 switch (fcode)
11943 {
11944 case BUILT_IN_MEMCPY_CHK:
11945 fn = built_in_decls[BUILT_IN_MEMCPY];
11946 break;
11947 case BUILT_IN_MEMPCPY_CHK:
11948 fn = built_in_decls[BUILT_IN_MEMPCPY];
11949 break;
11950 case BUILT_IN_MEMMOVE_CHK:
11951 fn = built_in_decls[BUILT_IN_MEMMOVE];
11952 break;
11953 case BUILT_IN_MEMSET_CHK:
11954 fn = built_in_decls[BUILT_IN_MEMSET];
11955 break;
11956 default:
11957 break;
11958 }
11959
11960 if (!fn)
c2f47e15 11961 return NULL_TREE;
0a39fd54 11962
c2f47e15 11963 return build_call_expr (fn, 3, dest, src, len);
0a39fd54 11964}
11965
11966/* Fold a call to the __st[rp]cpy_chk builtin.
c2f47e15 11967 DEST, SRC, and SIZE are the arguments to the call.
11968 IGNORE is true if return value can be ignored. FCODE is the BUILT_IN_*
0a39fd54 11969 code of the builtin. If MAXLEN is not NULL, it is maximum length of
11970 strings passed as second argument. */
11971
11972tree
c2f47e15 11973fold_builtin_stxcpy_chk (tree fndecl, tree dest, tree src, tree size,
11974 tree maxlen, bool ignore,
0a39fd54 11975 enum built_in_function fcode)
11976{
c2f47e15 11977 tree len, fn;
0a39fd54 11978
c2f47e15 11979 if (!validate_arg (dest, POINTER_TYPE)
11980 || !validate_arg (src, POINTER_TYPE)
11981 || !validate_arg (size, INTEGER_TYPE))
11982 return NULL_TREE;
0a39fd54 11983
11984 /* If SRC and DEST are the same (and not volatile), return DEST. */
11985 if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
11986 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
a0c938f0 11987
0a39fd54 11988 if (! host_integerp (size, 1))
c2f47e15 11989 return NULL_TREE;
0a39fd54 11990
11991 if (! integer_all_onesp (size))
11992 {
11993 len = c_strlen (src, 1);
11994 if (! len || ! host_integerp (len, 1))
11995 {
11996 /* If LEN is not constant, try MAXLEN too.
11997 For MAXLEN only allow optimizing into non-_ocs function
11998 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
11999 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
12000 {
12001 if (fcode == BUILT_IN_STPCPY_CHK)
12002 {
12003 if (! ignore)
c2f47e15 12004 return NULL_TREE;
0a39fd54 12005
12006 /* If return value of __stpcpy_chk is ignored,
12007 optimize into __strcpy_chk. */
12008 fn = built_in_decls[BUILT_IN_STRCPY_CHK];
12009 if (!fn)
c2f47e15 12010 return NULL_TREE;
0a39fd54 12011
c2f47e15 12012 return build_call_expr (fn, 3, dest, src, size);
0a39fd54 12013 }
12014
12015 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 12016 return NULL_TREE;
0a39fd54 12017
12018 /* If c_strlen returned something, but not a constant,
12019 transform __strcpy_chk into __memcpy_chk. */
12020 fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
12021 if (!fn)
c2f47e15 12022 return NULL_TREE;
0a39fd54 12023
12024 len = size_binop (PLUS_EXPR, len, ssize_int (1));
0a39fd54 12025 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
c2f47e15 12026 build_call_expr (fn, 4,
12027 dest, src, len, size));
0a39fd54 12028 }
0a39fd54 12029 }
ad89623c 12030 else
12031 maxlen = len;
12032
12033 if (! tree_int_cst_lt (maxlen, size))
c2f47e15 12034 return NULL_TREE;
0a39fd54 12035 }
12036
0a39fd54 12037 /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available. */
12038 fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK
12039 ? BUILT_IN_STPCPY : BUILT_IN_STRCPY];
12040 if (!fn)
c2f47e15 12041 return NULL_TREE;
0a39fd54 12042
c2f47e15 12043 return build_call_expr (fn, 2, dest, src);
0a39fd54 12044}
12045
c2f47e15 12046/* Fold a call to the __strncpy_chk builtin. DEST, SRC, LEN, and SIZE
12047 are the arguments to the call. If MAXLEN is not NULL, it is maximum
12048 length passed as third argument. */
0a39fd54 12049
12050tree
c2f47e15 12051fold_builtin_strncpy_chk (tree dest, tree src, tree len, tree size,
12052 tree maxlen)
0a39fd54 12053{
c2f47e15 12054 tree fn;
0a39fd54 12055
c2f47e15 12056 if (!validate_arg (dest, POINTER_TYPE)
12057 || !validate_arg (src, POINTER_TYPE)
12058 || !validate_arg (len, INTEGER_TYPE)
12059 || !validate_arg (size, INTEGER_TYPE))
12060 return NULL_TREE;
0a39fd54 12061
12062 if (! host_integerp (size, 1))
c2f47e15 12063 return NULL_TREE;
0a39fd54 12064
12065 if (! integer_all_onesp (size))
12066 {
12067 if (! host_integerp (len, 1))
12068 {
12069 /* If LEN is not constant, try MAXLEN too.
12070 For MAXLEN only allow optimizing into non-_ocs function
12071 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12072 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 12073 return NULL_TREE;
0a39fd54 12074 }
ad89623c 12075 else
12076 maxlen = len;
0a39fd54 12077
ad89623c 12078 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12079 return NULL_TREE;
0a39fd54 12080 }
12081
0a39fd54 12082 /* If __builtin_strncpy_chk is used, assume strncpy is available. */
12083 fn = built_in_decls[BUILT_IN_STRNCPY];
12084 if (!fn)
c2f47e15 12085 return NULL_TREE;
0a39fd54 12086
c2f47e15 12087 return build_call_expr (fn, 3, dest, src, len);
0a39fd54 12088}
12089
c2f47e15 12090/* Fold a call to the __strcat_chk builtin FNDECL. DEST, SRC, and SIZE
12091 are the arguments to the call. */
0a39fd54 12092
12093static tree
c2f47e15 12094fold_builtin_strcat_chk (tree fndecl, tree dest, tree src, tree size)
0a39fd54 12095{
c2f47e15 12096 tree fn;
0a39fd54 12097 const char *p;
12098
c2f47e15 12099 if (!validate_arg (dest, POINTER_TYPE)
12100 || !validate_arg (src, POINTER_TYPE)
12101 || !validate_arg (size, INTEGER_TYPE))
12102 return NULL_TREE;
0a39fd54 12103
12104 p = c_getstr (src);
12105 /* If the SRC parameter is "", return DEST. */
12106 if (p && *p == '\0')
12107 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
12108
12109 if (! host_integerp (size, 1) || ! integer_all_onesp (size))
c2f47e15 12110 return NULL_TREE;
0a39fd54 12111
12112 /* If __builtin_strcat_chk is used, assume strcat is available. */
12113 fn = built_in_decls[BUILT_IN_STRCAT];
12114 if (!fn)
c2f47e15 12115 return NULL_TREE;
0a39fd54 12116
c2f47e15 12117 return build_call_expr (fn, 2, dest, src);
0a39fd54 12118}
12119
c2f47e15 12120/* Fold a call to the __strncat_chk builtin with arguments DEST, SRC,
12121 LEN, and SIZE. */
0a39fd54 12122
12123static tree
c2f47e15 12124fold_builtin_strncat_chk (tree fndecl,
12125 tree dest, tree src, tree len, tree size)
0a39fd54 12126{
c2f47e15 12127 tree fn;
0a39fd54 12128 const char *p;
12129
c2f47e15 12130 if (!validate_arg (dest, POINTER_TYPE)
12131 || !validate_arg (src, POINTER_TYPE)
12132 || !validate_arg (size, INTEGER_TYPE)
12133 || !validate_arg (size, INTEGER_TYPE))
12134 return NULL_TREE;
0a39fd54 12135
12136 p = c_getstr (src);
12137 /* If the SRC parameter is "" or if LEN is 0, return DEST. */
12138 if (p && *p == '\0')
12139 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
12140 else if (integer_zerop (len))
12141 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
12142
12143 if (! host_integerp (size, 1))
c2f47e15 12144 return NULL_TREE;
0a39fd54 12145
12146 if (! integer_all_onesp (size))
12147 {
12148 tree src_len = c_strlen (src, 1);
12149 if (src_len
12150 && host_integerp (src_len, 1)
12151 && host_integerp (len, 1)
12152 && ! tree_int_cst_lt (len, src_len))
12153 {
12154 /* If LEN >= strlen (SRC), optimize into __strcat_chk. */
12155 fn = built_in_decls[BUILT_IN_STRCAT_CHK];
12156 if (!fn)
c2f47e15 12157 return NULL_TREE;
0a39fd54 12158
c2f47e15 12159 return build_call_expr (fn, 3, dest, src, size);
0a39fd54 12160 }
c2f47e15 12161 return NULL_TREE;
0a39fd54 12162 }
12163
0a39fd54 12164 /* If __builtin_strncat_chk is used, assume strncat is available. */
12165 fn = built_in_decls[BUILT_IN_STRNCAT];
12166 if (!fn)
c2f47e15 12167 return NULL_TREE;
0a39fd54 12168
c2f47e15 12169 return build_call_expr (fn, 3, dest, src, len);
0a39fd54 12170}
12171
c2f47e15 12172/* Fold a call EXP to __{,v}sprintf_chk. Return NULL_TREE if
0a39fd54 12173 a normal call should be emitted rather than expanding the function
12174 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
12175
12176static tree
c2f47e15 12177fold_builtin_sprintf_chk (tree exp, enum built_in_function fcode)
0a39fd54 12178{
12179 tree dest, size, len, fn, fmt, flag;
12180 const char *fmt_str;
c2f47e15 12181 int nargs = call_expr_nargs (exp);
0a39fd54 12182
12183 /* Verify the required arguments in the original call. */
c2f47e15 12184 if (nargs < 4)
12185 return NULL_TREE;
12186 dest = CALL_EXPR_ARG (exp, 0);
12187 if (!validate_arg (dest, POINTER_TYPE))
12188 return NULL_TREE;
12189 flag = CALL_EXPR_ARG (exp, 1);
12190 if (!validate_arg (flag, INTEGER_TYPE))
12191 return NULL_TREE;
12192 size = CALL_EXPR_ARG (exp, 2);
12193 if (!validate_arg (size, INTEGER_TYPE))
12194 return NULL_TREE;
12195 fmt = CALL_EXPR_ARG (exp, 3);
12196 if (!validate_arg (fmt, POINTER_TYPE))
12197 return NULL_TREE;
0a39fd54 12198
12199 if (! host_integerp (size, 1))
c2f47e15 12200 return NULL_TREE;
0a39fd54 12201
12202 len = NULL_TREE;
12203
d4473c84 12204 if (!init_target_chars ())
c2f47e15 12205 return NULL_TREE;
99eabcc1 12206
0a39fd54 12207 /* Check whether the format is a literal string constant. */
12208 fmt_str = c_getstr (fmt);
12209 if (fmt_str != NULL)
12210 {
12211 /* If the format doesn't contain % args or %%, we know the size. */
99eabcc1 12212 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 12213 {
c2f47e15 12214 if (fcode != BUILT_IN_SPRINTF_CHK || nargs == 4)
0a39fd54 12215 len = build_int_cstu (size_type_node, strlen (fmt_str));
12216 }
12217 /* If the format is "%s" and first ... argument is a string literal,
12218 we know the size too. */
c2f47e15 12219 else if (fcode == BUILT_IN_SPRINTF_CHK
12220 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12221 {
12222 tree arg;
12223
c2f47e15 12224 if (nargs == 5)
0a39fd54 12225 {
c2f47e15 12226 arg = CALL_EXPR_ARG (exp, 4);
12227 if (validate_arg (arg, POINTER_TYPE))
0a39fd54 12228 {
12229 len = c_strlen (arg, 1);
12230 if (! len || ! host_integerp (len, 1))
12231 len = NULL_TREE;
12232 }
12233 }
12234 }
12235 }
12236
12237 if (! integer_all_onesp (size))
12238 {
12239 if (! len || ! tree_int_cst_lt (len, size))
c2f47e15 12240 return NULL_TREE;
0a39fd54 12241 }
12242
12243 /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
12244 or if format doesn't contain % chars or is "%s". */
12245 if (! integer_zerop (flag))
12246 {
12247 if (fmt_str == NULL)
c2f47e15 12248 return NULL_TREE;
12249 if (strchr (fmt_str, target_percent) != NULL
12250 && strcmp (fmt_str, target_percent_s))
12251 return NULL_TREE;
0a39fd54 12252 }
12253
0a39fd54 12254 /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
12255 fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
12256 ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
12257 if (!fn)
c2f47e15 12258 return NULL_TREE;
0a39fd54 12259
c2f47e15 12260 return rewrite_call_expr (exp, 4, fn, 2, dest, fmt);
0a39fd54 12261}
12262
c2f47e15 12263/* Fold a call EXP to {,v}snprintf. Return NULL_TREE if
0a39fd54 12264 a normal call should be emitted rather than expanding the function
12265 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
12266 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
12267 passed as second argument. */
12268
12269tree
c2f47e15 12270fold_builtin_snprintf_chk (tree exp, tree maxlen,
0a39fd54 12271 enum built_in_function fcode)
12272{
12273 tree dest, size, len, fn, fmt, flag;
12274 const char *fmt_str;
12275
12276 /* Verify the required arguments in the original call. */
c2f47e15 12277 if (call_expr_nargs (exp) < 5)
12278 return NULL_TREE;
12279 dest = CALL_EXPR_ARG (exp, 0);
12280 if (!validate_arg (dest, POINTER_TYPE))
12281 return NULL_TREE;
12282 len = CALL_EXPR_ARG (exp, 1);
12283 if (!validate_arg (len, INTEGER_TYPE))
12284 return NULL_TREE;
12285 flag = CALL_EXPR_ARG (exp, 2);
12286 if (!validate_arg (flag, INTEGER_TYPE))
12287 return NULL_TREE;
12288 size = CALL_EXPR_ARG (exp, 3);
12289 if (!validate_arg (size, INTEGER_TYPE))
12290 return NULL_TREE;
12291 fmt = CALL_EXPR_ARG (exp, 4);
12292 if (!validate_arg (fmt, POINTER_TYPE))
12293 return NULL_TREE;
0a39fd54 12294
12295 if (! host_integerp (size, 1))
c2f47e15 12296 return NULL_TREE;
0a39fd54 12297
12298 if (! integer_all_onesp (size))
12299 {
12300 if (! host_integerp (len, 1))
12301 {
12302 /* If LEN is not constant, try MAXLEN too.
12303 For MAXLEN only allow optimizing into non-_ocs function
12304 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12305 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 12306 return NULL_TREE;
0a39fd54 12307 }
ad89623c 12308 else
12309 maxlen = len;
0a39fd54 12310
ad89623c 12311 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12312 return NULL_TREE;
0a39fd54 12313 }
12314
d4473c84 12315 if (!init_target_chars ())
c2f47e15 12316 return NULL_TREE;
99eabcc1 12317
0a39fd54 12318 /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
12319 or if format doesn't contain % chars or is "%s". */
12320 if (! integer_zerop (flag))
12321 {
12322 fmt_str = c_getstr (fmt);
12323 if (fmt_str == NULL)
c2f47e15 12324 return NULL_TREE;
12325 if (strchr (fmt_str, target_percent) != NULL
12326 && strcmp (fmt_str, target_percent_s))
12327 return NULL_TREE;
0a39fd54 12328 }
12329
0a39fd54 12330 /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
12331 available. */
12332 fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
12333 ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
12334 if (!fn)
c2f47e15 12335 return NULL_TREE;
0a39fd54 12336
c2f47e15 12337 return rewrite_call_expr (exp, 5, fn, 3, dest, len, fmt);
0a39fd54 12338}
12339
12340/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 12341 FMT and ARG are the arguments to the call; we don't fold cases with
12342 more than 2 arguments, and ARG may be null if this is a 1-argument case.
0a39fd54 12343
c2f47e15 12344 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 12345 simplified form of the call as a tree. FCODE is the BUILT_IN_*
12346 code of the function to be simplified. */
12347
12348static tree
c2f47e15 12349fold_builtin_printf (tree fndecl, tree fmt, tree arg, bool ignore,
0a39fd54 12350 enum built_in_function fcode)
12351{
c2f47e15 12352 tree fn_putchar, fn_puts, newarg, call = NULL_TREE;
0a39fd54 12353 const char *fmt_str = NULL;
12354
12355 /* If the return value is used, don't do the transformation. */
12356 if (! ignore)
c2f47e15 12357 return NULL_TREE;
0a39fd54 12358
12359 /* Verify the required arguments in the original call. */
c2f47e15 12360 if (!validate_arg (fmt, POINTER_TYPE))
12361 return NULL_TREE;
0a39fd54 12362
12363 /* Check whether the format is a literal string constant. */
12364 fmt_str = c_getstr (fmt);
12365 if (fmt_str == NULL)
12366 return NULL_TREE;
12367
12368 if (fcode == BUILT_IN_PRINTF_UNLOCKED)
12369 {
6d77ed92 12370 /* If we're using an unlocked function, assume the other
12371 unlocked functions exist explicitly. */
12372 fn_putchar = built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED];
12373 fn_puts = built_in_decls[BUILT_IN_PUTS_UNLOCKED];
0a39fd54 12374 }
12375 else
12376 {
12377 fn_putchar = implicit_built_in_decls[BUILT_IN_PUTCHAR];
12378 fn_puts = implicit_built_in_decls[BUILT_IN_PUTS];
12379 }
12380
d4473c84 12381 if (!init_target_chars ())
c2f47e15 12382 return NULL_TREE;
a0c938f0 12383
c2f47e15 12384 if (strcmp (fmt_str, target_percent_s) == 0
12385 || strchr (fmt_str, target_percent) == NULL)
0a39fd54 12386 {
12387 const char *str;
12388
99eabcc1 12389 if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12390 {
12391 if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 12392 return NULL_TREE;
0a39fd54 12393
c2f47e15 12394 if (!arg || !validate_arg (arg, POINTER_TYPE))
12395 return NULL_TREE;
0a39fd54 12396
c2f47e15 12397 str = c_getstr (arg);
0a39fd54 12398 if (str == NULL)
c2f47e15 12399 return NULL_TREE;
0a39fd54 12400 }
12401 else
12402 {
12403 /* The format specifier doesn't contain any '%' characters. */
12404 if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
c2f47e15 12405 && arg)
12406 return NULL_TREE;
0a39fd54 12407 str = fmt_str;
12408 }
12409
12410 /* If the string was "", printf does nothing. */
12411 if (str[0] == '\0')
12412 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
12413
12414 /* If the string has length of 1, call putchar. */
12415 if (str[1] == '\0')
12416 {
12417 /* Given printf("c"), (where c is any one character,)
12418 convert "c"[0] to an int and pass that to the replacement
12419 function. */
c2f47e15 12420 newarg = build_int_cst (NULL_TREE, str[0]);
12421 if (fn_putchar)
12422 call = build_call_expr (fn_putchar, 1, newarg);
0a39fd54 12423 }
12424 else
12425 {
12426 /* If the string was "string\n", call puts("string"). */
12427 size_t len = strlen (str);
99eabcc1 12428 if ((unsigned char)str[len - 1] == target_newline)
0a39fd54 12429 {
12430 /* Create a NUL-terminated string that's one char shorter
12431 than the original, stripping off the trailing '\n'. */
12432 char *newstr = alloca (len);
12433 memcpy (newstr, str, len - 1);
12434 newstr[len - 1] = 0;
12435
c2f47e15 12436 newarg = build_string_literal (len, newstr);
12437 if (fn_puts)
12438 call = build_call_expr (fn_puts, 1, newarg);
0a39fd54 12439 }
12440 else
12441 /* We'd like to arrange to call fputs(string,stdout) here,
12442 but we need stdout and don't have a way to get it yet. */
c2f47e15 12443 return NULL_TREE;
0a39fd54 12444 }
12445 }
12446
12447 /* The other optimizations can be done only on the non-va_list variants. */
12448 else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 12449 return NULL_TREE;
0a39fd54 12450
12451 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
99eabcc1 12452 else if (strcmp (fmt_str, target_percent_s_newline) == 0)
0a39fd54 12453 {
c2f47e15 12454 if (!arg || !validate_arg (arg, POINTER_TYPE))
12455 return NULL_TREE;
12456 if (fn_puts)
12457 call = build_call_expr (fn_puts, 1, arg);
0a39fd54 12458 }
12459
12460 /* If the format specifier was "%c", call __builtin_putchar(arg). */
99eabcc1 12461 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 12462 {
c2f47e15 12463 if (!arg || !validate_arg (arg, INTEGER_TYPE))
12464 return NULL_TREE;
12465 if (fn_putchar)
12466 call = build_call_expr (fn_putchar, 1, arg);
0a39fd54 12467 }
12468
c2f47e15 12469 if (!call)
12470 return NULL_TREE;
0a39fd54 12471
0a39fd54 12472 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
12473}
12474
12475/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 12476 FP, FMT, and ARG are the arguments to the call. We don't fold calls with
12477 more than 3 arguments, and ARG may be null in the 2-argument case.
0a39fd54 12478
c2f47e15 12479 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 12480 simplified form of the call as a tree. FCODE is the BUILT_IN_*
12481 code of the function to be simplified. */
12482
12483static tree
c2f47e15 12484fold_builtin_fprintf (tree fndecl, tree fp, tree fmt, tree arg, bool ignore,
0a39fd54 12485 enum built_in_function fcode)
12486{
c2f47e15 12487 tree fn_fputc, fn_fputs, call = NULL_TREE;
0a39fd54 12488 const char *fmt_str = NULL;
12489
12490 /* If the return value is used, don't do the transformation. */
12491 if (! ignore)
c2f47e15 12492 return NULL_TREE;
0a39fd54 12493
12494 /* Verify the required arguments in the original call. */
c2f47e15 12495 if (!validate_arg (fp, POINTER_TYPE))
12496 return NULL_TREE;
12497 if (!validate_arg (fmt, POINTER_TYPE))
12498 return NULL_TREE;
0a39fd54 12499
12500 /* Check whether the format is a literal string constant. */
12501 fmt_str = c_getstr (fmt);
12502 if (fmt_str == NULL)
12503 return NULL_TREE;
12504
12505 if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
12506 {
6d77ed92 12507 /* If we're using an unlocked function, assume the other
12508 unlocked functions exist explicitly. */
12509 fn_fputc = built_in_decls[BUILT_IN_FPUTC_UNLOCKED];
12510 fn_fputs = built_in_decls[BUILT_IN_FPUTS_UNLOCKED];
0a39fd54 12511 }
12512 else
12513 {
12514 fn_fputc = implicit_built_in_decls[BUILT_IN_FPUTC];
12515 fn_fputs = implicit_built_in_decls[BUILT_IN_FPUTS];
12516 }
12517
d4473c84 12518 if (!init_target_chars ())
c2f47e15 12519 return NULL_TREE;
a0c938f0 12520
0a39fd54 12521 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 12522 if (strchr (fmt_str, target_percent) == NULL)
0a39fd54 12523 {
12524 if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
c2f47e15 12525 && arg)
12526 return NULL_TREE;
0a39fd54 12527
12528 /* If the format specifier was "", fprintf does nothing. */
12529 if (fmt_str[0] == '\0')
12530 {
12531 /* If FP has side-effects, just wait until gimplification is
12532 done. */
12533 if (TREE_SIDE_EFFECTS (fp))
c2f47e15 12534 return NULL_TREE;
0a39fd54 12535
12536 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
12537 }
12538
12539 /* When "string" doesn't contain %, replace all cases of
12540 fprintf (fp, string) with fputs (string, fp). The fputs
12541 builtin will take care of special cases like length == 1. */
c2f47e15 12542 if (fn_fputs)
12543 call = build_call_expr (fn_fputs, 2, fmt, fp);
0a39fd54 12544 }
12545
12546 /* The other optimizations can be done only on the non-va_list variants. */
12547 else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
c2f47e15 12548 return NULL_TREE;
0a39fd54 12549
12550 /* If the format specifier was "%s", call __builtin_fputs (arg, fp). */
99eabcc1 12551 else if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12552 {
c2f47e15 12553 if (!arg || !validate_arg (arg, POINTER_TYPE))
12554 return NULL_TREE;
12555 if (fn_fputs)
12556 call = build_call_expr (fn_fputs, 2, arg, fp);
0a39fd54 12557 }
12558
12559 /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */
99eabcc1 12560 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 12561 {
c2f47e15 12562 if (!arg || !validate_arg (arg, INTEGER_TYPE))
12563 return NULL_TREE;
12564 if (fn_fputc)
12565 call = build_call_expr (fn_fputc, 2, arg, fp);
0a39fd54 12566 }
12567
c2f47e15 12568 if (!call)
12569 return NULL_TREE;
0a39fd54 12570 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
12571}
99eabcc1 12572
12573/* Initialize format string characters in the target charset. */
12574
12575static bool
12576init_target_chars (void)
12577{
12578 static bool init;
12579 if (!init)
12580 {
12581 target_newline = lang_hooks.to_target_charset ('\n');
12582 target_percent = lang_hooks.to_target_charset ('%');
12583 target_c = lang_hooks.to_target_charset ('c');
12584 target_s = lang_hooks.to_target_charset ('s');
12585 if (target_newline == 0 || target_percent == 0 || target_c == 0
12586 || target_s == 0)
12587 return false;
12588
12589 target_percent_c[0] = target_percent;
12590 target_percent_c[1] = target_c;
12591 target_percent_c[2] = '\0';
12592
12593 target_percent_s[0] = target_percent;
12594 target_percent_s[1] = target_s;
12595 target_percent_s[2] = '\0';
12596
12597 target_percent_s_newline[0] = target_percent;
12598 target_percent_s_newline[1] = target_s;
12599 target_percent_s_newline[2] = target_newline;
12600 target_percent_s_newline[3] = '\0';
a0c938f0 12601
99eabcc1 12602 init = true;
12603 }
12604 return true;
12605}
bffb7645 12606
f0c477f2 12607/* Helper function for do_mpfr_arg*(). Ensure M is a normal number
12608 and no overflow/underflow occurred. INEXACT is true if M was not
fa7637bd 12609 exactly calculated. TYPE is the tree type for the result. This
f0c477f2 12610 function assumes that you cleared the MPFR flags and then
12611 calculated M to see if anything subsequently set a flag prior to
12612 entering this function. Return NULL_TREE if any checks fail. */
12613
12614static tree
d4473c84 12615do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
f0c477f2 12616{
12617 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
12618 overflow/underflow occurred. If -frounding-math, proceed iff the
12619 result of calling FUNC was exact. */
d4473c84 12620 if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
f0c477f2 12621 && (!flag_rounding_math || !inexact))
12622 {
12623 REAL_VALUE_TYPE rr;
12624
66fa16e6 12625 real_from_mpfr (&rr, m, type, GMP_RNDN);
f0c477f2 12626 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
12627 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
12628 but the mpft_t is not, then we underflowed in the
12629 conversion. */
776a7bab 12630 if (real_isfinite (&rr)
f0c477f2 12631 && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
12632 {
12633 REAL_VALUE_TYPE rmode;
12634
12635 real_convert (&rmode, TYPE_MODE (type), &rr);
12636 /* Proceed iff the specified mode can hold the value. */
12637 if (real_identical (&rmode, &rr))
12638 return build_real (type, rmode);
12639 }
12640 }
12641 return NULL_TREE;
12642}
12643
bffb7645 12644/* If argument ARG is a REAL_CST, call the one-argument mpfr function
12645 FUNC on it and return the resulting value as a tree with type TYPE.
728bac60 12646 If MIN and/or MAX are not NULL, then the supplied ARG must be
12647 within those bounds. If INCLUSIVE is true, then MIN/MAX are
12648 acceptable values, otherwise they are not. The mpfr precision is
12649 set to the precision of TYPE. We assume that function FUNC returns
12650 zero if the result could be calculated exactly within the requested
12651 precision. */
bffb7645 12652
12653static tree
728bac60 12654do_mpfr_arg1 (tree arg, tree type, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
12655 const REAL_VALUE_TYPE *min, const REAL_VALUE_TYPE *max,
12656 bool inclusive)
bffb7645 12657{
12658 tree result = NULL_TREE;
12659
12660 STRIP_NOPS (arg);
12661
bd7d6fa4 12662 /* To proceed, MPFR must exactly represent the target floating point
12663 format, which only happens when the target base equals two. */
12664 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12665 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
bffb7645 12666 {
f0c477f2 12667 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
bffb7645 12668
776a7bab 12669 if (real_isfinite (ra)
f0c477f2 12670 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min))
12671 && (!max || real_compare (inclusive ? LE_EXPR: LT_EXPR , ra, max)))
bffb7645 12672 {
f0c477f2 12673 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
debf9994 12674 int inexact;
bffb7645 12675 mpfr_t m;
12676
12677 mpfr_init2 (m, prec);
66fa16e6 12678 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 12679 mpfr_clear_flags ();
debf9994 12680 inexact = func (m, m, GMP_RNDN);
f0c477f2 12681 result = do_mpfr_ckconv (m, type, inexact);
bffb7645 12682 mpfr_clear (m);
12683 }
12684 }
12685
12686 return result;
12687}
f0c477f2 12688
12689/* If argument ARG is a REAL_CST, call the two-argument mpfr function
12690 FUNC on it and return the resulting value as a tree with type TYPE.
12691 The mpfr precision is set to the precision of TYPE. We assume that
12692 function FUNC returns zero if the result could be calculated
12693 exactly within the requested precision. */
12694
12695static tree
12696do_mpfr_arg2 (tree arg1, tree arg2, tree type,
12697 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
12698{
12699 tree result = NULL_TREE;
12700
12701 STRIP_NOPS (arg1);
12702 STRIP_NOPS (arg2);
12703
bd7d6fa4 12704 /* To proceed, MPFR must exactly represent the target floating point
12705 format, which only happens when the target base equals two. */
12706 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12707 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
12708 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
f0c477f2 12709 {
12710 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
12711 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
12712
776a7bab 12713 if (real_isfinite (ra1) && real_isfinite (ra2))
f0c477f2 12714 {
12715 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12716 int inexact;
12717 mpfr_t m1, m2;
12718
12719 mpfr_inits2 (prec, m1, m2, NULL);
66fa16e6 12720 mpfr_from_real (m1, ra1, GMP_RNDN);
12721 mpfr_from_real (m2, ra2, GMP_RNDN);
d4473c84 12722 mpfr_clear_flags ();
f0c477f2 12723 inexact = func (m1, m1, m2, GMP_RNDN);
12724 result = do_mpfr_ckconv (m1, type, inexact);
12725 mpfr_clears (m1, m2, NULL);
12726 }
12727 }
12728
12729 return result;
12730}
d92f994c 12731
9917422b 12732/* If argument ARG is a REAL_CST, call the three-argument mpfr function
12733 FUNC on it and return the resulting value as a tree with type TYPE.
12734 The mpfr precision is set to the precision of TYPE. We assume that
12735 function FUNC returns zero if the result could be calculated
12736 exactly within the requested precision. */
12737
12738static tree
12739do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type,
12740 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
12741{
12742 tree result = NULL_TREE;
12743
12744 STRIP_NOPS (arg1);
12745 STRIP_NOPS (arg2);
12746 STRIP_NOPS (arg3);
12747
bd7d6fa4 12748 /* To proceed, MPFR must exactly represent the target floating point
12749 format, which only happens when the target base equals two. */
12750 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12751 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
12752 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2)
12753 && TREE_CODE (arg3) == REAL_CST && !TREE_OVERFLOW (arg3))
9917422b 12754 {
12755 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
12756 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
12757 const REAL_VALUE_TYPE *const ra3 = &TREE_REAL_CST (arg3);
12758
776a7bab 12759 if (real_isfinite (ra1) && real_isfinite (ra2) && real_isfinite (ra3))
9917422b 12760 {
12761 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12762 int inexact;
12763 mpfr_t m1, m2, m3;
12764
12765 mpfr_inits2 (prec, m1, m2, m3, NULL);
66fa16e6 12766 mpfr_from_real (m1, ra1, GMP_RNDN);
12767 mpfr_from_real (m2, ra2, GMP_RNDN);
12768 mpfr_from_real (m3, ra3, GMP_RNDN);
d4473c84 12769 mpfr_clear_flags ();
9917422b 12770 inexact = func (m1, m1, m2, m3, GMP_RNDN);
12771 result = do_mpfr_ckconv (m1, type, inexact);
12772 mpfr_clears (m1, m2, m3, NULL);
12773 }
12774 }
12775
12776 return result;
12777}
12778
d92f994c 12779/* If argument ARG is a REAL_CST, call mpfr_sin_cos() on it and set
12780 the pointers *(ARG_SINP) and *(ARG_COSP) to the resulting values.
d735c391 12781 If ARG_SINP and ARG_COSP are NULL then the result is returned
12782 as a complex value.
d92f994c 12783 The type is taken from the type of ARG and is used for setting the
12784 precision of the calculation and results. */
12785
12786static tree
12787do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp)
12788{
bd7d6fa4 12789 tree const type = TREE_TYPE (arg);
d92f994c 12790 tree result = NULL_TREE;
12791
12792 STRIP_NOPS (arg);
12793
bd7d6fa4 12794 /* To proceed, MPFR must exactly represent the target floating point
12795 format, which only happens when the target base equals two. */
12796 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12797 && TREE_CODE (arg) == REAL_CST
12798 && !TREE_OVERFLOW (arg))
d92f994c 12799 {
12800 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
12801
776a7bab 12802 if (real_isfinite (ra))
d92f994c 12803 {
d92f994c 12804 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12805 tree result_s, result_c;
12806 int inexact;
12807 mpfr_t m, ms, mc;
12808
12809 mpfr_inits2 (prec, m, ms, mc, NULL);
66fa16e6 12810 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 12811 mpfr_clear_flags ();
d92f994c 12812 inexact = mpfr_sin_cos (ms, mc, m, GMP_RNDN);
12813 result_s = do_mpfr_ckconv (ms, type, inexact);
12814 result_c = do_mpfr_ckconv (mc, type, inexact);
12815 mpfr_clears (m, ms, mc, NULL);
12816 if (result_s && result_c)
12817 {
d735c391 12818 /* If we are to return in a complex value do so. */
12819 if (!arg_sinp && !arg_cosp)
12820 return build_complex (build_complex_type (type),
12821 result_c, result_s);
12822
d92f994c 12823 /* Dereference the sin/cos pointer arguments. */
12824 arg_sinp = build_fold_indirect_ref (arg_sinp);
12825 arg_cosp = build_fold_indirect_ref (arg_cosp);
12826 /* Proceed if valid pointer type were passed in. */
12827 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_sinp)) == TYPE_MAIN_VARIANT (type)
12828 && TYPE_MAIN_VARIANT (TREE_TYPE (arg_cosp)) == TYPE_MAIN_VARIANT (type))
12829 {
12830 /* Set the values. */
41076ef6 12831 result_s = fold_build2 (MODIFY_EXPR, type, arg_sinp,
35cc02b5 12832 result_s);
d92f994c 12833 TREE_SIDE_EFFECTS (result_s) = 1;
41076ef6 12834 result_c = fold_build2 (MODIFY_EXPR, type, arg_cosp,
35cc02b5 12835 result_c);
d92f994c 12836 TREE_SIDE_EFFECTS (result_c) = 1;
12837 /* Combine the assignments into a compound expr. */
12838 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
12839 result_s, result_c));
12840 }
12841 }
12842 }
12843 }
12844 return result;
12845}
65dd1378 12846
12847#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
12848/* If argument ARG1 is an INTEGER_CST and ARG2 is a REAL_CST, call the
12849 two-argument mpfr order N Bessel function FUNC on them and return
12850 the resulting value as a tree with type TYPE. The mpfr precision
12851 is set to the precision of TYPE. We assume that function FUNC
12852 returns zero if the result could be calculated exactly within the
12853 requested precision. */
12854static tree
12855do_mpfr_bessel_n (tree arg1, tree arg2, tree type,
12856 int (*func)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
12857 const REAL_VALUE_TYPE *min, bool inclusive)
12858{
12859 tree result = NULL_TREE;
12860
12861 STRIP_NOPS (arg1);
12862 STRIP_NOPS (arg2);
12863
12864 /* To proceed, MPFR must exactly represent the target floating point
12865 format, which only happens when the target base equals two. */
12866 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
12867 && host_integerp (arg1, 0)
12868 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
12869 {
12870 const HOST_WIDE_INT n = tree_low_cst(arg1, 0);
12871 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg2);
12872
12873 if (n == (long)n
776a7bab 12874 && real_isfinite (ra)
65dd1378 12875 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min)))
12876 {
12877 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12878 int inexact;
12879 mpfr_t m;
12880
12881 mpfr_init2 (m, prec);
12882 mpfr_from_real (m, ra, GMP_RNDN);
12883 mpfr_clear_flags ();
12884 inexact = func (m, n, m, GMP_RNDN);
12885 result = do_mpfr_ckconv (m, type, inexact);
12886 mpfr_clear (m);
12887 }
12888 }
12889
12890 return result;
12891}
e5407ca6 12892
12893/* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
12894 the pointer *(ARG_QUO) and return the result. The type is taken
12895 from the type of ARG0 and is used for setting the precision of the
12896 calculation and results. */
12897
12898static tree
12899do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
12900{
12901 tree const type = TREE_TYPE (arg0);
12902 tree result = NULL_TREE;
12903
12904 STRIP_NOPS (arg0);
12905 STRIP_NOPS (arg1);
12906
12907 /* To proceed, MPFR must exactly represent the target floating point
12908 format, which only happens when the target base equals two. */
12909 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
12910 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
12911 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
12912 {
12913 const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
12914 const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
12915
776a7bab 12916 if (real_isfinite (ra0) && real_isfinite (ra1))
e5407ca6 12917 {
12918 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12919 tree result_rem;
12920 long integer_quo;
12921 mpfr_t m0, m1;
12922
12923 mpfr_inits2 (prec, m0, m1, NULL);
12924 mpfr_from_real (m0, ra0, GMP_RNDN);
12925 mpfr_from_real (m1, ra1, GMP_RNDN);
12926 mpfr_clear_flags ();
12927 mpfr_remquo (m0, &integer_quo, m0, m1, GMP_RNDN);
12928 /* Remquo is independent of the rounding mode, so pass
12929 inexact=0 to do_mpfr_ckconv(). */
12930 result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
12931 mpfr_clears (m0, m1, NULL);
12932 if (result_rem)
12933 {
12934 /* MPFR calculates quo in the host's long so it may
12935 return more bits in quo than the target int can hold
12936 if sizeof(host long) > sizeof(target int). This can
12937 happen even for native compilers in LP64 mode. In
12938 these cases, modulo the quo value with the largest
12939 number that the target int can hold while leaving one
12940 bit for the sign. */
12941 if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
12942 integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
12943
12944 /* Dereference the quo pointer argument. */
12945 arg_quo = build_fold_indirect_ref (arg_quo);
12946 /* Proceed iff a valid pointer type was passed in. */
12947 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
12948 {
12949 /* Set the value. */
12950 tree result_quo = fold_build2 (MODIFY_EXPR,
12951 TREE_TYPE (arg_quo), arg_quo,
12952 build_int_cst (NULL, integer_quo));
12953 TREE_SIDE_EFFECTS (result_quo) = 1;
12954 /* Combine the quo assignment with the rem. */
12955 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
12956 result_quo, result_rem));
12957 }
12958 }
12959 }
12960 }
12961 return result;
12962}
e84da7c1 12963
12964/* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
12965 resulting value as a tree with type TYPE. The mpfr precision is
12966 set to the precision of TYPE. We assume that this mpfr function
12967 returns zero if the result could be calculated exactly within the
12968 requested precision. In addition, the integer pointer represented
12969 by ARG_SG will be dereferenced and set to the appropriate signgam
12970 (-1,1) value. */
12971
12972static tree
12973do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
12974{
12975 tree result = NULL_TREE;
12976
12977 STRIP_NOPS (arg);
12978
12979 /* To proceed, MPFR must exactly represent the target floating point
12980 format, which only happens when the target base equals two. Also
12981 verify ARG is a constant and that ARG_SG is an int pointer. */
12982 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
12983 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
12984 && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
12985 && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
12986 {
12987 const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
12988
12989 /* In addition to NaN and Inf, the argument cannot be zero or a
12990 negative integer. */
776a7bab 12991 if (real_isfinite (ra)
e84da7c1 12992 && ra->cl != rvc_zero
12993 && !(real_isneg(ra) && real_isinteger(ra, TYPE_MODE (type))))
12994 {
12995 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12996 int inexact, sg;
12997 mpfr_t m;
12998 tree result_lg;
12999
13000 mpfr_init2 (m, prec);
13001 mpfr_from_real (m, ra, GMP_RNDN);
13002 mpfr_clear_flags ();
13003 inexact = mpfr_lgamma (m, &sg, m, GMP_RNDN);
13004 result_lg = do_mpfr_ckconv (m, type, inexact);
13005 mpfr_clear (m);
13006 if (result_lg)
13007 {
13008 tree result_sg;
13009
13010 /* Dereference the arg_sg pointer argument. */
13011 arg_sg = build_fold_indirect_ref (arg_sg);
13012 /* Assign the signgam value into *arg_sg. */
13013 result_sg = fold_build2 (MODIFY_EXPR,
13014 TREE_TYPE (arg_sg), arg_sg,
13015 build_int_cst (NULL, sg));
13016 TREE_SIDE_EFFECTS (result_sg) = 1;
13017 /* Combine the signgam assignment with the lgamma result. */
13018 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13019 result_sg, result_lg));
13020 }
13021 }
13022 }
13023
13024 return result;
13025}
65dd1378 13026#endif