]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/builtins.c
PR middle-end/30251
[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
10Software Foundation; either version 2, or (at your option) any later
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
f12b58b3 19along with GCC; see the file COPYING. If not, write to the Free
67ce556b 20Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2102110-1301, USA. */
53800dbe 22
23#include "config.h"
24#include "system.h"
805e22b2 25#include "coretypes.h"
26#include "tm.h"
53800dbe 27#include "machmode.h"
ef258422 28#include "real.h"
53800dbe 29#include "rtl.h"
30#include "tree.h"
9ff0637e 31#include "tree-gimple.h"
53800dbe 32#include "flags.h"
33#include "regs.h"
34#include "hard-reg-set.h"
35#include "except.h"
36#include "function.h"
53800dbe 37#include "insn-config.h"
38#include "expr.h"
d8fc4d0b 39#include "optabs.h"
40#include "libfuncs.h"
53800dbe 41#include "recog.h"
42#include "output.h"
43#include "typeclass.h"
53800dbe 44#include "toplev.h"
689df48e 45#include "predict.h"
1dd6c958 46#include "tm_p.h"
fc2a2dcb 47#include "target.h"
63c62881 48#include "langhooks.h"
0ec80471 49#include "basic-block.h"
fd62c19a 50#include "tree-mudflap.h"
5a84fdd6 51#include "tree-flow.h"
162719b3 52#include "value-prof.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);
128static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
129static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
aecda0d6 130static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
c2f47e15 131static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
132static rtx expand_builtin_memset_args (tree, tree, tree, rtx, enum machine_mode, tree);
aecda0d6 133static rtx expand_builtin_bzero (tree);
134static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
c2f47e15 135static rtx expand_builtin_strstr (tree, rtx, enum machine_mode);
136static rtx expand_builtin_strpbrk (tree, rtx, enum machine_mode);
137static rtx expand_builtin_strchr (tree, rtx, enum machine_mode);
138static rtx expand_builtin_strrchr (tree, rtx, enum machine_mode);
aecda0d6 139static rtx expand_builtin_alloca (tree, rtx);
140static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
141static rtx expand_builtin_frame_address (tree, tree);
19bf118a 142static rtx expand_builtin_fputs (tree, rtx, bool);
143static rtx expand_builtin_printf (tree, rtx, enum machine_mode, bool);
144static rtx expand_builtin_fprintf (tree, rtx, enum machine_mode, bool);
6411575e 145static rtx expand_builtin_sprintf (tree, rtx, enum machine_mode);
aecda0d6 146static tree stabilize_va_list (tree, int);
147static rtx expand_builtin_expect (tree, rtx);
148static tree fold_builtin_constant_p (tree);
c2f47e15 149static tree fold_builtin_expect (tree);
aecda0d6 150static tree fold_builtin_classify_type (tree);
e6e27594 151static tree fold_builtin_strlen (tree);
aecda0d6 152static tree fold_builtin_inf (tree, int);
153static tree fold_builtin_nan (tree, tree, int);
c2f47e15 154static tree rewrite_call_expr (tree, int, tree, int, ...);
155static bool validate_arg (tree, enum tree_code code);
277f8dd2 156static bool integer_valued_real_p (tree);
76b9b24b 157static tree fold_trunc_transparent_mathfn (tree, tree);
aecda0d6 158static bool readonly_data_expr (tree);
159static rtx expand_builtin_fabs (tree, rtx, rtx);
27f261ef 160static rtx expand_builtin_signbit (tree, rtx);
e6e27594 161static tree fold_builtin_sqrt (tree, tree);
162static tree fold_builtin_cbrt (tree, tree);
c2f47e15 163static tree fold_builtin_pow (tree, tree, tree, tree);
164static tree fold_builtin_powi (tree, tree, tree, tree);
e6e27594 165static tree fold_builtin_cos (tree, tree, tree);
cacdc1af 166static tree fold_builtin_cosh (tree, tree, tree);
bffb7645 167static tree fold_builtin_tan (tree, tree);
7169af54 168static tree fold_builtin_trunc (tree, tree);
169static tree fold_builtin_floor (tree, tree);
170static tree fold_builtin_ceil (tree, tree);
171static tree fold_builtin_round (tree, tree);
ad52b9b7 172static tree fold_builtin_int_roundingfn (tree, tree);
10b9666f 173static tree fold_builtin_bitop (tree, tree);
c2f47e15 174static tree fold_builtin_memory_op (tree, tree, tree, tree, bool, int);
175static tree fold_builtin_strchr (tree, tree, tree);
7959b13b 176static tree fold_builtin_memchr (tree, tree, tree, tree);
c2f47e15 177static tree fold_builtin_memcmp (tree, tree, tree);
178static tree fold_builtin_strcmp (tree, tree);
179static tree fold_builtin_strncmp (tree, tree, tree);
64c18e8d 180static tree fold_builtin_signbit (tree, tree);
c2f47e15 181static tree fold_builtin_copysign (tree, tree, tree, tree);
467214fd 182static tree fold_builtin_isascii (tree);
183static tree fold_builtin_toascii (tree);
184static tree fold_builtin_isdigit (tree);
d1aade50 185static tree fold_builtin_fabs (tree, tree);
186static tree fold_builtin_abs (tree, tree);
c2f47e15 187static tree fold_builtin_unordered_cmp (tree, tree, tree, enum tree_code,
d5019fe8 188 enum tree_code);
c2f47e15 189static tree fold_builtin_n (tree, tree *, int, bool);
190static tree fold_builtin_0 (tree, bool);
3d3d84b8 191static tree fold_builtin_1 (tree, tree, bool);
c2f47e15 192static tree fold_builtin_2 (tree, tree, tree, bool);
193static tree fold_builtin_3 (tree, tree, tree, tree, bool);
194static tree fold_builtin_4 (tree, tree, tree, tree, tree, bool);
195static tree fold_builtin_varargs (tree, tree, bool);
196
197static tree fold_builtin_strpbrk (tree, tree, tree);
198static tree fold_builtin_strstr (tree, tree, tree);
199static tree fold_builtin_strrchr (tree, tree, tree);
200static tree fold_builtin_strcat (tree, tree);
201static tree fold_builtin_strncat (tree, tree, tree);
202static tree fold_builtin_strspn (tree, tree);
203static tree fold_builtin_strcspn (tree, tree);
204static tree fold_builtin_sprintf (tree, tree, tree, int);
4ee9c684 205
0a39fd54 206static rtx expand_builtin_object_size (tree);
207static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
208 enum built_in_function);
209static void maybe_emit_chk_warning (tree, enum built_in_function);
210static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
c2f47e15 211static tree fold_builtin_object_size (tree, tree);
212static tree fold_builtin_strcat_chk (tree, tree, tree, tree);
213static tree fold_builtin_strncat_chk (tree, tree, tree, tree, tree);
0a39fd54 214static tree fold_builtin_sprintf_chk (tree, enum built_in_function);
c2f47e15 215static tree fold_builtin_printf (tree, tree, tree, bool, enum built_in_function);
216static tree fold_builtin_fprintf (tree, tree, tree, tree, bool,
217 enum built_in_function);
99eabcc1 218static bool init_target_chars (void);
219
220static unsigned HOST_WIDE_INT target_newline;
221static unsigned HOST_WIDE_INT target_percent;
222static unsigned HOST_WIDE_INT target_c;
223static unsigned HOST_WIDE_INT target_s;
224static char target_percent_c[3];
225static char target_percent_s[3];
226static char target_percent_s_newline[4];
728bac60 227static tree do_mpfr_arg1 (tree, tree, int (*)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
228 const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, bool);
f0c477f2 229static tree do_mpfr_arg2 (tree, tree, tree,
230 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
9917422b 231static tree do_mpfr_arg3 (tree, tree, tree, tree,
232 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
d92f994c 233static tree do_mpfr_sincos (tree, tree, tree);
65dd1378 234#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
235static tree do_mpfr_bessel_n (tree, tree, tree,
236 int (*)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
237 const REAL_VALUE_TYPE *, bool);
238#endif
0a39fd54 239
b6a5fc45 240/* Return true if NODE should be considered for inline expansion regardless
241 of the optimization level. This means whenever a function is invoked with
242 its "internal" name, which normally contains the prefix "__builtin". */
243
244static bool called_as_built_in (tree node)
245{
246 const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
247 if (strncmp (name, "__builtin_", 10) == 0)
248 return true;
249 if (strncmp (name, "__sync_", 7) == 0)
250 return true;
251 return false;
252}
4ee9c684 253
53800dbe 254/* Return the alignment in bits of EXP, a pointer valued expression.
255 But don't return more than MAX_ALIGN no matter what.
256 The alignment returned is, by default, the alignment of the thing that
27d0c333 257 EXP points to. If it is not a POINTER_TYPE, 0 is returned.
53800dbe 258
259 Otherwise, look at the expression to see if we can do better, i.e., if the
260 expression is actually pointing at an object whose alignment is tighter. */
261
f656b751 262int
aecda0d6 263get_pointer_alignment (tree exp, unsigned int max_align)
53800dbe 264{
27d0c333 265 unsigned int align, inner;
53800dbe 266
189575ff 267 /* We rely on TER to compute accurate alignment information. */
268 if (!(optimize && flag_tree_ter))
269 return 0;
270
535e2026 271 if (!POINTER_TYPE_P (TREE_TYPE (exp)))
272 return 0;
273
53800dbe 274 align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
275 align = MIN (align, max_align);
276
277 while (1)
278 {
279 switch (TREE_CODE (exp))
280 {
281 case NOP_EXPR:
282 case CONVERT_EXPR:
283 case NON_LVALUE_EXPR:
284 exp = TREE_OPERAND (exp, 0);
552752f7 285 if (! POINTER_TYPE_P (TREE_TYPE (exp)))
53800dbe 286 return align;
325d1c45 287
53800dbe 288 inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
289 align = MIN (inner, max_align);
290 break;
291
292 case PLUS_EXPR:
293 /* If sum of pointer + int, restrict our maximum alignment to that
294 imposed by the integer. If not, we can't do any better than
295 ALIGN. */
325d1c45 296 if (! host_integerp (TREE_OPERAND (exp, 1), 1))
53800dbe 297 return align;
298
0994d2ed 299 while (((tree_low_cst (TREE_OPERAND (exp, 1), 1))
300 & (max_align / BITS_PER_UNIT - 1))
53800dbe 301 != 0)
302 max_align >>= 1;
303
304 exp = TREE_OPERAND (exp, 0);
305 break;
306
307 case ADDR_EXPR:
308 /* See what we are pointing at and look at its alignment. */
309 exp = TREE_OPERAND (exp, 0);
3c15318e 310 inner = max_align;
d2df7679 311 if (handled_component_p (exp))
1eee24cf 312 {
d2df7679 313 HOST_WIDE_INT bitsize, bitpos;
314 tree offset;
315 enum machine_mode mode;
316 int unsignedp, volatilep;
317
318 exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
319 &mode, &unsignedp, &volatilep, true);
320 if (bitpos)
321 inner = MIN (inner, (unsigned) (bitpos & -bitpos));
322 if (offset && TREE_CODE (offset) == PLUS_EXPR
323 && host_integerp (TREE_OPERAND (offset, 1), 1))
324 {
325 /* Any overflow in calculating offset_bits won't change
326 the alignment. */
327 unsigned offset_bits
328 = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
329 * BITS_PER_UNIT);
330
331 if (offset_bits)
332 inner = MIN (inner, (offset_bits & -offset_bits));
333 offset = TREE_OPERAND (offset, 0);
334 }
335 if (offset && TREE_CODE (offset) == MULT_EXPR
336 && host_integerp (TREE_OPERAND (offset, 1), 1))
337 {
338 /* Any overflow in calculating offset_factor won't change
339 the alignment. */
340 unsigned offset_factor
341 = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
342 * BITS_PER_UNIT);
343
344 if (offset_factor)
345 inner = MIN (inner, (offset_factor & -offset_factor));
346 }
347 else if (offset)
348 inner = MIN (inner, BITS_PER_UNIT);
1eee24cf 349 }
53800dbe 350 if (TREE_CODE (exp) == FUNCTION_DECL)
3c15318e 351 align = FUNCTION_BOUNDARY;
9308e976 352 else if (DECL_P (exp))
3c15318e 353 align = MIN (inner, DECL_ALIGN (exp));
53800dbe 354#ifdef CONSTANT_ALIGNMENT
ce45a448 355 else if (CONSTANT_CLASS_P (exp))
e068b646 356 align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align));
53800dbe 357#endif
d2df7679 358 else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR
359 || TREE_CODE (exp) == INDIRECT_REF)
360 align = MIN (TYPE_ALIGN (TREE_TYPE (exp)), inner);
3c15318e 361 else
362 align = MIN (align, inner);
363 return MIN (align, max_align);
53800dbe 364
365 default:
366 return align;
367 }
368 }
369}
370
371/* Compute the length of a C string. TREE_STRING_LENGTH is not the right
372 way, because it could contain a zero byte in the middle.
373 TREE_STRING_LENGTH is the size of the character array, not the string.
374
4172d65e 375 ONLY_VALUE should be nonzero if the result is not going to be emitted
c09841f6 376 into the instruction stream and zero if it is going to be expanded.
4172d65e 377 E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
681fab1e 378 is returned, otherwise NULL, since
379 len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
380 evaluate the side-effects.
381
902de8ed 382 The value returned is of type `ssizetype'.
383
53800dbe 384 Unfortunately, string_constant can't access the values of const char
385 arrays with initializers, so neither can we do so here. */
386
4ee9c684 387tree
681fab1e 388c_strlen (tree src, int only_value)
53800dbe 389{
390 tree offset_node;
27d0c333 391 HOST_WIDE_INT offset;
392 int max;
44acf429 393 const char *ptr;
53800dbe 394
681fab1e 395 STRIP_NOPS (src);
396 if (TREE_CODE (src) == COND_EXPR
397 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
398 {
399 tree len1, len2;
400
401 len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
402 len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
0862b7e9 403 if (tree_int_cst_equal (len1, len2))
681fab1e 404 return len1;
405 }
406
407 if (TREE_CODE (src) == COMPOUND_EXPR
408 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
409 return c_strlen (TREE_OPERAND (src, 1), only_value);
410
53800dbe 411 src = string_constant (src, &offset_node);
412 if (src == 0)
c2f47e15 413 return NULL_TREE;
902de8ed 414
83d79705 415 max = TREE_STRING_LENGTH (src) - 1;
53800dbe 416 ptr = TREE_STRING_POINTER (src);
902de8ed 417
53800dbe 418 if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
419 {
420 /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
421 compute the offset to the following null if we don't know where to
422 start searching for it. */
423 int i;
902de8ed 424
53800dbe 425 for (i = 0; i < max; i++)
426 if (ptr[i] == 0)
c2f47e15 427 return NULL_TREE;
902de8ed 428
53800dbe 429 /* We don't know the starting offset, but we do know that the string
430 has no internal zero bytes. We can assume that the offset falls
431 within the bounds of the string; otherwise, the programmer deserves
432 what he gets. Subtract the offset from the length of the string,
902de8ed 433 and return that. This would perhaps not be valid if we were dealing
434 with named arrays in addition to literal string constants. */
435
436 return size_diffop (size_int (max), offset_node);
53800dbe 437 }
438
439 /* We have a known offset into the string. Start searching there for
27d0c333 440 a null character if we can represent it as a single HOST_WIDE_INT. */
dabc4084 441 if (offset_node == 0)
53800dbe 442 offset = 0;
dabc4084 443 else if (! host_integerp (offset_node, 0))
444 offset = -1;
53800dbe 445 else
27d0c333 446 offset = tree_low_cst (offset_node, 0);
902de8ed 447
53800dbe 448 /* If the offset is known to be out of bounds, warn, and call strlen at
449 runtime. */
450 if (offset < 0 || offset > max)
451 {
c3ceba8e 452 warning (0, "offset outside bounds of constant string");
c2f47e15 453 return NULL_TREE;
53800dbe 454 }
902de8ed 455
53800dbe 456 /* Use strlen to search for the first zero byte. Since any strings
457 constructed with build_string will have nulls appended, we win even
458 if we get handed something like (char[4])"abcd".
459
460 Since OFFSET is our starting index into the string, no further
461 calculation is needed. */
902de8ed 462 return ssize_int (strlen (ptr + offset));
53800dbe 463}
464
83d79705 465/* Return a char pointer for a C string if it is a string constant
466 or sum of string constant and integer constant. */
467
468static const char *
aecda0d6 469c_getstr (tree src)
83d79705 470{
471 tree offset_node;
83d79705 472
473 src = string_constant (src, &offset_node);
474 if (src == 0)
475 return 0;
476
8c85fcb7 477 if (offset_node == 0)
478 return TREE_STRING_POINTER (src);
479 else if (!host_integerp (offset_node, 1)
480 || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
83d79705 481 return 0;
83d79705 482
8c85fcb7 483 return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
83d79705 484}
485
8c85fcb7 486/* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
487 GET_MODE_BITSIZE (MODE) bits from string constant STR. */
ecc318ff 488
6840589f 489static rtx
aecda0d6 490c_readstr (const char *str, enum machine_mode mode)
6840589f 491{
492 HOST_WIDE_INT c[2];
493 HOST_WIDE_INT ch;
494 unsigned int i, j;
495
64db345d 496 gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
7d3f6cc7 497
6840589f 498 c[0] = 0;
499 c[1] = 0;
500 ch = 1;
501 for (i = 0; i < GET_MODE_SIZE (mode); i++)
502 {
503 j = i;
504 if (WORDS_BIG_ENDIAN)
505 j = GET_MODE_SIZE (mode) - i - 1;
506 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
507 && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
508 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
509 j *= BITS_PER_UNIT;
64db345d 510 gcc_assert (j <= 2 * HOST_BITS_PER_WIDE_INT);
7d3f6cc7 511
6840589f 512 if (ch)
513 ch = (unsigned char) str[i];
514 c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
515 }
516 return immed_double_const (c[0], c[1], mode);
517}
518
ecc318ff 519/* Cast a target constant CST to target CHAR and if that value fits into
5206b159 520 host char type, return zero and put that value into variable pointed to by
ecc318ff 521 P. */
522
523static int
aecda0d6 524target_char_cast (tree cst, char *p)
ecc318ff 525{
526 unsigned HOST_WIDE_INT val, hostval;
527
27d0c333 528 if (!host_integerp (cst, 1)
ecc318ff 529 || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
530 return 1;
531
27d0c333 532 val = tree_low_cst (cst, 1);
ecc318ff 533 if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
534 val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
535
536 hostval = val;
537 if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
538 hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
539
540 if (val != hostval)
541 return 1;
542
543 *p = hostval;
544 return 0;
545}
546
4ee9c684 547/* Similar to save_expr, but assumes that arbitrary code is not executed
548 in between the multiple evaluations. In particular, we assume that a
549 non-addressable local variable will not be modified. */
550
551static tree
552builtin_save_expr (tree exp)
553{
554 if (TREE_ADDRESSABLE (exp) == 0
555 && (TREE_CODE (exp) == PARM_DECL
556 || (TREE_CODE (exp) == VAR_DECL && !TREE_STATIC (exp))))
557 return exp;
558
559 return save_expr (exp);
560}
561
53800dbe 562/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
563 times to get the address of either a higher stack frame, or a return
564 address located within it (depending on FNDECL_CODE). */
902de8ed 565
c626df3d 566static rtx
869d0ef0 567expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
53800dbe 568{
569 int i;
570
869d0ef0 571#ifdef INITIAL_FRAME_ADDRESS_RTX
572 rtx tem = INITIAL_FRAME_ADDRESS_RTX;
573#else
e3e15c50 574 rtx tem;
575
1b74fde7 576 /* For a zero count with __builtin_return_address, we don't care what
577 frame address we return, because target-specific definitions will
578 override us. Therefore frame pointer elimination is OK, and using
579 the soft frame pointer is OK.
580
fa7637bd 581 For a nonzero count, or a zero count with __builtin_frame_address,
1b74fde7 582 we require a stable offset from the current frame pointer to the
583 previous one, so we must use the hard frame pointer, and
e3e15c50 584 we must disable frame pointer elimination. */
1b74fde7 585 if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
e3e15c50 586 tem = frame_pointer_rtx;
a0c938f0 587 else
e3e15c50 588 {
589 tem = hard_frame_pointer_rtx;
590
591 /* Tell reload not to eliminate the frame pointer. */
592 current_function_accesses_prior_frames = 1;
593 }
869d0ef0 594#endif
595
53800dbe 596 /* Some machines need special handling before we can access
3a69c60c 597 arbitrary frames. For example, on the SPARC, we must first flush
53800dbe 598 all register windows to the stack. */
599#ifdef SETUP_FRAME_ADDRESSES
600 if (count > 0)
601 SETUP_FRAME_ADDRESSES ();
602#endif
603
3a69c60c 604 /* On the SPARC, the return address is not in the frame, it is in a
53800dbe 605 register. There is no way to access it off of the current frame
606 pointer, but it can be accessed off the previous frame pointer by
607 reading the value from the register window save area. */
608#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
609 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
610 count--;
611#endif
612
613 /* Scan back COUNT frames to the specified frame. */
614 for (i = 0; i < count; i++)
615 {
616 /* Assume the dynamic chain pointer is in the word that the
617 frame address points to, unless otherwise specified. */
618#ifdef DYNAMIC_CHAIN_ADDRESS
619 tem = DYNAMIC_CHAIN_ADDRESS (tem);
620#endif
621 tem = memory_address (Pmode, tem);
00060fc2 622 tem = gen_frame_mem (Pmode, tem);
83fc1478 623 tem = copy_to_reg (tem);
53800dbe 624 }
625
3a69c60c 626 /* For __builtin_frame_address, return what we've got. But, on
627 the SPARC for example, we may have to add a bias. */
53800dbe 628 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
3a69c60c 629#ifdef FRAME_ADDR_RTX
630 return FRAME_ADDR_RTX (tem);
631#else
53800dbe 632 return tem;
3a69c60c 633#endif
53800dbe 634
3a69c60c 635 /* For __builtin_return_address, get the return address from that frame. */
53800dbe 636#ifdef RETURN_ADDR_RTX
637 tem = RETURN_ADDR_RTX (count, tem);
638#else
639 tem = memory_address (Pmode,
640 plus_constant (tem, GET_MODE_SIZE (Pmode)));
00060fc2 641 tem = gen_frame_mem (Pmode, tem);
53800dbe 642#endif
643 return tem;
644}
645
f7c44134 646/* Alias set used for setjmp buffer. */
647static HOST_WIDE_INT setjmp_alias_set = -1;
648
6b7f6858 649/* Construct the leading half of a __builtin_setjmp call. Control will
2c8a1497 650 return to RECEIVER_LABEL. This is also called directly by the SJLJ
651 exception handling code. */
53800dbe 652
6b7f6858 653void
aecda0d6 654expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
53800dbe 655{
53800dbe 656 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
53800dbe 657 rtx stack_save;
f7c44134 658 rtx mem;
53800dbe 659
f7c44134 660 if (setjmp_alias_set == -1)
661 setjmp_alias_set = new_alias_set ();
662
85d654dd 663 buf_addr = convert_memory_address (Pmode, buf_addr);
53800dbe 664
37ae8504 665 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
53800dbe 666
6b7f6858 667 /* We store the frame pointer and the address of receiver_label in
668 the buffer and use the rest of it for the stack save area, which
669 is machine-dependent. */
53800dbe 670
f7c44134 671 mem = gen_rtx_MEM (Pmode, buf_addr);
ab6ab77e 672 set_mem_alias_set (mem, setjmp_alias_set);
e3e026e8 673 emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
f7c44134 674
675 mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
ab6ab77e 676 set_mem_alias_set (mem, setjmp_alias_set);
f7c44134 677
678 emit_move_insn (validize_mem (mem),
6b7f6858 679 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
53800dbe 680
681 stack_save = gen_rtx_MEM (sa_mode,
682 plus_constant (buf_addr,
683 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 684 set_mem_alias_set (stack_save, setjmp_alias_set);
53800dbe 685 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
686
687 /* If there is further processing to do, do it. */
688#ifdef HAVE_builtin_setjmp_setup
689 if (HAVE_builtin_setjmp_setup)
690 emit_insn (gen_builtin_setjmp_setup (buf_addr));
691#endif
692
6b7f6858 693 /* Tell optimize_save_area_alloca that extra work is going to
694 need to go on during alloca. */
3b0fa6b6 695 current_function_calls_setjmp = 1;
80ab81b9 696
697 /* Set this so all the registers get saved in our frame; we need to be
2c0e001b 698 able to copy the saved values for any registers from frames we unwind. */
80ab81b9 699 current_function_has_nonlocal_label = 1;
6b7f6858 700}
53800dbe 701
2c8a1497 702/* Construct the trailing part of a __builtin_setjmp call. This is
703 also called directly by the SJLJ exception handling code. */
6b7f6858 704
705void
aecda0d6 706expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
6b7f6858 707{
53800dbe 708 /* Clobber the FP when we get here, so we have to make sure it's
709 marked as used by this function. */
710 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
711
712 /* Mark the static chain as clobbered here so life information
713 doesn't get messed up for it. */
714 emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
715
716 /* Now put in the code to restore the frame pointer, and argument
491e04ef 717 pointer, if needed. */
53800dbe 718#ifdef HAVE_nonlocal_goto
719 if (! HAVE_nonlocal_goto)
720#endif
5a1c3f40 721 {
722 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
723 /* This might change the hard frame pointer in ways that aren't
724 apparent to early optimization passes, so force a clobber. */
725 emit_insn (gen_rtx_CLOBBER (VOIDmode, hard_frame_pointer_rtx));
726 }
53800dbe 727
728#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
729 if (fixed_regs[ARG_POINTER_REGNUM])
730 {
731#ifdef ELIMINABLE_REGS
732 size_t i;
e99c3a1d 733 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
53800dbe 734
3098b2d3 735 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
53800dbe 736 if (elim_regs[i].from == ARG_POINTER_REGNUM
737 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
738 break;
739
3098b2d3 740 if (i == ARRAY_SIZE (elim_regs))
53800dbe 741#endif
742 {
743 /* Now restore our arg pointer from the address at which it
05927e40 744 was saved in our stack frame. */
53800dbe 745 emit_move_insn (virtual_incoming_args_rtx,
05927e40 746 copy_to_reg (get_arg_pointer_save_area (cfun)));
53800dbe 747 }
748 }
749#endif
750
751#ifdef HAVE_builtin_setjmp_receiver
752 if (HAVE_builtin_setjmp_receiver)
6b7f6858 753 emit_insn (gen_builtin_setjmp_receiver (receiver_label));
53800dbe 754 else
755#endif
756#ifdef HAVE_nonlocal_goto_receiver
757 if (HAVE_nonlocal_goto_receiver)
758 emit_insn (gen_nonlocal_goto_receiver ());
759 else
760#endif
6b7f6858 761 { /* Nothing */ }
57f6bb94 762
763 /* @@@ This is a kludge. Not all machine descriptions define a blockage
764 insn, but we must not allow the code we just generated to be reordered
765 by scheduling. Specifically, the update of the frame pointer must
766 happen immediately, not later. So emit an ASM_INPUT to act as blockage
767 insn. */
768 emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
6b7f6858 769}
53800dbe 770
53800dbe 771/* __builtin_longjmp is passed a pointer to an array of five words (not
772 all will be used on all machines). It operates similarly to the C
773 library function of the same name, but is more efficient. Much of
2c8a1497 774 the code below is copied from the handling of non-local gotos. */
53800dbe 775
c626df3d 776static void
aecda0d6 777expand_builtin_longjmp (rtx buf_addr, rtx value)
53800dbe 778{
4712c7d6 779 rtx fp, lab, stack, insn, last;
53800dbe 780 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
781
f7c44134 782 if (setjmp_alias_set == -1)
783 setjmp_alias_set = new_alias_set ();
784
85d654dd 785 buf_addr = convert_memory_address (Pmode, buf_addr);
479e4d5e 786
53800dbe 787 buf_addr = force_reg (Pmode, buf_addr);
788
789 /* We used to store value in static_chain_rtx, but that fails if pointers
790 are smaller than integers. We instead require that the user must pass
791 a second argument of 1, because that is what builtin_setjmp will
792 return. This also makes EH slightly more efficient, since we are no
793 longer copying around a value that we don't care about. */
64db345d 794 gcc_assert (value == const1_rtx);
53800dbe 795
4712c7d6 796 last = get_last_insn ();
53800dbe 797#ifdef HAVE_builtin_longjmp
798 if (HAVE_builtin_longjmp)
799 emit_insn (gen_builtin_longjmp (buf_addr));
800 else
801#endif
802 {
803 fp = gen_rtx_MEM (Pmode, buf_addr);
804 lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
805 GET_MODE_SIZE (Pmode)));
806
807 stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
808 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 809 set_mem_alias_set (fp, setjmp_alias_set);
810 set_mem_alias_set (lab, setjmp_alias_set);
811 set_mem_alias_set (stack, setjmp_alias_set);
53800dbe 812
813 /* Pick up FP, label, and SP from the block and jump. This code is
814 from expand_goto in stmt.c; see there for detailed comments. */
03fd9d2c 815#ifdef HAVE_nonlocal_goto
53800dbe 816 if (HAVE_nonlocal_goto)
817 /* We have to pass a value to the nonlocal_goto pattern that will
818 get copied into the static_chain pointer, but it does not matter
819 what that value is, because builtin_setjmp does not use it. */
28d202a8 820 emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
53800dbe 821 else
822#endif
823 {
824 lab = copy_to_reg (lab);
825
2a871ad1 826 emit_insn (gen_rtx_CLOBBER (VOIDmode,
827 gen_rtx_MEM (BLKmode,
828 gen_rtx_SCRATCH (VOIDmode))));
829 emit_insn (gen_rtx_CLOBBER (VOIDmode,
830 gen_rtx_MEM (BLKmode,
831 hard_frame_pointer_rtx)));
832
53800dbe 833 emit_move_insn (hard_frame_pointer_rtx, fp);
834 emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
835
836 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
837 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
838 emit_indirect_jump (lab);
839 }
840 }
615166bb 841
842 /* Search backwards and mark the jump insn as a non-local goto.
843 Note that this precludes the use of __builtin_longjmp to a
844 __builtin_setjmp target in the same function. However, we've
845 already cautioned the user that these functions are for
846 internal exception handling use only. */
449c0509 847 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
848 {
64db345d 849 gcc_assert (insn != last);
7d3f6cc7 850
6d7dc5b9 851 if (JUMP_P (insn))
449c0509 852 {
853 REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
854 REG_NOTES (insn));
855 break;
856 }
6d7dc5b9 857 else if (CALL_P (insn))
9342ee68 858 break;
449c0509 859 }
53800dbe 860}
861
4ee9c684 862/* Expand a call to __builtin_nonlocal_goto. We're passed the target label
863 and the address of the save area. */
864
865static rtx
c2f47e15 866expand_builtin_nonlocal_goto (tree exp)
4ee9c684 867{
868 tree t_label, t_save_area;
869 rtx r_label, r_save_area, r_fp, r_sp, insn;
870
c2f47e15 871 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4ee9c684 872 return NULL_RTX;
873
c2f47e15 874 t_label = CALL_EXPR_ARG (exp, 0);
875 t_save_area = CALL_EXPR_ARG (exp, 1);
4ee9c684 876
8ec3c5c2 877 r_label = expand_normal (t_label);
3dce56cc 878 r_label = convert_memory_address (Pmode, r_label);
8ec3c5c2 879 r_save_area = expand_normal (t_save_area);
3dce56cc 880 r_save_area = convert_memory_address (Pmode, r_save_area);
4ee9c684 881 r_fp = gen_rtx_MEM (Pmode, r_save_area);
882 r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
883 plus_constant (r_save_area, GET_MODE_SIZE (Pmode)));
884
885 current_function_has_nonlocal_goto = 1;
886
03fd9d2c 887#ifdef HAVE_nonlocal_goto
4ee9c684 888 /* ??? We no longer need to pass the static chain value, afaik. */
889 if (HAVE_nonlocal_goto)
890 emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
891 else
892#endif
893 {
894 r_label = copy_to_reg (r_label);
895
896 emit_insn (gen_rtx_CLOBBER (VOIDmode,
897 gen_rtx_MEM (BLKmode,
898 gen_rtx_SCRATCH (VOIDmode))));
899
900 emit_insn (gen_rtx_CLOBBER (VOIDmode,
901 gen_rtx_MEM (BLKmode,
902 hard_frame_pointer_rtx)));
491e04ef 903
4ee9c684 904 /* Restore frame pointer for containing function.
905 This sets the actual hard register used for the frame pointer
906 to the location of the function's incoming static chain info.
907 The non-local goto handler will then adjust it to contain the
908 proper value and reload the argument pointer, if needed. */
909 emit_move_insn (hard_frame_pointer_rtx, r_fp);
910 emit_stack_restore (SAVE_NONLOCAL, r_sp, NULL_RTX);
491e04ef 911
4ee9c684 912 /* USE of hard_frame_pointer_rtx added for consistency;
913 not clear if really needed. */
914 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
915 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
916 emit_indirect_jump (r_label);
917 }
491e04ef 918
4ee9c684 919 /* Search backwards to the jump insn and mark it as a
920 non-local goto. */
921 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
922 {
6d7dc5b9 923 if (JUMP_P (insn))
4ee9c684 924 {
925 REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO,
926 const0_rtx, REG_NOTES (insn));
927 break;
928 }
6d7dc5b9 929 else if (CALL_P (insn))
4ee9c684 930 break;
931 }
932
933 return const0_rtx;
934}
935
843d08a9 936/* __builtin_update_setjmp_buf is passed a pointer to an array of five words
937 (not all will be used on all machines) that was passed to __builtin_setjmp.
938 It updates the stack pointer in that block to correspond to the current
939 stack pointer. */
940
941static void
942expand_builtin_update_setjmp_buf (rtx buf_addr)
943{
944 enum machine_mode sa_mode = Pmode;
945 rtx stack_save;
946
947
948#ifdef HAVE_save_stack_nonlocal
949 if (HAVE_save_stack_nonlocal)
950 sa_mode = insn_data[(int) CODE_FOR_save_stack_nonlocal].operand[0].mode;
951#endif
952#ifdef STACK_SAVEAREA_MODE
953 sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
954#endif
955
956 stack_save
957 = gen_rtx_MEM (sa_mode,
958 memory_address
959 (sa_mode,
960 plus_constant (buf_addr, 2 * GET_MODE_SIZE (Pmode))));
961
962#ifdef HAVE_setjmp
963 if (HAVE_setjmp)
964 emit_insn (gen_setjmp ());
965#endif
966
967 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
968}
969
5e3608d8 970/* Expand a call to __builtin_prefetch. For a target that does not support
971 data prefetch, evaluate the memory address argument in case it has side
972 effects. */
973
974static void
c2f47e15 975expand_builtin_prefetch (tree exp)
5e3608d8 976{
977 tree arg0, arg1, arg2;
c2f47e15 978 int nargs;
5e3608d8 979 rtx op0, op1, op2;
980
c2f47e15 981 if (!validate_arglist (exp, POINTER_TYPE, 0))
26a5cadb 982 return;
983
c2f47e15 984 arg0 = CALL_EXPR_ARG (exp, 0);
985
26a5cadb 986 /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
987 zero (read) and argument 2 (locality) defaults to 3 (high degree of
988 locality). */
c2f47e15 989 nargs = call_expr_nargs (exp);
990 if (nargs > 1)
991 arg1 = CALL_EXPR_ARG (exp, 1);
26a5cadb 992 else
c2f47e15 993 arg1 = integer_zero_node;
994 if (nargs > 2)
995 arg2 = CALL_EXPR_ARG (exp, 2);
996 else
997 arg2 = build_int_cst (NULL_TREE, 3);
5e3608d8 998
999 /* Argument 0 is an address. */
1000 op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
1001
1002 /* Argument 1 (read/write flag) must be a compile-time constant int. */
1003 if (TREE_CODE (arg1) != INTEGER_CST)
1004 {
07e3a3d2 1005 error ("second argument to %<__builtin_prefetch%> must be a constant");
9342ee68 1006 arg1 = integer_zero_node;
5e3608d8 1007 }
8ec3c5c2 1008 op1 = expand_normal (arg1);
5e3608d8 1009 /* Argument 1 must be either zero or one. */
1010 if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
1011 {
c3ceba8e 1012 warning (0, "invalid second argument to %<__builtin_prefetch%>;"
07e3a3d2 1013 " using zero");
5e3608d8 1014 op1 = const0_rtx;
1015 }
1016
1017 /* Argument 2 (locality) must be a compile-time constant int. */
1018 if (TREE_CODE (arg2) != INTEGER_CST)
1019 {
07e3a3d2 1020 error ("third argument to %<__builtin_prefetch%> must be a constant");
5e3608d8 1021 arg2 = integer_zero_node;
1022 }
8ec3c5c2 1023 op2 = expand_normal (arg2);
5e3608d8 1024 /* Argument 2 must be 0, 1, 2, or 3. */
1025 if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
1026 {
c3ceba8e 1027 warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
5e3608d8 1028 op2 = const0_rtx;
1029 }
1030
1031#ifdef HAVE_prefetch
1032 if (HAVE_prefetch)
1033 {
f0ce3b1f 1034 if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate)
4cd21437 1035 (op0,
f0ce3b1f 1036 insn_data[(int) CODE_FOR_prefetch].operand[0].mode))
19bf118a 1037 || (GET_MODE (op0) != Pmode))
9342ee68 1038 {
85d654dd 1039 op0 = convert_memory_address (Pmode, op0);
9342ee68 1040 op0 = force_reg (Pmode, op0);
1041 }
5e3608d8 1042 emit_insn (gen_prefetch (op0, op1, op2));
1043 }
5e3608d8 1044#endif
0a534ba7 1045
f0ce3b1f 1046 /* Don't do anything with direct references to volatile memory, but
1047 generate code to handle other side effects. */
e16ceb8e 1048 if (!MEM_P (op0) && side_effects_p (op0))
f0ce3b1f 1049 emit_insn (op0);
5e3608d8 1050}
1051
f7c44134 1052/* Get a MEM rtx for expression EXP which is the address of an operand
d8ae1baa 1053 to be used in a string instruction (cmpstrsi, movmemsi, ..). LEN is
1054 the maximum length of the block of memory that might be accessed or
1055 NULL if unknown. */
f7c44134 1056
53800dbe 1057static rtx
d8ae1baa 1058get_memory_rtx (tree exp, tree len)
53800dbe 1059{
bb2327a8 1060 rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
1061 rtx mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
2a631e19 1062
f7c44134 1063 /* Get an expression we can use to find the attributes to assign to MEM.
1064 If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
1065 we can. First remove any nops. */
1066 while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
f0ce3b1f 1067 || TREE_CODE (exp) == NON_LVALUE_EXPR)
f7c44134 1068 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
1069 exp = TREE_OPERAND (exp, 0);
1070
1071 if (TREE_CODE (exp) == ADDR_EXPR)
a1a25d19 1072 exp = TREE_OPERAND (exp, 0);
f7c44134 1073 else if (POINTER_TYPE_P (TREE_TYPE (exp)))
a1a25d19 1074 exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
1075 else
1076 exp = NULL;
1077
1078 /* Honor attributes derived from exp, except for the alias set
1079 (as builtin stringops may alias with anything) and the size
1080 (as stringops may access multiple array elements). */
1081 if (exp)
eec8e941 1082 {
a1a25d19 1083 set_mem_attributes (mem, exp, 0);
d8ae1baa 1084
1085 /* Allow the string and memory builtins to overflow from one
1086 field into another, see http://gcc.gnu.org/PR23561.
1087 Thus avoid COMPONENT_REFs in MEM_EXPR unless we know the whole
1088 memory accessed by the string or memory builtin will fit
1089 within the field. */
1090 if (MEM_EXPR (mem) && TREE_CODE (MEM_EXPR (mem)) == COMPONENT_REF)
1091 {
1092 tree mem_expr = MEM_EXPR (mem);
1093 HOST_WIDE_INT offset = -1, length = -1;
1094 tree inner = exp;
1095
1096 while (TREE_CODE (inner) == ARRAY_REF
1097 || TREE_CODE (inner) == NOP_EXPR
1098 || TREE_CODE (inner) == CONVERT_EXPR
1099 || TREE_CODE (inner) == NON_LVALUE_EXPR
1100 || TREE_CODE (inner) == VIEW_CONVERT_EXPR
1101 || TREE_CODE (inner) == SAVE_EXPR)
1102 inner = TREE_OPERAND (inner, 0);
1103
1104 gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
1105
1106 if (MEM_OFFSET (mem)
1107 && GET_CODE (MEM_OFFSET (mem)) == CONST_INT)
1108 offset = INTVAL (MEM_OFFSET (mem));
1109
1110 if (offset >= 0 && len && host_integerp (len, 0))
1111 length = tree_low_cst (len, 0);
1112
1113 while (TREE_CODE (inner) == COMPONENT_REF)
1114 {
1115 tree field = TREE_OPERAND (inner, 1);
1116 gcc_assert (! DECL_BIT_FIELD (field));
1117 gcc_assert (TREE_CODE (mem_expr) == COMPONENT_REF);
1118 gcc_assert (field == TREE_OPERAND (mem_expr, 1));
1119
1120 if (length >= 0
1121 && TYPE_SIZE_UNIT (TREE_TYPE (inner))
1122 && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0))
1123 {
1124 HOST_WIDE_INT size
1125 = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0);
1126 /* If we can prove the memory starting at XEXP (mem, 0)
1127 and ending at XEXP (mem, 0) + LENGTH will fit into
1128 this field, we can keep that COMPONENT_REF in MEM_EXPR. */
1129 if (offset <= size
1130 && length <= size
1131 && offset + length <= size)
1132 break;
1133 }
1134
1135 if (offset >= 0
1136 && host_integerp (DECL_FIELD_OFFSET (field), 0))
1137 offset += tree_low_cst (DECL_FIELD_OFFSET (field), 0)
1138 + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
1139 / BITS_PER_UNIT;
1140 else
1141 {
1142 offset = -1;
1143 length = -1;
1144 }
1145
1146 mem_expr = TREE_OPERAND (mem_expr, 0);
1147 inner = TREE_OPERAND (inner, 0);
d8ae1baa 1148 }
1149
1150 if (mem_expr == NULL)
1151 offset = -1;
1152 if (mem_expr != MEM_EXPR (mem))
1153 {
1154 set_mem_expr (mem, mem_expr);
1155 set_mem_offset (mem, offset >= 0 ? GEN_INT (offset) : NULL_RTX);
1156 }
1157 }
eec8e941 1158 set_mem_alias_set (mem, 0);
a1a25d19 1159 set_mem_size (mem, NULL_RTX);
eec8e941 1160 }
53800dbe 1161
53800dbe 1162 return mem;
1163}
1164\f
1165/* Built-in functions to perform an untyped call and return. */
1166
1167/* For each register that may be used for calling a function, this
1168 gives a mode used to copy the register's value. VOIDmode indicates
1169 the register is not used for calling a function. If the machine
1170 has register windows, this gives only the outbound registers.
1171 INCOMING_REGNO gives the corresponding inbound register. */
1172static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
1173
1174/* For each register that may be used for returning values, this gives
1175 a mode used to copy the register's value. VOIDmode indicates the
1176 register is not used for returning values. If the machine has
1177 register windows, this gives only the outbound registers.
1178 INCOMING_REGNO gives the corresponding inbound register. */
1179static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
1180
1181/* For each register that may be used for calling a function, this
1182 gives the offset of that register into the block returned by
1183 __builtin_apply_args. 0 indicates that the register is not
1184 used for calling a function. */
1185static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
1186
53800dbe 1187/* Return the size required for the block returned by __builtin_apply_args,
1188 and initialize apply_args_mode. */
1189
1190static int
aecda0d6 1191apply_args_size (void)
53800dbe 1192{
1193 static int size = -1;
58e9ce8f 1194 int align;
1195 unsigned int regno;
53800dbe 1196 enum machine_mode mode;
1197
1198 /* The values computed by this function never change. */
1199 if (size < 0)
1200 {
1201 /* The first value is the incoming arg-pointer. */
1202 size = GET_MODE_SIZE (Pmode);
1203
1204 /* The second value is the structure value address unless this is
1205 passed as an "invisible" first argument. */
6812c89e 1206 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1207 size += GET_MODE_SIZE (Pmode);
1208
1209 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1210 if (FUNCTION_ARG_REGNO_P (regno))
1211 {
0862b7e9 1212 mode = reg_raw_mode[regno];
1213
64db345d 1214 gcc_assert (mode != VOIDmode);
53800dbe 1215
1216 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1217 if (size % align != 0)
1218 size = CEIL (size, align) * align;
1219 apply_args_reg_offset[regno] = size;
1220 size += GET_MODE_SIZE (mode);
1221 apply_args_mode[regno] = mode;
1222 }
1223 else
1224 {
1225 apply_args_mode[regno] = VOIDmode;
1226 apply_args_reg_offset[regno] = 0;
1227 }
1228 }
1229 return size;
1230}
1231
1232/* Return the size required for the block returned by __builtin_apply,
1233 and initialize apply_result_mode. */
1234
1235static int
aecda0d6 1236apply_result_size (void)
53800dbe 1237{
1238 static int size = -1;
1239 int align, regno;
1240 enum machine_mode mode;
1241
1242 /* The values computed by this function never change. */
1243 if (size < 0)
1244 {
1245 size = 0;
1246
1247 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1248 if (FUNCTION_VALUE_REGNO_P (regno))
1249 {
0862b7e9 1250 mode = reg_raw_mode[regno];
1251
64db345d 1252 gcc_assert (mode != VOIDmode);
53800dbe 1253
1254 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1255 if (size % align != 0)
1256 size = CEIL (size, align) * align;
1257 size += GET_MODE_SIZE (mode);
1258 apply_result_mode[regno] = mode;
1259 }
1260 else
1261 apply_result_mode[regno] = VOIDmode;
1262
1263 /* Allow targets that use untyped_call and untyped_return to override
1264 the size so that machine-specific information can be stored here. */
1265#ifdef APPLY_RESULT_SIZE
1266 size = APPLY_RESULT_SIZE;
1267#endif
1268 }
1269 return size;
1270}
1271
1272#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1273/* Create a vector describing the result block RESULT. If SAVEP is true,
1274 the result block is used to save the values; otherwise it is used to
1275 restore the values. */
1276
1277static rtx
aecda0d6 1278result_vector (int savep, rtx result)
53800dbe 1279{
1280 int regno, size, align, nelts;
1281 enum machine_mode mode;
1282 rtx reg, mem;
f0af5a88 1283 rtx *savevec = alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
bf8e3599 1284
53800dbe 1285 size = nelts = 0;
1286 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1287 if ((mode = apply_result_mode[regno]) != VOIDmode)
1288 {
1289 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1290 if (size % align != 0)
1291 size = CEIL (size, align) * align;
1292 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
e513d163 1293 mem = adjust_address (result, mode, size);
53800dbe 1294 savevec[nelts++] = (savep
1295 ? gen_rtx_SET (VOIDmode, mem, reg)
1296 : gen_rtx_SET (VOIDmode, reg, mem));
1297 size += GET_MODE_SIZE (mode);
1298 }
1299 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1300}
1301#endif /* HAVE_untyped_call or HAVE_untyped_return */
1302
1303/* Save the state required to perform an untyped call with the same
1304 arguments as were passed to the current function. */
1305
1306static rtx
aecda0d6 1307expand_builtin_apply_args_1 (void)
53800dbe 1308{
1c7e61a7 1309 rtx registers, tem;
53800dbe 1310 int size, align, regno;
1311 enum machine_mode mode;
6812c89e 1312 rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
53800dbe 1313
1314 /* Create a block where the arg-pointer, structure value address,
1315 and argument registers can be saved. */
1316 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1317
1318 /* Walk past the arg-pointer and structure value address. */
1319 size = GET_MODE_SIZE (Pmode);
6812c89e 1320 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1321 size += GET_MODE_SIZE (Pmode);
1322
1323 /* Save each register used in calling a function to the block. */
1324 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1325 if ((mode = apply_args_mode[regno]) != VOIDmode)
1326 {
53800dbe 1327 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1328 if (size % align != 0)
1329 size = CEIL (size, align) * align;
1330
1331 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1332
e513d163 1333 emit_move_insn (adjust_address (registers, mode, size), tem);
53800dbe 1334 size += GET_MODE_SIZE (mode);
1335 }
1336
1337 /* Save the arg pointer to the block. */
1c7e61a7 1338 tem = copy_to_reg (virtual_incoming_args_rtx);
f083a92b 1339#ifdef STACK_GROWS_DOWNWARD
1c7e61a7 1340 /* We need the pointer as the caller actually passed them to us, not
9d4b544c 1341 as we might have pretended they were passed. Make sure it's a valid
1342 operand, as emit_move_insn isn't expected to handle a PLUS. */
1343 tem
1344 = force_operand (plus_constant (tem, current_function_pretend_args_size),
1345 NULL_RTX);
1c7e61a7 1346#endif
1347 emit_move_insn (adjust_address (registers, Pmode, 0), tem);
0862b7e9 1348
53800dbe 1349 size = GET_MODE_SIZE (Pmode);
1350
1351 /* Save the structure value address unless this is passed as an
1352 "invisible" first argument. */
45550790 1353 if (struct_incoming_value)
53800dbe 1354 {
e513d163 1355 emit_move_insn (adjust_address (registers, Pmode, size),
45550790 1356 copy_to_reg (struct_incoming_value));
53800dbe 1357 size += GET_MODE_SIZE (Pmode);
1358 }
1359
1360 /* Return the address of the block. */
1361 return copy_addr_to_reg (XEXP (registers, 0));
1362}
1363
1364/* __builtin_apply_args returns block of memory allocated on
1365 the stack into which is stored the arg pointer, structure
1366 value address, static chain, and all the registers that might
1367 possibly be used in performing a function call. The code is
1368 moved to the start of the function so the incoming values are
1369 saved. */
27d0c333 1370
53800dbe 1371static rtx
aecda0d6 1372expand_builtin_apply_args (void)
53800dbe 1373{
1374 /* Don't do __builtin_apply_args more than once in a function.
1375 Save the result of the first call and reuse it. */
1376 if (apply_args_value != 0)
1377 return apply_args_value;
1378 {
1379 /* When this function is called, it means that registers must be
1380 saved on entry to this function. So we migrate the
1381 call to the first insn of this function. */
1382 rtx temp;
1383 rtx seq;
1384
1385 start_sequence ();
1386 temp = expand_builtin_apply_args_1 ();
1387 seq = get_insns ();
1388 end_sequence ();
1389
1390 apply_args_value = temp;
1391
31d3e01c 1392 /* Put the insns after the NOTE that starts the function.
1393 If this is inside a start_sequence, make the outer-level insn
53800dbe 1394 chain current, so the code is placed at the start of the
1395 function. */
1396 push_topmost_sequence ();
0ec80471 1397 emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
53800dbe 1398 pop_topmost_sequence ();
1399 return temp;
1400 }
1401}
1402
1403/* Perform an untyped call and save the state required to perform an
1404 untyped return of whatever value was returned by the given function. */
1405
1406static rtx
aecda0d6 1407expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
53800dbe 1408{
1409 int size, align, regno;
1410 enum machine_mode mode;
2a631e19 1411 rtx incoming_args, result, reg, dest, src, call_insn;
53800dbe 1412 rtx old_stack_level = 0;
1413 rtx call_fusage = 0;
6812c89e 1414 rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
53800dbe 1415
85d654dd 1416 arguments = convert_memory_address (Pmode, arguments);
726ec87c 1417
53800dbe 1418 /* Create a block where the return registers can be saved. */
1419 result = assign_stack_local (BLKmode, apply_result_size (), -1);
1420
53800dbe 1421 /* Fetch the arg pointer from the ARGUMENTS block. */
1422 incoming_args = gen_reg_rtx (Pmode);
726ec87c 1423 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
53800dbe 1424#ifndef STACK_GROWS_DOWNWARD
ad99e708 1425 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1426 incoming_args, 0, OPTAB_LIB_WIDEN);
53800dbe 1427#endif
1428
04a46d40 1429 /* Push a new argument block and copy the arguments. Do not allow
1430 the (potential) memcpy call below to interfere with our stack
1431 manipulations. */
53800dbe 1432 do_pending_stack_adjust ();
04a46d40 1433 NO_DEFER_POP;
53800dbe 1434
2358393e 1435 /* Save the stack with nonlocal if available. */
53800dbe 1436#ifdef HAVE_save_stack_nonlocal
1437 if (HAVE_save_stack_nonlocal)
1438 emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
1439 else
1440#endif
1441 emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
1442
59647703 1443 /* Allocate a block of memory onto the stack and copy the memory
1444 arguments to the outgoing arguments address. */
1445 allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
1446 dest = virtual_outgoing_args_rtx;
1447#ifndef STACK_GROWS_DOWNWARD
1448 if (GET_CODE (argsize) == CONST_INT)
1449 dest = plus_constant (dest, -INTVAL (argsize));
1450 else
1451 dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1452#endif
2a631e19 1453 dest = gen_rtx_MEM (BLKmode, dest);
1454 set_mem_align (dest, PARM_BOUNDARY);
1455 src = gen_rtx_MEM (BLKmode, incoming_args);
1456 set_mem_align (src, PARM_BOUNDARY);
0378dbdc 1457 emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
53800dbe 1458
1459 /* Refer to the argument block. */
1460 apply_args_size ();
1461 arguments = gen_rtx_MEM (BLKmode, arguments);
2a631e19 1462 set_mem_align (arguments, PARM_BOUNDARY);
53800dbe 1463
1464 /* Walk past the arg-pointer and structure value address. */
1465 size = GET_MODE_SIZE (Pmode);
45550790 1466 if (struct_value)
53800dbe 1467 size += GET_MODE_SIZE (Pmode);
1468
1469 /* Restore each of the registers previously saved. Make USE insns
1470 for each of these registers for use in making the call. */
1471 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1472 if ((mode = apply_args_mode[regno]) != VOIDmode)
1473 {
1474 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1475 if (size % align != 0)
1476 size = CEIL (size, align) * align;
1477 reg = gen_rtx_REG (mode, regno);
e513d163 1478 emit_move_insn (reg, adjust_address (arguments, mode, size));
53800dbe 1479 use_reg (&call_fusage, reg);
1480 size += GET_MODE_SIZE (mode);
1481 }
1482
1483 /* Restore the structure value address unless this is passed as an
1484 "invisible" first argument. */
1485 size = GET_MODE_SIZE (Pmode);
45550790 1486 if (struct_value)
53800dbe 1487 {
1488 rtx value = gen_reg_rtx (Pmode);
e513d163 1489 emit_move_insn (value, adjust_address (arguments, Pmode, size));
45550790 1490 emit_move_insn (struct_value, value);
8ad4c111 1491 if (REG_P (struct_value))
45550790 1492 use_reg (&call_fusage, struct_value);
53800dbe 1493 size += GET_MODE_SIZE (Pmode);
1494 }
1495
1496 /* All arguments and registers used for the call are set up by now! */
4ee9c684 1497 function = prepare_call_address (function, NULL, &call_fusage, 0, 0);
53800dbe 1498
1499 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1500 and we don't want to load it into a register as an optimization,
1501 because prepare_call_address already did it if it should be done. */
1502 if (GET_CODE (function) != SYMBOL_REF)
1503 function = memory_address (FUNCTION_MODE, function);
1504
1505 /* Generate the actual call instruction and save the return value. */
1506#ifdef HAVE_untyped_call
1507 if (HAVE_untyped_call)
1508 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1509 result, result_vector (1, result)));
1510 else
1511#endif
1512#ifdef HAVE_call_value
1513 if (HAVE_call_value)
1514 {
1515 rtx valreg = 0;
1516
1517 /* Locate the unique return register. It is not possible to
1518 express a call that sets more than one return register using
1519 call_value; use untyped_call for that. In fact, untyped_call
1520 only needs to save the return registers in the given block. */
1521 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1522 if ((mode = apply_result_mode[regno]) != VOIDmode)
1523 {
64db345d 1524 gcc_assert (!valreg); /* HAVE_untyped_call required. */
7d3f6cc7 1525
53800dbe 1526 valreg = gen_rtx_REG (mode, regno);
1527 }
1528
2ed6c343 1529 emit_call_insn (GEN_CALL_VALUE (valreg,
53800dbe 1530 gen_rtx_MEM (FUNCTION_MODE, function),
1531 const0_rtx, NULL_RTX, const0_rtx));
1532
e513d163 1533 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
53800dbe 1534 }
1535 else
1536#endif
64db345d 1537 gcc_unreachable ();
53800dbe 1538
d5f9786f 1539 /* Find the CALL insn we just emitted, and attach the register usage
1540 information. */
1541 call_insn = last_call_insn ();
1542 add_function_usage_to (call_insn, call_fusage);
53800dbe 1543
1544 /* Restore the stack. */
1545#ifdef HAVE_save_stack_nonlocal
1546 if (HAVE_save_stack_nonlocal)
1547 emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1548 else
1549#endif
1550 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1551
04a46d40 1552 OK_DEFER_POP;
1553
53800dbe 1554 /* Return the address of the result block. */
85d654dd 1555 result = copy_addr_to_reg (XEXP (result, 0));
1556 return convert_memory_address (ptr_mode, result);
53800dbe 1557}
1558
1559/* Perform an untyped return. */
1560
1561static void
aecda0d6 1562expand_builtin_return (rtx result)
53800dbe 1563{
1564 int size, align, regno;
1565 enum machine_mode mode;
1566 rtx reg;
1567 rtx call_fusage = 0;
1568
85d654dd 1569 result = convert_memory_address (Pmode, result);
726ec87c 1570
53800dbe 1571 apply_result_size ();
1572 result = gen_rtx_MEM (BLKmode, result);
1573
1574#ifdef HAVE_untyped_return
1575 if (HAVE_untyped_return)
1576 {
1577 emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1578 emit_barrier ();
1579 return;
1580 }
1581#endif
1582
1583 /* Restore the return value and note that each value is used. */
1584 size = 0;
1585 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1586 if ((mode = apply_result_mode[regno]) != VOIDmode)
1587 {
1588 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1589 if (size % align != 0)
1590 size = CEIL (size, align) * align;
1591 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
e513d163 1592 emit_move_insn (reg, adjust_address (result, mode, size));
53800dbe 1593
1594 push_to_sequence (call_fusage);
1595 emit_insn (gen_rtx_USE (VOIDmode, reg));
1596 call_fusage = get_insns ();
1597 end_sequence ();
1598 size += GET_MODE_SIZE (mode);
1599 }
1600
1601 /* Put the USE insns before the return. */
31d3e01c 1602 emit_insn (call_fusage);
53800dbe 1603
1604 /* Return whatever values was restored by jumping directly to the end
1605 of the function. */
62380d2d 1606 expand_naked_return ();
53800dbe 1607}
1608
539a3a92 1609/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
27d0c333 1610
539a3a92 1611static enum type_class
aecda0d6 1612type_to_class (tree type)
539a3a92 1613{
1614 switch (TREE_CODE (type))
1615 {
1616 case VOID_TYPE: return void_type_class;
1617 case INTEGER_TYPE: return integer_type_class;
539a3a92 1618 case ENUMERAL_TYPE: return enumeral_type_class;
1619 case BOOLEAN_TYPE: return boolean_type_class;
1620 case POINTER_TYPE: return pointer_type_class;
1621 case REFERENCE_TYPE: return reference_type_class;
1622 case OFFSET_TYPE: return offset_type_class;
1623 case REAL_TYPE: return real_type_class;
1624 case COMPLEX_TYPE: return complex_type_class;
1625 case FUNCTION_TYPE: return function_type_class;
1626 case METHOD_TYPE: return method_type_class;
1627 case RECORD_TYPE: return record_type_class;
1628 case UNION_TYPE:
1629 case QUAL_UNION_TYPE: return union_type_class;
1630 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1631 ? string_type_class : array_type_class);
539a3a92 1632 case LANG_TYPE: return lang_type_class;
1633 default: return no_type_class;
1634 }
1635}
bf8e3599 1636
c2f47e15 1637/* Expand a call EXP to __builtin_classify_type. */
27d0c333 1638
53800dbe 1639static rtx
c2f47e15 1640expand_builtin_classify_type (tree exp)
53800dbe 1641{
c2f47e15 1642 if (call_expr_nargs (exp))
1643 return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0))));
53800dbe 1644 return GEN_INT (no_type_class);
1645}
1646
07976da7 1647/* This helper macro, meant to be used in mathfn_built_in below,
1648 determines which among a set of three builtin math functions is
1649 appropriate for a given type mode. The `F' and `L' cases are
1650 automatically generated from the `double' case. */
1651#define CASE_MATHFN(BUILT_IN_MATHFN) \
1652 case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1653 fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1654 fcodel = BUILT_IN_MATHFN##L ; break;
1655
1656/* Return mathematic function equivalent to FN but operating directly
1657 on TYPE, if available. If we can't do the conversion, return zero. */
0a68165a 1658tree
aecda0d6 1659mathfn_built_in (tree type, enum built_in_function fn)
0a68165a 1660{
07976da7 1661 enum built_in_function fcode, fcodef, fcodel;
1662
1663 switch (fn)
1664 {
746114e8 1665 CASE_MATHFN (BUILT_IN_ACOS)
1666 CASE_MATHFN (BUILT_IN_ACOSH)
1667 CASE_MATHFN (BUILT_IN_ASIN)
1668 CASE_MATHFN (BUILT_IN_ASINH)
07976da7 1669 CASE_MATHFN (BUILT_IN_ATAN)
746114e8 1670 CASE_MATHFN (BUILT_IN_ATAN2)
1671 CASE_MATHFN (BUILT_IN_ATANH)
1672 CASE_MATHFN (BUILT_IN_CBRT)
07976da7 1673 CASE_MATHFN (BUILT_IN_CEIL)
d735c391 1674 CASE_MATHFN (BUILT_IN_CEXPI)
746114e8 1675 CASE_MATHFN (BUILT_IN_COPYSIGN)
07976da7 1676 CASE_MATHFN (BUILT_IN_COS)
746114e8 1677 CASE_MATHFN (BUILT_IN_COSH)
1678 CASE_MATHFN (BUILT_IN_DREM)
1679 CASE_MATHFN (BUILT_IN_ERF)
1680 CASE_MATHFN (BUILT_IN_ERFC)
07976da7 1681 CASE_MATHFN (BUILT_IN_EXP)
746114e8 1682 CASE_MATHFN (BUILT_IN_EXP10)
1683 CASE_MATHFN (BUILT_IN_EXP2)
1684 CASE_MATHFN (BUILT_IN_EXPM1)
1685 CASE_MATHFN (BUILT_IN_FABS)
1686 CASE_MATHFN (BUILT_IN_FDIM)
07976da7 1687 CASE_MATHFN (BUILT_IN_FLOOR)
746114e8 1688 CASE_MATHFN (BUILT_IN_FMA)
1689 CASE_MATHFN (BUILT_IN_FMAX)
1690 CASE_MATHFN (BUILT_IN_FMIN)
1691 CASE_MATHFN (BUILT_IN_FMOD)
1692 CASE_MATHFN (BUILT_IN_FREXP)
1693 CASE_MATHFN (BUILT_IN_GAMMA)
1694 CASE_MATHFN (BUILT_IN_HUGE_VAL)
1695 CASE_MATHFN (BUILT_IN_HYPOT)
1696 CASE_MATHFN (BUILT_IN_ILOGB)
1697 CASE_MATHFN (BUILT_IN_INF)
69b779ea 1698 CASE_MATHFN (BUILT_IN_ISINF)
746114e8 1699 CASE_MATHFN (BUILT_IN_J0)
1700 CASE_MATHFN (BUILT_IN_J1)
1701 CASE_MATHFN (BUILT_IN_JN)
ac148751 1702 CASE_MATHFN (BUILT_IN_LCEIL)
746114e8 1703 CASE_MATHFN (BUILT_IN_LDEXP)
ad52b9b7 1704 CASE_MATHFN (BUILT_IN_LFLOOR)
746114e8 1705 CASE_MATHFN (BUILT_IN_LGAMMA)
ac148751 1706 CASE_MATHFN (BUILT_IN_LLCEIL)
ad52b9b7 1707 CASE_MATHFN (BUILT_IN_LLFLOOR)
746114e8 1708 CASE_MATHFN (BUILT_IN_LLRINT)
1709 CASE_MATHFN (BUILT_IN_LLROUND)
07976da7 1710 CASE_MATHFN (BUILT_IN_LOG)
746114e8 1711 CASE_MATHFN (BUILT_IN_LOG10)
1712 CASE_MATHFN (BUILT_IN_LOG1P)
1713 CASE_MATHFN (BUILT_IN_LOG2)
1714 CASE_MATHFN (BUILT_IN_LOGB)
1715 CASE_MATHFN (BUILT_IN_LRINT)
1716 CASE_MATHFN (BUILT_IN_LROUND)
1717 CASE_MATHFN (BUILT_IN_MODF)
1718 CASE_MATHFN (BUILT_IN_NAN)
1719 CASE_MATHFN (BUILT_IN_NANS)
07976da7 1720 CASE_MATHFN (BUILT_IN_NEARBYINT)
746114e8 1721 CASE_MATHFN (BUILT_IN_NEXTAFTER)
1722 CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1723 CASE_MATHFN (BUILT_IN_POW)
757c219d 1724 CASE_MATHFN (BUILT_IN_POWI)
746114e8 1725 CASE_MATHFN (BUILT_IN_POW10)
1726 CASE_MATHFN (BUILT_IN_REMAINDER)
1727 CASE_MATHFN (BUILT_IN_REMQUO)
1728 CASE_MATHFN (BUILT_IN_RINT)
07976da7 1729 CASE_MATHFN (BUILT_IN_ROUND)
746114e8 1730 CASE_MATHFN (BUILT_IN_SCALB)
1731 CASE_MATHFN (BUILT_IN_SCALBLN)
1732 CASE_MATHFN (BUILT_IN_SCALBN)
1733 CASE_MATHFN (BUILT_IN_SIGNIFICAND)
07976da7 1734 CASE_MATHFN (BUILT_IN_SIN)
746114e8 1735 CASE_MATHFN (BUILT_IN_SINCOS)
1736 CASE_MATHFN (BUILT_IN_SINH)
07976da7 1737 CASE_MATHFN (BUILT_IN_SQRT)
1738 CASE_MATHFN (BUILT_IN_TAN)
746114e8 1739 CASE_MATHFN (BUILT_IN_TANH)
1740 CASE_MATHFN (BUILT_IN_TGAMMA)
07976da7 1741 CASE_MATHFN (BUILT_IN_TRUNC)
746114e8 1742 CASE_MATHFN (BUILT_IN_Y0)
1743 CASE_MATHFN (BUILT_IN_Y1)
1744 CASE_MATHFN (BUILT_IN_YN)
07976da7 1745
0a68165a 1746 default:
c2f47e15 1747 return NULL_TREE;
0a68165a 1748 }
07976da7 1749
96b9f485 1750 if (TYPE_MAIN_VARIANT (type) == double_type_node)
07976da7 1751 return implicit_built_in_decls[fcode];
96b9f485 1752 else if (TYPE_MAIN_VARIANT (type) == float_type_node)
07976da7 1753 return implicit_built_in_decls[fcodef];
96b9f485 1754 else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
07976da7 1755 return implicit_built_in_decls[fcodel];
1756 else
c2f47e15 1757 return NULL_TREE;
0a68165a 1758}
1759
0fd605a5 1760/* If errno must be maintained, expand the RTL to check if the result,
1761 TARGET, of a built-in function call, EXP, is NaN, and if so set
1762 errno to EDOM. */
1763
1764static void
aecda0d6 1765expand_errno_check (tree exp, rtx target)
0fd605a5 1766{
7f05340e 1767 rtx lab = gen_label_rtx ();
0fd605a5 1768
7f05340e 1769 /* Test the result; if it is NaN, set errno=EDOM because
1770 the argument was not in the domain. */
1771 emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
1772 0, lab);
0fd605a5 1773
1774#ifdef TARGET_EDOM
7f05340e 1775 /* If this built-in doesn't throw an exception, set errno directly. */
c2f47e15 1776 if (TREE_NOTHROW (TREE_OPERAND (CALL_EXPR_FN (exp), 0)))
7f05340e 1777 {
0fd605a5 1778#ifdef GEN_ERRNO_RTX
7f05340e 1779 rtx errno_rtx = GEN_ERRNO_RTX;
0fd605a5 1780#else
7f05340e 1781 rtx errno_rtx
0fd605a5 1782 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1783#endif
7f05340e 1784 emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
0fd605a5 1785 emit_label (lab);
7f05340e 1786 return;
0fd605a5 1787 }
7f05340e 1788#endif
1789
1790 /* We can't set errno=EDOM directly; let the library call do it.
1791 Pop the arguments right away in case the call gets deleted. */
1792 NO_DEFER_POP;
1793 expand_call (exp, target, 0);
1794 OK_DEFER_POP;
1795 emit_label (lab);
0fd605a5 1796}
1797
6b43bae4 1798/* Expand a call to one of the builtin math functions (sqrt, exp, or log).
c2f47e15 1799 Return NULL_RTX if a normal call should be emitted rather than expanding
1800 the function in-line. EXP is the expression that is a call to the builtin
53800dbe 1801 function; if convenient, the result should be placed in TARGET.
1802 SUBTARGET may be used as the target for computing one of EXP's operands. */
27d0c333 1803
53800dbe 1804static rtx
aecda0d6 1805expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
53800dbe 1806{
bf8e3599 1807 optab builtin_optab;
bd421108 1808 rtx op0, insns, before_call;
c6e6ecb1 1809 tree fndecl = get_callee_fndecl (exp);
7f05340e 1810 enum machine_mode mode;
528ee710 1811 bool errno_set = false;
68e6cb9d 1812 tree arg, narg;
53800dbe 1813
c2f47e15 1814 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
1815 return NULL_RTX;
53800dbe 1816
c2f47e15 1817 arg = CALL_EXPR_ARG (exp, 0);
53800dbe 1818
1819 switch (DECL_FUNCTION_CODE (fndecl))
1820 {
4f35b1fc 1821 CASE_FLT_FN (BUILT_IN_SQRT):
7f05340e 1822 errno_set = ! tree_expr_nonnegative_p (arg);
1823 builtin_optab = sqrt_optab;
1824 break;
4f35b1fc 1825 CASE_FLT_FN (BUILT_IN_EXP):
528ee710 1826 errno_set = true; builtin_optab = exp_optab; break;
4f35b1fc 1827 CASE_FLT_FN (BUILT_IN_EXP10):
1828 CASE_FLT_FN (BUILT_IN_POW10):
750ef9f5 1829 errno_set = true; builtin_optab = exp10_optab; break;
4f35b1fc 1830 CASE_FLT_FN (BUILT_IN_EXP2):
750ef9f5 1831 errno_set = true; builtin_optab = exp2_optab; break;
4f35b1fc 1832 CASE_FLT_FN (BUILT_IN_EXPM1):
a6b4eed2 1833 errno_set = true; builtin_optab = expm1_optab; break;
4f35b1fc 1834 CASE_FLT_FN (BUILT_IN_LOGB):
4efbc641 1835 errno_set = true; builtin_optab = logb_optab; break;
4f35b1fc 1836 CASE_FLT_FN (BUILT_IN_LOG):
528ee710 1837 errno_set = true; builtin_optab = log_optab; break;
4f35b1fc 1838 CASE_FLT_FN (BUILT_IN_LOG10):
d3cd9bde 1839 errno_set = true; builtin_optab = log10_optab; break;
4f35b1fc 1840 CASE_FLT_FN (BUILT_IN_LOG2):
d3cd9bde 1841 errno_set = true; builtin_optab = log2_optab; break;
4f35b1fc 1842 CASE_FLT_FN (BUILT_IN_LOG1P):
f474cd93 1843 errno_set = true; builtin_optab = log1p_optab; break;
4f35b1fc 1844 CASE_FLT_FN (BUILT_IN_ASIN):
8de2f465 1845 builtin_optab = asin_optab; break;
4f35b1fc 1846 CASE_FLT_FN (BUILT_IN_ACOS):
8de2f465 1847 builtin_optab = acos_optab; break;
4f35b1fc 1848 CASE_FLT_FN (BUILT_IN_TAN):
528ee710 1849 builtin_optab = tan_optab; break;
4f35b1fc 1850 CASE_FLT_FN (BUILT_IN_ATAN):
528ee710 1851 builtin_optab = atan_optab; break;
4f35b1fc 1852 CASE_FLT_FN (BUILT_IN_FLOOR):
528ee710 1853 builtin_optab = floor_optab; break;
4f35b1fc 1854 CASE_FLT_FN (BUILT_IN_CEIL):
528ee710 1855 builtin_optab = ceil_optab; break;
4f35b1fc 1856 CASE_FLT_FN (BUILT_IN_TRUNC):
a7cc195f 1857 builtin_optab = btrunc_optab; break;
4f35b1fc 1858 CASE_FLT_FN (BUILT_IN_ROUND):
528ee710 1859 builtin_optab = round_optab; break;
4f35b1fc 1860 CASE_FLT_FN (BUILT_IN_NEARBYINT):
0ddf4ad9 1861 builtin_optab = nearbyint_optab;
1862 if (flag_trapping_math)
1863 break;
1864 /* Else fallthrough and expand as rint. */
4f35b1fc 1865 CASE_FLT_FN (BUILT_IN_RINT):
aef94a0f 1866 builtin_optab = rint_optab; break;
42721db0 1867 default:
64db345d 1868 gcc_unreachable ();
53800dbe 1869 }
1870
7f05340e 1871 /* Make a suitable register to place result in. */
1872 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 1873
7f05340e 1874 if (! flag_errno_math || ! HONOR_NANS (mode))
1875 errno_set = false;
1876
bd421108 1877 /* Before working hard, check whether the instruction is available. */
1878 if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
68e6cb9d 1879 {
bd421108 1880 target = gen_reg_rtx (mode);
7f05340e 1881
bd421108 1882 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
1883 need to expand the argument again. This way, we will not perform
1884 side-effects more the once. */
4ee9c684 1885 narg = builtin_save_expr (arg);
bd421108 1886 if (narg != arg)
1887 {
9a5acb98 1888 arg = narg;
c2f47e15 1889 exp = build_call_expr (fndecl, 1, arg);
bd421108 1890 }
7f05340e 1891
1db6d067 1892 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
7f05340e 1893
bd421108 1894 start_sequence ();
53800dbe 1895
bd421108 1896 /* Compute into TARGET.
1897 Set TARGET to wherever the result comes back. */
1898 target = expand_unop (mode, builtin_optab, op0, target, 0);
1899
1900 if (target != 0)
1901 {
1902 if (errno_set)
1903 expand_errno_check (exp, target);
1904
1905 /* Output the entire sequence. */
1906 insns = get_insns ();
1907 end_sequence ();
1908 emit_insn (insns);
1909 return target;
1910 }
1911
1912 /* If we were unable to expand via the builtin, stop the sequence
1913 (without outputting the insns) and call to the library function
1914 with the stabilized argument list. */
53800dbe 1915 end_sequence ();
53800dbe 1916 }
1917
bd421108 1918 before_call = get_last_insn ();
1919
1920 target = expand_call (exp, target, target == const0_rtx);
53800dbe 1921
bd421108 1922 /* If this is a sqrt operation and we don't care about errno, try to
1923 attach a REG_EQUAL note with a SQRT rtx to the emitted libcall.
1924 This allows the semantics of the libcall to be visible to the RTL
1925 optimizers. */
1926 if (builtin_optab == sqrt_optab && !errno_set)
1927 {
1928 /* Search backwards through the insns emitted by expand_call looking
1929 for the instruction with the REG_RETVAL note. */
1930 rtx last = get_last_insn ();
1931 while (last != before_call)
1932 {
1933 if (find_reg_note (last, REG_RETVAL, NULL))
1934 {
1935 rtx note = find_reg_note (last, REG_EQUAL, NULL);
1936 /* Check that the REQ_EQUAL note is an EXPR_LIST with
1937 two elements, i.e. symbol_ref(sqrt) and the operand. */
1938 if (note
1939 && GET_CODE (note) == EXPR_LIST
1940 && GET_CODE (XEXP (note, 0)) == EXPR_LIST
1941 && XEXP (XEXP (note, 0), 1) != NULL_RTX
1942 && XEXP (XEXP (XEXP (note, 0), 1), 1) == NULL_RTX)
1943 {
1944 rtx operand = XEXP (XEXP (XEXP (note, 0), 1), 0);
1945 /* Check operand is a register with expected mode. */
1946 if (operand
8ad4c111 1947 && REG_P (operand)
bd421108 1948 && GET_MODE (operand) == mode)
1949 {
1950 /* Replace the REG_EQUAL note with a SQRT rtx. */
1951 rtx equiv = gen_rtx_SQRT (mode, operand);
1952 set_unique_reg_note (last, REG_EQUAL, equiv);
1953 }
1954 }
1955 break;
1956 }
1957 last = PREV_INSN (last);
1958 }
1959 }
0fd605a5 1960
1961 return target;
1962}
1963
1964/* Expand a call to the builtin binary math functions (pow and atan2).
c2f47e15 1965 Return NULL_RTX if a normal call should be emitted rather than expanding the
0fd605a5 1966 function in-line. EXP is the expression that is a call to the builtin
1967 function; if convenient, the result should be placed in TARGET.
1968 SUBTARGET may be used as the target for computing one of EXP's
1969 operands. */
1970
1971static rtx
aecda0d6 1972expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
0fd605a5 1973{
1974 optab builtin_optab;
1975 rtx op0, op1, insns;
4737caf2 1976 int op1_type = REAL_TYPE;
c6e6ecb1 1977 tree fndecl = get_callee_fndecl (exp);
c2f47e15 1978 tree arg0, arg1, narg;
7f05340e 1979 enum machine_mode mode;
0fd605a5 1980 bool errno_set = true;
1981 bool stable = true;
1982
73a954a1 1983 switch (DECL_FUNCTION_CODE (fndecl))
1984 {
1985 CASE_FLT_FN (BUILT_IN_SCALBN):
1986 CASE_FLT_FN (BUILT_IN_SCALBLN):
1987 CASE_FLT_FN (BUILT_IN_LDEXP):
1988 op1_type = INTEGER_TYPE;
1989 default:
1990 break;
1991 }
4737caf2 1992
c2f47e15 1993 if (!validate_arglist (exp, REAL_TYPE, op1_type, VOID_TYPE))
1994 return NULL_RTX;
0fd605a5 1995
c2f47e15 1996 arg0 = CALL_EXPR_ARG (exp, 0);
1997 arg1 = CALL_EXPR_ARG (exp, 1);
0fd605a5 1998
0fd605a5 1999 switch (DECL_FUNCTION_CODE (fndecl))
2000 {
4f35b1fc 2001 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 2002 builtin_optab = pow_optab; break;
4f35b1fc 2003 CASE_FLT_FN (BUILT_IN_ATAN2):
0fd605a5 2004 builtin_optab = atan2_optab; break;
73a954a1 2005 CASE_FLT_FN (BUILT_IN_SCALB):
2006 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2007 return 0;
2008 builtin_optab = scalb_optab; break;
2009 CASE_FLT_FN (BUILT_IN_SCALBN):
2010 CASE_FLT_FN (BUILT_IN_SCALBLN):
2011 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2012 return 0;
2013 /* Fall through... */
4f35b1fc 2014 CASE_FLT_FN (BUILT_IN_LDEXP):
4737caf2 2015 builtin_optab = ldexp_optab; break;
4f35b1fc 2016 CASE_FLT_FN (BUILT_IN_FMOD):
80ed5c06 2017 builtin_optab = fmod_optab; break;
ef722005 2018 CASE_FLT_FN (BUILT_IN_REMAINDER):
4f35b1fc 2019 CASE_FLT_FN (BUILT_IN_DREM):
ef722005 2020 builtin_optab = remainder_optab; break;
0fd605a5 2021 default:
64db345d 2022 gcc_unreachable ();
0fd605a5 2023 }
2024
7f05340e 2025 /* Make a suitable register to place result in. */
2026 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2027
2028 /* Before working hard, check whether the instruction is available. */
2029 if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
c2f47e15 2030 return NULL_RTX;
fc4eef90 2031
7f05340e 2032 target = gen_reg_rtx (mode);
2033
2034 if (! flag_errno_math || ! HONOR_NANS (mode))
2035 errno_set = false;
2036
4ee9c684 2037 /* Always stabilize the argument list. */
2038 narg = builtin_save_expr (arg1);
68e6cb9d 2039 if (narg != arg1)
7f05340e 2040 {
9a5acb98 2041 arg1 = narg;
68e6cb9d 2042 stable = false;
2043 }
4ee9c684 2044 narg = builtin_save_expr (arg0);
68e6cb9d 2045 if (narg != arg0)
2046 {
9a5acb98 2047 arg0 = narg;
68e6cb9d 2048 stable = false;
7f05340e 2049 }
68e6cb9d 2050
2051 if (! stable)
c2f47e15 2052 exp = build_call_expr (fndecl, 2, arg0, arg1);
7f05340e 2053
8ec3c5c2 2054 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2055 op1 = expand_normal (arg1);
7f05340e 2056
7f05340e 2057 start_sequence ();
2058
0fd605a5 2059 /* Compute into TARGET.
2060 Set TARGET to wherever the result comes back. */
7f05340e 2061 target = expand_binop (mode, builtin_optab, op0, op1,
0fd605a5 2062 target, 0, OPTAB_DIRECT);
53800dbe 2063
68e6cb9d 2064 /* If we were unable to expand via the builtin, stop the sequence
2065 (without outputting the insns) and call to the library function
2066 with the stabilized argument list. */
0fd605a5 2067 if (target == 0)
2068 {
2069 end_sequence ();
68e6cb9d 2070 return expand_call (exp, target, target == const0_rtx);
53800dbe 2071 }
2072
a4356fb9 2073 if (errno_set)
2074 expand_errno_check (exp, target);
0fd605a5 2075
53800dbe 2076 /* Output the entire sequence. */
2077 insns = get_insns ();
2078 end_sequence ();
31d3e01c 2079 emit_insn (insns);
bf8e3599 2080
53800dbe 2081 return target;
2082}
2083
6b43bae4 2084/* Expand a call to the builtin sin and cos math functions.
c2f47e15 2085 Return NULL_RTX if a normal call should be emitted rather than expanding the
6b43bae4 2086 function in-line. EXP is the expression that is a call to the builtin
2087 function; if convenient, the result should be placed in TARGET.
2088 SUBTARGET may be used as the target for computing one of EXP's
2089 operands. */
2090
2091static rtx
2092expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
2093{
2094 optab builtin_optab;
7511b819 2095 rtx op0, insns;
6b43bae4 2096 tree fndecl = get_callee_fndecl (exp);
6b43bae4 2097 enum machine_mode mode;
6b43bae4 2098 tree arg, narg;
2099
c2f47e15 2100 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2101 return NULL_RTX;
6b43bae4 2102
c2f47e15 2103 arg = CALL_EXPR_ARG (exp, 0);
6b43bae4 2104
2105 switch (DECL_FUNCTION_CODE (fndecl))
2106 {
4f35b1fc 2107 CASE_FLT_FN (BUILT_IN_SIN):
2108 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2109 builtin_optab = sincos_optab; break;
2110 default:
64db345d 2111 gcc_unreachable ();
6b43bae4 2112 }
2113
2114 /* Make a suitable register to place result in. */
2115 mode = TYPE_MODE (TREE_TYPE (exp));
2116
6b43bae4 2117 /* Check if sincos insn is available, otherwise fallback
0bed3869 2118 to sin or cos insn. */
7d4c98bc 2119 if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
6b43bae4 2120 switch (DECL_FUNCTION_CODE (fndecl))
2121 {
4f35b1fc 2122 CASE_FLT_FN (BUILT_IN_SIN):
6b43bae4 2123 builtin_optab = sin_optab; break;
4f35b1fc 2124 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2125 builtin_optab = cos_optab; break;
2126 default:
64db345d 2127 gcc_unreachable ();
6b43bae4 2128 }
6b43bae4 2129
2130 /* Before working hard, check whether the instruction is available. */
2131 if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2132 {
2133 target = gen_reg_rtx (mode);
2134
2135 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2136 need to expand the argument again. This way, we will not perform
2137 side-effects more the once. */
2138 narg = save_expr (arg);
2139 if (narg != arg)
2140 {
9a5acb98 2141 arg = narg;
c2f47e15 2142 exp = build_call_expr (fndecl, 1, arg);
6b43bae4 2143 }
2144
1db6d067 2145 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
6b43bae4 2146
6b43bae4 2147 start_sequence ();
2148
2149 /* Compute into TARGET.
2150 Set TARGET to wherever the result comes back. */
2151 if (builtin_optab == sincos_optab)
2152 {
64db345d 2153 int result;
7d3f6cc7 2154
6b43bae4 2155 switch (DECL_FUNCTION_CODE (fndecl))
2156 {
4f35b1fc 2157 CASE_FLT_FN (BUILT_IN_SIN):
64db345d 2158 result = expand_twoval_unop (builtin_optab, op0, 0, target, 0);
6b43bae4 2159 break;
4f35b1fc 2160 CASE_FLT_FN (BUILT_IN_COS):
64db345d 2161 result = expand_twoval_unop (builtin_optab, op0, target, 0, 0);
6b43bae4 2162 break;
2163 default:
64db345d 2164 gcc_unreachable ();
6b43bae4 2165 }
64db345d 2166 gcc_assert (result);
6b43bae4 2167 }
2168 else
2169 {
2170 target = expand_unop (mode, builtin_optab, op0, target, 0);
2171 }
2172
2173 if (target != 0)
2174 {
6b43bae4 2175 /* Output the entire sequence. */
2176 insns = get_insns ();
2177 end_sequence ();
2178 emit_insn (insns);
2179 return target;
2180 }
2181
2182 /* If we were unable to expand via the builtin, stop the sequence
2183 (without outputting the insns) and call to the library function
2184 with the stabilized argument list. */
2185 end_sequence ();
2186 }
2187
6b43bae4 2188 target = expand_call (exp, target, target == const0_rtx);
2189
2190 return target;
2191}
2192
a67a90e5 2193/* Expand a call to one of the builtin math functions that operate on
2194 floating point argument and output an integer result (ilogb, isinf,
2195 isnan, etc).
2196 Return 0 if a normal call should be emitted rather than expanding the
2197 function in-line. EXP is the expression that is a call to the builtin
2198 function; if convenient, the result should be placed in TARGET.
2199 SUBTARGET may be used as the target for computing one of EXP's operands. */
2200
2201static rtx
2202expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
2203{
2204 optab builtin_optab;
2205 enum insn_code icode;
2206 rtx op0;
2207 tree fndecl = get_callee_fndecl (exp);
a67a90e5 2208 enum machine_mode mode;
2209 bool errno_set = false;
2210 tree arg, narg;
2211
c2f47e15 2212 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2213 return NULL_RTX;
a67a90e5 2214
c2f47e15 2215 arg = CALL_EXPR_ARG (exp, 0);
a67a90e5 2216
2217 switch (DECL_FUNCTION_CODE (fndecl))
2218 {
2219 CASE_FLT_FN (BUILT_IN_ILOGB):
2220 errno_set = true; builtin_optab = ilogb_optab; break;
69b779ea 2221 CASE_FLT_FN (BUILT_IN_ISINF):
2222 builtin_optab = isinf_optab; break;
a67a90e5 2223 default:
2224 gcc_unreachable ();
2225 }
2226
2227 /* There's no easy way to detect the case we need to set EDOM. */
2228 if (flag_errno_math && errno_set)
2229 return NULL_RTX;
2230
2231 /* Optab mode depends on the mode of the input argument. */
2232 mode = TYPE_MODE (TREE_TYPE (arg));
2233
2234 icode = builtin_optab->handlers[(int) mode].insn_code;
2235
2236 /* Before working hard, check whether the instruction is available. */
2237 if (icode != CODE_FOR_nothing)
2238 {
2239 /* Make a suitable register to place result in. */
2240 if (!target
2241 || GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
2242 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
2243
2244 gcc_assert (insn_data[icode].operand[0].predicate
2245 (target, GET_MODE (target)));
2246
2247 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2248 need to expand the argument again. This way, we will not perform
2249 side-effects more the once. */
2250 narg = builtin_save_expr (arg);
2251 if (narg != arg)
2252 {
2253 arg = narg;
c2f47e15 2254 exp = build_call_expr (fndecl, 1, arg);
a67a90e5 2255 }
2256
1db6d067 2257 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
a67a90e5 2258
2259 if (mode != GET_MODE (op0))
2260 op0 = convert_to_mode (mode, op0, 0);
2261
2262 /* Compute into TARGET.
2263 Set TARGET to wherever the result comes back. */
2264 emit_unop_insn (icode, target, op0, UNKNOWN);
2265 return target;
2266 }
2267
2268 target = expand_call (exp, target, target == const0_rtx);
2269
2270 return target;
2271}
2272
c3147c1a 2273/* Expand a call to the builtin sincos math function.
c2f47e15 2274 Return NULL_RTX if a normal call should be emitted rather than expanding the
c3147c1a 2275 function in-line. EXP is the expression that is a call to the builtin
2276 function. */
2277
2278static rtx
2279expand_builtin_sincos (tree exp)
2280{
2281 rtx op0, op1, op2, target1, target2;
c3147c1a 2282 enum machine_mode mode;
2283 tree arg, sinp, cosp;
2284 int result;
2285
c2f47e15 2286 if (!validate_arglist (exp, REAL_TYPE,
2287 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2288 return NULL_RTX;
c3147c1a 2289
c2f47e15 2290 arg = CALL_EXPR_ARG (exp, 0);
2291 sinp = CALL_EXPR_ARG (exp, 1);
2292 cosp = CALL_EXPR_ARG (exp, 2);
c3147c1a 2293
2294 /* Make a suitable register to place result in. */
2295 mode = TYPE_MODE (TREE_TYPE (arg));
2296
2297 /* Check if sincos insn is available, otherwise emit the call. */
2298 if (sincos_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
2299 return NULL_RTX;
2300
2301 target1 = gen_reg_rtx (mode);
2302 target2 = gen_reg_rtx (mode);
2303
8ec3c5c2 2304 op0 = expand_normal (arg);
2305 op1 = expand_normal (build_fold_indirect_ref (sinp));
2306 op2 = expand_normal (build_fold_indirect_ref (cosp));
c3147c1a 2307
2308 /* Compute into target1 and target2.
2309 Set TARGET to wherever the result comes back. */
2310 result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
2311 gcc_assert (result);
2312
2313 /* Move target1 and target2 to the memory locations indicated
2314 by op1 and op2. */
2315 emit_move_insn (op1, target1);
2316 emit_move_insn (op2, target2);
2317
2318 return const0_rtx;
2319}
2320
d735c391 2321/* Expand a call to the internal cexpi builtin to the sincos math function.
2322 EXP is the expression that is a call to the builtin function; if convenient,
2323 the result should be placed in TARGET. SUBTARGET may be used as the target
2324 for computing one of EXP's operands. */
2325
2326static rtx
2327expand_builtin_cexpi (tree exp, rtx target, rtx subtarget)
2328{
2329 tree fndecl = get_callee_fndecl (exp);
d735c391 2330 tree arg, type;
c2f47e15 2331 enum machine_mode mode;
d735c391 2332 rtx op0, op1, op2;
2333
c2f47e15 2334 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2335 return NULL_RTX;
d735c391 2336
c2f47e15 2337 arg = CALL_EXPR_ARG (exp, 0);
d735c391 2338 type = TREE_TYPE (arg);
2339 mode = TYPE_MODE (TREE_TYPE (arg));
2340
2341 /* Try expanding via a sincos optab, fall back to emitting a libcall
18b8d8ae 2342 to sincos or cexp. We are sure we have sincos or cexp because cexpi
2343 is only generated from sincos, cexp or if we have either of them. */
d735c391 2344 if (sincos_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2345 {
2346 op1 = gen_reg_rtx (mode);
2347 op2 = gen_reg_rtx (mode);
2348
1db6d067 2349 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
d735c391 2350
2351 /* Compute into op1 and op2. */
2352 expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
2353 }
18b8d8ae 2354 else if (TARGET_HAS_SINCOS)
d735c391 2355 {
c2f47e15 2356 tree call, fn = NULL_TREE;
d735c391 2357 tree top1, top2;
2358 rtx op1a, op2a;
2359
2360 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2361 fn = built_in_decls[BUILT_IN_SINCOSF];
2362 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2363 fn = built_in_decls[BUILT_IN_SINCOS];
2364 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2365 fn = built_in_decls[BUILT_IN_SINCOSL];
c2f47e15 2366 else
2367 gcc_unreachable ();
d735c391 2368
2369 op1 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
2370 op2 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
2371 op1a = copy_to_mode_reg (Pmode, XEXP (op1, 0));
2372 op2a = copy_to_mode_reg (Pmode, XEXP (op2, 0));
2373 top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
2374 top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
2375
d735c391 2376 /* Make sure not to fold the sincos call again. */
2377 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
c2f47e15 2378 expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
2379 call, 3, arg, top1, top2));
d735c391 2380 }
18b8d8ae 2381 else
2382 {
0ecbc158 2383 tree call, fn = NULL_TREE, narg;
18b8d8ae 2384 tree ctype = build_complex_type (type);
2385
0ecbc158 2386 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2387 fn = built_in_decls[BUILT_IN_CEXPF];
2388 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2389 fn = built_in_decls[BUILT_IN_CEXP];
2390 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2391 fn = built_in_decls[BUILT_IN_CEXPL];
c2f47e15 2392 else
2393 gcc_unreachable ();
fc0dfa6e 2394
2395 /* If we don't have a decl for cexp create one. This is the
2396 friendliest fallback if the user calls __builtin_cexpi
2397 without full target C99 function support. */
2398 if (fn == NULL_TREE)
2399 {
2400 tree fntype;
2401 const char *name = NULL;
2402
2403 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2404 name = "cexpf";
2405 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2406 name = "cexp";
2407 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2408 name = "cexpl";
2409
2410 fntype = build_function_type_list (ctype, ctype, NULL_TREE);
2411 fn = build_fn_decl (name, fntype);
2412 }
2413
18b8d8ae 2414 narg = fold_build2 (COMPLEX_EXPR, ctype,
2415 build_real (type, dconst0), arg);
2416
2417 /* Make sure not to fold the cexp call again. */
2418 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
3737e769 2419 return expand_expr (build_call_nary (ctype, call, 1, narg),
1db6d067 2420 target, VOIDmode, EXPAND_NORMAL);
18b8d8ae 2421 }
d735c391 2422
2423 /* Now build the proper return type. */
2424 return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
2425 make_tree (TREE_TYPE (arg), op2),
2426 make_tree (TREE_TYPE (arg), op1)),
1db6d067 2427 target, VOIDmode, EXPAND_NORMAL);
d735c391 2428}
2429
7d3afc77 2430/* Expand a call to one of the builtin rounding functions gcc defines
2431 as an extension (lfloor and lceil). As these are gcc extensions we
2432 do not need to worry about setting errno to EDOM.
ad52b9b7 2433 If expanding via optab fails, lower expression to (int)(floor(x)).
2434 EXP is the expression that is a call to the builtin function;
2435 if convenient, the result should be placed in TARGET. SUBTARGET may
2436 be used as the target for computing one of EXP's operands. */
2437
2438static rtx
2439expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget)
2440{
9c42dd28 2441 convert_optab builtin_optab;
ad52b9b7 2442 rtx op0, insns, tmp;
2443 tree fndecl = get_callee_fndecl (exp);
ad52b9b7 2444 enum built_in_function fallback_fn;
2445 tree fallback_fndecl;
2446 enum machine_mode mode;
2447 tree arg, narg;
2448
c2f47e15 2449 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
ad52b9b7 2450 gcc_unreachable ();
2451
c2f47e15 2452 arg = CALL_EXPR_ARG (exp, 0);
ad52b9b7 2453
2454 switch (DECL_FUNCTION_CODE (fndecl))
2455 {
4f35b1fc 2456 CASE_FLT_FN (BUILT_IN_LCEIL):
2457 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 2458 builtin_optab = lceil_optab;
2459 fallback_fn = BUILT_IN_CEIL;
2460 break;
2461
4f35b1fc 2462 CASE_FLT_FN (BUILT_IN_LFLOOR):
2463 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 2464 builtin_optab = lfloor_optab;
2465 fallback_fn = BUILT_IN_FLOOR;
2466 break;
2467
2468 default:
2469 gcc_unreachable ();
2470 }
2471
2472 /* Make a suitable register to place result in. */
2473 mode = TYPE_MODE (TREE_TYPE (exp));
2474
9c42dd28 2475 target = gen_reg_rtx (mode);
ad52b9b7 2476
9c42dd28 2477 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2478 need to expand the argument again. This way, we will not perform
2479 side-effects more the once. */
2480 narg = builtin_save_expr (arg);
2481 if (narg != arg)
2482 {
2483 arg = narg;
c2f47e15 2484 exp = build_call_expr (fndecl, 1, arg);
9c42dd28 2485 }
ad52b9b7 2486
1db6d067 2487 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
ad52b9b7 2488
9c42dd28 2489 start_sequence ();
ad52b9b7 2490
9c42dd28 2491 /* Compute into TARGET. */
2492 if (expand_sfix_optab (target, op0, builtin_optab))
2493 {
2494 /* Output the entire sequence. */
2495 insns = get_insns ();
ad52b9b7 2496 end_sequence ();
9c42dd28 2497 emit_insn (insns);
2498 return target;
ad52b9b7 2499 }
2500
9c42dd28 2501 /* If we were unable to expand via the builtin, stop the sequence
2502 (without outputting the insns). */
2503 end_sequence ();
2504
ad52b9b7 2505 /* Fall back to floating point rounding optab. */
2506 fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
fc0dfa6e 2507
2508 /* For non-C99 targets we may end up without a fallback fndecl here
2509 if the user called __builtin_lfloor directly. In this case emit
2510 a call to the floor/ceil variants nevertheless. This should result
2511 in the best user experience for not full C99 targets. */
2512 if (fallback_fndecl == NULL_TREE)
2513 {
2514 tree fntype;
2515 const char *name = NULL;
2516
2517 switch (DECL_FUNCTION_CODE (fndecl))
2518 {
2519 case BUILT_IN_LCEIL:
2520 case BUILT_IN_LLCEIL:
2521 name = "ceil";
2522 break;
2523 case BUILT_IN_LCEILF:
2524 case BUILT_IN_LLCEILF:
2525 name = "ceilf";
2526 break;
2527 case BUILT_IN_LCEILL:
2528 case BUILT_IN_LLCEILL:
2529 name = "ceill";
2530 break;
2531 case BUILT_IN_LFLOOR:
2532 case BUILT_IN_LLFLOOR:
2533 name = "floor";
2534 break;
2535 case BUILT_IN_LFLOORF:
2536 case BUILT_IN_LLFLOORF:
2537 name = "floorf";
2538 break;
2539 case BUILT_IN_LFLOORL:
2540 case BUILT_IN_LLFLOORL:
2541 name = "floorl";
2542 break;
2543 default:
2544 gcc_unreachable ();
2545 }
2546
2547 fntype = build_function_type_list (TREE_TYPE (arg),
2548 TREE_TYPE (arg), NULL_TREE);
2549 fallback_fndecl = build_fn_decl (name, fntype);
2550 }
2551
c2f47e15 2552 exp = build_call_expr (fallback_fndecl, 1, arg);
ad52b9b7 2553
d4c690af 2554 tmp = expand_normal (exp);
ad52b9b7 2555
2556 /* Truncate the result of floating point optab to integer
2557 via expand_fix (). */
2558 target = gen_reg_rtx (mode);
2559 expand_fix (target, tmp, 0);
2560
2561 return target;
2562}
2563
7d3afc77 2564/* Expand a call to one of the builtin math functions doing integer
2565 conversion (lrint).
2566 Return 0 if a normal call should be emitted rather than expanding the
2567 function in-line. EXP is the expression that is a call to the builtin
2568 function; if convenient, the result should be placed in TARGET.
2569 SUBTARGET may be used as the target for computing one of EXP's operands. */
2570
2571static rtx
2572expand_builtin_int_roundingfn_2 (tree exp, rtx target, rtx subtarget)
2573{
5f51ee59 2574 convert_optab builtin_optab;
7d3afc77 2575 rtx op0, insns;
2576 tree fndecl = get_callee_fndecl (exp);
7d3afc77 2577 tree arg, narg;
c2f47e15 2578 enum machine_mode mode;
7d3afc77 2579
2580 /* There's no easy way to detect the case we need to set EDOM. */
2581 if (flag_errno_math)
2582 return NULL_RTX;
2583
c2f47e15 2584 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2585 gcc_unreachable ();
2586
2587 arg = CALL_EXPR_ARG (exp, 0);
7d3afc77 2588
2589 switch (DECL_FUNCTION_CODE (fndecl))
2590 {
2591 CASE_FLT_FN (BUILT_IN_LRINT):
2592 CASE_FLT_FN (BUILT_IN_LLRINT):
2593 builtin_optab = lrint_optab; break;
ef2f1a10 2594 CASE_FLT_FN (BUILT_IN_LROUND):
2595 CASE_FLT_FN (BUILT_IN_LLROUND):
2596 builtin_optab = lround_optab; break;
7d3afc77 2597 default:
2598 gcc_unreachable ();
2599 }
2600
2601 /* Make a suitable register to place result in. */
2602 mode = TYPE_MODE (TREE_TYPE (exp));
2603
5f51ee59 2604 target = gen_reg_rtx (mode);
7d3afc77 2605
5f51ee59 2606 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2607 need to expand the argument again. This way, we will not perform
2608 side-effects more the once. */
2609 narg = builtin_save_expr (arg);
2610 if (narg != arg)
2611 {
2612 arg = narg;
c2f47e15 2613 exp = build_call_expr (fndecl, 1, arg);
5f51ee59 2614 }
7d3afc77 2615
1db6d067 2616 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
7d3afc77 2617
5f51ee59 2618 start_sequence ();
7d3afc77 2619
5f51ee59 2620 if (expand_sfix_optab (target, op0, builtin_optab))
2621 {
2622 /* Output the entire sequence. */
2623 insns = get_insns ();
7d3afc77 2624 end_sequence ();
5f51ee59 2625 emit_insn (insns);
2626 return target;
7d3afc77 2627 }
2628
5f51ee59 2629 /* If we were unable to expand via the builtin, stop the sequence
2630 (without outputting the insns) and call to the library function
2631 with the stabilized argument list. */
2632 end_sequence ();
2633
7d3afc77 2634 target = expand_call (exp, target, target == const0_rtx);
2635
2636 return target;
2637}
2638
f1b844c6 2639/* To evaluate powi(x,n), the floating point value x raised to the
2640 constant integer exponent n, we use a hybrid algorithm that
2641 combines the "window method" with look-up tables. For an
2642 introduction to exponentiation algorithms and "addition chains",
2643 see section 4.6.3, "Evaluation of Powers" of Donald E. Knuth,
2644 "Seminumerical Algorithms", Vol. 2, "The Art of Computer Programming",
2645 3rd Edition, 1998, and Daniel M. Gordon, "A Survey of Fast Exponentiation
2646 Methods", Journal of Algorithms, Vol. 27, pp. 129-146, 1998. */
2647
2648/* Provide a default value for POWI_MAX_MULTS, the maximum number of
2649 multiplications to inline before calling the system library's pow
2650 function. powi(x,n) requires at worst 2*bits(n)-2 multiplications,
2651 so this default never requires calling pow, powf or powl. */
0862b7e9 2652
f1b844c6 2653#ifndef POWI_MAX_MULTS
2654#define POWI_MAX_MULTS (2*HOST_BITS_PER_WIDE_INT-2)
2655#endif
2656
2657/* The size of the "optimal power tree" lookup table. All
2658 exponents less than this value are simply looked up in the
2659 powi_table below. This threshold is also used to size the
2660 cache of pseudo registers that hold intermediate results. */
2661#define POWI_TABLE_SIZE 256
2662
2663/* The size, in bits of the window, used in the "window method"
2664 exponentiation algorithm. This is equivalent to a radix of
2665 (1<<POWI_WINDOW_SIZE) in the corresponding "m-ary method". */
2666#define POWI_WINDOW_SIZE 3
2667
2668/* The following table is an efficient representation of an
2669 "optimal power tree". For each value, i, the corresponding
2670 value, j, in the table states than an optimal evaluation
2671 sequence for calculating pow(x,i) can be found by evaluating
2672 pow(x,j)*pow(x,i-j). An optimal power tree for the first
2673 100 integers is given in Knuth's "Seminumerical algorithms". */
2674
2675static const unsigned char powi_table[POWI_TABLE_SIZE] =
2676 {
2677 0, 1, 1, 2, 2, 3, 3, 4, /* 0 - 7 */
2678 4, 6, 5, 6, 6, 10, 7, 9, /* 8 - 15 */
2679 8, 16, 9, 16, 10, 12, 11, 13, /* 16 - 23 */
2680 12, 17, 13, 18, 14, 24, 15, 26, /* 24 - 31 */
2681 16, 17, 17, 19, 18, 33, 19, 26, /* 32 - 39 */
2682 20, 25, 21, 40, 22, 27, 23, 44, /* 40 - 47 */
2683 24, 32, 25, 34, 26, 29, 27, 44, /* 48 - 55 */
2684 28, 31, 29, 34, 30, 60, 31, 36, /* 56 - 63 */
2685 32, 64, 33, 34, 34, 46, 35, 37, /* 64 - 71 */
2686 36, 65, 37, 50, 38, 48, 39, 69, /* 72 - 79 */
2687 40, 49, 41, 43, 42, 51, 43, 58, /* 80 - 87 */
2688 44, 64, 45, 47, 46, 59, 47, 76, /* 88 - 95 */
2689 48, 65, 49, 66, 50, 67, 51, 66, /* 96 - 103 */
2690 52, 70, 53, 74, 54, 104, 55, 74, /* 104 - 111 */
2691 56, 64, 57, 69, 58, 78, 59, 68, /* 112 - 119 */
2692 60, 61, 61, 80, 62, 75, 63, 68, /* 120 - 127 */
2693 64, 65, 65, 128, 66, 129, 67, 90, /* 128 - 135 */
2694 68, 73, 69, 131, 70, 94, 71, 88, /* 136 - 143 */
2695 72, 128, 73, 98, 74, 132, 75, 121, /* 144 - 151 */
2696 76, 102, 77, 124, 78, 132, 79, 106, /* 152 - 159 */
2697 80, 97, 81, 160, 82, 99, 83, 134, /* 160 - 167 */
2698 84, 86, 85, 95, 86, 160, 87, 100, /* 168 - 175 */
2699 88, 113, 89, 98, 90, 107, 91, 122, /* 176 - 183 */
2700 92, 111, 93, 102, 94, 126, 95, 150, /* 184 - 191 */
2701 96, 128, 97, 130, 98, 133, 99, 195, /* 192 - 199 */
2702 100, 128, 101, 123, 102, 164, 103, 138, /* 200 - 207 */
2703 104, 145, 105, 146, 106, 109, 107, 149, /* 208 - 215 */
2704 108, 200, 109, 146, 110, 170, 111, 157, /* 216 - 223 */
2705 112, 128, 113, 130, 114, 182, 115, 132, /* 224 - 231 */
2706 116, 200, 117, 132, 118, 158, 119, 206, /* 232 - 239 */
2707 120, 240, 121, 162, 122, 147, 123, 152, /* 240 - 247 */
2708 124, 166, 125, 214, 126, 138, 127, 153, /* 248 - 255 */
2709 };
2710
2711
2712/* Return the number of multiplications required to calculate
2713 powi(x,n) where n is less than POWI_TABLE_SIZE. This is a
2714 subroutine of powi_cost. CACHE is an array indicating
2715 which exponents have already been calculated. */
2716
2717static int
2718powi_lookup_cost (unsigned HOST_WIDE_INT n, bool *cache)
2719{
2720 /* If we've already calculated this exponent, then this evaluation
2721 doesn't require any additional multiplications. */
2722 if (cache[n])
2723 return 0;
2724
2725 cache[n] = true;
2726 return powi_lookup_cost (n - powi_table[n], cache)
2727 + powi_lookup_cost (powi_table[n], cache) + 1;
2728}
2729
2730/* Return the number of multiplications required to calculate
2731 powi(x,n) for an arbitrary x, given the exponent N. This
2732 function needs to be kept in sync with expand_powi below. */
2733
2734static int
2735powi_cost (HOST_WIDE_INT n)
2736{
2737 bool cache[POWI_TABLE_SIZE];
2738 unsigned HOST_WIDE_INT digit;
2739 unsigned HOST_WIDE_INT val;
2740 int result;
2741
2742 if (n == 0)
2743 return 0;
2744
2745 /* Ignore the reciprocal when calculating the cost. */
2746 val = (n < 0) ? -n : n;
2747
2748 /* Initialize the exponent cache. */
2749 memset (cache, 0, POWI_TABLE_SIZE * sizeof (bool));
2750 cache[1] = true;
2751
2752 result = 0;
2753
2754 while (val >= POWI_TABLE_SIZE)
2755 {
2756 if (val & 1)
2757 {
2758 digit = val & ((1 << POWI_WINDOW_SIZE) - 1);
2759 result += powi_lookup_cost (digit, cache)
2760 + POWI_WINDOW_SIZE + 1;
2761 val >>= POWI_WINDOW_SIZE;
2762 }
2763 else
2764 {
2765 val >>= 1;
2766 result++;
2767 }
2768 }
0862b7e9 2769
6881dbab 2770 return result + powi_lookup_cost (val, cache);
f1b844c6 2771}
2772
2773/* Recursive subroutine of expand_powi. This function takes the array,
2774 CACHE, of already calculated exponents and an exponent N and returns
2775 an RTX that corresponds to CACHE[1]**N, as calculated in mode MODE. */
2776
2777static rtx
2778expand_powi_1 (enum machine_mode mode, unsigned HOST_WIDE_INT n, rtx *cache)
2779{
2780 unsigned HOST_WIDE_INT digit;
2781 rtx target, result;
2782 rtx op0, op1;
2783
2784 if (n < POWI_TABLE_SIZE)
2785 {
2786 if (cache[n])
a0c938f0 2787 return cache[n];
f1b844c6 2788
2789 target = gen_reg_rtx (mode);
2790 cache[n] = target;
2791
2792 op0 = expand_powi_1 (mode, n - powi_table[n], cache);
2793 op1 = expand_powi_1 (mode, powi_table[n], cache);
2794 }
2795 else if (n & 1)
2796 {
2797 target = gen_reg_rtx (mode);
2798 digit = n & ((1 << POWI_WINDOW_SIZE) - 1);
2799 op0 = expand_powi_1 (mode, n - digit, cache);
2800 op1 = expand_powi_1 (mode, digit, cache);
2801 }
2802 else
2803 {
2804 target = gen_reg_rtx (mode);
2805 op0 = expand_powi_1 (mode, n >> 1, cache);
2806 op1 = op0;
2807 }
2808
2809 result = expand_mult (mode, op0, op1, target, 0);
2810 if (result != target)
2811 emit_move_insn (target, result);
2812 return target;
2813}
2814
2815/* Expand the RTL to evaluate powi(x,n) in mode MODE. X is the
2816 floating point operand in mode MODE, and N is the exponent. This
2817 function needs to be kept in sync with powi_cost above. */
0862b7e9 2818
f1b844c6 2819static rtx
2820expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n)
2821{
2822 unsigned HOST_WIDE_INT val;
2823 rtx cache[POWI_TABLE_SIZE];
2824 rtx result;
2825
2826 if (n == 0)
2827 return CONST1_RTX (mode);
2828
2829 val = (n < 0) ? -n : n;
2830
19bf118a 2831 memset (cache, 0, sizeof (cache));
f1b844c6 2832 cache[1] = x;
2833
2834 result = expand_powi_1 (mode, (n < 0) ? -n : n, cache);
2835
2836 /* If the original exponent was negative, reciprocate the result. */
2837 if (n < 0)
2838 result = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2839 result, NULL_RTX, 0, OPTAB_LIB_WIDEN);
2840
2841 return result;
2842}
2843
c2f47e15 2844/* Expand a call to the pow built-in mathematical function. Return NULL_RTX if
f1b844c6 2845 a normal call should be emitted rather than expanding the function
2846 in-line. EXP is the expression that is a call to the builtin
2847 function; if convenient, the result should be placed in TARGET. */
2848
2849static rtx
2850expand_builtin_pow (tree exp, rtx target, rtx subtarget)
2851{
c2f47e15 2852 tree arg0, arg1;
2853 tree fn, narg0;
1c4709b4 2854 tree type = TREE_TYPE (exp);
2855 REAL_VALUE_TYPE cint, c, c2;
2856 HOST_WIDE_INT n;
2857 rtx op, op2;
2858 enum machine_mode mode = TYPE_MODE (type);
f1b844c6 2859
c2f47e15 2860 if (! validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2861 return NULL_RTX;
f1b844c6 2862
c2f47e15 2863 arg0 = CALL_EXPR_ARG (exp, 0);
2864 arg1 = CALL_EXPR_ARG (exp, 1);
f1b844c6 2865
1c4709b4 2866 if (TREE_CODE (arg1) != REAL_CST
f96bd2bf 2867 || TREE_OVERFLOW (arg1))
1c4709b4 2868 return expand_builtin_mathfn_2 (exp, target, subtarget);
2869
2870 /* Handle constant exponents. */
2871
2872 /* For integer valued exponents we can expand to an optimal multiplication
2873 sequence using expand_powi. */
2874 c = TREE_REAL_CST (arg1);
2875 n = real_to_integer (&c);
2876 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
2877 if (real_identical (&c, &cint)
2878 && ((n >= -1 && n <= 2)
2879 || (flag_unsafe_math_optimizations
2880 && !optimize_size
2881 && powi_cost (n) <= POWI_MAX_MULTS)))
f1b844c6 2882 {
1db6d067 2883 op = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 2884 if (n != 1)
2885 {
2886 op = force_reg (mode, op);
2887 op = expand_powi (op, mode, n);
2888 }
2889 return op;
2890 }
2891
2892 narg0 = builtin_save_expr (arg0);
f1b844c6 2893
1c4709b4 2894 /* If the exponent is not integer valued, check if it is half of an integer.
2895 In this case we can expand to sqrt (x) * x**(n/2). */
2896 fn = mathfn_built_in (type, BUILT_IN_SQRT);
2897 if (fn != NULL_TREE)
2898 {
2899 real_arithmetic (&c2, MULT_EXPR, &c, &dconst2);
2900 n = real_to_integer (&c2);
f1b844c6 2901 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
1c4709b4 2902 if (real_identical (&c2, &cint)
2903 && ((flag_unsafe_math_optimizations
2904 && !optimize_size
2905 && powi_cost (n/2) <= POWI_MAX_MULTS)
2906 || n == 1))
f1b844c6 2907 {
c2f47e15 2908 tree call_expr = build_call_expr (fn, 1, narg0);
1c4709b4 2909 op = expand_builtin (call_expr, NULL_RTX, subtarget, mode, 0);
2910 if (n != 1)
8c5cac78 2911 {
1db6d067 2912 op2 = expand_expr (narg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 2913 op2 = force_reg (mode, op2);
2914 op2 = expand_powi (op2, mode, abs (n / 2));
2915 op = expand_simple_binop (mode, MULT, op, op2, NULL_RTX,
2916 0, OPTAB_LIB_WIDEN);
2917 /* If the original exponent was negative, reciprocate the
2918 result. */
2919 if (n < 0)
2920 op = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2921 op, NULL_RTX, 0, OPTAB_LIB_WIDEN);
8c5cac78 2922 }
1c4709b4 2923 return op;
f1b844c6 2924 }
2925 }
b613c2a6 2926
1c4709b4 2927 /* Try if the exponent is a third of an integer. In this case
5a84ba55 2928 we can expand to x**(n/3) * cbrt(x)**(n%3). As cbrt (x) is
2929 different from pow (x, 1./3.) due to rounding and behavior
2930 with negative x we need to constrain this transformation to
2931 unsafe math and positive x or finite math. */
1c4709b4 2932 fn = mathfn_built_in (type, BUILT_IN_CBRT);
5a84ba55 2933 if (fn != NULL_TREE
2934 && flag_unsafe_math_optimizations
2935 && (tree_expr_nonnegative_p (arg0)
2936 || !HONOR_NANS (mode)))
1c4709b4 2937 {
2938 real_arithmetic (&c2, MULT_EXPR, &c, &dconst3);
2939 real_round (&c2, mode, &c2);
2940 n = real_to_integer (&c2);
2941 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
2942 real_arithmetic (&c2, RDIV_EXPR, &cint, &dconst3);
2943 real_convert (&c2, mode, &c2);
2944 if (real_identical (&c2, &c)
2945 && ((!optimize_size
1c4709b4 2946 && powi_cost (n/3) <= POWI_MAX_MULTS)
2947 || n == 1))
2948 {
c2f47e15 2949 tree call_expr = build_call_expr (fn, 1,narg0);
1c4709b4 2950 op = expand_builtin (call_expr, NULL_RTX, subtarget, mode, 0);
2951 if (abs (n) % 3 == 2)
2952 op = expand_simple_binop (mode, MULT, op, op, op,
2953 0, OPTAB_LIB_WIDEN);
2954 if (n != 1)
2955 {
1db6d067 2956 op2 = expand_expr (narg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 2957 op2 = force_reg (mode, op2);
2958 op2 = expand_powi (op2, mode, abs (n / 3));
2959 op = expand_simple_binop (mode, MULT, op, op2, NULL_RTX,
2960 0, OPTAB_LIB_WIDEN);
2961 /* If the original exponent was negative, reciprocate the
2962 result. */
2963 if (n < 0)
2964 op = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2965 op, NULL_RTX, 0, OPTAB_LIB_WIDEN);
2966 }
2967 return op;
2968 }
2969 }
2970
2971 /* Fall back to optab expansion. */
b613c2a6 2972 return expand_builtin_mathfn_2 (exp, target, subtarget);
f1b844c6 2973}
2974
c2f47e15 2975/* Expand a call to the powi built-in mathematical function. Return NULL_RTX if
757c219d 2976 a normal call should be emitted rather than expanding the function
2977 in-line. EXP is the expression that is a call to the builtin
2978 function; if convenient, the result should be placed in TARGET. */
2979
2980static rtx
2981expand_builtin_powi (tree exp, rtx target, rtx subtarget)
2982{
757c219d 2983 tree arg0, arg1;
2984 rtx op0, op1;
2985 enum machine_mode mode;
d0405f40 2986 enum machine_mode mode2;
757c219d 2987
c2f47e15 2988 if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
2989 return NULL_RTX;
757c219d 2990
c2f47e15 2991 arg0 = CALL_EXPR_ARG (exp, 0);
2992 arg1 = CALL_EXPR_ARG (exp, 1);
757c219d 2993 mode = TYPE_MODE (TREE_TYPE (exp));
2994
2995 /* Handle constant power. */
2996
2997 if (TREE_CODE (arg1) == INTEGER_CST
f96bd2bf 2998 && !TREE_OVERFLOW (arg1))
757c219d 2999 {
3000 HOST_WIDE_INT n = TREE_INT_CST_LOW (arg1);
3001
3002 /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
3003 Otherwise, check the number of multiplications required. */
3004 if ((TREE_INT_CST_HIGH (arg1) == 0
3005 || TREE_INT_CST_HIGH (arg1) == -1)
3006 && ((n >= -1 && n <= 2)
3007 || (! optimize_size
3008 && powi_cost (n) <= POWI_MAX_MULTS)))
3009 {
1db6d067 3010 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
757c219d 3011 op0 = force_reg (mode, op0);
3012 return expand_powi (op0, mode, n);
3013 }
3014 }
3015
3016 /* Emit a libcall to libgcc. */
3017
c2f47e15 3018 /* Mode of the 2nd argument must match that of an int. */
d0405f40 3019 mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
3020
757c219d 3021 if (target == NULL_RTX)
3022 target = gen_reg_rtx (mode);
3023
1db6d067 3024 op0 = expand_expr (arg0, subtarget, mode, EXPAND_NORMAL);
757c219d 3025 if (GET_MODE (op0) != mode)
3026 op0 = convert_to_mode (mode, op0, 0);
1db6d067 3027 op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
d0405f40 3028 if (GET_MODE (op1) != mode2)
3029 op1 = convert_to_mode (mode2, op1, 0);
757c219d 3030
3031 target = emit_library_call_value (powi_optab->handlers[(int) mode].libfunc,
3032 target, LCT_CONST_MAKE_BLOCK, mode, 2,
d0405f40 3033 op0, mode, op1, mode2);
757c219d 3034
3035 return target;
3036}
3037
c2f47e15 3038/* Expand expression EXP which is a call to the strlen builtin. Return
3039 NULL_RTX if we failed the caller should emit a normal call, otherwise
aed0bd19 3040 try to get the result in TARGET, if convenient. */
f7c44134 3041
53800dbe 3042static rtx
c2f47e15 3043expand_builtin_strlen (tree exp, rtx target,
aecda0d6 3044 enum machine_mode target_mode)
53800dbe 3045{
c2f47e15 3046 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
3047 return NULL_RTX;
53800dbe 3048 else
3049 {
911c0150 3050 rtx pat;
c2f47e15 3051 tree len;
3052 tree src = CALL_EXPR_ARG (exp, 0);
911c0150 3053 rtx result, src_reg, char_rtx, before_strlen;
80cd7a5e 3054 enum machine_mode insn_mode = target_mode, char_mode;
ef2c4a29 3055 enum insn_code icode = CODE_FOR_nothing;
6248e345 3056 int align;
3057
3058 /* If the length can be computed at compile-time, return it. */
681fab1e 3059 len = c_strlen (src, 0);
6248e345 3060 if (len)
80cd7a5e 3061 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
6248e345 3062
681fab1e 3063 /* If the length can be computed at compile-time and is constant
3064 integer, but there are side-effects in src, evaluate
3065 src for side-effects, then return len.
3066 E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
3067 can be optimized into: i++; x = 3; */
3068 len = c_strlen (src, 1);
3069 if (len && TREE_CODE (len) == INTEGER_CST)
3070 {
3071 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
3072 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
3073 }
3074
6248e345 3075 align = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
53800dbe 3076
53800dbe 3077 /* If SRC is not a pointer type, don't do this operation inline. */
3078 if (align == 0)
c2f47e15 3079 return NULL_RTX;
53800dbe 3080
911c0150 3081 /* Bail out if we can't compute strlen in the right mode. */
53800dbe 3082 while (insn_mode != VOIDmode)
3083 {
3084 icode = strlen_optab->handlers[(int) insn_mode].insn_code;
3085 if (icode != CODE_FOR_nothing)
c28ae87f 3086 break;
53800dbe 3087
3088 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
3089 }
3090 if (insn_mode == VOIDmode)
c2f47e15 3091 return NULL_RTX;
53800dbe 3092
3093 /* Make a place to write the result of the instruction. */
3094 result = target;
3095 if (! (result != 0
8ad4c111 3096 && REG_P (result)
53800dbe 3097 && GET_MODE (result) == insn_mode
3098 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3099 result = gen_reg_rtx (insn_mode);
3100
911c0150 3101 /* Make a place to hold the source address. We will not expand
3102 the actual source until we are sure that the expansion will
3103 not fail -- there are trees that cannot be expanded twice. */
3104 src_reg = gen_reg_rtx (Pmode);
53800dbe 3105
911c0150 3106 /* Mark the beginning of the strlen sequence so we can emit the
3107 source operand later. */
f0ce3b1f 3108 before_strlen = get_last_insn ();
53800dbe 3109
53800dbe 3110 char_rtx = const0_rtx;
f7c44134 3111 char_mode = insn_data[(int) icode].operand[2].mode;
3112 if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
3113 char_mode))
53800dbe 3114 char_rtx = copy_to_mode_reg (char_mode, char_rtx);
3115
911c0150 3116 pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
3117 char_rtx, GEN_INT (align));
3118 if (! pat)
c2f47e15 3119 return NULL_RTX;
911c0150 3120 emit_insn (pat);
3121
3122 /* Now that we are assured of success, expand the source. */
3123 start_sequence ();
c5aba89c 3124 pat = expand_expr (src, src_reg, ptr_mode, EXPAND_NORMAL);
911c0150 3125 if (pat != src_reg)
3126 emit_move_insn (src_reg, pat);
31d3e01c 3127 pat = get_insns ();
911c0150 3128 end_sequence ();
bceb0d1f 3129
3130 if (before_strlen)
3131 emit_insn_after (pat, before_strlen);
3132 else
3133 emit_insn_before (pat, get_insns ());
53800dbe 3134
3135 /* Return the value in the proper mode for this function. */
80cd7a5e 3136 if (GET_MODE (result) == target_mode)
911c0150 3137 target = result;
53800dbe 3138 else if (target != 0)
911c0150 3139 convert_move (target, result, 0);
53800dbe 3140 else
80cd7a5e 3141 target = convert_to_mode (target_mode, result, 0);
911c0150 3142
3143 return target;
53800dbe 3144 }
3145}
3146
c2f47e15 3147/* Expand a call to the strstr builtin. Return NULL_RTX if we failed the
17f5ea87 3148 caller should emit a normal call, otherwise try to get the result
3149 in TARGET, if convenient (and in mode MODE if that's convenient). */
3150
3151static rtx
c2f47e15 3152expand_builtin_strstr (tree exp, rtx target, enum machine_mode mode)
17f5ea87 3153{
c2f47e15 3154 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
17f5ea87 3155 {
c2f47e15 3156 tree type = TREE_TYPE (exp);
3157 tree result = fold_builtin_strstr (CALL_EXPR_ARG (exp, 0),
3158 CALL_EXPR_ARG (exp, 1), type);
2c84ee37 3159 if (result)
3160 return expand_expr (result, target, mode, EXPAND_NORMAL);
17f5ea87 3161 }
c2f47e15 3162 return NULL_RTX;
17f5ea87 3163}
3164
c2f47e15 3165/* Expand a call to the strchr builtin. Return NULL_RTX if we failed the
46f3a74a 3166 caller should emit a normal call, otherwise try to get the result
3167 in TARGET, if convenient (and in mode MODE if that's convenient). */
3168
3169static rtx
c2f47e15 3170expand_builtin_strchr (tree exp, rtx target, enum machine_mode mode)
46f3a74a 3171{
c2f47e15 3172 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
46f3a74a 3173 {
c2f47e15 3174 tree type = TREE_TYPE (exp);
3175 tree result = fold_builtin_strchr (CALL_EXPR_ARG (exp, 0),
3176 CALL_EXPR_ARG (exp, 1), type);
2c84ee37 3177 if (result)
3178 return expand_expr (result, target, mode, EXPAND_NORMAL);
83d79705 3179
2c84ee37 3180 /* FIXME: Should use strchrM optab so that ports can optimize this. */
83d79705 3181 }
c2f47e15 3182 return NULL_RTX;
83d79705 3183}
3184
c2f47e15 3185/* Expand a call to the strrchr builtin. Return NULL_RTX if we failed the
83d79705 3186 caller should emit a normal call, otherwise try to get the result
3187 in TARGET, if convenient (and in mode MODE if that's convenient). */
3188
3189static rtx
c2f47e15 3190expand_builtin_strrchr (tree exp, rtx target, enum machine_mode mode)
83d79705 3191{
c2f47e15 3192 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
83d79705 3193 {
c2f47e15 3194 tree type = TREE_TYPE (exp);
3195 tree result = fold_builtin_strrchr (CALL_EXPR_ARG (exp, 0),
3196 CALL_EXPR_ARG (exp, 1), type);
2c84ee37 3197 if (result)
3198 return expand_expr (result, target, mode, EXPAND_NORMAL);
83d79705 3199 }
c2f47e15 3200 return NULL_RTX;
83d79705 3201}
3202
c2f47e15 3203/* Expand a call to the strpbrk builtin. Return NULL_RTX if we failed the
83d79705 3204 caller should emit a normal call, otherwise try to get the result
3205 in TARGET, if convenient (and in mode MODE if that's convenient). */
3206
3207static rtx
c2f47e15 3208expand_builtin_strpbrk (tree exp, rtx target, enum machine_mode mode)
83d79705 3209{
c2f47e15 3210 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
83d79705 3211 {
c2f47e15 3212 tree type = TREE_TYPE (exp);
3213 tree result = fold_builtin_strpbrk (CALL_EXPR_ARG (exp, 0),
3214 CALL_EXPR_ARG (exp, 1), type);
2c84ee37 3215 if (result)
3216 return expand_expr (result, target, mode, EXPAND_NORMAL);
46f3a74a 3217 }
c2f47e15 3218 return NULL_RTX;
46f3a74a 3219}
3220
6840589f 3221/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3222 bytes from constant string DATA + OFFSET and return it as target
3223 constant. */
3224
3225static rtx
aecda0d6 3226builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
3227 enum machine_mode mode)
6840589f 3228{
3229 const char *str = (const char *) data;
3230
64db345d 3231 gcc_assert (offset >= 0
3232 && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
3233 <= strlen (str) + 1));
6840589f 3234
3235 return c_readstr (str + offset, mode);
3236}
3237
c2f47e15 3238/* Expand a call EXP to the memcpy builtin.
3239 Return NULL_RTX if we failed, the caller should emit a normal call,
3b824fa6 3240 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3241 mode MODE if that's convenient). */
c2f47e15 3242
53800dbe 3243static rtx
5a0de151 3244expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode)
53800dbe 3245{
8e76ec06 3246 tree fndecl = get_callee_fndecl (exp);
c2f47e15 3247
3248 if (!validate_arglist (exp,
3249 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3250 return NULL_RTX;
53800dbe 3251 else
3252 {
c2f47e15 3253 tree dest = CALL_EXPR_ARG (exp, 0);
3254 tree src = CALL_EXPR_ARG (exp, 1);
3255 tree len = CALL_EXPR_ARG (exp, 2);
6840589f 3256 const char *src_str;
27d0c333 3257 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3258 unsigned int dest_align
3259 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
53800dbe 3260 rtx dest_mem, src_mem, dest_addr, len_rtx;
c2f47e15 3261 tree result = fold_builtin_memory_op (dest, src, len,
3262 TREE_TYPE (TREE_TYPE (fndecl)),
4f46f2b9 3263 false, /*endp=*/0);
162719b3 3264 HOST_WIDE_INT expected_size = -1;
3265 unsigned int expected_align = 0;
5a0de151 3266
3267 if (result)
4f46f2b9 3268 {
3269 while (TREE_CODE (result) == COMPOUND_EXPR)
3270 {
3271 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3272 EXPAND_NORMAL);
3273 result = TREE_OPERAND (result, 1);
3274 }
3275 return expand_expr (result, target, mode, EXPAND_NORMAL);
3276 }
53800dbe 3277
6f428e8b 3278 /* If DEST is not a pointer type, call the normal function. */
3279 if (dest_align == 0)
c2f47e15 3280 return NULL_RTX;
6f428e8b 3281
6f428e8b 3282 /* If either SRC is not a pointer type, don't do this
a0c938f0 3283 operation in-line. */
6f428e8b 3284 if (src_align == 0)
c2f47e15 3285 return NULL_RTX;
162719b3 3286
3287 stringop_block_profile (exp, &expected_align, &expected_size);
3288 if (expected_align < dest_align)
3289 expected_align = dest_align;
d8ae1baa 3290 dest_mem = get_memory_rtx (dest, len);
2a631e19 3291 set_mem_align (dest_mem, dest_align);
8ec3c5c2 3292 len_rtx = expand_normal (len);
6840589f 3293 src_str = c_getstr (src);
3294
3295 /* If SRC is a string constant and block move would be done
3296 by pieces, we can avoid loading the string from memory
3297 and only stored the computed constants. */
3298 if (src_str
6840589f 3299 && GET_CODE (len_rtx) == CONST_INT
3300 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3301 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
b9a7cc69 3302 (void *) src_str, dest_align))
6840589f 3303 {
9fe0e1b8 3304 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3305 builtin_memcpy_read_str,
b9a7cc69 3306 (void *) src_str, dest_align, 0);
e5716f7e 3307 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3308 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3309 return dest_mem;
6840589f 3310 }
3311
d8ae1baa 3312 src_mem = get_memory_rtx (src, len);
2a631e19 3313 set_mem_align (src_mem, src_align);
53800dbe 3314
53800dbe 3315 /* Copy word part most expediently. */
162719b3 3316 dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
3317 CALL_EXPR_TAILCALL (exp)
3318 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3319 expected_align, expected_size);
53800dbe 3320
3321 if (dest_addr == 0)
e5716f7e 3322 {
3323 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3324 dest_addr = convert_memory_address (ptr_mode, dest_addr);
e5716f7e 3325 }
9fe0e1b8 3326 return dest_addr;
53800dbe 3327 }
3328}
3329
c2f47e15 3330/* Expand a call EXP to the mempcpy builtin.
3331 Return NULL_RTX if we failed; the caller should emit a normal call,
647661c6 3332 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3333 mode MODE if that's convenient). If ENDP is 0 return the
3334 destination pointer, if ENDP is 1 return the end pointer ala
3335 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3336 stpcpy. */
647661c6 3337
3338static rtx
c2f47e15 3339expand_builtin_mempcpy(tree exp, rtx target, enum machine_mode mode)
647661c6 3340{
c2f47e15 3341 if (!validate_arglist (exp,
3342 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3343 return NULL_RTX;
3344 else
3345 {
3346 tree dest = CALL_EXPR_ARG (exp, 0);
3347 tree src = CALL_EXPR_ARG (exp, 1);
3348 tree len = CALL_EXPR_ARG (exp, 2);
3349 return expand_builtin_mempcpy_args (dest, src, len,
3350 TREE_TYPE (exp),
3351 target, mode, /*endp=*/ 1);
3352 }
3353}
3354
3355/* Helper function to do the actual work for expand_builtin_mempcpy. The
3356 arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out
3357 so that this can also be called without constructing an actual CALL_EXPR.
3358 TYPE is the return type of the call. The other arguments and return value
3359 are the same as for expand_builtin_mempcpy. */
3360
3361static rtx
3362expand_builtin_mempcpy_args (tree dest, tree src, tree len, tree type,
3363 rtx target, enum machine_mode mode, int endp)
3364{
3365 /* If return value is ignored, transform mempcpy into memcpy. */
3366 if (target == const0_rtx)
9fe0e1b8 3367 {
3368 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
3369
3370 if (!fn)
c2f47e15 3371 return NULL_RTX;
9fe0e1b8 3372
c2f47e15 3373 return expand_expr (build_call_expr (fn, 3, dest, src, len),
9fe0e1b8 3374 target, mode, EXPAND_NORMAL);
3375 }
647661c6 3376 else
3377 {
9fe0e1b8 3378 const char *src_str;
3379 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3380 unsigned int dest_align
3381 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3382 rtx dest_mem, src_mem, len_rtx;
c2f47e15 3383 tree result = fold_builtin_memory_op (dest, src, len, type, false, endp);
9fe0e1b8 3384
7da1412b 3385 if (result)
4f46f2b9 3386 {
3387 while (TREE_CODE (result) == COMPOUND_EXPR)
3388 {
3389 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3390 EXPAND_NORMAL);
3391 result = TREE_OPERAND (result, 1);
3392 }
3393 return expand_expr (result, target, mode, EXPAND_NORMAL);
3394 }
a0c938f0 3395
7da1412b 3396 /* If either SRC or DEST is not a pointer type, don't do this
a0c938f0 3397 operation in-line. */
7da1412b 3398 if (dest_align == 0 || src_align == 0)
c2f47e15 3399 return NULL_RTX;
9fe0e1b8 3400
6217c238 3401 /* If LEN is not constant, call the normal function. */
3402 if (! host_integerp (len, 1))
c2f47e15 3403 return NULL_RTX;
0862b7e9 3404
8ec3c5c2 3405 len_rtx = expand_normal (len);
9fe0e1b8 3406 src_str = c_getstr (src);
647661c6 3407
9fe0e1b8 3408 /* If SRC is a string constant and block move would be done
3409 by pieces, we can avoid loading the string from memory
3410 and only stored the computed constants. */
3411 if (src_str
3412 && GET_CODE (len_rtx) == CONST_INT
3413 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3414 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
b9a7cc69 3415 (void *) src_str, dest_align))
9fe0e1b8 3416 {
d8ae1baa 3417 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3418 set_mem_align (dest_mem, dest_align);
3419 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3420 builtin_memcpy_read_str,
b9a7cc69 3421 (void *) src_str, dest_align, endp);
9fe0e1b8 3422 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3423 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3424 return dest_mem;
647661c6 3425 }
3426
9fe0e1b8 3427 if (GET_CODE (len_rtx) == CONST_INT
3428 && can_move_by_pieces (INTVAL (len_rtx),
3429 MIN (dest_align, src_align)))
3430 {
d8ae1baa 3431 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3432 set_mem_align (dest_mem, dest_align);
d8ae1baa 3433 src_mem = get_memory_rtx (src, len);
9fe0e1b8 3434 set_mem_align (src_mem, src_align);
3435 dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
3436 MIN (dest_align, src_align), endp);
3437 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3438 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3439 return dest_mem;
3440 }
3441
c2f47e15 3442 return NULL_RTX;
647661c6 3443 }
3444}
3445
c2f47e15 3446/* Expand expression EXP, which is a call to the memmove builtin. Return
3447 NULL_RTX if we failed; the caller should emit a normal call. */
c4950093 3448
3449static rtx
c2f47e15 3450expand_builtin_memmove (tree exp, rtx target, enum machine_mode mode, int ignore)
c4950093 3451{
c2f47e15 3452 if (!validate_arglist (exp,
3453 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3454 return NULL_RTX;
c4950093 3455 else
3456 {
c2f47e15 3457 tree dest = CALL_EXPR_ARG (exp, 0);
3458 tree src = CALL_EXPR_ARG (exp, 1);
3459 tree len = CALL_EXPR_ARG (exp, 2);
3460 return expand_builtin_memmove_args (dest, src, len, TREE_TYPE (exp),
3461 target, mode, ignore);
3462 }
3463}
7e72af53 3464
c2f47e15 3465/* Helper function to do the actual work for expand_builtin_memmove. The
3466 arguments to the builtin_memmove call DEST, SRC, and LEN are broken out
3467 so that this can also be called without constructing an actual CALL_EXPR.
3468 TYPE is the return type of the call. The other arguments and return value
3469 are the same as for expand_builtin_memmove. */
3470
3471static rtx
3472expand_builtin_memmove_args (tree dest, tree src, tree len,
3473 tree type, rtx target, enum machine_mode mode,
3474 int ignore)
3475{
3476 tree result = fold_builtin_memory_op (dest, src, len, type, ignore, /*endp=*/3);
3477
3478 if (result)
3479 {
3480 while (TREE_CODE (result) == COMPOUND_EXPR)
4f46f2b9 3481 {
c2f47e15 3482 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3483 EXPAND_NORMAL);
3484 result = TREE_OPERAND (result, 1);
4f46f2b9 3485 }
c2f47e15 3486 return expand_expr (result, target, mode, EXPAND_NORMAL);
3487 }
3488
3489 /* Otherwise, call the normal function. */
3490 return NULL_RTX;
c4950093 3491}
3492
c2f47e15 3493/* Expand expression EXP, which is a call to the bcopy builtin. Return
3494 NULL_RTX if we failed the caller should emit a normal call. */
c4950093 3495
3496static rtx
c2f47e15 3497expand_builtin_bcopy (tree exp, int ignore)
c4950093 3498{
0b25db21 3499 tree type = TREE_TYPE (exp);
c2f47e15 3500 tree src, dest, size;
c4950093 3501
c2f47e15 3502 if (!validate_arglist (exp,
3503 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
c4950093 3504 return NULL_RTX;
3505
c2f47e15 3506 src = CALL_EXPR_ARG (exp, 0);
3507 dest = CALL_EXPR_ARG (exp, 1);
3508 size = CALL_EXPR_ARG (exp, 2);
c4950093 3509
c2f47e15 3510 /* Transform bcopy(ptr x, ptr y, int z) to memmove(ptr y, ptr x, size_t z).
3511 This is done this way so that if it isn't expanded inline, we fall
3512 back to calling bcopy instead of memmove. */
3513 return expand_builtin_memmove_args (dest, src,
3514 fold_convert (sizetype, size),
3515 type, const0_rtx, VOIDmode,
3516 ignore);
c4950093 3517}
3518
727c62dd 3519#ifndef HAVE_movstr
3520# define HAVE_movstr 0
3521# define CODE_FOR_movstr CODE_FOR_nothing
3522#endif
3523
c2f47e15 3524/* Expand into a movstr instruction, if one is available. Return NULL_RTX if
727c62dd 3525 we failed, the caller should emit a normal call, otherwise try to
3526 get the result in TARGET, if convenient. If ENDP is 0 return the
3527 destination pointer, if ENDP is 1 return the end pointer ala
3528 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3529 stpcpy. */
3530
3531static rtx
3532expand_movstr (tree dest, tree src, rtx target, int endp)
3533{
3534 rtx end;
3535 rtx dest_mem;
3536 rtx src_mem;
3537 rtx insn;
3538 const struct insn_data * data;
3539
3540 if (!HAVE_movstr)
c2f47e15 3541 return NULL_RTX;
727c62dd 3542
d8ae1baa 3543 dest_mem = get_memory_rtx (dest, NULL);
3544 src_mem = get_memory_rtx (src, NULL);
727c62dd 3545 if (!endp)
3546 {
3547 target = force_reg (Pmode, XEXP (dest_mem, 0));
3548 dest_mem = replace_equiv_address (dest_mem, target);
3549 end = gen_reg_rtx (Pmode);
3550 }
3551 else
3552 {
3553 if (target == 0 || target == const0_rtx)
3554 {
3555 end = gen_reg_rtx (Pmode);
3556 if (target == 0)
3557 target = end;
3558 }
3559 else
3560 end = target;
3561 }
3562
3563 data = insn_data + CODE_FOR_movstr;
3564
3565 if (data->operand[0].mode != VOIDmode)
3566 end = gen_lowpart (data->operand[0].mode, end);
3567
3568 insn = data->genfun (end, dest_mem, src_mem);
3569
64db345d 3570 gcc_assert (insn);
727c62dd 3571
3572 emit_insn (insn);
3573
3574 /* movstr is supposed to set end to the address of the NUL
3575 terminator. If the caller requested a mempcpy-like return value,
3576 adjust it. */
3577 if (endp == 1 && target != const0_rtx)
c5aba89c 3578 {
3579 rtx tem = plus_constant (gen_lowpart (GET_MODE (target), end), 1);
3580 emit_move_insn (target, force_operand (tem, NULL_RTX));
3581 }
727c62dd 3582
3583 return target;
3584}
3585
c2f47e15 3586/* Expand expression EXP, which is a call to the strcpy builtin. Return
3587 NULL_RTX if we failed the caller should emit a normal call, otherwise
3588 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3589 convenient). */
902de8ed 3590
53800dbe 3591static rtx
c2f47e15 3592expand_builtin_strcpy (tree fndecl, tree exp, rtx target, enum machine_mode mode)
53800dbe 3593{
c2f47e15 3594 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3595 {
3596 tree dest = CALL_EXPR_ARG (exp, 0);
3597 tree src = CALL_EXPR_ARG (exp, 1);
3598 return expand_builtin_strcpy_args (fndecl, dest, src, target, mode);
3599 }
3600 return NULL_RTX;
3601}
3602
3603/* Helper function to do the actual work for expand_builtin_strcpy. The
3604 arguments to the builtin_strcpy call DEST and SRC are broken out
3605 so that this can also be called without constructing an actual CALL_EXPR.
3606 The other arguments and return value are the same as for
3607 expand_builtin_strcpy. */
3608
3609static rtx
3610expand_builtin_strcpy_args (tree fndecl, tree dest, tree src,
3611 rtx target, enum machine_mode mode)
3612{
3613 tree result = fold_builtin_strcpy (fndecl, dest, src, 0);
3614 if (result)
3615 return expand_expr (result, target, mode, EXPAND_NORMAL);
3616 return expand_movstr (dest, src, target, /*endp=*/0);
902de8ed 3617
53800dbe 3618}
3619
c2f47e15 3620/* Expand a call EXP to the stpcpy builtin.
3621 Return NULL_RTX if we failed the caller should emit a normal call,
3b824fa6 3622 otherwise try to get the result in TARGET, if convenient (and in
3623 mode MODE if that's convenient). */
3624
3625static rtx
dc369150 3626expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
3b824fa6 3627{
c2f47e15 3628 tree dst, src;
3629
3630 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3631 return NULL_RTX;
3632
3633 dst = CALL_EXPR_ARG (exp, 0);
3634 src = CALL_EXPR_ARG (exp, 1);
3635
727c62dd 3636 /* If return value is ignored, transform stpcpy into strcpy. */
3637 if (target == const0_rtx)
978836e5 3638 {
3639 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
3640 if (!fn)
c2f47e15 3641 return NULL_RTX;
978836e5 3642
c2f47e15 3643 return expand_expr (build_call_expr (fn, 2, dst, src),
3644 target, mode, EXPAND_NORMAL);
978836e5 3645 }
3b824fa6 3646 else
3647 {
c2f47e15 3648 tree len, lenp1;
727c62dd 3649 rtx ret;
647661c6 3650
9fe0e1b8 3651 /* Ensure we get an actual string whose length can be evaluated at
a0c938f0 3652 compile-time, not an expression containing a string. This is
3653 because the latter will potentially produce pessimized code
3654 when used to produce the return value. */
681fab1e 3655 if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
c2f47e15 3656 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3657
7d705727 3658 lenp1 = size_binop (PLUS_EXPR, len, ssize_int (1));
c2f47e15 3659 ret = expand_builtin_mempcpy_args (dst, src, lenp1, TREE_TYPE (exp),
3660 target, mode, /*endp=*/2);
727c62dd 3661
3662 if (ret)
3663 return ret;
3664
3665 if (TREE_CODE (len) == INTEGER_CST)
3666 {
8ec3c5c2 3667 rtx len_rtx = expand_normal (len);
727c62dd 3668
3669 if (GET_CODE (len_rtx) == CONST_INT)
3670 {
c2f47e15 3671 ret = expand_builtin_strcpy_args (get_callee_fndecl (exp),
3672 dst, src, target, mode);
727c62dd 3673
3674 if (ret)
3675 {
3676 if (! target)
7ac87324 3677 {
3678 if (mode != VOIDmode)
3679 target = gen_reg_rtx (mode);
3680 else
3681 target = gen_reg_rtx (GET_MODE (ret));
3682 }
727c62dd 3683 if (GET_MODE (target) != GET_MODE (ret))
3684 ret = gen_lowpart (GET_MODE (target), ret);
3685
c5aba89c 3686 ret = plus_constant (ret, INTVAL (len_rtx));
3687 ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
64db345d 3688 gcc_assert (ret);
727c62dd 3689
3690 return target;
3691 }
3692 }
3693 }
3694
c2f47e15 3695 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3696 }
3697}
3698
6840589f 3699/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3700 bytes from constant string DATA + OFFSET and return it as target
3701 constant. */
3702
3703static rtx
aecda0d6 3704builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
3705 enum machine_mode mode)
6840589f 3706{
3707 const char *str = (const char *) data;
3708
3709 if ((unsigned HOST_WIDE_INT) offset > strlen (str))
3710 return const0_rtx;
3711
3712 return c_readstr (str + offset, mode);
3713}
3714
c2f47e15 3715/* Expand expression EXP, which is a call to the strncpy builtin. Return
3716 NULL_RTX if we failed the caller should emit a normal call. */
ed09096d 3717
3718static rtx
8ff6a5cd 3719expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode)
ed09096d 3720{
ea726109 3721 tree fndecl = get_callee_fndecl (exp);
c2f47e15 3722
3723 if (validate_arglist (exp,
3724 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
ed09096d 3725 {
c2f47e15 3726 tree dest = CALL_EXPR_ARG (exp, 0);
3727 tree src = CALL_EXPR_ARG (exp, 1);
3728 tree len = CALL_EXPR_ARG (exp, 2);
3729 tree slen = c_strlen (src, 1);
3730 tree result = fold_builtin_strncpy (fndecl, dest, src, len, slen);
a0c938f0 3731
8ff6a5cd 3732 if (result)
4f46f2b9 3733 {
3734 while (TREE_CODE (result) == COMPOUND_EXPR)
3735 {
3736 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3737 EXPAND_NORMAL);
3738 result = TREE_OPERAND (result, 1);
3739 }
3740 return expand_expr (result, target, mode, EXPAND_NORMAL);
3741 }
6840589f 3742
8ff6a5cd 3743 /* We must be passed a constant len and src parameter. */
3744 if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
c2f47e15 3745 return NULL_RTX;
ed09096d 3746
3747 slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
3748
3749 /* We're required to pad with trailing zeros if the requested
a0c938f0 3750 len is greater than strlen(s2)+1. In that case try to
6840589f 3751 use store_by_pieces, if it fails, punt. */
ed09096d 3752 if (tree_int_cst_lt (slen, len))
6840589f 3753 {
27d0c333 3754 unsigned int dest_align
3755 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
c2f47e15 3756 const char *p = c_getstr (src);
6840589f 3757 rtx dest_mem;
3758
27d0c333 3759 if (!p || dest_align == 0 || !host_integerp (len, 1)
3760 || !can_store_by_pieces (tree_low_cst (len, 1),
6840589f 3761 builtin_strncpy_read_str,
b9a7cc69 3762 (void *) p, dest_align))
c2f47e15 3763 return NULL_RTX;
6840589f 3764
d8ae1baa 3765 dest_mem = get_memory_rtx (dest, len);
27d0c333 3766 store_by_pieces (dest_mem, tree_low_cst (len, 1),
6840589f 3767 builtin_strncpy_read_str,
b9a7cc69 3768 (void *) p, dest_align, 0);
e5716f7e 3769 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3770 dest_mem = convert_memory_address (ptr_mode, dest_mem);
e5716f7e 3771 return dest_mem;
6840589f 3772 }
ed09096d 3773 }
c2f47e15 3774 return NULL_RTX;
ed09096d 3775}
3776
ecc318ff 3777/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3778 bytes from constant string DATA + OFFSET and return it as target
3779 constant. */
3780
f656b751 3781rtx
aecda0d6 3782builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3783 enum machine_mode mode)
ecc318ff 3784{
3785 const char *c = (const char *) data;
3786 char *p = alloca (GET_MODE_SIZE (mode));
3787
3788 memset (p, *c, GET_MODE_SIZE (mode));
3789
3790 return c_readstr (p, mode);
3791}
3792
a7ec6974 3793/* Callback routine for store_by_pieces. Return the RTL of a register
3794 containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
3795 char value given in the RTL register data. For example, if mode is
3796 4 bytes wide, return the RTL for 0x01010101*data. */
3797
3798static rtx
aecda0d6 3799builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3800 enum machine_mode mode)
a7ec6974 3801{
3802 rtx target, coeff;
3803 size_t size;
3804 char *p;
3805
3806 size = GET_MODE_SIZE (mode);
f0ce3b1f 3807 if (size == 1)
3808 return (rtx) data;
a7ec6974 3809
3810 p = alloca (size);
3811 memset (p, 1, size);
3812 coeff = c_readstr (p, mode);
3813
f0ce3b1f 3814 target = convert_to_mode (mode, (rtx) data, 1);
a7ec6974 3815 target = expand_mult (mode, target, coeff, NULL_RTX, 1);
3816 return force_reg (mode, target);
3817}
3818
c2f47e15 3819/* Expand expression EXP, which is a call to the memset builtin. Return
3820 NULL_RTX if we failed the caller should emit a normal call, otherwise
3821 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3822 convenient). */
902de8ed 3823
53800dbe 3824static rtx
c2f47e15 3825expand_builtin_memset (tree exp, rtx target, enum machine_mode mode)
53800dbe 3826{
c2f47e15 3827 if (!validate_arglist (exp,
3828 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
3829 return NULL_RTX;
53800dbe 3830 else
3831 {
c2f47e15 3832 tree dest = CALL_EXPR_ARG (exp, 0);
3833 tree val = CALL_EXPR_ARG (exp, 1);
3834 tree len = CALL_EXPR_ARG (exp, 2);
3835 return expand_builtin_memset_args (dest, val, len, target, mode, exp);
3836 }
3837}
53800dbe 3838
c2f47e15 3839/* Helper function to do the actual work for expand_builtin_memset. The
3840 arguments to the builtin_memset call DEST, VAL, and LEN are broken out
3841 so that this can also be called without constructing an actual CALL_EXPR.
3842 The other arguments and return value are the same as for
3843 expand_builtin_memset. */
6b961939 3844
c2f47e15 3845static rtx
3846expand_builtin_memset_args (tree dest, tree val, tree len,
3847 rtx target, enum machine_mode mode, tree orig_exp)
3848{
3849 tree fndecl, fn;
3850 enum built_in_function fcode;
3851 char c;
3852 unsigned int dest_align;
3853 rtx dest_mem, dest_addr, len_rtx;
3854 HOST_WIDE_INT expected_size = -1;
3855 unsigned int expected_align = 0;
53800dbe 3856
c2f47e15 3857 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
162719b3 3858
c2f47e15 3859 /* If DEST is not a pointer type, don't do this operation in-line. */
3860 if (dest_align == 0)
3861 return NULL_RTX;
6f428e8b 3862
c2f47e15 3863 stringop_block_profile (orig_exp, &expected_align, &expected_size);
3864 if (expected_align < dest_align)
3865 expected_align = dest_align;
6b961939 3866
c2f47e15 3867 /* If the LEN parameter is zero, return DEST. */
3868 if (integer_zerop (len))
3869 {
3870 /* Evaluate and ignore VAL in case it has side-effects. */
3871 expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
3872 return expand_expr (dest, target, mode, EXPAND_NORMAL);
3873 }
7a3e5564 3874
c2f47e15 3875 /* Stabilize the arguments in case we fail. */
3876 dest = builtin_save_expr (dest);
3877 val = builtin_save_expr (val);
3878 len = builtin_save_expr (len);
a7ec6974 3879
c2f47e15 3880 len_rtx = expand_normal (len);
3881 dest_mem = get_memory_rtx (dest, len);
a7ec6974 3882
c2f47e15 3883 if (TREE_CODE (val) != INTEGER_CST)
3884 {
3885 rtx val_rtx;
a7ec6974 3886
c2f47e15 3887 val_rtx = expand_normal (val);
3888 val_rtx = convert_to_mode (TYPE_MODE (unsigned_char_type_node),
3889 val_rtx, 0);
53800dbe 3890
c2f47e15 3891 /* Assume that we can memset by pieces if we can store
3892 * the coefficients by pieces (in the required modes).
3893 * We can't pass builtin_memset_gen_str as that emits RTL. */
3894 c = 1;
3895 if (host_integerp (len, 1)
3896 && !(optimize_size && tree_low_cst (len, 1) > 1)
3897 && can_store_by_pieces (tree_low_cst (len, 1),
3898 builtin_memset_read_str, &c, dest_align))
3899 {
3900 val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
3901 val_rtx);
3902 store_by_pieces (dest_mem, tree_low_cst (len, 1),
3903 builtin_memset_gen_str, val_rtx, dest_align, 0);
3904 }
3905 else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
3906 dest_align, expected_align,
3907 expected_size))
6b961939 3908 goto do_libcall;
c2f47e15 3909
3910 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3911 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3912 return dest_mem;
3913 }
53800dbe 3914
c2f47e15 3915 if (target_char_cast (val, &c))
3916 goto do_libcall;
ecc318ff 3917
c2f47e15 3918 if (c)
3919 {
3920 if (host_integerp (len, 1)
3921 && !(optimize_size && tree_low_cst (len, 1) > 1)
3922 && can_store_by_pieces (tree_low_cst (len, 1),
3923 builtin_memset_read_str, &c, dest_align))
3924 store_by_pieces (dest_mem, tree_low_cst (len, 1),
3925 builtin_memset_read_str, &c, dest_align, 0);
3926 else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
3927 dest_align, expected_align,
3928 expected_size))
3929 goto do_libcall;
3930
3931 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3932 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3933 return dest_mem;
3934 }
ecc318ff 3935
c2f47e15 3936 set_mem_align (dest_mem, dest_align);
3937 dest_addr = clear_storage_hints (dest_mem, len_rtx,
3938 CALL_EXPR_TAILCALL (orig_exp)
3939 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3940 expected_align, expected_size);
53800dbe 3941
c2f47e15 3942 if (dest_addr == 0)
3943 {
3944 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3945 dest_addr = convert_memory_address (ptr_mode, dest_addr);
3946 }
53800dbe 3947
c2f47e15 3948 return dest_addr;
6b961939 3949
c2f47e15 3950 do_libcall:
3951 fndecl = get_callee_fndecl (orig_exp);
3952 fcode = DECL_FUNCTION_CODE (fndecl);
3953 if (fcode == BUILT_IN_MEMSET)
3954 fn = build_call_expr (fndecl, 3, dest, val, len);
3955 else if (fcode == BUILT_IN_BZERO)
3956 fn = build_call_expr (fndecl, 2, dest, len);
3957 else
3958 gcc_unreachable ();
3959 if (TREE_CODE (fn) == CALL_EXPR)
3960 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
3961 return expand_call (fn, target, target == const0_rtx);
53800dbe 3962}
3963
c2f47e15 3964/* Expand expression EXP, which is a call to the bzero builtin. Return
3965 NULL_RTX if we failed the caller should emit a normal call. */
27d0c333 3966
ffc83088 3967static rtx
0b25db21 3968expand_builtin_bzero (tree exp)
ffc83088 3969{
c2f47e15 3970 tree dest, size;
ffc83088 3971
c2f47e15 3972 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
7369e7ba 3973 return NULL_RTX;
ffc83088 3974
c2f47e15 3975 dest = CALL_EXPR_ARG (exp, 0);
3976 size = CALL_EXPR_ARG (exp, 1);
bf8e3599 3977
7369e7ba 3978 /* New argument list transforming bzero(ptr x, int y) to
6f428e8b 3979 memset(ptr x, int 0, size_t y). This is done this way
3980 so that if it isn't expanded inline, we fallback to
3981 calling bzero instead of memset. */
bf8e3599 3982
c2f47e15 3983 return expand_builtin_memset_args (dest, integer_zero_node,
3984 fold_convert (sizetype, size),
3985 const0_rtx, VOIDmode, exp);
ffc83088 3986}
3987
7959b13b 3988/* Expand a call to the memchr builtin. Return NULL_RTX if we failed the
3989 caller should emit a normal call, otherwise try to get the result
3990 in TARGET, if convenient (and in mode MODE if that's convenient). */
3991
3992static rtx
3993expand_builtin_memchr (tree exp, rtx target, enum machine_mode mode)
3994{
3995 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE,
3996 INTEGER_TYPE, VOID_TYPE))
3997 {
3998 tree type = TREE_TYPE (exp);
3999 tree result = fold_builtin_memchr (CALL_EXPR_ARG (exp, 0),
4000 CALL_EXPR_ARG (exp, 1),
4001 CALL_EXPR_ARG (exp, 2), type);
4002 if (result)
4003 return expand_expr (result, target, mode, EXPAND_NORMAL);
4004 }
4005 return NULL_RTX;
4006}
4007
7a3f89b5 4008/* Expand expression EXP, which is a call to the memcmp built-in function.
c2f47e15 4009 Return NULL_RTX if we failed and the
53800dbe 4010 caller should emit a normal call, otherwise try to get the result in
6f428e8b 4011 TARGET, if convenient (and in mode MODE, if that's convenient). */
27d0c333 4012
53800dbe 4013static rtx
c2f47e15 4014expand_builtin_memcmp (tree exp, rtx target, enum machine_mode mode)
53800dbe 4015{
c2f47e15 4016 if (!validate_arglist (exp,
4017 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4018 return NULL_RTX;
218bc19e 4019 else
6f428e8b 4020 {
c2f47e15 4021 tree result = fold_builtin_memcmp (CALL_EXPR_ARG (exp, 0),
4022 CALL_EXPR_ARG (exp, 1),
4023 CALL_EXPR_ARG (exp, 2));
218bc19e 4024 if (result)
4025 return expand_expr (result, target, mode, EXPAND_NORMAL);
6f428e8b 4026 }
4027
6ac5504b 4028#if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi
53800dbe 4029 {
0cd832f0 4030 rtx arg1_rtx, arg2_rtx, arg3_rtx;
53800dbe 4031 rtx result;
0cd832f0 4032 rtx insn;
c2f47e15 4033 tree arg1 = CALL_EXPR_ARG (exp, 0);
4034 tree arg2 = CALL_EXPR_ARG (exp, 1);
4035 tree len = CALL_EXPR_ARG (exp, 2);
53800dbe 4036
4037 int arg1_align
4038 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4039 int arg2_align
4040 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
b428c0a5 4041 enum machine_mode insn_mode;
4042
4043#ifdef HAVE_cmpmemsi
4044 if (HAVE_cmpmemsi)
4045 insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
4046 else
4047#endif
6ac5504b 4048#ifdef HAVE_cmpstrnsi
4049 if (HAVE_cmpstrnsi)
4050 insn_mode = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
b428c0a5 4051 else
4052#endif
c2f47e15 4053 return NULL_RTX;
53800dbe 4054
4055 /* If we don't have POINTER_TYPE, call the function. */
4056 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4057 return NULL_RTX;
53800dbe 4058
4059 /* Make a place to write the result of the instruction. */
4060 result = target;
4061 if (! (result != 0
8ad4c111 4062 && REG_P (result) && GET_MODE (result) == insn_mode
53800dbe 4063 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4064 result = gen_reg_rtx (insn_mode);
4065
d8ae1baa 4066 arg1_rtx = get_memory_rtx (arg1, len);
4067 arg2_rtx = get_memory_rtx (arg2, len);
8ec3c5c2 4068 arg3_rtx = expand_normal (len);
83f88f8e 4069
4070 /* Set MEM_SIZE as appropriate. */
4071 if (GET_CODE (arg3_rtx) == CONST_INT)
4072 {
4073 set_mem_size (arg1_rtx, arg3_rtx);
4074 set_mem_size (arg2_rtx, arg3_rtx);
4075 }
4076
b428c0a5 4077#ifdef HAVE_cmpmemsi
4078 if (HAVE_cmpmemsi)
4079 insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4080 GEN_INT (MIN (arg1_align, arg2_align)));
0cd832f0 4081 else
b428c0a5 4082#endif
6ac5504b 4083#ifdef HAVE_cmpstrnsi
4084 if (HAVE_cmpstrnsi)
4085 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4086 GEN_INT (MIN (arg1_align, arg2_align)));
b428c0a5 4087 else
4088#endif
64db345d 4089 gcc_unreachable ();
0cd832f0 4090
4091 if (insn)
4092 emit_insn (insn);
4093 else
2c5d421b 4094 emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK,
0cd832f0 4095 TYPE_MODE (integer_type_node), 3,
4096 XEXP (arg1_rtx, 0), Pmode,
4097 XEXP (arg2_rtx, 0), Pmode,
4098 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
78a8ed03 4099 TYPE_UNSIGNED (sizetype)),
0cd832f0 4100 TYPE_MODE (sizetype));
53800dbe 4101
4102 /* Return the value in the proper mode for this function. */
4103 mode = TYPE_MODE (TREE_TYPE (exp));
4104 if (GET_MODE (result) == mode)
4105 return result;
4106 else if (target != 0)
4107 {
4108 convert_move (target, result, 0);
4109 return target;
4110 }
4111 else
4112 return convert_to_mode (mode, result, 0);
4113 }
83d79705 4114#endif
53800dbe 4115
c2f47e15 4116 return NULL_RTX;
6f428e8b 4117}
4118
c2f47e15 4119/* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX
53800dbe 4120 if we failed the caller should emit a normal call, otherwise try to get
4121 the result in TARGET, if convenient. */
902de8ed 4122
53800dbe 4123static rtx
aecda0d6 4124expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
53800dbe 4125{
c2f47e15 4126 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4127 return NULL_RTX;
218bc19e 4128 else
ef6c187e 4129 {
c2f47e15 4130 tree result = fold_builtin_strcmp (CALL_EXPR_ARG (exp, 0),
4131 CALL_EXPR_ARG (exp, 1));
218bc19e 4132 if (result)
4133 return expand_expr (result, target, mode, EXPAND_NORMAL);
ef6c187e 4134 }
bf8e3599 4135
6ac5504b 4136#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
4137 if (cmpstr_optab[SImode] != CODE_FOR_nothing
4138 || cmpstrn_optab[SImode] != CODE_FOR_nothing)
4139 {
4140 rtx arg1_rtx, arg2_rtx;
4141 rtx result, insn = NULL_RTX;
4142 tree fndecl, fn;
c2f47e15 4143 tree arg1 = CALL_EXPR_ARG (exp, 0);
4144 tree arg2 = CALL_EXPR_ARG (exp, 1);
a0c938f0 4145
6ac5504b 4146 int arg1_align
4147 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4148 int arg2_align
4149 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4150
4151 /* If we don't have POINTER_TYPE, call the function. */
4152 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4153 return NULL_RTX;
7a3f89b5 4154
6ac5504b 4155 /* Stabilize the arguments in case gen_cmpstr(n)si fail. */
4156 arg1 = builtin_save_expr (arg1);
4157 arg2 = builtin_save_expr (arg2);
7a3f89b5 4158
d8ae1baa 4159 arg1_rtx = get_memory_rtx (arg1, NULL);
4160 arg2_rtx = get_memory_rtx (arg2, NULL);
53800dbe 4161
6ac5504b 4162#ifdef HAVE_cmpstrsi
4163 /* Try to call cmpstrsi. */
4164 if (HAVE_cmpstrsi)
4165 {
a0c938f0 4166 enum machine_mode insn_mode
6ac5504b 4167 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
4168
4169 /* Make a place to write the result of the instruction. */
4170 result = target;
4171 if (! (result != 0
4172 && REG_P (result) && GET_MODE (result) == insn_mode
4173 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4174 result = gen_reg_rtx (insn_mode);
4175
4176 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
4177 GEN_INT (MIN (arg1_align, arg2_align)));
4178 }
4179#endif
03fd9d2c 4180#ifdef HAVE_cmpstrnsi
6ac5504b 4181 /* Try to determine at least one length and call cmpstrnsi. */
a0c938f0 4182 if (!insn && HAVE_cmpstrnsi)
6ac5504b 4183 {
4184 tree len;
4185 rtx arg3_rtx;
4186
a0c938f0 4187 enum machine_mode insn_mode
6ac5504b 4188 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
4189 tree len1 = c_strlen (arg1, 1);
4190 tree len2 = c_strlen (arg2, 1);
4191
4192 if (len1)
4193 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
4194 if (len2)
4195 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
4196
4197 /* If we don't have a constant length for the first, use the length
4198 of the second, if we know it. We don't require a constant for
4199 this case; some cost analysis could be done if both are available
4200 but neither is constant. For now, assume they're equally cheap,
4201 unless one has side effects. If both strings have constant lengths,
4202 use the smaller. */
4203
4204 if (!len1)
4205 len = len2;
4206 else if (!len2)
4207 len = len1;
4208 else if (TREE_SIDE_EFFECTS (len1))
4209 len = len2;
4210 else if (TREE_SIDE_EFFECTS (len2))
4211 len = len1;
4212 else if (TREE_CODE (len1) != INTEGER_CST)
4213 len = len2;
4214 else if (TREE_CODE (len2) != INTEGER_CST)
4215 len = len1;
4216 else if (tree_int_cst_lt (len1, len2))
4217 len = len1;
4218 else
4219 len = len2;
4220
4221 /* If both arguments have side effects, we cannot optimize. */
4222 if (!len || TREE_SIDE_EFFECTS (len))
6b961939 4223 goto do_libcall;
53800dbe 4224
8ec3c5c2 4225 arg3_rtx = expand_normal (len);
902de8ed 4226
6ac5504b 4227 /* Make a place to write the result of the instruction. */
4228 result = target;
4229 if (! (result != 0
4230 && REG_P (result) && GET_MODE (result) == insn_mode
4231 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4232 result = gen_reg_rtx (insn_mode);
53800dbe 4233
6ac5504b 4234 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4235 GEN_INT (MIN (arg1_align, arg2_align)));
4236 }
4237#endif
3f8aefe2 4238
6ac5504b 4239 if (insn)
4240 {
4241 emit_insn (insn);
3f8aefe2 4242
6ac5504b 4243 /* Return the value in the proper mode for this function. */
4244 mode = TYPE_MODE (TREE_TYPE (exp));
4245 if (GET_MODE (result) == mode)
4246 return result;
4247 if (target == 0)
4248 return convert_to_mode (mode, result, 0);
4249 convert_move (target, result, 0);
4250 return target;
4251 }
902de8ed 4252
6ac5504b 4253 /* Expand the library call ourselves using a stabilized argument
4254 list to avoid re-evaluating the function's arguments twice. */
2694880e 4255#ifdef HAVE_cmpstrnsi
6b961939 4256 do_libcall:
2694880e 4257#endif
6ac5504b 4258 fndecl = get_callee_fndecl (exp);
c2f47e15 4259 fn = build_call_expr (fndecl, 2, arg1, arg2);
6ac5504b 4260 if (TREE_CODE (fn) == CALL_EXPR)
4261 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4262 return expand_call (fn, target, target == const0_rtx);
4263 }
7a3f89b5 4264#endif
c2f47e15 4265 return NULL_RTX;
83d79705 4266}
53800dbe 4267
c2f47e15 4268/* Expand expression EXP, which is a call to the strncmp builtin. Return
4269 NULL_RTX if we failed the caller should emit a normal call, otherwise try to get
ed09096d 4270 the result in TARGET, if convenient. */
27d0c333 4271
ed09096d 4272static rtx
aecda0d6 4273expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
ed09096d 4274{
c2f47e15 4275 if (!validate_arglist (exp,
4276 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4277 return NULL_RTX;
218bc19e 4278 else
ef6c187e 4279 {
c2f47e15 4280 tree result = fold_builtin_strncmp (CALL_EXPR_ARG (exp, 0),
4281 CALL_EXPR_ARG (exp, 1),
4282 CALL_EXPR_ARG (exp, 2));
218bc19e 4283 if (result)
4284 return expand_expr (result, target, mode, EXPAND_NORMAL);
ef6c187e 4285 }
ed09096d 4286
6e34e617 4287 /* If c_strlen can determine an expression for one of the string
6ac5504b 4288 lengths, and it doesn't have side effects, then emit cmpstrnsi
7a3f89b5 4289 using length MIN(strlen(string)+1, arg3). */
6ac5504b 4290#ifdef HAVE_cmpstrnsi
4291 if (HAVE_cmpstrnsi)
7a3f89b5 4292 {
4293 tree len, len1, len2;
4294 rtx arg1_rtx, arg2_rtx, arg3_rtx;
4295 rtx result, insn;
0b25db21 4296 tree fndecl, fn;
c2f47e15 4297 tree arg1 = CALL_EXPR_ARG (exp, 0);
4298 tree arg2 = CALL_EXPR_ARG (exp, 1);
4299 tree arg3 = CALL_EXPR_ARG (exp, 2);
6f428e8b 4300
7a3f89b5 4301 int arg1_align
4302 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4303 int arg2_align
4304 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4305 enum machine_mode insn_mode
6ac5504b 4306 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
bf8e3599 4307
681fab1e 4308 len1 = c_strlen (arg1, 1);
4309 len2 = c_strlen (arg2, 1);
7a3f89b5 4310
4311 if (len1)
4312 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
4313 if (len2)
4314 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
4315
4316 /* If we don't have a constant length for the first, use the length
4317 of the second, if we know it. We don't require a constant for
4318 this case; some cost analysis could be done if both are available
4319 but neither is constant. For now, assume they're equally cheap,
4320 unless one has side effects. If both strings have constant lengths,
4321 use the smaller. */
4322
4323 if (!len1)
4324 len = len2;
4325 else if (!len2)
4326 len = len1;
4327 else if (TREE_SIDE_EFFECTS (len1))
4328 len = len2;
4329 else if (TREE_SIDE_EFFECTS (len2))
4330 len = len1;
4331 else if (TREE_CODE (len1) != INTEGER_CST)
4332 len = len2;
4333 else if (TREE_CODE (len2) != INTEGER_CST)
4334 len = len1;
4335 else if (tree_int_cst_lt (len1, len2))
4336 len = len1;
4337 else
4338 len = len2;
6e34e617 4339
7a3f89b5 4340 /* If both arguments have side effects, we cannot optimize. */
4341 if (!len || TREE_SIDE_EFFECTS (len))
c2f47e15 4342 return NULL_RTX;
bf8e3599 4343
7a3f89b5 4344 /* The actual new length parameter is MIN(len,arg3). */
49d00087 4345 len = fold_build2 (MIN_EXPR, TREE_TYPE (len), len,
4346 fold_convert (TREE_TYPE (len), arg3));
7a3f89b5 4347
4348 /* If we don't have POINTER_TYPE, call the function. */
4349 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4350 return NULL_RTX;
7a3f89b5 4351
4352 /* Make a place to write the result of the instruction. */
4353 result = target;
4354 if (! (result != 0
8ad4c111 4355 && REG_P (result) && GET_MODE (result) == insn_mode
7a3f89b5 4356 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4357 result = gen_reg_rtx (insn_mode);
4358
6ac5504b 4359 /* Stabilize the arguments in case gen_cmpstrnsi fails. */
4ee9c684 4360 arg1 = builtin_save_expr (arg1);
4361 arg2 = builtin_save_expr (arg2);
4362 len = builtin_save_expr (len);
3f8aefe2 4363
d8ae1baa 4364 arg1_rtx = get_memory_rtx (arg1, len);
4365 arg2_rtx = get_memory_rtx (arg2, len);
8ec3c5c2 4366 arg3_rtx = expand_normal (len);
6ac5504b 4367 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4368 GEN_INT (MIN (arg1_align, arg2_align)));
3f8aefe2 4369 if (insn)
4370 {
4371 emit_insn (insn);
4372
4373 /* Return the value in the proper mode for this function. */
4374 mode = TYPE_MODE (TREE_TYPE (exp));
4375 if (GET_MODE (result) == mode)
4376 return result;
4377 if (target == 0)
4378 return convert_to_mode (mode, result, 0);
4379 convert_move (target, result, 0);
4380 return target;
4381 }
7a3f89b5 4382
3f8aefe2 4383 /* Expand the library call ourselves using a stabilized argument
4384 list to avoid re-evaluating the function's arguments twice. */
3f8aefe2 4385 fndecl = get_callee_fndecl (exp);
c2f47e15 4386 fn = build_call_expr (fndecl, 3, arg1, arg2, len);
0b25db21 4387 if (TREE_CODE (fn) == CALL_EXPR)
4388 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4389 return expand_call (fn, target, target == const0_rtx);
7a3f89b5 4390 }
4391#endif
c2f47e15 4392 return NULL_RTX;
ed09096d 4393}
4394
49f0327b 4395/* Expand expression EXP, which is a call to the strcat builtin.
c2f47e15 4396 Return NULL_RTX if we failed the caller should emit a normal call,
49f0327b 4397 otherwise try to get the result in TARGET, if convenient. */
27d0c333 4398
49f0327b 4399static rtx
c2f47e15 4400expand_builtin_strcat (tree fndecl, tree exp, rtx target, enum machine_mode mode)
49f0327b 4401{
c2f47e15 4402 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4403 return NULL_RTX;
49f0327b 4404 else
4405 {
c2f47e15 4406 tree dst = CALL_EXPR_ARG (exp, 0);
4407 tree src = CALL_EXPR_ARG (exp, 1);
49f0327b 4408 const char *p = c_getstr (src);
4409
1d89860b 4410 /* If the string length is zero, return the dst parameter. */
a0c938f0 4411 if (p && *p == '\0')
1d89860b 4412 return expand_expr (dst, target, mode, EXPAND_NORMAL);
a0c938f0 4413
1d89860b 4414 if (!optimize_size)
ca71f89b 4415 {
1d89860b 4416 /* See if we can store by pieces into (dst + strlen(dst)). */
4417 tree newsrc, newdst,
4418 strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
4419 rtx insns;
4420
4421 /* Stabilize the argument list. */
4422 newsrc = builtin_save_expr (src);
1d89860b 4423 dst = builtin_save_expr (dst);
4424
4425 start_sequence ();
4426
4427 /* Create strlen (dst). */
c2f47e15 4428 newdst = build_call_expr (strlen_fn, 1, dst);
1d89860b 4429 /* Create (dst + (cast) strlen (dst)). */
4430 newdst = fold_convert (TREE_TYPE (dst), newdst);
4431 newdst = fold_build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
4432
4433 newdst = builtin_save_expr (newdst);
1d89860b 4434
c2f47e15 4435 if (!expand_builtin_strcpy_args (fndecl, newdst, newsrc, target, mode))
ca71f89b 4436 {
1d89860b 4437 end_sequence (); /* Stop sequence. */
c2f47e15 4438 return NULL_RTX;
ca71f89b 4439 }
a0c938f0 4440
1d89860b 4441 /* Output the entire sequence. */
4442 insns = get_insns ();
4443 end_sequence ();
4444 emit_insn (insns);
a0c938f0 4445
1d89860b 4446 return expand_expr (dst, target, mode, EXPAND_NORMAL);
ca71f89b 4447 }
49f0327b 4448
c2f47e15 4449 return NULL_RTX;
49f0327b 4450 }
4451}
4452
4453/* Expand expression EXP, which is a call to the strncat builtin.
c2f47e15 4454 Return NULL_RTX if we failed the caller should emit a normal call,
49f0327b 4455 otherwise try to get the result in TARGET, if convenient. */
27d0c333 4456
49f0327b 4457static rtx
c2f47e15 4458expand_builtin_strncat (tree exp, rtx target, enum machine_mode mode)
49f0327b 4459{
c2f47e15 4460 if (validate_arglist (exp,
4461 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
49f0327b 4462 {
c2f47e15 4463 tree result = fold_builtin_strncat (CALL_EXPR_ARG (exp, 0),
4464 CALL_EXPR_ARG (exp, 1),
4465 CALL_EXPR_ARG (exp, 2));
2c84ee37 4466 if (result)
4467 return expand_expr (result, target, mode, EXPAND_NORMAL);
49f0327b 4468 }
c2f47e15 4469 return NULL_RTX;
49f0327b 4470}
4471
4472/* Expand expression EXP, which is a call to the strspn builtin.
c2f47e15 4473 Return NULL_RTX if we failed the caller should emit a normal call,
49f0327b 4474 otherwise try to get the result in TARGET, if convenient. */
27d0c333 4475
49f0327b 4476static rtx
c2f47e15 4477expand_builtin_strspn (tree exp, rtx target, enum machine_mode mode)
49f0327b 4478{
c2f47e15 4479 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
49f0327b 4480 {
c2f47e15 4481 tree result = fold_builtin_strspn (CALL_EXPR_ARG (exp, 0),
4482 CALL_EXPR_ARG (exp, 1));
2c84ee37 4483 if (result)
4484 return expand_expr (result, target, mode, EXPAND_NORMAL);
49f0327b 4485 }
c2f47e15 4486 return NULL_RTX;
49f0327b 4487}
4488
4489/* Expand expression EXP, which is a call to the strcspn 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_strcspn (tree exp, rtx target, enum machine_mode mode)
49f0327b 4495{
c2f47e15 4496 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
49f0327b 4497 {
c2f47e15 4498 tree result = fold_builtin_strcspn (CALL_EXPR_ARG (exp, 0),
4499 CALL_EXPR_ARG (exp, 1));
2c84ee37 4500 if (result)
4501 return expand_expr (result, target, mode, EXPAND_NORMAL);
49f0327b 4502 }
c2f47e15 4503 return NULL_RTX;
49f0327b 4504}
4505
a66c9326 4506/* Expand a call to __builtin_saveregs, generating the result in TARGET,
4507 if that's convenient. */
902de8ed 4508
a66c9326 4509rtx
aecda0d6 4510expand_builtin_saveregs (void)
53800dbe 4511{
a66c9326 4512 rtx val, seq;
53800dbe 4513
4514 /* Don't do __builtin_saveregs more than once in a function.
4515 Save the result of the first call and reuse it. */
4516 if (saveregs_value != 0)
4517 return saveregs_value;
53800dbe 4518
a66c9326 4519 /* When this function is called, it means that registers must be
4520 saved on entry to this function. So we migrate the call to the
4521 first insn of this function. */
4522
4523 start_sequence ();
53800dbe 4524
a66c9326 4525 /* Do whatever the machine needs done in this case. */
45550790 4526 val = targetm.calls.expand_builtin_saveregs ();
53800dbe 4527
a66c9326 4528 seq = get_insns ();
4529 end_sequence ();
53800dbe 4530
a66c9326 4531 saveregs_value = val;
53800dbe 4532
31d3e01c 4533 /* Put the insns after the NOTE that starts the function. If this
4534 is inside a start_sequence, make the outer-level insn chain current, so
a66c9326 4535 the code is placed at the start of the function. */
4536 push_topmost_sequence ();
0ec80471 4537 emit_insn_after (seq, entry_of_function ());
a66c9326 4538 pop_topmost_sequence ();
4539
4540 return val;
53800dbe 4541}
4542
4543/* __builtin_args_info (N) returns word N of the arg space info
4544 for the current function. The number and meanings of words
4545 is controlled by the definition of CUMULATIVE_ARGS. */
f7c44134 4546
53800dbe 4547static rtx
c2f47e15 4548expand_builtin_args_info (tree exp)
53800dbe 4549{
53800dbe 4550 int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
4551 int *word_ptr = (int *) &current_function_args_info;
53800dbe 4552
64db345d 4553 gcc_assert (sizeof (CUMULATIVE_ARGS) % sizeof (int) == 0);
53800dbe 4554
c2f47e15 4555 if (call_expr_nargs (exp) != 0)
53800dbe 4556 {
c2f47e15 4557 if (!host_integerp (CALL_EXPR_ARG (exp, 0), 0))
eb586f2c 4558 error ("argument of %<__builtin_args_info%> must be constant");
53800dbe 4559 else
4560 {
c2f47e15 4561 HOST_WIDE_INT wordnum = tree_low_cst (CALL_EXPR_ARG (exp, 0), 0);
53800dbe 4562
27d0c333 4563 if (wordnum < 0 || wordnum >= nwords)
eb586f2c 4564 error ("argument of %<__builtin_args_info%> out of range");
53800dbe 4565 else
4566 return GEN_INT (word_ptr[wordnum]);
4567 }
4568 }
4569 else
eb586f2c 4570 error ("missing argument in %<__builtin_args_info%>");
53800dbe 4571
4572 return const0_rtx;
53800dbe 4573}
4574
79012a9d 4575/* Expand a call to __builtin_next_arg. */
27d0c333 4576
53800dbe 4577static rtx
79012a9d 4578expand_builtin_next_arg (void)
53800dbe 4579{
79012a9d 4580 /* Checking arguments is already done in fold_builtin_next_arg
4581 that must be called before this function. */
53800dbe 4582 return expand_binop (Pmode, add_optab,
4583 current_function_internal_arg_pointer,
4584 current_function_arg_offset_rtx,
4585 NULL_RTX, 0, OPTAB_LIB_WIDEN);
4586}
4587
a66c9326 4588/* Make it easier for the backends by protecting the valist argument
4589 from multiple evaluations. */
4590
4591static tree
aecda0d6 4592stabilize_va_list (tree valist, int needs_lvalue)
a66c9326 4593{
11a61dea 4594 if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
a66c9326 4595 {
2d47cc32 4596 if (TREE_SIDE_EFFECTS (valist))
4597 valist = save_expr (valist);
11a61dea 4598
2d47cc32 4599 /* For this case, the backends will be expecting a pointer to
4600 TREE_TYPE (va_list_type_node), but it's possible we've
4601 actually been given an array (an actual va_list_type_node).
4602 So fix it. */
4603 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
8a15c04a 4604 {
bf8e3599 4605 tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
fcdd3ab3 4606 valist = build_fold_addr_expr_with_type (valist, p1);
8a15c04a 4607 }
a66c9326 4608 }
11a61dea 4609 else
a66c9326 4610 {
2d47cc32 4611 tree pt;
11a61dea 4612
2d47cc32 4613 if (! needs_lvalue)
4614 {
11a61dea 4615 if (! TREE_SIDE_EFFECTS (valist))
4616 return valist;
bf8e3599 4617
11a61dea 4618 pt = build_pointer_type (va_list_type_node);
49d00087 4619 valist = fold_build1 (ADDR_EXPR, pt, valist);
a66c9326 4620 TREE_SIDE_EFFECTS (valist) = 1;
a66c9326 4621 }
2d47cc32 4622
11a61dea 4623 if (TREE_SIDE_EFFECTS (valist))
2d47cc32 4624 valist = save_expr (valist);
fcdd3ab3 4625 valist = build_fold_indirect_ref (valist);
a66c9326 4626 }
4627
4628 return valist;
4629}
4630
2e15d750 4631/* The "standard" definition of va_list is void*. */
4632
4633tree
4634std_build_builtin_va_list (void)
4635{
4636 return ptr_type_node;
4637}
4638
a66c9326 4639/* The "standard" implementation of va_start: just assign `nextarg' to
4640 the variable. */
27d0c333 4641
a66c9326 4642void
aecda0d6 4643std_expand_builtin_va_start (tree valist, rtx nextarg)
a66c9326 4644{
4645 tree t;
4646
41076ef6 4647 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist,
05abc81b 4648 make_tree (ptr_type_node, nextarg));
a66c9326 4649 TREE_SIDE_EFFECTS (t) = 1;
4650
4651 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4652}
4653
c2f47e15 4654/* Expand EXP, a call to __builtin_va_start. */
27d0c333 4655
a66c9326 4656static rtx
c2f47e15 4657expand_builtin_va_start (tree exp)
a66c9326 4658{
4659 rtx nextarg;
c2f47e15 4660 tree valist;
a66c9326 4661
c2f47e15 4662 if (call_expr_nargs (exp) < 2)
cb166087 4663 {
4664 error ("too few arguments to function %<va_start%>");
4665 return const0_rtx;
4666 }
a66c9326 4667
c2f47e15 4668 if (fold_builtin_next_arg (exp, true))
79012a9d 4669 return const0_rtx;
7c2f0500 4670
79012a9d 4671 nextarg = expand_builtin_next_arg ();
c2f47e15 4672 valist = stabilize_va_list (CALL_EXPR_ARG (exp, 0), 1);
a66c9326 4673
4674#ifdef EXPAND_BUILTIN_VA_START
7df226a2 4675 EXPAND_BUILTIN_VA_START (valist, nextarg);
a66c9326 4676#else
7df226a2 4677 std_expand_builtin_va_start (valist, nextarg);
a66c9326 4678#endif
4679
4680 return const0_rtx;
4681}
4682
a66c9326 4683/* The "standard" implementation of va_arg: read the value from the
4684 current (padded) address and increment by the (padded) size. */
f7c44134 4685
e0eca1fa 4686tree
4687std_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
fcdd3ab3 4688{
52cc2eeb 4689 tree addr, t, type_size, rounded_size, valist_tmp;
b8e8e485 4690 unsigned HOST_WIDE_INT align, boundary;
bef380a4 4691 bool indirect;
52cc2eeb 4692
4693#ifdef ARGS_GROW_DOWNWARD
4694 /* All of the alignment and movement below is for args-grow-up machines.
4695 As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
4696 implement their own specialized gimplify_va_arg_expr routines. */
64db345d 4697 gcc_unreachable ();
52cc2eeb 4698#endif
fcdd3ab3 4699
bef380a4 4700 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
4701 if (indirect)
4702 type = build_pointer_type (type);
4703
52cc2eeb 4704 align = PARM_BOUNDARY / BITS_PER_UNIT;
bcff3604 4705 boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type) / BITS_PER_UNIT;
fcdd3ab3 4706
52cc2eeb 4707 /* Hoist the valist value into a temporary for the moment. */
ecdeeb37 4708 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
4709
fcdd3ab3 4710 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
4711 requires greater alignment, we must perform dynamic alignment. */
85c1f587 4712 if (boundary > align
4713 && !integer_zerop (TYPE_SIZE (type)))
fcdd3ab3 4714 {
bcff3604 4715 t = fold_convert (TREE_TYPE (valist), size_int (boundary - 1));
41076ef6 4716 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
52cc2eeb 4717 build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t));
4718 gimplify_and_add (t, pre_p);
4719
bcff3604 4720 t = fold_convert (TREE_TYPE (valist), size_int (-boundary));
41076ef6 4721 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
52cc2eeb 4722 build2 (BIT_AND_EXPR, TREE_TYPE (valist), valist_tmp, t));
ecdeeb37 4723 gimplify_and_add (t, pre_p);
fcdd3ab3 4724 }
c5dc0c32 4725 else
4726 boundary = align;
4727
4728 /* If the actual alignment is less than the alignment of the type,
4729 adjust the type accordingly so that we don't assume strict alignment
4730 when deferencing the pointer. */
4731 boundary *= BITS_PER_UNIT;
4732 if (boundary < TYPE_ALIGN (type))
4733 {
4734 type = build_variant_type_copy (type);
4735 TYPE_ALIGN (type) = boundary;
4736 }
fcdd3ab3 4737
bcff3604 4738 /* Compute the rounded size of the type. */
52cc2eeb 4739 type_size = size_in_bytes (type);
4740 rounded_size = round_up (type_size, align);
4741
fcdd3ab3 4742 /* Reduce rounded_size so it's sharable with the postqueue. */
4743 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
4744
4745 /* Get AP. */
ecdeeb37 4746 addr = valist_tmp;
52cc2eeb 4747 if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
fcdd3ab3 4748 {
4749 /* Small args are padded downward. */
49d00087 4750 t = fold_build2 (GT_EXPR, sizetype, rounded_size, size_int (align));
4751 t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
4752 size_binop (MINUS_EXPR, rounded_size, type_size));
52cc2eeb 4753 t = fold_convert (TREE_TYPE (addr), t);
49d00087 4754 addr = fold_build2 (PLUS_EXPR, TREE_TYPE (addr), addr, t);
fcdd3ab3 4755 }
4756
fcdd3ab3 4757 /* Compute new value for AP. */
52cc2eeb 4758 t = fold_convert (TREE_TYPE (valist), rounded_size);
4759 t = build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t);
41076ef6 4760 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
ecdeeb37 4761 gimplify_and_add (t, pre_p);
e0eca1fa 4762
4763 addr = fold_convert (build_pointer_type (type), addr);
fcdd3ab3 4764
bef380a4 4765 if (indirect)
f2462d6c 4766 addr = build_va_arg_indirect_ref (addr);
4767
4768 return build_va_arg_indirect_ref (addr);
4769}
a0930a69 4770
f2462d6c 4771/* Build an indirect-ref expression over the given TREE, which represents a
4772 piece of a va_arg() expansion. */
4773tree
4774build_va_arg_indirect_ref (tree addr)
4775{
a0930a69 4776 addr = build_fold_indirect_ref (addr);
f2462d6c 4777
a0930a69 4778 if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */
4779 mf_mark (addr);
bef380a4 4780
a0930a69 4781 return addr;
433006a9 4782}
4783
fcdd3ab3 4784/* Return a dummy expression of type TYPE in order to keep going after an
4785 error. */
4786
4787static tree
4788dummy_object (tree type)
4789{
535664e3 4790 tree t = build_int_cst (build_pointer_type (type), 0);
fcdd3ab3 4791 return build1 (INDIRECT_REF, type, t);
4792}
4793
2799a2b7 4794/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
4795 builtin function, but a very special sort of operator. */
fcdd3ab3 4796
4797enum gimplify_status
4798gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p)
4799{
4800 tree promoted_type, want_va_type, have_va_type;
4801 tree valist = TREE_OPERAND (*expr_p, 0);
4802 tree type = TREE_TYPE (*expr_p);
4803 tree t;
4804
4805 /* Verify that valist is of the proper type. */
fcdd3ab3 4806 want_va_type = va_list_type_node;
4807 have_va_type = TREE_TYPE (valist);
f43dda35 4808
4809 if (have_va_type == error_mark_node)
4810 return GS_ERROR;
4811
fcdd3ab3 4812 if (TREE_CODE (want_va_type) == ARRAY_TYPE)
4813 {
4814 /* If va_list is an array type, the argument may have decayed
4815 to a pointer type, e.g. by being passed to another function.
a0c938f0 4816 In that case, unwrap both types so that we can compare the
fcdd3ab3 4817 underlying records. */
4818 if (TREE_CODE (have_va_type) == ARRAY_TYPE
552752f7 4819 || POINTER_TYPE_P (have_va_type))
fcdd3ab3 4820 {
4821 want_va_type = TREE_TYPE (want_va_type);
4822 have_va_type = TREE_TYPE (have_va_type);
4823 }
4824 }
4825
4826 if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
4827 {
eb586f2c 4828 error ("first argument to %<va_arg%> not of type %<va_list%>");
e0eca1fa 4829 return GS_ERROR;
fcdd3ab3 4830 }
4831
4832 /* Generate a diagnostic for requesting data of a type that cannot
4833 be passed through `...' due to type promotion at the call site. */
4834 else if ((promoted_type = lang_hooks.types.type_promotes_to (type))
4835 != type)
4836 {
4837 static bool gave_help;
4838
4839 /* Unfortunately, this is merely undefined, rather than a constraint
4840 violation, so we cannot make this an error. If this call is never
4841 executed, the program is still strictly conforming. */
c3ceba8e 4842 warning (0, "%qT is promoted to %qT when passed through %<...%>",
fcdd3ab3 4843 type, promoted_type);
4844 if (! gave_help)
4845 {
4846 gave_help = true;
c3ceba8e 4847 warning (0, "(so you should pass %qT not %qT to %<va_arg%>)",
fcdd3ab3 4848 promoted_type, type);
4849 }
4850
4851 /* We can, however, treat "undefined" any way we please.
4852 Call abort to encourage the user to fix the program. */
4853 inform ("if this code is reached, the program will abort");
c2f47e15 4854 t = build_call_expr (implicit_built_in_decls[BUILT_IN_TRAP], 0);
fcdd3ab3 4855 append_to_statement_list (t, pre_p);
4856
4857 /* This is dead code, but go ahead and finish so that the
4858 mode of the result comes out right. */
4859 *expr_p = dummy_object (type);
4860 return GS_ALL_DONE;
4861 }
4862 else
4863 {
4864 /* Make it easier for the backends by protecting the valist argument
a0c938f0 4865 from multiple evaluations. */
e0eca1fa 4866 if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
4867 {
4868 /* For this case, the backends will be expecting a pointer to
4869 TREE_TYPE (va_list_type_node), but it's possible we've
4870 actually been given an array (an actual va_list_type_node).
4871 So fix it. */
4872 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
4873 {
4874 tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
4875 valist = build_fold_addr_expr_with_type (valist, p1);
4876 }
4877 gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
4878 }
4879 else
4880 gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
fcdd3ab3 4881
17a6380d 4882 if (!targetm.gimplify_va_arg_expr)
89f18f73 4883 /* FIXME:Once most targets are converted we should merely
4884 assert this is non-null. */
fcdd3ab3 4885 return GS_ALL_DONE;
4886
17a6380d 4887 *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
fcdd3ab3 4888 return GS_OK;
4889 }
4890}
4891
c2f47e15 4892/* Expand EXP, a call to __builtin_va_end. */
f7c44134 4893
a66c9326 4894static rtx
c2f47e15 4895expand_builtin_va_end (tree exp)
a66c9326 4896{
c2f47e15 4897 tree valist = CALL_EXPR_ARG (exp, 0);
8a15c04a 4898
8a15c04a 4899 /* Evaluate for side effects, if needed. I hate macros that don't
4900 do that. */
4901 if (TREE_SIDE_EFFECTS (valist))
4902 expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
a66c9326 4903
4904 return const0_rtx;
4905}
4906
c2f47e15 4907/* Expand EXP, a call to __builtin_va_copy. We do this as a
a66c9326 4908 builtin rather than just as an assignment in stdarg.h because of the
4909 nastiness of array-type va_list types. */
f7c44134 4910
a66c9326 4911static rtx
c2f47e15 4912expand_builtin_va_copy (tree exp)
a66c9326 4913{
4914 tree dst, src, t;
4915
c2f47e15 4916 dst = CALL_EXPR_ARG (exp, 0);
4917 src = CALL_EXPR_ARG (exp, 1);
a66c9326 4918
4919 dst = stabilize_va_list (dst, 1);
4920 src = stabilize_va_list (src, 0);
4921
4922 if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
4923 {
41076ef6 4924 t = build2 (MODIFY_EXPR, va_list_type_node, dst, src);
a66c9326 4925 TREE_SIDE_EFFECTS (t) = 1;
4926 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4927 }
4928 else
4929 {
11a61dea 4930 rtx dstb, srcb, size;
4931
4932 /* Evaluate to pointers. */
4933 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
4934 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
4935 size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
4936 VOIDmode, EXPAND_NORMAL);
4937
85d654dd 4938 dstb = convert_memory_address (Pmode, dstb);
4939 srcb = convert_memory_address (Pmode, srcb);
726ec87c 4940
11a61dea 4941 /* "Dereference" to BLKmode memories. */
4942 dstb = gen_rtx_MEM (BLKmode, dstb);
ab6ab77e 4943 set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
2a631e19 4944 set_mem_align (dstb, TYPE_ALIGN (va_list_type_node));
11a61dea 4945 srcb = gen_rtx_MEM (BLKmode, srcb);
ab6ab77e 4946 set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
2a631e19 4947 set_mem_align (srcb, TYPE_ALIGN (va_list_type_node));
11a61dea 4948
4949 /* Copy. */
0378dbdc 4950 emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
a66c9326 4951 }
4952
4953 return const0_rtx;
4954}
4955
53800dbe 4956/* Expand a call to one of the builtin functions __builtin_frame_address or
4957 __builtin_return_address. */
27d0c333 4958
53800dbe 4959static rtx
c2f47e15 4960expand_builtin_frame_address (tree fndecl, tree exp)
53800dbe 4961{
53800dbe 4962 /* The argument must be a nonnegative integer constant.
4963 It counts the number of frames to scan up the stack.
4964 The value is the return address saved in that frame. */
c2f47e15 4965 if (call_expr_nargs (exp) == 0)
53800dbe 4966 /* Warning about missing arg was already issued. */
4967 return const0_rtx;
c2f47e15 4968 else if (! host_integerp (CALL_EXPR_ARG (exp, 0), 1))
53800dbe 4969 {
4970 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
07e3a3d2 4971 error ("invalid argument to %<__builtin_frame_address%>");
53800dbe 4972 else
07e3a3d2 4973 error ("invalid argument to %<__builtin_return_address%>");
53800dbe 4974 return const0_rtx;
4975 }
4976 else
4977 {
27d0c333 4978 rtx tem
4979 = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
c2f47e15 4980 tree_low_cst (CALL_EXPR_ARG (exp, 0), 1));
53800dbe 4981
4982 /* Some ports cannot access arbitrary stack frames. */
4983 if (tem == NULL)
4984 {
4985 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
c3ceba8e 4986 warning (0, "unsupported argument to %<__builtin_frame_address%>");
53800dbe 4987 else
c3ceba8e 4988 warning (0, "unsupported argument to %<__builtin_return_address%>");
53800dbe 4989 return const0_rtx;
4990 }
4991
4992 /* For __builtin_frame_address, return what we've got. */
4993 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4994 return tem;
4995
8ad4c111 4996 if (!REG_P (tem)
53800dbe 4997 && ! CONSTANT_P (tem))
4998 tem = copy_to_mode_reg (Pmode, tem);
4999 return tem;
5000 }
5001}
5002
c2f47e15 5003/* Expand EXP, a call to the alloca builtin. Return NULL_RTX if
53800dbe 5004 we failed and the caller should emit a normal call, otherwise try to get
5005 the result in TARGET, if convenient. */
15c6cf6b 5006
53800dbe 5007static rtx
c2f47e15 5008expand_builtin_alloca (tree exp, rtx target)
53800dbe 5009{
5010 rtx op0;
15c6cf6b 5011 rtx result;
53800dbe 5012
4ee9c684 5013 /* In -fmudflap-instrumented code, alloca() and __builtin_alloca()
5014 should always expand to function calls. These can be intercepted
5015 in libmudflap. */
5016 if (flag_mudflap)
c2f47e15 5017 return NULL_RTX;
4ee9c684 5018
c2f47e15 5019 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
5020 return NULL_RTX;
53800dbe 5021
5022 /* Compute the argument. */
c2f47e15 5023 op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
53800dbe 5024
5025 /* Allocate the desired space. */
15c6cf6b 5026 result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
85d654dd 5027 result = convert_memory_address (ptr_mode, result);
15c6cf6b 5028
5029 return result;
53800dbe 5030}
5031
c2f47e15 5032/* Expand a call to a bswap builtin with argument ARG0. MODE
42791117 5033 is the mode to expand with. */
5034
5035static rtx
c2f47e15 5036expand_builtin_bswap (tree exp, rtx target, rtx subtarget)
42791117 5037{
5038 enum machine_mode mode;
5039 tree arg;
5040 rtx op0;
5041
c2f47e15 5042 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
5043 return NULL_RTX;
42791117 5044
c2f47e15 5045 arg = CALL_EXPR_ARG (exp, 0);
42791117 5046 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 5047 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
42791117 5048
5049 target = expand_unop (mode, bswap_optab, op0, target, 1);
5050
5051 gcc_assert (target);
5052
5053 return convert_to_mode (mode, target, 0);
5054}
5055
c2f47e15 5056/* Expand a call to a unary builtin in EXP.
5057 Return NULL_RTX if a normal call should be emitted rather than expanding the
53800dbe 5058 function in-line. If convenient, the result should be placed in TARGET.
5059 SUBTARGET may be used as the target for computing one of EXP's operands. */
15c6cf6b 5060
53800dbe 5061static rtx
c2f47e15 5062expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target,
aecda0d6 5063 rtx subtarget, optab op_optab)
53800dbe 5064{
5065 rtx op0;
c2f47e15 5066
5067 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
5068 return NULL_RTX;
53800dbe 5069
5070 /* Compute the argument. */
1db6d067 5071 op0 = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
5072 VOIDmode, EXPAND_NORMAL);
6a08d0ab 5073 /* Compute op, into TARGET if possible.
53800dbe 5074 Set TARGET to wherever the result comes back. */
c2f47e15 5075 target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
6a08d0ab 5076 op_optab, op0, target, 1);
64db345d 5077 gcc_assert (target);
7d3f6cc7 5078
efb070c8 5079 return convert_to_mode (target_mode, target, 0);
53800dbe 5080}
89cfe6e5 5081
df94cd3b 5082/* If the string passed to fputs is a constant and is one character
2c0e001b 5083 long, we attempt to transform this call into __builtin_fputc(). */
15c6cf6b 5084
df94cd3b 5085static rtx
c2f47e15 5086expand_builtin_fputs (tree exp, rtx target, bool unlocked)
df94cd3b 5087{
2c0e001b 5088 /* Verify the arguments in the original call. */
c2f47e15 5089 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
ce1b14f4 5090 {
c2f47e15 5091 tree result = fold_builtin_fputs (CALL_EXPR_ARG (exp, 0),
5092 CALL_EXPR_ARG (exp, 1),
5093 (target == const0_rtx),
2c84ee37 5094 unlocked, NULL_TREE);
5095 if (result)
5096 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
ce1b14f4 5097 }
c2f47e15 5098 return NULL_RTX;
3311f67b 5099}
5100
5a74f77e 5101/* Expand a call to __builtin_expect. We just return our argument
5102 as the builtin_expect semantic should've been already executed by
5103 tree branch prediction pass. */
89cfe6e5 5104
5105static rtx
c2f47e15 5106expand_builtin_expect (tree exp, rtx target)
89cfe6e5 5107{
c2f47e15 5108 tree arg, c;
89cfe6e5 5109
c2f47e15 5110 if (call_expr_nargs (exp) < 2)
89cfe6e5 5111 return const0_rtx;
c2f47e15 5112 arg = CALL_EXPR_ARG (exp, 0);
5113 c = CALL_EXPR_ARG (exp, 1);
89cfe6e5 5114
c2f47e15 5115 target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5a74f77e 5116 /* When guessing was done, the hints should be already stripped away. */
5117 gcc_assert (!flag_guess_branch_prob);
89cfe6e5 5118 return target;
5119}
689df48e 5120
c22de3f0 5121void
aecda0d6 5122expand_builtin_trap (void)
a0ef1725 5123{
5124#ifdef HAVE_trap
5125 if (HAVE_trap)
5126 emit_insn (gen_trap ());
5127 else
5128#endif
5129 emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
5130 emit_barrier ();
5131}
78a74442 5132
c2f47e15 5133/* Expand EXP, a call to fabs, fabsf or fabsl.
5134 Return NULL_RTX if a normal call should be emitted rather than expanding
78a74442 5135 the function inline. If convenient, the result should be placed
5136 in TARGET. SUBTARGET may be used as the target for computing
5137 the operand. */
5138
5139static rtx
c2f47e15 5140expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
78a74442 5141{
5142 enum machine_mode mode;
5143 tree arg;
5144 rtx op0;
5145
c2f47e15 5146 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
5147 return NULL_RTX;
78a74442 5148
c2f47e15 5149 arg = CALL_EXPR_ARG (exp, 0);
78a74442 5150 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 5151 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
78a74442 5152 return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
5153}
5154
c2f47e15 5155/* Expand EXP, a call to copysign, copysignf, or copysignl.
270436f3 5156 Return NULL is a normal call should be emitted rather than expanding the
5157 function inline. If convenient, the result should be placed in TARGET.
5158 SUBTARGET may be used as the target for computing the operand. */
5159
5160static rtx
c2f47e15 5161expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
270436f3 5162{
5163 rtx op0, op1;
5164 tree arg;
5165
c2f47e15 5166 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
5167 return NULL_RTX;
270436f3 5168
c2f47e15 5169 arg = CALL_EXPR_ARG (exp, 0);
8ec3c5c2 5170 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
270436f3 5171
c2f47e15 5172 arg = CALL_EXPR_ARG (exp, 1);
8ec3c5c2 5173 op1 = expand_normal (arg);
270436f3 5174
5175 return expand_copysign (op0, op1, target);
5176}
5177
19bf118a 5178/* Create a new constant string literal and return a char* pointer to it.
5179 The STRING_CST value is the LEN characters at STR. */
1e8e9920 5180tree
19bf118a 5181build_string_literal (int len, const char *str)
5182{
5183 tree t, elem, index, type;
5184
5185 t = build_string (len, str);
5186 elem = build_type_variant (char_type_node, 1, 0);
7016c612 5187 index = build_index_type (build_int_cst (NULL_TREE, len - 1));
19bf118a 5188 type = build_array_type (elem, index);
5189 TREE_TYPE (t) = type;
5190 TREE_CONSTANT (t) = 1;
4ee9c684 5191 TREE_INVARIANT (t) = 1;
19bf118a 5192 TREE_READONLY (t) = 1;
5193 TREE_STATIC (t) = 1;
5194
5195 type = build_pointer_type (type);
5196 t = build1 (ADDR_EXPR, type, t);
5197
5198 type = build_pointer_type (elem);
5199 t = build1 (NOP_EXPR, type, t);
5200 return t;
5201}
5202
0b25db21 5203/* Expand EXP, a call to printf or printf_unlocked.
c2f47e15 5204 Return NULL_RTX if a normal call should be emitted rather than transforming
19bf118a 5205 the function inline. If convenient, the result should be placed in
0862b7e9 5206 TARGET with mode MODE. UNLOCKED indicates this is a printf_unlocked
19bf118a 5207 call. */
5208static rtx
0b25db21 5209expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
19bf118a 5210 bool unlocked)
5211{
6d77ed92 5212 /* If we're using an unlocked function, assume the other unlocked
5213 functions exist explicitly. */
5214 tree const fn_putchar = unlocked ? built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
5215 : implicit_built_in_decls[BUILT_IN_PUTCHAR];
5216 tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED]
5217 : implicit_built_in_decls[BUILT_IN_PUTS];
19bf118a 5218 const char *fmt_str;
c2f47e15 5219 tree fn = 0;
5220 tree fmt, arg;
5221 int nargs = call_expr_nargs (exp);
19bf118a 5222
5223 /* If the return value is used, don't do the transformation. */
5224 if (target != const0_rtx)
c2f47e15 5225 return NULL_RTX;
19bf118a 5226
5227 /* Verify the required arguments in the original call. */
c2f47e15 5228 if (nargs == 0)
5229 return NULL_RTX;
5230 fmt = CALL_EXPR_ARG (exp, 0);
552752f7 5231 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
c2f47e15 5232 return NULL_RTX;
19bf118a 5233
5234 /* Check whether the format is a literal string constant. */
5235 fmt_str = c_getstr (fmt);
5236 if (fmt_str == NULL)
c2f47e15 5237 return NULL_RTX;
19bf118a 5238
d4473c84 5239 if (!init_target_chars ())
c2f47e15 5240 return NULL_RTX;
a0c938f0 5241
19bf118a 5242 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
99eabcc1 5243 if (strcmp (fmt_str, target_percent_s_newline) == 0)
19bf118a 5244 {
c2f47e15 5245 if ((nargs != 2)
5246 || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (exp, 1))))
5247 return NULL_RTX;
5248 if (fn_puts)
5249 fn = build_call_expr (fn_puts, 1, CALL_EXPR_ARG (exp, 1));
19bf118a 5250 }
5251 /* If the format specifier was "%c", call __builtin_putchar(arg). */
99eabcc1 5252 else if (strcmp (fmt_str, target_percent_c) == 0)
19bf118a 5253 {
c2f47e15 5254 if ((nargs != 2)
5255 || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1))) != INTEGER_TYPE)
5256 return NULL_RTX;
5257 if (fn_putchar)
5258 fn = build_call_expr (fn_putchar, 1, CALL_EXPR_ARG (exp, 1));
19bf118a 5259 }
5260 else
5261 {
5262 /* We can't handle anything else with % args or %% ... yet. */
99eabcc1 5263 if (strchr (fmt_str, target_percent))
c2f47e15 5264 return NULL_RTX;
19bf118a 5265
c2f47e15 5266 if (nargs > 1)
5267 return NULL_RTX;
19bf118a 5268
5269 /* If the format specifier was "", printf does nothing. */
5270 if (fmt_str[0] == '\0')
5271 return const0_rtx;
5272 /* If the format specifier has length of 1, call putchar. */
5273 if (fmt_str[1] == '\0')
5274 {
5275 /* Given printf("c"), (where c is any one character,)
5276 convert "c"[0] to an int and pass that to the replacement
5277 function. */
7016c612 5278 arg = build_int_cst (NULL_TREE, fmt_str[0]);
c2f47e15 5279 if (fn_putchar)
5280 fn = build_call_expr (fn_putchar, 1, arg);
19bf118a 5281 }
5282 else
5283 {
5284 /* If the format specifier was "string\n", call puts("string"). */
5285 size_t len = strlen (fmt_str);
99eabcc1 5286 if ((unsigned char)fmt_str[len - 1] == target_newline)
19bf118a 5287 {
91c82c20 5288 /* Create a NUL-terminated string that's one char shorter
19bf118a 5289 than the original, stripping off the trailing '\n'. */
4acc30e5 5290 char *newstr = alloca (len);
19bf118a 5291 memcpy (newstr, fmt_str, len - 1);
5292 newstr[len - 1] = 0;
19bf118a 5293 arg = build_string_literal (len, newstr);
c2f47e15 5294 if (fn_puts)
5295 fn = build_call_expr (fn_puts, 1, arg);
19bf118a 5296 }
5297 else
5298 /* We'd like to arrange to call fputs(string,stdout) here,
5299 but we need stdout and don't have a way to get it yet. */
c2f47e15 5300 return NULL_RTX;
19bf118a 5301 }
5302 }
5303
5304 if (!fn)
c2f47e15 5305 return NULL_RTX;
0b25db21 5306 if (TREE_CODE (fn) == CALL_EXPR)
5307 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
5308 return expand_expr (fn, target, mode, EXPAND_NORMAL);
19bf118a 5309}
5310
0b25db21 5311/* Expand EXP, a call to fprintf or fprintf_unlocked.
c2f47e15 5312 Return NULL_RTX if a normal call should be emitted rather than transforming
19bf118a 5313 the function inline. If convenient, the result should be placed in
0862b7e9 5314 TARGET with mode MODE. UNLOCKED indicates this is a fprintf_unlocked
19bf118a 5315 call. */
5316static rtx
0b25db21 5317expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
a0c938f0 5318 bool unlocked)
19bf118a 5319{
6d77ed92 5320 /* If we're using an unlocked function, assume the other unlocked
5321 functions exist explicitly. */
5322 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
5323 : implicit_built_in_decls[BUILT_IN_FPUTC];
5324 tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
5325 : implicit_built_in_decls[BUILT_IN_FPUTS];
19bf118a 5326 const char *fmt_str;
c2f47e15 5327 tree fn = 0;
5328 tree fmt, fp, arg;
5329 int nargs = call_expr_nargs (exp);
19bf118a 5330
5331 /* If the return value is used, don't do the transformation. */
5332 if (target != const0_rtx)
c2f47e15 5333 return NULL_RTX;
19bf118a 5334
5335 /* Verify the required arguments in the original call. */
c2f47e15 5336 if (nargs < 2)
5337 return NULL_RTX;
5338 fp = CALL_EXPR_ARG (exp, 0);
552752f7 5339 if (! POINTER_TYPE_P (TREE_TYPE (fp)))
c2f47e15 5340 return NULL_RTX;
5341 fmt = CALL_EXPR_ARG (exp, 1);
552752f7 5342 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
c2f47e15 5343 return NULL_RTX;
19bf118a 5344
5345 /* Check whether the format is a literal string constant. */
5346 fmt_str = c_getstr (fmt);
5347 if (fmt_str == NULL)
c2f47e15 5348 return NULL_RTX;
19bf118a 5349
d4473c84 5350 if (!init_target_chars ())
c2f47e15 5351 return NULL_RTX;
a0c938f0 5352
19bf118a 5353 /* If the format specifier was "%s", call __builtin_fputs(arg,fp). */
99eabcc1 5354 if (strcmp (fmt_str, target_percent_s) == 0)
19bf118a 5355 {
c2f47e15 5356 if ((nargs != 3)
5357 || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (exp, 2))))
5358 return NULL_RTX;
5359 arg = CALL_EXPR_ARG (exp, 2);
5360 if (fn_fputs)
5361 fn = build_call_expr (fn_fputs, 2, arg, fp);
19bf118a 5362 }
5363 /* If the format specifier was "%c", call __builtin_fputc(arg,fp). */
99eabcc1 5364 else if (strcmp (fmt_str, target_percent_c) == 0)
19bf118a 5365 {
c2f47e15 5366 if ((nargs != 3)
5367 || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2))) != INTEGER_TYPE)
5368 return NULL_RTX;
5369 arg = CALL_EXPR_ARG (exp, 2);
5370 if (fn_fputc)
5371 fn = build_call_expr (fn_fputc, 2, arg, fp);
19bf118a 5372 }
5373 else
5374 {
5375 /* We can't handle anything else with % args or %% ... yet. */
99eabcc1 5376 if (strchr (fmt_str, target_percent))
c2f47e15 5377 return NULL_RTX;
19bf118a 5378
c2f47e15 5379 if (nargs > 2)
5380 return NULL_RTX;
19bf118a 5381
5382 /* If the format specifier was "", fprintf does nothing. */
5383 if (fmt_str[0] == '\0')
5384 {
5385 /* Evaluate and ignore FILE* argument for side-effects. */
5386 expand_expr (fp, const0_rtx, VOIDmode, EXPAND_NORMAL);
5387 return const0_rtx;
5388 }
5389
5390 /* When "string" doesn't contain %, replace all cases of
5391 fprintf(stream,string) with fputs(string,stream). The fputs
5392 builtin will take care of special cases like length == 1. */
c2f47e15 5393 if (fn_fputs)
5394 fn = build_call_expr (fn_fputs, 2, fmt, fp);
19bf118a 5395 }
5396
5397 if (!fn)
c2f47e15 5398 return NULL_RTX;
0b25db21 5399 if (TREE_CODE (fn) == CALL_EXPR)
5400 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
5401 return expand_expr (fn, target, mode, EXPAND_NORMAL);
19bf118a 5402}
5403
c2f47e15 5404/* Expand a call EXP to sprintf. Return NULL_RTX if
6411575e 5405 a normal call should be emitted rather than expanding the function
5406 inline. If convenient, the result should be placed in TARGET with
5407 mode MODE. */
5408
5409static rtx
c2f47e15 5410expand_builtin_sprintf (tree exp, rtx target, enum machine_mode mode)
6411575e 5411{
c2f47e15 5412 tree dest, fmt;
a7a723f0 5413 const char *fmt_str;
c2f47e15 5414 int nargs = call_expr_nargs (exp);
6411575e 5415
5416 /* Verify the required arguments in the original call. */
c2f47e15 5417 if (nargs < 2)
5418 return NULL_RTX;
5419 dest = CALL_EXPR_ARG (exp, 0);
552752f7 5420 if (! POINTER_TYPE_P (TREE_TYPE (dest)))
c2f47e15 5421 return NULL_RTX;
5422 fmt = CALL_EXPR_ARG (exp, 0);
552752f7 5423 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
c2f47e15 5424 return NULL_RTX;
6411575e 5425
5426 /* Check whether the format is a literal string constant. */
a7a723f0 5427 fmt_str = c_getstr (fmt);
5428 if (fmt_str == NULL)
c2f47e15 5429 return NULL_RTX;
6411575e 5430
d4473c84 5431 if (!init_target_chars ())
c2f47e15 5432 return NULL_RTX;
99eabcc1 5433
6411575e 5434 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 5435 if (strchr (fmt_str, target_percent) == 0)
6411575e 5436 {
5437 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
5438 tree exp;
5439
c2f47e15 5440 if ((nargs > 2) || ! fn)
5441 return NULL_RTX;
5442 expand_expr (build_call_expr (fn, 2, dest, fmt),
6411575e 5443 const0_rtx, VOIDmode, EXPAND_NORMAL);
5444 if (target == const0_rtx)
5445 return const0_rtx;
7016c612 5446 exp = build_int_cst (NULL_TREE, strlen (fmt_str));
6411575e 5447 return expand_expr (exp, target, mode, EXPAND_NORMAL);
5448 }
a7a723f0 5449 /* If the format is "%s", use strcpy if the result isn't used. */
99eabcc1 5450 else if (strcmp (fmt_str, target_percent_s) == 0)
6411575e 5451 {
a7a723f0 5452 tree fn, arg, len;
5453 fn = implicit_built_in_decls[BUILT_IN_STRCPY];
6411575e 5454
a7a723f0 5455 if (! fn)
c2f47e15 5456 return NULL_RTX;
5457 if (nargs != 3)
5458 return NULL_RTX;
5459 arg = CALL_EXPR_ARG (exp, 2);
552752f7 5460 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
c2f47e15 5461 return NULL_RTX;
6411575e 5462
5463 if (target != const0_rtx)
5464 {
681fab1e 5465 len = c_strlen (arg, 1);
a7a723f0 5466 if (! len || TREE_CODE (len) != INTEGER_CST)
c2f47e15 5467 return NULL_RTX;
6411575e 5468 }
5469 else
a7a723f0 5470 len = NULL_TREE;
6411575e 5471
c2f47e15 5472 expand_expr (build_call_expr (fn, 2, dest, arg),
6411575e 5473 const0_rtx, VOIDmode, EXPAND_NORMAL);
5474
5475 if (target == const0_rtx)
5476 return const0_rtx;
a7a723f0 5477 return expand_expr (len, target, mode, EXPAND_NORMAL);
6411575e 5478 }
5479
c2f47e15 5480 return NULL_RTX;
6411575e 5481}
27f261ef 5482
4ee9c684 5483/* Expand a call to either the entry or exit function profiler. */
5484
5485static rtx
5486expand_builtin_profile_func (bool exitp)
5487{
5488 rtx this, which;
5489
5490 this = DECL_RTL (current_function_decl);
64db345d 5491 gcc_assert (MEM_P (this));
5492 this = XEXP (this, 0);
4ee9c684 5493
5494 if (exitp)
5495 which = profile_function_exit_libfunc;
5496 else
5497 which = profile_function_entry_libfunc;
5498
5499 emit_library_call (which, LCT_NORMAL, VOIDmode, 2, this, Pmode,
5500 expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
869d0ef0 5501 0),
4ee9c684 5502 Pmode);
5503
5504 return const0_rtx;
5505}
5506
5507/* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
5508
5509static rtx
5510round_trampoline_addr (rtx tramp)
5511{
5512 rtx temp, addend, mask;
5513
5514 /* If we don't need too much alignment, we'll have been guaranteed
5515 proper alignment by get_trampoline_type. */
5516 if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
5517 return tramp;
5518
5519 /* Round address up to desired boundary. */
5520 temp = gen_reg_rtx (Pmode);
5521 addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
5522 mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
5523
5524 temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
5525 temp, 0, OPTAB_LIB_WIDEN);
5526 tramp = expand_simple_binop (Pmode, AND, temp, mask,
5527 temp, 0, OPTAB_LIB_WIDEN);
5528
5529 return tramp;
5530}
5531
5532static rtx
c2f47e15 5533expand_builtin_init_trampoline (tree exp)
4ee9c684 5534{
5535 tree t_tramp, t_func, t_chain;
5536 rtx r_tramp, r_func, r_chain;
5537#ifdef TRAMPOLINE_TEMPLATE
5538 rtx blktramp;
5539#endif
5540
c2f47e15 5541 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
4ee9c684 5542 POINTER_TYPE, VOID_TYPE))
5543 return NULL_RTX;
5544
c2f47e15 5545 t_tramp = CALL_EXPR_ARG (exp, 0);
5546 t_func = CALL_EXPR_ARG (exp, 1);
5547 t_chain = CALL_EXPR_ARG (exp, 2);
4ee9c684 5548
8ec3c5c2 5549 r_tramp = expand_normal (t_tramp);
5550 r_func = expand_normal (t_func);
5551 r_chain = expand_normal (t_chain);
4ee9c684 5552
5553 /* Generate insns to initialize the trampoline. */
5554 r_tramp = round_trampoline_addr (r_tramp);
5555#ifdef TRAMPOLINE_TEMPLATE
5556 blktramp = gen_rtx_MEM (BLKmode, r_tramp);
5557 set_mem_align (blktramp, TRAMPOLINE_ALIGNMENT);
5558 emit_block_move (blktramp, assemble_trampoline_template (),
5559 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
5560#endif
5561 trampolines_created = 1;
5562 INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain);
5563
5564 return const0_rtx;
5565}
5566
5567static rtx
c2f47e15 5568expand_builtin_adjust_trampoline (tree exp)
4ee9c684 5569{
5570 rtx tramp;
5571
c2f47e15 5572 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
4ee9c684 5573 return NULL_RTX;
5574
c2f47e15 5575 tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
4ee9c684 5576 tramp = round_trampoline_addr (tramp);
5577#ifdef TRAMPOLINE_ADJUST_ADDRESS
5578 TRAMPOLINE_ADJUST_ADDRESS (tramp);
5579#endif
5580
5581 return tramp;
5582}
5583
004e23c4 5584/* Expand a call to the built-in signbit, signbitf, signbitl, signbitd32,
5585 signbitd64, or signbitd128 function.
27f261ef 5586 Return NULL_RTX if a normal call should be emitted rather than expanding
5587 the function in-line. EXP is the expression that is a call to the builtin
5588 function; if convenient, the result should be placed in TARGET. */
5589
5590static rtx
5591expand_builtin_signbit (tree exp, rtx target)
5592{
5593 const struct real_format *fmt;
5594 enum machine_mode fmode, imode, rmode;
5595 HOST_WIDE_INT hi, lo;
c2f47e15 5596 tree arg;
ca4f1f5b 5597 int word, bitpos;
27f261ef 5598 rtx temp;
5599
c2f47e15 5600 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
5601 return NULL_RTX;
27f261ef 5602
c2f47e15 5603 arg = CALL_EXPR_ARG (exp, 0);
27f261ef 5604 fmode = TYPE_MODE (TREE_TYPE (arg));
5605 rmode = TYPE_MODE (TREE_TYPE (exp));
5606 fmt = REAL_MODE_FORMAT (fmode);
5607
5608 /* For floating point formats without a sign bit, implement signbit
5609 as "ARG < 0.0". */
8d564692 5610 bitpos = fmt->signbit_ro;
ca4f1f5b 5611 if (bitpos < 0)
27f261ef 5612 {
5613 /* But we can't do this if the format supports signed zero. */
5614 if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
c2f47e15 5615 return NULL_RTX;
27f261ef 5616
49d00087 5617 arg = fold_build2 (LT_EXPR, TREE_TYPE (exp), arg,
5618 build_real (TREE_TYPE (arg), dconst0));
27f261ef 5619 return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5620 }
5621
8ec3c5c2 5622 temp = expand_normal (arg);
ca4f1f5b 5623 if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
27f261ef 5624 {
ca4f1f5b 5625 imode = int_mode_for_mode (fmode);
5626 if (imode == BLKmode)
c2f47e15 5627 return NULL_RTX;
ca4f1f5b 5628 temp = gen_lowpart (imode, temp);
24fd4260 5629 }
5630 else
5631 {
ca4f1f5b 5632 imode = word_mode;
5633 /* Handle targets with different FP word orders. */
5634 if (FLOAT_WORDS_BIG_ENDIAN)
a0c938f0 5635 word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
ca4f1f5b 5636 else
a0c938f0 5637 word = bitpos / BITS_PER_WORD;
ca4f1f5b 5638 temp = operand_subword_force (temp, word, fmode);
5639 bitpos = bitpos % BITS_PER_WORD;
5640 }
5641
44b0f1d0 5642 /* Force the intermediate word_mode (or narrower) result into a
5643 register. This avoids attempting to create paradoxical SUBREGs
5644 of floating point modes below. */
5645 temp = force_reg (imode, temp);
5646
ca4f1f5b 5647 /* If the bitpos is within the "result mode" lowpart, the operation
5648 can be implement with a single bitwise AND. Otherwise, we need
5649 a right shift and an AND. */
5650
5651 if (bitpos < GET_MODE_BITSIZE (rmode))
5652 {
24fd4260 5653 if (bitpos < HOST_BITS_PER_WIDE_INT)
27f261ef 5654 {
24fd4260 5655 hi = 0;
5656 lo = (HOST_WIDE_INT) 1 << bitpos;
27f261ef 5657 }
5658 else
24fd4260 5659 {
5660 hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
5661 lo = 0;
5662 }
27f261ef 5663
ca4f1f5b 5664 if (imode != rmode)
5665 temp = gen_lowpart (rmode, temp);
24fd4260 5666 temp = expand_binop (rmode, and_optab, temp,
5667 immed_double_const (lo, hi, rmode),
ca4f1f5b 5668 NULL_RTX, 1, OPTAB_LIB_WIDEN);
27f261ef 5669 }
ca4f1f5b 5670 else
5671 {
5672 /* Perform a logical right shift to place the signbit in the least
a0c938f0 5673 significant bit, then truncate the result to the desired mode
ca4f1f5b 5674 and mask just this bit. */
5675 temp = expand_shift (RSHIFT_EXPR, imode, temp,
5676 build_int_cst (NULL_TREE, bitpos), NULL_RTX, 1);
5677 temp = gen_lowpart (rmode, temp);
5678 temp = expand_binop (rmode, and_optab, temp, const1_rtx,
5679 NULL_RTX, 1, OPTAB_LIB_WIDEN);
5680 }
5681
27f261ef 5682 return temp;
5683}
73673831 5684
5685/* Expand fork or exec calls. TARGET is the desired target of the
c2f47e15 5686 call. EXP is the call. FN is the
73673831 5687 identificator of the actual function. IGNORE is nonzero if the
5688 value is to be ignored. */
5689
5690static rtx
c2f47e15 5691expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
73673831 5692{
5693 tree id, decl;
5694 tree call;
5695
5696 /* If we are not profiling, just call the function. */
5697 if (!profile_arc_flag)
5698 return NULL_RTX;
5699
5700 /* Otherwise call the wrapper. This should be equivalent for the rest of
5701 compiler, so the code does not diverge, and the wrapper may run the
9c9bad97 5702 code necessary for keeping the profiling sane. */
73673831 5703
5704 switch (DECL_FUNCTION_CODE (fn))
5705 {
5706 case BUILT_IN_FORK:
5707 id = get_identifier ("__gcov_fork");
5708 break;
5709
5710 case BUILT_IN_EXECL:
5711 id = get_identifier ("__gcov_execl");
5712 break;
5713
5714 case BUILT_IN_EXECV:
5715 id = get_identifier ("__gcov_execv");
5716 break;
5717
5718 case BUILT_IN_EXECLP:
5719 id = get_identifier ("__gcov_execlp");
5720 break;
5721
5722 case BUILT_IN_EXECLE:
5723 id = get_identifier ("__gcov_execle");
5724 break;
5725
5726 case BUILT_IN_EXECVP:
5727 id = get_identifier ("__gcov_execvp");
5728 break;
5729
5730 case BUILT_IN_EXECVE:
5731 id = get_identifier ("__gcov_execve");
5732 break;
5733
5734 default:
64db345d 5735 gcc_unreachable ();
73673831 5736 }
5737
5738 decl = build_decl (FUNCTION_DECL, id, TREE_TYPE (fn));
5739 DECL_EXTERNAL (decl) = 1;
5740 TREE_PUBLIC (decl) = 1;
5741 DECL_ARTIFICIAL (decl) = 1;
5742 TREE_NOTHROW (decl) = 1;
e82d310b 5743 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
5744 DECL_VISIBILITY_SPECIFIED (decl) = 1;
c2f47e15 5745 call = rewrite_call_expr (exp, 0, decl, 0);
73673831 5746 return expand_call (call, target, ignore);
c2f47e15 5747 }
5748
b6a5fc45 5749
5750\f
3e272de8 5751/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
5752 the pointer in these functions is void*, the tree optimizers may remove
5753 casts. The mode computed in expand_builtin isn't reliable either, due
5754 to __sync_bool_compare_and_swap.
5755
5756 FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
5757 group of builtins. This gives us log2 of the mode size. */
5758
5759static inline enum machine_mode
5760get_builtin_sync_mode (int fcode_diff)
5761{
ad3a13b5 5762 /* The size is not negotiable, so ask not to get BLKmode in return
5763 if the target indicates that a smaller size would be better. */
5764 return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
3e272de8 5765}
5766
041e0215 5767/* Expand the memory expression LOC and return the appropriate memory operand
5768 for the builtin_sync operations. */
5769
5770static rtx
5771get_builtin_sync_mem (tree loc, enum machine_mode mode)
5772{
5773 rtx addr, mem;
5774
1db6d067 5775 addr = expand_expr (loc, NULL_RTX, Pmode, EXPAND_SUM);
041e0215 5776
5777 /* Note that we explicitly do not want any alias information for this
5778 memory, so that we kill all other live memories. Otherwise we don't
5779 satisfy the full barrier semantics of the intrinsic. */
5780 mem = validize_mem (gen_rtx_MEM (mode, addr));
5781
5782 set_mem_align (mem, get_pointer_alignment (loc, BIGGEST_ALIGNMENT));
c94cfd1c 5783 set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
041e0215 5784 MEM_VOLATILE_P (mem) = 1;
5785
5786 return mem;
5787}
5788
b6a5fc45 5789/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
c2f47e15 5790 EXP is the CALL_EXPR. CODE is the rtx code
b6a5fc45 5791 that corresponds to the arithmetic or logical operation from the name;
5792 an exception here is that NOT actually means NAND. TARGET is an optional
5793 place for us to store the results; AFTER is true if this is the
5794 fetch_and_xxx form. IGNORE is true if we don't actually care about
5795 the result of the operation at all. */
5796
5797static rtx
c2f47e15 5798expand_builtin_sync_operation (enum machine_mode mode, tree exp,
3e272de8 5799 enum rtx_code code, bool after,
b6a5fc45 5800 rtx target, bool ignore)
5801{
041e0215 5802 rtx val, mem;
a8bb7059 5803 enum machine_mode old_mode;
b6a5fc45 5804
5805 /* Expand the operands. */
c2f47e15 5806 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5807
1db6d067 5808 val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
a8bb7059 5809 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5810 of CONST_INTs, where we know the old_mode only from the call argument. */
5811 old_mode = GET_MODE (val);
5812 if (old_mode == VOIDmode)
5813 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5814 val = convert_modes (mode, old_mode, val, 1);
b6a5fc45 5815
b6a5fc45 5816 if (ignore)
5817 return expand_sync_operation (mem, val, code);
5818 else
5819 return expand_sync_fetch_operation (mem, val, code, after, target);
5820}
5821
5822/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
c2f47e15 5823 intrinsics. EXP is the CALL_EXPR. IS_BOOL is
b6a5fc45 5824 true if this is the boolean form. TARGET is a place for us to store the
5825 results; this is NOT optional if IS_BOOL is true. */
5826
5827static rtx
c2f47e15 5828expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
3e272de8 5829 bool is_bool, rtx target)
b6a5fc45 5830{
041e0215 5831 rtx old_val, new_val, mem;
a8bb7059 5832 enum machine_mode old_mode;
b6a5fc45 5833
5834 /* Expand the operands. */
c2f47e15 5835 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5836
c2f47e15 5837
1db6d067 5838 old_val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX,
5839 mode, EXPAND_NORMAL);
a8bb7059 5840 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5841 of CONST_INTs, where we know the old_mode only from the call argument. */
5842 old_mode = GET_MODE (old_val);
5843 if (old_mode == VOIDmode)
5844 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5845 old_val = convert_modes (mode, old_mode, old_val, 1);
b6a5fc45 5846
1db6d067 5847 new_val = expand_expr (CALL_EXPR_ARG (exp, 2), NULL_RTX,
5848 mode, EXPAND_NORMAL);
a8bb7059 5849 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5850 of CONST_INTs, where we know the old_mode only from the call argument. */
5851 old_mode = GET_MODE (new_val);
5852 if (old_mode == VOIDmode)
5853 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2)));
5854 new_val = convert_modes (mode, old_mode, new_val, 1);
b6a5fc45 5855
b6a5fc45 5856 if (is_bool)
5857 return expand_bool_compare_and_swap (mem, old_val, new_val, target);
5858 else
5859 return expand_val_compare_and_swap (mem, old_val, new_val, target);
5860}
5861
5862/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
5863 general form is actually an atomic exchange, and some targets only
5864 support a reduced form with the second argument being a constant 1.
c2f47e15 5865 EXP is the CALL_EXPR; TARGET is an optional place for us to store
5866 the results. */
b6a5fc45 5867
5868static rtx
c2f47e15 5869expand_builtin_lock_test_and_set (enum machine_mode mode, tree exp,
3e272de8 5870 rtx target)
b6a5fc45 5871{
041e0215 5872 rtx val, mem;
a8bb7059 5873 enum machine_mode old_mode;
b6a5fc45 5874
5875 /* Expand the operands. */
c2f47e15 5876 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1db6d067 5877 val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
a8bb7059 5878 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5879 of CONST_INTs, where we know the old_mode only from the call argument. */
5880 old_mode = GET_MODE (val);
5881 if (old_mode == VOIDmode)
5882 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5883 val = convert_modes (mode, old_mode, val, 1);
b6a5fc45 5884
b6a5fc45 5885 return expand_sync_lock_test_and_set (mem, val, target);
5886}
5887
5888/* Expand the __sync_synchronize intrinsic. */
5889
5890static void
5891expand_builtin_synchronize (void)
5892{
82e58396 5893 tree x;
b6a5fc45 5894
5895#ifdef HAVE_memory_barrier
5896 if (HAVE_memory_barrier)
5897 {
5898 emit_insn (gen_memory_barrier ());
5899 return;
5900 }
5901#endif
5902
82e58396 5903 /* If no explicit memory barrier instruction is available, create an
5904 empty asm stmt with a memory clobber. */
5905 x = build4 (ASM_EXPR, void_type_node, build_string (0, ""), NULL, NULL,
5906 tree_cons (NULL, build_string (6, "memory"), NULL));
5907 ASM_VOLATILE_P (x) = 1;
5908 expand_asm_expr (x);
b6a5fc45 5909}
5910
c2f47e15 5911/* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */
b6a5fc45 5912
5913static void
c2f47e15 5914expand_builtin_lock_release (enum machine_mode mode, tree exp)
b6a5fc45 5915{
b6a5fc45 5916 enum insn_code icode;
041e0215 5917 rtx mem, insn;
3e272de8 5918 rtx val = const0_rtx;
b6a5fc45 5919
5920 /* Expand the operands. */
c2f47e15 5921 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5922
5923 /* If there is an explicit operation in the md file, use it. */
5924 icode = sync_lock_release[mode];
5925 if (icode != CODE_FOR_nothing)
5926 {
5927 if (!insn_data[icode].operand[1].predicate (val, mode))
5928 val = force_reg (mode, val);
5929
5930 insn = GEN_FCN (icode) (mem, val);
5931 if (insn)
5932 {
5933 emit_insn (insn);
5934 return;
5935 }
5936 }
5937
5938 /* Otherwise we can implement this operation by emitting a barrier
5939 followed by a store of zero. */
5940 expand_builtin_synchronize ();
5941 emit_move_insn (mem, val);
5942}
53800dbe 5943\f
5944/* Expand an expression EXP that calls a built-in function,
5945 with result going to TARGET if that's convenient
5946 (and in mode MODE if that's convenient).
5947 SUBTARGET may be used as the target for computing one of EXP's operands.
5948 IGNORE is nonzero if the value is to be ignored. */
5949
5950rtx
aecda0d6 5951expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
5952 int ignore)
53800dbe 5953{
c6e6ecb1 5954 tree fndecl = get_callee_fndecl (exp);
53800dbe 5955 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
efb070c8 5956 enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
53800dbe 5957
8305149e 5958 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
883b2e73 5959 return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
bf8e3599 5960
53800dbe 5961 /* When not optimizing, generate calls to library functions for a certain
5962 set of builtins. */
cd9ff771 5963 if (!optimize
b6a5fc45 5964 && !called_as_built_in (fndecl)
cd9ff771 5965 && DECL_ASSEMBLER_NAME_SET_P (fndecl)
5966 && fcode != BUILT_IN_ALLOCA)
5967 return expand_call (exp, target, ignore);
53800dbe 5968
8d6d7930 5969 /* The built-in function expanders test for target == const0_rtx
5970 to determine whether the function's result will be ignored. */
5971 if (ignore)
5972 target = const0_rtx;
5973
5974 /* If the result of a pure or const built-in function is ignored, and
5975 none of its arguments are volatile, we can avoid expanding the
5976 built-in call and just evaluate the arguments for side-effects. */
5977 if (target == const0_rtx
5978 && (DECL_IS_PURE (fndecl) || TREE_READONLY (fndecl)))
5979 {
5980 bool volatilep = false;
5981 tree arg;
c2f47e15 5982 call_expr_arg_iterator iter;
8d6d7930 5983
c2f47e15 5984 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5985 if (TREE_THIS_VOLATILE (arg))
8d6d7930 5986 {
5987 volatilep = true;
5988 break;
5989 }
5990
5991 if (! volatilep)
5992 {
c2f47e15 5993 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5994 expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
8d6d7930 5995 return const0_rtx;
5996 }
5997 }
5998
53800dbe 5999 switch (fcode)
6000 {
4f35b1fc 6001 CASE_FLT_FN (BUILT_IN_FABS):
c2f47e15 6002 target = expand_builtin_fabs (exp, target, subtarget);
78a74442 6003 if (target)
a0c938f0 6004 return target;
78a74442 6005 break;
6006
4f35b1fc 6007 CASE_FLT_FN (BUILT_IN_COPYSIGN):
c2f47e15 6008 target = expand_builtin_copysign (exp, target, subtarget);
270436f3 6009 if (target)
6010 return target;
6011 break;
6012
7d3f6cc7 6013 /* Just do a normal library call if we were unable to fold
6014 the values. */
4f35b1fc 6015 CASE_FLT_FN (BUILT_IN_CABS):
78a74442 6016 break;
53800dbe 6017
4f35b1fc 6018 CASE_FLT_FN (BUILT_IN_EXP):
6019 CASE_FLT_FN (BUILT_IN_EXP10):
6020 CASE_FLT_FN (BUILT_IN_POW10):
6021 CASE_FLT_FN (BUILT_IN_EXP2):
6022 CASE_FLT_FN (BUILT_IN_EXPM1):
6023 CASE_FLT_FN (BUILT_IN_LOGB):
4f35b1fc 6024 CASE_FLT_FN (BUILT_IN_LOG):
6025 CASE_FLT_FN (BUILT_IN_LOG10):
6026 CASE_FLT_FN (BUILT_IN_LOG2):
6027 CASE_FLT_FN (BUILT_IN_LOG1P):
6028 CASE_FLT_FN (BUILT_IN_TAN):
6029 CASE_FLT_FN (BUILT_IN_ASIN):
6030 CASE_FLT_FN (BUILT_IN_ACOS):
6031 CASE_FLT_FN (BUILT_IN_ATAN):
7f3be425 6032 /* Treat these like sqrt only if unsafe math optimizations are allowed,
6033 because of possible accuracy problems. */
6034 if (! flag_unsafe_math_optimizations)
53800dbe 6035 break;
4f35b1fc 6036 CASE_FLT_FN (BUILT_IN_SQRT):
6037 CASE_FLT_FN (BUILT_IN_FLOOR):
6038 CASE_FLT_FN (BUILT_IN_CEIL):
6039 CASE_FLT_FN (BUILT_IN_TRUNC):
6040 CASE_FLT_FN (BUILT_IN_ROUND):
6041 CASE_FLT_FN (BUILT_IN_NEARBYINT):
6042 CASE_FLT_FN (BUILT_IN_RINT):
53800dbe 6043 target = expand_builtin_mathfn (exp, target, subtarget);
6044 if (target)
6045 return target;
6046 break;
6047
a67a90e5 6048 CASE_FLT_FN (BUILT_IN_ILOGB):
6049 if (! flag_unsafe_math_optimizations)
6050 break;
69b779ea 6051 CASE_FLT_FN (BUILT_IN_ISINF):
a67a90e5 6052 target = expand_builtin_interclass_mathfn (exp, target, subtarget);
6053 if (target)
6054 return target;
6055 break;
6056
4f35b1fc 6057 CASE_FLT_FN (BUILT_IN_LCEIL):
6058 CASE_FLT_FN (BUILT_IN_LLCEIL):
6059 CASE_FLT_FN (BUILT_IN_LFLOOR):
6060 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 6061 target = expand_builtin_int_roundingfn (exp, target, subtarget);
6062 if (target)
6063 return target;
6064 break;
6065
7d3afc77 6066 CASE_FLT_FN (BUILT_IN_LRINT):
6067 CASE_FLT_FN (BUILT_IN_LLRINT):
ef2f1a10 6068 CASE_FLT_FN (BUILT_IN_LROUND):
6069 CASE_FLT_FN (BUILT_IN_LLROUND):
7d3afc77 6070 target = expand_builtin_int_roundingfn_2 (exp, target, subtarget);
6071 if (target)
6072 return target;
6073 break;
6074
4f35b1fc 6075 CASE_FLT_FN (BUILT_IN_POW):
f1b844c6 6076 target = expand_builtin_pow (exp, target, subtarget);
6077 if (target)
6078 return target;
6079 break;
6080
4f35b1fc 6081 CASE_FLT_FN (BUILT_IN_POWI):
757c219d 6082 target = expand_builtin_powi (exp, target, subtarget);
6083 if (target)
6084 return target;
6085 break;
6086
4f35b1fc 6087 CASE_FLT_FN (BUILT_IN_ATAN2):
6088 CASE_FLT_FN (BUILT_IN_LDEXP):
73a954a1 6089 CASE_FLT_FN (BUILT_IN_SCALB):
6090 CASE_FLT_FN (BUILT_IN_SCALBN):
6091 CASE_FLT_FN (BUILT_IN_SCALBLN):
0fd605a5 6092 if (! flag_unsafe_math_optimizations)
6093 break;
ef722005 6094
6095 CASE_FLT_FN (BUILT_IN_FMOD):
6096 CASE_FLT_FN (BUILT_IN_REMAINDER):
6097 CASE_FLT_FN (BUILT_IN_DREM):
0fd605a5 6098 target = expand_builtin_mathfn_2 (exp, target, subtarget);
6099 if (target)
6100 return target;
6101 break;
6102
d735c391 6103 CASE_FLT_FN (BUILT_IN_CEXPI):
6104 target = expand_builtin_cexpi (exp, target, subtarget);
6105 gcc_assert (target);
6106 return target;
6107
4f35b1fc 6108 CASE_FLT_FN (BUILT_IN_SIN):
6109 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 6110 if (! flag_unsafe_math_optimizations)
6111 break;
6112 target = expand_builtin_mathfn_3 (exp, target, subtarget);
6113 if (target)
6114 return target;
6115 break;
6116
c3147c1a 6117 CASE_FLT_FN (BUILT_IN_SINCOS):
6118 if (! flag_unsafe_math_optimizations)
6119 break;
6120 target = expand_builtin_sincos (exp);
6121 if (target)
6122 return target;
6123 break;
6124
53800dbe 6125 case BUILT_IN_APPLY_ARGS:
6126 return expand_builtin_apply_args ();
6127
6128 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
6129 FUNCTION with a copy of the parameters described by
6130 ARGUMENTS, and ARGSIZE. It returns a block of memory
6131 allocated on the stack into which is stored all the registers
6132 that might possibly be used for returning the result of a
6133 function. ARGUMENTS is the value returned by
6134 __builtin_apply_args. ARGSIZE is the number of bytes of
6135 arguments that must be copied. ??? How should this value be
6136 computed? We'll also need a safe worst case value for varargs
6137 functions. */
6138 case BUILT_IN_APPLY:
c2f47e15 6139 if (!validate_arglist (exp, POINTER_TYPE,
0eb671f7 6140 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
c2f47e15 6141 && !validate_arglist (exp, REFERENCE_TYPE,
0eb671f7 6142 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 6143 return const0_rtx;
6144 else
6145 {
53800dbe 6146 rtx ops[3];
6147
c2f47e15 6148 ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
6149 ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
6150 ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
53800dbe 6151
6152 return expand_builtin_apply (ops[0], ops[1], ops[2]);
6153 }
6154
6155 /* __builtin_return (RESULT) causes the function to return the
6156 value described by RESULT. RESULT is address of the block of
6157 memory returned by __builtin_apply. */
6158 case BUILT_IN_RETURN:
c2f47e15 6159 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
6160 expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
53800dbe 6161 return const0_rtx;
6162
6163 case BUILT_IN_SAVEREGS:
a66c9326 6164 return expand_builtin_saveregs ();
53800dbe 6165
6166 case BUILT_IN_ARGS_INFO:
c2f47e15 6167 return expand_builtin_args_info (exp);
53800dbe 6168
6169 /* Return the address of the first anonymous stack arg. */
6170 case BUILT_IN_NEXT_ARG:
c2f47e15 6171 if (fold_builtin_next_arg (exp, false))
a0c938f0 6172 return const0_rtx;
79012a9d 6173 return expand_builtin_next_arg ();
53800dbe 6174
6175 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 6176 return expand_builtin_classify_type (exp);
53800dbe 6177
6178 case BUILT_IN_CONSTANT_P:
4ee9c684 6179 return const0_rtx;
53800dbe 6180
6181 case BUILT_IN_FRAME_ADDRESS:
6182 case BUILT_IN_RETURN_ADDRESS:
c2f47e15 6183 return expand_builtin_frame_address (fndecl, exp);
53800dbe 6184
6185 /* Returns the address of the area where the structure is returned.
6186 0 otherwise. */
6187 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
c2f47e15 6188 if (call_expr_nargs (exp) != 0
9342ee68 6189 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
e16ceb8e 6190 || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
9342ee68 6191 return const0_rtx;
53800dbe 6192 else
9342ee68 6193 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
53800dbe 6194
6195 case BUILT_IN_ALLOCA:
c2f47e15 6196 target = expand_builtin_alloca (exp, target);
53800dbe 6197 if (target)
6198 return target;
6199 break;
6200
4ee9c684 6201 case BUILT_IN_STACK_SAVE:
6202 return expand_stack_save ();
6203
6204 case BUILT_IN_STACK_RESTORE:
c2f47e15 6205 expand_stack_restore (CALL_EXPR_ARG (exp, 0));
4ee9c684 6206 return const0_rtx;
6207
42791117 6208 case BUILT_IN_BSWAP32:
6209 case BUILT_IN_BSWAP64:
c2f47e15 6210 target = expand_builtin_bswap (exp, target, subtarget);
42791117 6211
6212 if (target)
6213 return target;
6214 break;
6215
4f35b1fc 6216 CASE_INT_FN (BUILT_IN_FFS):
5053259b 6217 case BUILT_IN_FFSIMAX:
c2f47e15 6218 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6219 subtarget, ffs_optab);
6a08d0ab 6220 if (target)
6221 return target;
6222 break;
6223
4f35b1fc 6224 CASE_INT_FN (BUILT_IN_CLZ):
5053259b 6225 case BUILT_IN_CLZIMAX:
c2f47e15 6226 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6227 subtarget, clz_optab);
6a08d0ab 6228 if (target)
6229 return target;
6230 break;
6231
4f35b1fc 6232 CASE_INT_FN (BUILT_IN_CTZ):
5053259b 6233 case BUILT_IN_CTZIMAX:
c2f47e15 6234 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6235 subtarget, ctz_optab);
6a08d0ab 6236 if (target)
6237 return target;
6238 break;
6239
4f35b1fc 6240 CASE_INT_FN (BUILT_IN_POPCOUNT):
5053259b 6241 case BUILT_IN_POPCOUNTIMAX:
c2f47e15 6242 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6243 subtarget, popcount_optab);
6a08d0ab 6244 if (target)
6245 return target;
6246 break;
6247
4f35b1fc 6248 CASE_INT_FN (BUILT_IN_PARITY):
5053259b 6249 case BUILT_IN_PARITYIMAX:
c2f47e15 6250 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6251 subtarget, parity_optab);
53800dbe 6252 if (target)
6253 return target;
6254 break;
6255
6256 case BUILT_IN_STRLEN:
c2f47e15 6257 target = expand_builtin_strlen (exp, target, target_mode);
53800dbe 6258 if (target)
6259 return target;
6260 break;
6261
6262 case BUILT_IN_STRCPY:
c2f47e15 6263 target = expand_builtin_strcpy (fndecl, exp, target, mode);
53800dbe 6264 if (target)
6265 return target;
6266 break;
bf8e3599 6267
ed09096d 6268 case BUILT_IN_STRNCPY:
8ff6a5cd 6269 target = expand_builtin_strncpy (exp, target, mode);
ed09096d 6270 if (target)
6271 return target;
6272 break;
bf8e3599 6273
3b824fa6 6274 case BUILT_IN_STPCPY:
dc369150 6275 target = expand_builtin_stpcpy (exp, target, mode);
3b824fa6 6276 if (target)
6277 return target;
6278 break;
6279
49f0327b 6280 case BUILT_IN_STRCAT:
c2f47e15 6281 target = expand_builtin_strcat (fndecl, exp, target, mode);
49f0327b 6282 if (target)
6283 return target;
6284 break;
bf8e3599 6285
49f0327b 6286 case BUILT_IN_STRNCAT:
c2f47e15 6287 target = expand_builtin_strncat (exp, target, mode);
49f0327b 6288 if (target)
6289 return target;
6290 break;
bf8e3599 6291
49f0327b 6292 case BUILT_IN_STRSPN:
c2f47e15 6293 target = expand_builtin_strspn (exp, target, mode);
49f0327b 6294 if (target)
6295 return target;
6296 break;
bf8e3599 6297
49f0327b 6298 case BUILT_IN_STRCSPN:
c2f47e15 6299 target = expand_builtin_strcspn (exp, target, mode);
49f0327b 6300 if (target)
6301 return target;
6302 break;
bf8e3599 6303
17f5ea87 6304 case BUILT_IN_STRSTR:
c2f47e15 6305 target = expand_builtin_strstr (exp, target, mode);
17f5ea87 6306 if (target)
6307 return target;
6308 break;
bf8e3599 6309
46f3a74a 6310 case BUILT_IN_STRPBRK:
c2f47e15 6311 target = expand_builtin_strpbrk (exp, target, mode);
46f3a74a 6312 if (target)
6313 return target;
6314 break;
bf8e3599 6315
398aae36 6316 case BUILT_IN_INDEX:
83d79705 6317 case BUILT_IN_STRCHR:
c2f47e15 6318 target = expand_builtin_strchr (exp, target, mode);
83d79705 6319 if (target)
6320 return target;
6321 break;
6322
398aae36 6323 case BUILT_IN_RINDEX:
83d79705 6324 case BUILT_IN_STRRCHR:
c2f47e15 6325 target = expand_builtin_strrchr (exp, target, mode);
83d79705 6326 if (target)
6327 return target;
6328 break;
6329
53800dbe 6330 case BUILT_IN_MEMCPY:
5a0de151 6331 target = expand_builtin_memcpy (exp, target, mode);
3b824fa6 6332 if (target)
6333 return target;
6334 break;
6335
6336 case BUILT_IN_MEMPCPY:
c2f47e15 6337 target = expand_builtin_mempcpy (exp, target, mode);
53800dbe 6338 if (target)
6339 return target;
6340 break;
6341
c4950093 6342 case BUILT_IN_MEMMOVE:
c2f47e15 6343 target = expand_builtin_memmove (exp, target, mode, ignore);
c4950093 6344 if (target)
6345 return target;
6346 break;
6347
6348 case BUILT_IN_BCOPY:
c2f47e15 6349 target = expand_builtin_bcopy (exp, ignore);
c4950093 6350 if (target)
6351 return target;
6352 break;
6353
53800dbe 6354 case BUILT_IN_MEMSET:
c2f47e15 6355 target = expand_builtin_memset (exp, target, mode);
53800dbe 6356 if (target)
6357 return target;
6358 break;
6359
ffc83088 6360 case BUILT_IN_BZERO:
0b25db21 6361 target = expand_builtin_bzero (exp);
ffc83088 6362 if (target)
6363 return target;
6364 break;
6365
53800dbe 6366 case BUILT_IN_STRCMP:
83d79705 6367 target = expand_builtin_strcmp (exp, target, mode);
53800dbe 6368 if (target)
6369 return target;
6370 break;
6371
ed09096d 6372 case BUILT_IN_STRNCMP:
6373 target = expand_builtin_strncmp (exp, target, mode);
6374 if (target)
6375 return target;
6376 break;
6377
7959b13b 6378 case BUILT_IN_MEMCHR:
6379 target = expand_builtin_memchr (exp, target, mode);
6380 if (target)
6381 return target;
6382 break;
6383
071f1696 6384 case BUILT_IN_BCMP:
53800dbe 6385 case BUILT_IN_MEMCMP:
c2f47e15 6386 target = expand_builtin_memcmp (exp, target, mode);
53800dbe 6387 if (target)
6388 return target;
6389 break;
53800dbe 6390
6391 case BUILT_IN_SETJMP:
2c8a1497 6392 /* This should have been lowered to the builtins below. */
6393 gcc_unreachable ();
6394
6395 case BUILT_IN_SETJMP_SETUP:
6396 /* __builtin_setjmp_setup is passed a pointer to an array of five words
6397 and the receiver label. */
c2f47e15 6398 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2c8a1497 6399 {
c2f47e15 6400 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
2c8a1497 6401 VOIDmode, EXPAND_NORMAL);
c2f47e15 6402 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
2c8a1497 6403 rtx label_r = label_rtx (label);
6404
6405 /* This is copied from the handling of non-local gotos. */
6406 expand_builtin_setjmp_setup (buf_addr, label_r);
6407 nonlocal_goto_handler_labels
6408 = gen_rtx_EXPR_LIST (VOIDmode, label_r,
6409 nonlocal_goto_handler_labels);
6410 /* ??? Do not let expand_label treat us as such since we would
6411 not want to be both on the list of non-local labels and on
6412 the list of forced labels. */
6413 FORCED_LABEL (label) = 0;
6414 return const0_rtx;
6415 }
6416 break;
6417
6418 case BUILT_IN_SETJMP_DISPATCHER:
6419 /* __builtin_setjmp_dispatcher is passed the dispatcher label. */
c2f47e15 6420 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6421 {
c2f47e15 6422 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6423 rtx label_r = label_rtx (label);
6424
6425 /* Remove the dispatcher label from the list of non-local labels
6426 since the receiver labels have been added to it above. */
6427 remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels);
6428 return const0_rtx;
6429 }
6430 break;
6431
6432 case BUILT_IN_SETJMP_RECEIVER:
6433 /* __builtin_setjmp_receiver is passed the receiver label. */
c2f47e15 6434 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6435 {
c2f47e15 6436 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6437 rtx label_r = label_rtx (label);
6438
6439 expand_builtin_setjmp_receiver (label_r);
6440 return const0_rtx;
6441 }
6b7f6858 6442 break;
53800dbe 6443
6444 /* __builtin_longjmp is passed a pointer to an array of five words.
6445 It's similar to the C library longjmp function but works with
6446 __builtin_setjmp above. */
6447 case BUILT_IN_LONGJMP:
c2f47e15 6448 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 6449 {
c2f47e15 6450 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
8ec3c5c2 6451 VOIDmode, EXPAND_NORMAL);
c2f47e15 6452 rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
53800dbe 6453
6454 if (value != const1_rtx)
6455 {
1e5fcbe2 6456 error ("%<__builtin_longjmp%> second argument must be 1");
53800dbe 6457 return const0_rtx;
6458 }
6459
6460 expand_builtin_longjmp (buf_addr, value);
6461 return const0_rtx;
6462 }
2c8a1497 6463 break;
53800dbe 6464
4ee9c684 6465 case BUILT_IN_NONLOCAL_GOTO:
c2f47e15 6466 target = expand_builtin_nonlocal_goto (exp);
4ee9c684 6467 if (target)
6468 return target;
6469 break;
6470
843d08a9 6471 /* This updates the setjmp buffer that is its argument with the value
6472 of the current stack pointer. */
6473 case BUILT_IN_UPDATE_SETJMP_BUF:
c2f47e15 6474 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
843d08a9 6475 {
6476 rtx buf_addr
c2f47e15 6477 = expand_normal (CALL_EXPR_ARG (exp, 0));
843d08a9 6478
6479 expand_builtin_update_setjmp_buf (buf_addr);
6480 return const0_rtx;
6481 }
6482 break;
6483
53800dbe 6484 case BUILT_IN_TRAP:
a0ef1725 6485 expand_builtin_trap ();
53800dbe 6486 return const0_rtx;
6487
19bf118a 6488 case BUILT_IN_PRINTF:
0b25db21 6489 target = expand_builtin_printf (exp, target, mode, false);
19bf118a 6490 if (target)
6491 return target;
6492 break;
6493
6494 case BUILT_IN_PRINTF_UNLOCKED:
0b25db21 6495 target = expand_builtin_printf (exp, target, mode, true);
19bf118a 6496 if (target)
6497 return target;
6498 break;
6499
df94cd3b 6500 case BUILT_IN_FPUTS:
c2f47e15 6501 target = expand_builtin_fputs (exp, target, false);
c013a46e 6502 if (target)
6503 return target;
6504 break;
6505 case BUILT_IN_FPUTS_UNLOCKED:
c2f47e15 6506 target = expand_builtin_fputs (exp, target, true);
19bf118a 6507 if (target)
6508 return target;
6509 break;
6510
6511 case BUILT_IN_FPRINTF:
0b25db21 6512 target = expand_builtin_fprintf (exp, target, mode, false);
19bf118a 6513 if (target)
6514 return target;
6515 break;
6516
6517 case BUILT_IN_FPRINTF_UNLOCKED:
0b25db21 6518 target = expand_builtin_fprintf (exp, target, mode, true);
df94cd3b 6519 if (target)
6520 return target;
6521 break;
bf8e3599 6522
6411575e 6523 case BUILT_IN_SPRINTF:
c2f47e15 6524 target = expand_builtin_sprintf (exp, target, mode);
6411575e 6525 if (target)
6526 return target;
6527 break;
6528
4f35b1fc 6529 CASE_FLT_FN (BUILT_IN_SIGNBIT):
004e23c4 6530 case BUILT_IN_SIGNBITD32:
6531 case BUILT_IN_SIGNBITD64:
6532 case BUILT_IN_SIGNBITD128:
27f261ef 6533 target = expand_builtin_signbit (exp, target);
6534 if (target)
6535 return target;
6536 break;
6537
53800dbe 6538 /* Various hooks for the DWARF 2 __throw routine. */
6539 case BUILT_IN_UNWIND_INIT:
6540 expand_builtin_unwind_init ();
6541 return const0_rtx;
6542 case BUILT_IN_DWARF_CFA:
6543 return virtual_cfa_rtx;
6544#ifdef DWARF2_UNWIND_INFO
f8f023a5 6545 case BUILT_IN_DWARF_SP_COLUMN:
6546 return expand_builtin_dwarf_sp_column ();
695e919b 6547 case BUILT_IN_INIT_DWARF_REG_SIZES:
c2f47e15 6548 expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
695e919b 6549 return const0_rtx;
53800dbe 6550#endif
6551 case BUILT_IN_FROB_RETURN_ADDR:
c2f47e15 6552 return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6553 case BUILT_IN_EXTRACT_RETURN_ADDR:
c2f47e15 6554 return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6555 case BUILT_IN_EH_RETURN:
c2f47e15 6556 expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
6557 CALL_EXPR_ARG (exp, 1));
53800dbe 6558 return const0_rtx;
df4b504c 6559#ifdef EH_RETURN_DATA_REGNO
6560 case BUILT_IN_EH_RETURN_DATA_REGNO:
c2f47e15 6561 return expand_builtin_eh_return_data_regno (exp);
df4b504c 6562#endif
26093bf4 6563 case BUILT_IN_EXTEND_POINTER:
c2f47e15 6564 return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
26093bf4 6565
7ccc713a 6566 case BUILT_IN_VA_START:
a66c9326 6567 case BUILT_IN_STDARG_START:
c2f47e15 6568 return expand_builtin_va_start (exp);
a66c9326 6569 case BUILT_IN_VA_END:
c2f47e15 6570 return expand_builtin_va_end (exp);
a66c9326 6571 case BUILT_IN_VA_COPY:
c2f47e15 6572 return expand_builtin_va_copy (exp);
89cfe6e5 6573 case BUILT_IN_EXPECT:
c2f47e15 6574 return expand_builtin_expect (exp, target);
5e3608d8 6575 case BUILT_IN_PREFETCH:
c2f47e15 6576 expand_builtin_prefetch (exp);
5e3608d8 6577 return const0_rtx;
6578
4ee9c684 6579 case BUILT_IN_PROFILE_FUNC_ENTER:
6580 return expand_builtin_profile_func (false);
6581 case BUILT_IN_PROFILE_FUNC_EXIT:
6582 return expand_builtin_profile_func (true);
6583
6584 case BUILT_IN_INIT_TRAMPOLINE:
c2f47e15 6585 return expand_builtin_init_trampoline (exp);
4ee9c684 6586 case BUILT_IN_ADJUST_TRAMPOLINE:
c2f47e15 6587 return expand_builtin_adjust_trampoline (exp);
4ee9c684 6588
73673831 6589 case BUILT_IN_FORK:
6590 case BUILT_IN_EXECL:
6591 case BUILT_IN_EXECV:
6592 case BUILT_IN_EXECLP:
6593 case BUILT_IN_EXECLE:
6594 case BUILT_IN_EXECVP:
6595 case BUILT_IN_EXECVE:
c2f47e15 6596 target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
73673831 6597 if (target)
6598 return target;
6599 break;
53800dbe 6600
b6a5fc45 6601 case BUILT_IN_FETCH_AND_ADD_1:
6602 case BUILT_IN_FETCH_AND_ADD_2:
6603 case BUILT_IN_FETCH_AND_ADD_4:
6604 case BUILT_IN_FETCH_AND_ADD_8:
27213ba3 6605 case BUILT_IN_FETCH_AND_ADD_16:
3e272de8 6606 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_ADD_1);
c2f47e15 6607 target = expand_builtin_sync_operation (mode, exp, PLUS,
b6a5fc45 6608 false, target, ignore);
6609 if (target)
6610 return target;
6611 break;
6612
6613 case BUILT_IN_FETCH_AND_SUB_1:
6614 case BUILT_IN_FETCH_AND_SUB_2:
6615 case BUILT_IN_FETCH_AND_SUB_4:
6616 case BUILT_IN_FETCH_AND_SUB_8:
27213ba3 6617 case BUILT_IN_FETCH_AND_SUB_16:
3e272de8 6618 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_SUB_1);
c2f47e15 6619 target = expand_builtin_sync_operation (mode, exp, MINUS,
b6a5fc45 6620 false, target, ignore);
6621 if (target)
6622 return target;
6623 break;
6624
6625 case BUILT_IN_FETCH_AND_OR_1:
6626 case BUILT_IN_FETCH_AND_OR_2:
6627 case BUILT_IN_FETCH_AND_OR_4:
6628 case BUILT_IN_FETCH_AND_OR_8:
27213ba3 6629 case BUILT_IN_FETCH_AND_OR_16:
3e272de8 6630 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_OR_1);
c2f47e15 6631 target = expand_builtin_sync_operation (mode, exp, IOR,
b6a5fc45 6632 false, target, ignore);
6633 if (target)
6634 return target;
6635 break;
6636
6637 case BUILT_IN_FETCH_AND_AND_1:
6638 case BUILT_IN_FETCH_AND_AND_2:
6639 case BUILT_IN_FETCH_AND_AND_4:
6640 case BUILT_IN_FETCH_AND_AND_8:
27213ba3 6641 case BUILT_IN_FETCH_AND_AND_16:
3e272de8 6642 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_AND_1);
c2f47e15 6643 target = expand_builtin_sync_operation (mode, exp, AND,
b6a5fc45 6644 false, target, ignore);
6645 if (target)
6646 return target;
6647 break;
6648
6649 case BUILT_IN_FETCH_AND_XOR_1:
6650 case BUILT_IN_FETCH_AND_XOR_2:
6651 case BUILT_IN_FETCH_AND_XOR_4:
6652 case BUILT_IN_FETCH_AND_XOR_8:
27213ba3 6653 case BUILT_IN_FETCH_AND_XOR_16:
3e272de8 6654 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_XOR_1);
c2f47e15 6655 target = expand_builtin_sync_operation (mode, exp, XOR,
b6a5fc45 6656 false, target, ignore);
6657 if (target)
6658 return target;
6659 break;
6660
6661 case BUILT_IN_FETCH_AND_NAND_1:
6662 case BUILT_IN_FETCH_AND_NAND_2:
6663 case BUILT_IN_FETCH_AND_NAND_4:
6664 case BUILT_IN_FETCH_AND_NAND_8:
27213ba3 6665 case BUILT_IN_FETCH_AND_NAND_16:
3e272de8 6666 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_NAND_1);
c2f47e15 6667 target = expand_builtin_sync_operation (mode, exp, NOT,
b6a5fc45 6668 false, target, ignore);
6669 if (target)
6670 return target;
6671 break;
6672
6673 case BUILT_IN_ADD_AND_FETCH_1:
6674 case BUILT_IN_ADD_AND_FETCH_2:
6675 case BUILT_IN_ADD_AND_FETCH_4:
6676 case BUILT_IN_ADD_AND_FETCH_8:
27213ba3 6677 case BUILT_IN_ADD_AND_FETCH_16:
3e272de8 6678 mode = get_builtin_sync_mode (fcode - BUILT_IN_ADD_AND_FETCH_1);
c2f47e15 6679 target = expand_builtin_sync_operation (mode, exp, PLUS,
b6a5fc45 6680 true, target, ignore);
6681 if (target)
6682 return target;
6683 break;
6684
6685 case BUILT_IN_SUB_AND_FETCH_1:
6686 case BUILT_IN_SUB_AND_FETCH_2:
6687 case BUILT_IN_SUB_AND_FETCH_4:
6688 case BUILT_IN_SUB_AND_FETCH_8:
27213ba3 6689 case BUILT_IN_SUB_AND_FETCH_16:
3e272de8 6690 mode = get_builtin_sync_mode (fcode - BUILT_IN_SUB_AND_FETCH_1);
c2f47e15 6691 target = expand_builtin_sync_operation (mode, exp, MINUS,
b6a5fc45 6692 true, target, ignore);
6693 if (target)
6694 return target;
6695 break;
6696
6697 case BUILT_IN_OR_AND_FETCH_1:
6698 case BUILT_IN_OR_AND_FETCH_2:
6699 case BUILT_IN_OR_AND_FETCH_4:
6700 case BUILT_IN_OR_AND_FETCH_8:
27213ba3 6701 case BUILT_IN_OR_AND_FETCH_16:
3e272de8 6702 mode = get_builtin_sync_mode (fcode - BUILT_IN_OR_AND_FETCH_1);
c2f47e15 6703 target = expand_builtin_sync_operation (mode, exp, IOR,
b6a5fc45 6704 true, target, ignore);
6705 if (target)
6706 return target;
6707 break;
6708
6709 case BUILT_IN_AND_AND_FETCH_1:
6710 case BUILT_IN_AND_AND_FETCH_2:
6711 case BUILT_IN_AND_AND_FETCH_4:
6712 case BUILT_IN_AND_AND_FETCH_8:
27213ba3 6713 case BUILT_IN_AND_AND_FETCH_16:
3e272de8 6714 mode = get_builtin_sync_mode (fcode - BUILT_IN_AND_AND_FETCH_1);
c2f47e15 6715 target = expand_builtin_sync_operation (mode, exp, AND,
b6a5fc45 6716 true, target, ignore);
6717 if (target)
6718 return target;
6719 break;
6720
6721 case BUILT_IN_XOR_AND_FETCH_1:
6722 case BUILT_IN_XOR_AND_FETCH_2:
6723 case BUILT_IN_XOR_AND_FETCH_4:
6724 case BUILT_IN_XOR_AND_FETCH_8:
27213ba3 6725 case BUILT_IN_XOR_AND_FETCH_16:
3e272de8 6726 mode = get_builtin_sync_mode (fcode - BUILT_IN_XOR_AND_FETCH_1);
c2f47e15 6727 target = expand_builtin_sync_operation (mode, exp, XOR,
b6a5fc45 6728 true, target, ignore);
6729 if (target)
6730 return target;
6731 break;
6732
6733 case BUILT_IN_NAND_AND_FETCH_1:
6734 case BUILT_IN_NAND_AND_FETCH_2:
6735 case BUILT_IN_NAND_AND_FETCH_4:
6736 case BUILT_IN_NAND_AND_FETCH_8:
27213ba3 6737 case BUILT_IN_NAND_AND_FETCH_16:
3e272de8 6738 mode = get_builtin_sync_mode (fcode - BUILT_IN_NAND_AND_FETCH_1);
c2f47e15 6739 target = expand_builtin_sync_operation (mode, exp, NOT,
b6a5fc45 6740 true, target, ignore);
6741 if (target)
6742 return target;
6743 break;
6744
6745 case BUILT_IN_BOOL_COMPARE_AND_SWAP_1:
6746 case BUILT_IN_BOOL_COMPARE_AND_SWAP_2:
6747 case BUILT_IN_BOOL_COMPARE_AND_SWAP_4:
6748 case BUILT_IN_BOOL_COMPARE_AND_SWAP_8:
27213ba3 6749 case BUILT_IN_BOOL_COMPARE_AND_SWAP_16:
a601d32a 6750 if (mode == VOIDmode)
6751 mode = TYPE_MODE (boolean_type_node);
b6a5fc45 6752 if (!target || !register_operand (target, mode))
6753 target = gen_reg_rtx (mode);
3e272de8 6754
6755 mode = get_builtin_sync_mode (fcode - BUILT_IN_BOOL_COMPARE_AND_SWAP_1);
c2f47e15 6756 target = expand_builtin_compare_and_swap (mode, exp, true, target);
b6a5fc45 6757 if (target)
6758 return target;
6759 break;
6760
6761 case BUILT_IN_VAL_COMPARE_AND_SWAP_1:
6762 case BUILT_IN_VAL_COMPARE_AND_SWAP_2:
6763 case BUILT_IN_VAL_COMPARE_AND_SWAP_4:
6764 case BUILT_IN_VAL_COMPARE_AND_SWAP_8:
27213ba3 6765 case BUILT_IN_VAL_COMPARE_AND_SWAP_16:
3e272de8 6766 mode = get_builtin_sync_mode (fcode - BUILT_IN_VAL_COMPARE_AND_SWAP_1);
c2f47e15 6767 target = expand_builtin_compare_and_swap (mode, exp, false, target);
b6a5fc45 6768 if (target)
6769 return target;
6770 break;
6771
6772 case BUILT_IN_LOCK_TEST_AND_SET_1:
6773 case BUILT_IN_LOCK_TEST_AND_SET_2:
6774 case BUILT_IN_LOCK_TEST_AND_SET_4:
6775 case BUILT_IN_LOCK_TEST_AND_SET_8:
27213ba3 6776 case BUILT_IN_LOCK_TEST_AND_SET_16:
3e272de8 6777 mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_TEST_AND_SET_1);
c2f47e15 6778 target = expand_builtin_lock_test_and_set (mode, exp, target);
b6a5fc45 6779 if (target)
6780 return target;
6781 break;
6782
6783 case BUILT_IN_LOCK_RELEASE_1:
6784 case BUILT_IN_LOCK_RELEASE_2:
6785 case BUILT_IN_LOCK_RELEASE_4:
6786 case BUILT_IN_LOCK_RELEASE_8:
27213ba3 6787 case BUILT_IN_LOCK_RELEASE_16:
3e272de8 6788 mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_RELEASE_1);
c2f47e15 6789 expand_builtin_lock_release (mode, exp);
b6a5fc45 6790 return const0_rtx;
6791
6792 case BUILT_IN_SYNCHRONIZE:
6793 expand_builtin_synchronize ();
6794 return const0_rtx;
6795
0a39fd54 6796 case BUILT_IN_OBJECT_SIZE:
6797 return expand_builtin_object_size (exp);
6798
6799 case BUILT_IN_MEMCPY_CHK:
6800 case BUILT_IN_MEMPCPY_CHK:
6801 case BUILT_IN_MEMMOVE_CHK:
6802 case BUILT_IN_MEMSET_CHK:
6803 target = expand_builtin_memory_chk (exp, target, mode, fcode);
6804 if (target)
6805 return target;
6806 break;
6807
6808 case BUILT_IN_STRCPY_CHK:
6809 case BUILT_IN_STPCPY_CHK:
6810 case BUILT_IN_STRNCPY_CHK:
6811 case BUILT_IN_STRCAT_CHK:
b356dfef 6812 case BUILT_IN_STRNCAT_CHK:
0a39fd54 6813 case BUILT_IN_SNPRINTF_CHK:
6814 case BUILT_IN_VSNPRINTF_CHK:
6815 maybe_emit_chk_warning (exp, fcode);
6816 break;
6817
6818 case BUILT_IN_SPRINTF_CHK:
6819 case BUILT_IN_VSPRINTF_CHK:
6820 maybe_emit_sprintf_chk_warning (exp, fcode);
6821 break;
6822
92482ee0 6823 default: /* just do library call, if unknown builtin */
146c1b4f 6824 break;
53800dbe 6825 }
6826
6827 /* The switch statement above can drop through to cause the function
6828 to be called normally. */
6829 return expand_call (exp, target, ignore);
6830}
650e4c94 6831
805e22b2 6832/* Determine whether a tree node represents a call to a built-in
52203a9d 6833 function. If the tree T is a call to a built-in function with
6834 the right number of arguments of the appropriate types, return
6835 the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
6836 Otherwise the return value is END_BUILTINS. */
aecda0d6 6837
805e22b2 6838enum built_in_function
aecda0d6 6839builtin_mathfn_code (tree t)
805e22b2 6840{
c2f47e15 6841 tree fndecl, arg, parmlist;
52203a9d 6842 tree argtype, parmtype;
c2f47e15 6843 call_expr_arg_iterator iter;
805e22b2 6844
6845 if (TREE_CODE (t) != CALL_EXPR
c2f47e15 6846 || TREE_CODE (CALL_EXPR_FN (t)) != ADDR_EXPR)
805e22b2 6847 return END_BUILTINS;
6848
c6e6ecb1 6849 fndecl = get_callee_fndecl (t);
6850 if (fndecl == NULL_TREE
52203a9d 6851 || TREE_CODE (fndecl) != FUNCTION_DECL
805e22b2 6852 || ! DECL_BUILT_IN (fndecl)
6853 || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
6854 return END_BUILTINS;
6855
52203a9d 6856 parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
c2f47e15 6857 init_call_expr_arg_iterator (t, &iter);
52203a9d 6858 for (; parmlist; parmlist = TREE_CHAIN (parmlist))
e9f80ff5 6859 {
52203a9d 6860 /* If a function doesn't take a variable number of arguments,
6861 the last element in the list will have type `void'. */
6862 parmtype = TREE_VALUE (parmlist);
6863 if (VOID_TYPE_P (parmtype))
6864 {
c2f47e15 6865 if (more_call_expr_args_p (&iter))
52203a9d 6866 return END_BUILTINS;
6867 return DECL_FUNCTION_CODE (fndecl);
6868 }
6869
c2f47e15 6870 if (! more_call_expr_args_p (&iter))
e9f80ff5 6871 return END_BUILTINS;
c2f47e15 6872
6873 arg = next_call_expr_arg (&iter);
6874 argtype = TREE_TYPE (arg);
52203a9d 6875
6876 if (SCALAR_FLOAT_TYPE_P (parmtype))
6877 {
6878 if (! SCALAR_FLOAT_TYPE_P (argtype))
6879 return END_BUILTINS;
6880 }
6881 else if (COMPLEX_FLOAT_TYPE_P (parmtype))
6882 {
6883 if (! COMPLEX_FLOAT_TYPE_P (argtype))
6884 return END_BUILTINS;
6885 }
6886 else if (POINTER_TYPE_P (parmtype))
6887 {
6888 if (! POINTER_TYPE_P (argtype))
6889 return END_BUILTINS;
6890 }
6891 else if (INTEGRAL_TYPE_P (parmtype))
6892 {
6893 if (! INTEGRAL_TYPE_P (argtype))
6894 return END_BUILTINS;
6895 }
6896 else
e9f80ff5 6897 return END_BUILTINS;
e9f80ff5 6898 }
6899
52203a9d 6900 /* Variable-length argument list. */
805e22b2 6901 return DECL_FUNCTION_CODE (fndecl);
6902}
6903
c2f47e15 6904/* Fold a call to __builtin_constant_p, if we know its argument ARG will
6905 evaluate to a constant. */
650e4c94 6906
6907static tree
c2f47e15 6908fold_builtin_constant_p (tree arg)
650e4c94 6909{
650e4c94 6910 /* We return 1 for a numeric type that's known to be a constant
6911 value at compile-time or for an aggregate type that's a
6912 literal constant. */
c2f47e15 6913 STRIP_NOPS (arg);
650e4c94 6914
6915 /* If we know this is a constant, emit the constant of one. */
c2f47e15 6916 if (CONSTANT_CLASS_P (arg)
6917 || (TREE_CODE (arg) == CONSTRUCTOR
6918 && TREE_CONSTANT (arg)))
650e4c94 6919 return integer_one_node;
c2f47e15 6920 if (TREE_CODE (arg) == ADDR_EXPR)
adcfa3a3 6921 {
c2f47e15 6922 tree op = TREE_OPERAND (arg, 0);
adcfa3a3 6923 if (TREE_CODE (op) == STRING_CST
6924 || (TREE_CODE (op) == ARRAY_REF
6925 && integer_zerop (TREE_OPERAND (op, 1))
6926 && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
6927 return integer_one_node;
6928 }
650e4c94 6929
1fb4300c 6930 /* If this expression has side effects, show we don't know it to be a
6931 constant. Likewise if it's a pointer or aggregate type since in
6932 those case we only want literals, since those are only optimized
f97c71a1 6933 when generating RTL, not later.
6934 And finally, if we are compiling an initializer, not code, we
6935 need to return a definite result now; there's not going to be any
6936 more optimization done. */
c2f47e15 6937 if (TREE_SIDE_EFFECTS (arg)
6938 || AGGREGATE_TYPE_P (TREE_TYPE (arg))
6939 || POINTER_TYPE_P (TREE_TYPE (arg))
47be647d 6940 || cfun == 0
6941 || folding_initializer)
650e4c94 6942 return integer_zero_node;
6943
c2f47e15 6944 return NULL_TREE;
650e4c94 6945}
6946
c2f47e15 6947/* Fold a call to __builtin_expect with argument ARG, if we expect that a
6948 comparison against the argument will fold to a constant. In practice,
6949 this means a true constant or the address of a non-weak symbol. */
4ee9c684 6950
6951static tree
c2f47e15 6952fold_builtin_expect (tree arg)
4ee9c684 6953{
c2f47e15 6954 tree inner;
4ee9c684 6955
6956 /* If the argument isn't invariant, then there's nothing we can do. */
6957 if (!TREE_INVARIANT (arg))
c2f47e15 6958 return NULL_TREE;
4ee9c684 6959
6960 /* If we're looking at an address of a weak decl, then do not fold. */
6961 inner = arg;
6962 STRIP_NOPS (inner);
6963 if (TREE_CODE (inner) == ADDR_EXPR)
6964 {
6965 do
6966 {
6967 inner = TREE_OPERAND (inner, 0);
6968 }
6969 while (TREE_CODE (inner) == COMPONENT_REF
6970 || TREE_CODE (inner) == ARRAY_REF);
6971 if (DECL_P (inner) && DECL_WEAK (inner))
c2f47e15 6972 return NULL_TREE;
4ee9c684 6973 }
6974
6975 /* Otherwise, ARG already has the proper type for the return value. */
6976 return arg;
6977}
6978
c2f47e15 6979/* Fold a call to __builtin_classify_type with argument ARG. */
27d0c333 6980
539a3a92 6981static tree
c2f47e15 6982fold_builtin_classify_type (tree arg)
539a3a92 6983{
c2f47e15 6984 if (arg == 0)
7016c612 6985 return build_int_cst (NULL_TREE, no_type_class);
539a3a92 6986
c2f47e15 6987 return build_int_cst (NULL_TREE, type_to_class (TREE_TYPE (arg)));
539a3a92 6988}
6989
c2f47e15 6990/* Fold a call to __builtin_strlen with argument ARG. */
e6e27594 6991
6992static tree
c2f47e15 6993fold_builtin_strlen (tree arg)
e6e27594 6994{
c2f47e15 6995 if (!validate_arg (arg, POINTER_TYPE))
e6e27594 6996 return NULL_TREE;
6997 else
6998 {
c2f47e15 6999 tree len = c_strlen (arg, 0);
e6e27594 7000
7001 if (len)
7002 {
7003 /* Convert from the internal "sizetype" type to "size_t". */
7004 if (size_type_node)
7005 len = fold_convert (size_type_node, len);
7006 return len;
7007 }
7008
7009 return NULL_TREE;
7010 }
7011}
7012
92c43e3c 7013/* Fold a call to __builtin_inf or __builtin_huge_val. */
7014
7015static tree
aecda0d6 7016fold_builtin_inf (tree type, int warn)
92c43e3c 7017{
aa870c1b 7018 REAL_VALUE_TYPE real;
7019
40f4dbd5 7020 /* __builtin_inff is intended to be usable to define INFINITY on all
7021 targets. If an infinity is not available, INFINITY expands "to a
7022 positive constant of type float that overflows at translation
7023 time", footnote "In this case, using INFINITY will violate the
7024 constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
7025 Thus we pedwarn to ensure this constraint violation is
7026 diagnosed. */
92c43e3c 7027 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
40f4dbd5 7028 pedwarn ("target format does not support infinity");
92c43e3c 7029
aa870c1b 7030 real_inf (&real);
7031 return build_real (type, real);
92c43e3c 7032}
7033
c2f47e15 7034/* Fold a call to __builtin_nan or __builtin_nans with argument ARG. */
b0db7939 7035
7036static tree
c2f47e15 7037fold_builtin_nan (tree arg, tree type, int quiet)
b0db7939 7038{
7039 REAL_VALUE_TYPE real;
7040 const char *str;
7041
c2f47e15 7042 if (!validate_arg (arg, POINTER_TYPE))
7043 return NULL_TREE;
7044 str = c_getstr (arg);
b0db7939 7045 if (!str)
c2f47e15 7046 return NULL_TREE;
b0db7939 7047
7048 if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
c2f47e15 7049 return NULL_TREE;
b0db7939 7050
7051 return build_real (type, real);
7052}
7053
277f8dd2 7054/* Return true if the floating point expression T has an integer value.
7055 We also allow +Inf, -Inf and NaN to be considered integer values. */
7056
7057static bool
7058integer_valued_real_p (tree t)
7059{
7060 switch (TREE_CODE (t))
7061 {
7062 case FLOAT_EXPR:
7063 return true;
7064
7065 case ABS_EXPR:
7066 case SAVE_EXPR:
7067 case NON_LVALUE_EXPR:
7068 return integer_valued_real_p (TREE_OPERAND (t, 0));
7069
7070 case COMPOUND_EXPR:
41076ef6 7071 case MODIFY_EXPR:
277f8dd2 7072 case BIND_EXPR:
35cc02b5 7073 return integer_valued_real_p (GENERIC_TREE_OPERAND (t, 1));
277f8dd2 7074
7075 case PLUS_EXPR:
7076 case MINUS_EXPR:
7077 case MULT_EXPR:
7078 case MIN_EXPR:
7079 case MAX_EXPR:
7080 return integer_valued_real_p (TREE_OPERAND (t, 0))
7081 && integer_valued_real_p (TREE_OPERAND (t, 1));
7082
7083 case COND_EXPR:
7084 return integer_valued_real_p (TREE_OPERAND (t, 1))
7085 && integer_valued_real_p (TREE_OPERAND (t, 2));
7086
7087 case REAL_CST:
0570334c 7088 return real_isinteger (TREE_REAL_CST_PTR (t), TYPE_MODE (TREE_TYPE (t)));
277f8dd2 7089
7090 case NOP_EXPR:
7091 {
7092 tree type = TREE_TYPE (TREE_OPERAND (t, 0));
7093 if (TREE_CODE (type) == INTEGER_TYPE)
7094 return true;
7095 if (TREE_CODE (type) == REAL_TYPE)
7096 return integer_valued_real_p (TREE_OPERAND (t, 0));
7097 break;
7098 }
7099
7100 case CALL_EXPR:
7101 switch (builtin_mathfn_code (t))
7102 {
4f35b1fc 7103 CASE_FLT_FN (BUILT_IN_CEIL):
7104 CASE_FLT_FN (BUILT_IN_FLOOR):
7105 CASE_FLT_FN (BUILT_IN_NEARBYINT):
7106 CASE_FLT_FN (BUILT_IN_RINT):
7107 CASE_FLT_FN (BUILT_IN_ROUND):
7108 CASE_FLT_FN (BUILT_IN_TRUNC):
277f8dd2 7109 return true;
7110
d4a43a03 7111 CASE_FLT_FN (BUILT_IN_FMIN):
7112 CASE_FLT_FN (BUILT_IN_FMAX):
c2f47e15 7113 return integer_valued_real_p (CALL_EXPR_ARG (t, 0))
7114 && integer_valued_real_p (CALL_EXPR_ARG (t, 1));
d4a43a03 7115
277f8dd2 7116 default:
7117 break;
7118 }
7119 break;
7120
7121 default:
7122 break;
7123 }
7124 return false;
7125}
7126
c2f47e15 7127/* FNDECL is assumed to be a builtin where truncation can be propagated
6528f4f4 7128 across (for instance floor((double)f) == (double)floorf (f).
c2f47e15 7129 Do the transformation for a call with argument ARG. */
277f8dd2 7130
6528f4f4 7131static tree
c2f47e15 7132fold_trunc_transparent_mathfn (tree fndecl, tree arg)
6528f4f4 7133{
6528f4f4 7134 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
277f8dd2 7135
c2f47e15 7136 if (!validate_arg (arg, REAL_TYPE))
7137 return NULL_TREE;
6528f4f4 7138
277f8dd2 7139 /* Integer rounding functions are idempotent. */
7140 if (fcode == builtin_mathfn_code (arg))
7141 return arg;
7142
7143 /* If argument is already integer valued, and we don't need to worry
7144 about setting errno, there's no need to perform rounding. */
7145 if (! flag_errno_math && integer_valued_real_p (arg))
7146 return arg;
7147
7148 if (optimize)
6528f4f4 7149 {
277f8dd2 7150 tree arg0 = strip_float_extensions (arg);
2426241c 7151 tree ftype = TREE_TYPE (TREE_TYPE (fndecl));
6528f4f4 7152 tree newtype = TREE_TYPE (arg0);
7153 tree decl;
7154
7155 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7156 && (decl = mathfn_built_in (newtype, fcode)))
c2f47e15 7157 return fold_convert (ftype,
7158 build_call_expr (decl, 1,
7159 fold_convert (newtype, arg0)));
6528f4f4 7160 }
c2f47e15 7161 return NULL_TREE;
6528f4f4 7162}
7163
c2f47e15 7164/* FNDECL is assumed to be builtin which can narrow the FP type of
7165 the argument, for instance lround((double)f) -> lroundf (f).
7166 Do the transformation for a call with argument ARG. */
9ed65c7f 7167
7168static tree
c2f47e15 7169fold_fixed_mathfn (tree fndecl, tree arg)
9ed65c7f 7170{
9ed65c7f 7171 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9ed65c7f 7172
c2f47e15 7173 if (!validate_arg (arg, REAL_TYPE))
7174 return NULL_TREE;
9ed65c7f 7175
7176 /* If argument is already integer valued, and we don't need to worry
7177 about setting errno, there's no need to perform rounding. */
7178 if (! flag_errno_math && integer_valued_real_p (arg))
49d00087 7179 return fold_build1 (FIX_TRUNC_EXPR, TREE_TYPE (TREE_TYPE (fndecl)), arg);
9ed65c7f 7180
7181 if (optimize)
7182 {
7183 tree ftype = TREE_TYPE (arg);
7184 tree arg0 = strip_float_extensions (arg);
7185 tree newtype = TREE_TYPE (arg0);
7186 tree decl;
7187
7188 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7189 && (decl = mathfn_built_in (newtype, fcode)))
c2f47e15 7190 return build_call_expr (decl, 1, fold_convert (newtype, arg0));
9ed65c7f 7191 }
73a0da56 7192
7193 /* Canonicalize llround (x) to lround (x) on LP64 targets where
7194 sizeof (long long) == sizeof (long). */
7195 if (TYPE_PRECISION (long_long_integer_type_node)
7196 == TYPE_PRECISION (long_integer_type_node))
7197 {
7198 tree newfn = NULL_TREE;
7199 switch (fcode)
7200 {
7201 CASE_FLT_FN (BUILT_IN_LLCEIL):
7202 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
7203 break;
7204
7205 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7206 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
7207 break;
7208
7209 CASE_FLT_FN (BUILT_IN_LLROUND):
7210 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
7211 break;
7212
7213 CASE_FLT_FN (BUILT_IN_LLRINT):
7214 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
7215 break;
7216
7217 default:
7218 break;
7219 }
7220
7221 if (newfn)
7222 {
c2f47e15 7223 tree newcall = build_call_expr(newfn, 1, arg);
73a0da56 7224 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), newcall);
7225 }
7226 }
7227
c2f47e15 7228 return NULL_TREE;
9ed65c7f 7229}
7230
c2f47e15 7231/* Fold call to builtin cabs, cabsf or cabsl with argument ARG. TYPE is the
7232 return type. Return NULL_TREE if no simplification can be made. */
c63f4ad3 7233
7234static tree
c2f47e15 7235fold_builtin_cabs (tree arg, tree type, tree fndecl)
c63f4ad3 7236{
c2f47e15 7237 tree res;
c63f4ad3 7238
c63f4ad3 7239 if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
7240 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
7241 return NULL_TREE;
7242
b4725390 7243 /* Calculate the result when the argument is a constant. */
7244 if (TREE_CODE (arg) == COMPLEX_CST
7245 && (res = do_mpfr_arg2 (TREE_REALPART (arg), TREE_IMAGPART (arg),
7246 type, mpfr_hypot)))
7247 return res;
7248
1af0d139 7249 if (TREE_CODE (arg) == COMPLEX_EXPR)
7250 {
7251 tree real = TREE_OPERAND (arg, 0);
7252 tree imag = TREE_OPERAND (arg, 1);
7253
7254 /* If either part is zero, cabs is fabs of the other. */
7255 if (real_zerop (real))
7256 return fold_build1 (ABS_EXPR, type, imag);
7257 if (real_zerop (imag))
7258 return fold_build1 (ABS_EXPR, type, real);
7259
7260 /* cabs(x+xi) -> fabs(x)*sqrt(2). */
7261 if (flag_unsafe_math_optimizations
7262 && operand_equal_p (real, imag, OEP_PURE_SAME))
7263 {
2e7ca27b 7264 const REAL_VALUE_TYPE sqrt2_trunc
7265 = real_value_truncate (TYPE_MODE (type), dconstsqrt2);
1af0d139 7266 STRIP_NOPS (real);
7267 return fold_build2 (MULT_EXPR, type,
7268 fold_build1 (ABS_EXPR, type, real),
2e7ca27b 7269 build_real (type, sqrt2_trunc));
1af0d139 7270 }
7271 }
c63f4ad3 7272
749891b2 7273 /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */
7274 if (TREE_CODE (arg) == NEGATE_EXPR
7275 || TREE_CODE (arg) == CONJ_EXPR)
c2f47e15 7276 return build_call_expr (fndecl, 1, TREE_OPERAND (arg, 0));
749891b2 7277
7d3f6cc7 7278 /* Don't do this when optimizing for size. */
7279 if (flag_unsafe_math_optimizations
7280 && optimize && !optimize_size)
c63f4ad3 7281 {
0da0dbfa 7282 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
c63f4ad3 7283
7284 if (sqrtfn != NULL_TREE)
7285 {
c2f47e15 7286 tree rpart, ipart, result;
c63f4ad3 7287
4ee9c684 7288 arg = builtin_save_expr (arg);
29a6518e 7289
49d00087 7290 rpart = fold_build1 (REALPART_EXPR, type, arg);
7291 ipart = fold_build1 (IMAGPART_EXPR, type, arg);
c63f4ad3 7292
4ee9c684 7293 rpart = builtin_save_expr (rpart);
7294 ipart = builtin_save_expr (ipart);
c63f4ad3 7295
49d00087 7296 result = fold_build2 (PLUS_EXPR, type,
7297 fold_build2 (MULT_EXPR, type,
7298 rpart, rpart),
7299 fold_build2 (MULT_EXPR, type,
7300 ipart, ipart));
c63f4ad3 7301
c2f47e15 7302 return build_call_expr (sqrtfn, 1, result);
c63f4ad3 7303 }
7304 }
7305
7306 return NULL_TREE;
7307}
7308
c2f47e15 7309/* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG.
7310 Return NULL_TREE if no simplification can be made. */
e6e27594 7311
7312static tree
c2f47e15 7313fold_builtin_sqrt (tree arg, tree type)
e6e27594 7314{
7315
7316 enum built_in_function fcode;
b4e8ab0c 7317 tree res;
c2f47e15 7318
7319 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7320 return NULL_TREE;
7321
b4e8ab0c 7322 /* Calculate the result when the argument is a constant. */
7323 if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
7324 return res;
7325
e6e27594 7326 /* Optimize sqrt(expN(x)) = expN(x*0.5). */
7327 fcode = builtin_mathfn_code (arg);
7328 if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
7329 {
c2f47e15 7330 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
49d00087 7331 arg = fold_build2 (MULT_EXPR, type,
c2f47e15 7332 CALL_EXPR_ARG (arg, 0),
49d00087 7333 build_real (type, dconsthalf));
c2f47e15 7334 return build_call_expr (expfn, 1, arg);
e6e27594 7335 }
7336
7337 /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */
7338 if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
7339 {
7340 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7341
7342 if (powfn)
7343 {
c2f47e15 7344 tree arg0 = CALL_EXPR_ARG (arg, 0);
e6e27594 7345 tree tree_root;
7346 /* The inner root was either sqrt or cbrt. */
7347 REAL_VALUE_TYPE dconstroot =
7348 BUILTIN_SQRT_P (fcode) ? dconsthalf : dconstthird;
7349
7350 /* Adjust for the outer root. */
7351 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7352 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7353 tree_root = build_real (type, dconstroot);
c2f47e15 7354 return build_call_expr (powfn, 2, arg0, tree_root);
e6e27594 7355 }
7356 }
7357
bc33117f 7358 /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
e6e27594 7359 if (flag_unsafe_math_optimizations
7360 && (fcode == BUILT_IN_POW
7361 || fcode == BUILT_IN_POWF
7362 || fcode == BUILT_IN_POWL))
7363 {
c2f47e15 7364 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
7365 tree arg0 = CALL_EXPR_ARG (arg, 0);
7366 tree arg1 = CALL_EXPR_ARG (arg, 1);
bc33117f 7367 tree narg1;
7368 if (!tree_expr_nonnegative_p (arg0))
7369 arg0 = build1 (ABS_EXPR, type, arg0);
49d00087 7370 narg1 = fold_build2 (MULT_EXPR, type, arg1,
7371 build_real (type, dconsthalf));
c2f47e15 7372 return build_call_expr (powfn, 2, arg0, narg1);
e6e27594 7373 }
7374
7375 return NULL_TREE;
7376}
7377
c2f47e15 7378/* Fold a builtin function call to cbrt, cbrtf, or cbrtl with argument ARG.
7379 Return NULL_TREE if no simplification can be made. */
7380
e6e27594 7381static tree
c2f47e15 7382fold_builtin_cbrt (tree arg, tree type)
e6e27594 7383{
e6e27594 7384 const enum built_in_function fcode = builtin_mathfn_code (arg);
29f4cd78 7385 tree res;
e6e27594 7386
c2f47e15 7387 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7388 return NULL_TREE;
7389
29f4cd78 7390 /* Calculate the result when the argument is a constant. */
7391 if ((res = do_mpfr_arg1 (arg, type, mpfr_cbrt, NULL, NULL, 0)))
7392 return res;
e6e27594 7393
cdfeb715 7394 if (flag_unsafe_math_optimizations)
e6e27594 7395 {
cdfeb715 7396 /* Optimize cbrt(expN(x)) -> expN(x/3). */
7397 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 7398 {
c2f47e15 7399 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7400 const REAL_VALUE_TYPE third_trunc =
7401 real_value_truncate (TYPE_MODE (type), dconstthird);
49d00087 7402 arg = fold_build2 (MULT_EXPR, type,
c2f47e15 7403 CALL_EXPR_ARG (arg, 0),
49d00087 7404 build_real (type, third_trunc));
c2f47e15 7405 return build_call_expr (expfn, 1, arg);
cdfeb715 7406 }
e6e27594 7407
cdfeb715 7408 /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */
7409 if (BUILTIN_SQRT_P (fcode))
a0c938f0 7410 {
cdfeb715 7411 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
e6e27594 7412
cdfeb715 7413 if (powfn)
7414 {
c2f47e15 7415 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7416 tree tree_root;
7417 REAL_VALUE_TYPE dconstroot = dconstthird;
7418
7419 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7420 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7421 tree_root = build_real (type, dconstroot);
c2f47e15 7422 return build_call_expr (powfn, 2, arg0, tree_root);
cdfeb715 7423 }
e6e27594 7424 }
7425
cdfeb715 7426 /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */
7427 if (BUILTIN_CBRT_P (fcode))
a0c938f0 7428 {
c2f47e15 7429 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7430 if (tree_expr_nonnegative_p (arg0))
7431 {
7432 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7433
7434 if (powfn)
a0c938f0 7435 {
cdfeb715 7436 tree tree_root;
7437 REAL_VALUE_TYPE dconstroot;
a0c938f0 7438
cdfeb715 7439 real_arithmetic (&dconstroot, MULT_EXPR, &dconstthird, &dconstthird);
7440 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7441 tree_root = build_real (type, dconstroot);
c2f47e15 7442 return build_call_expr (powfn, 2, arg0, tree_root);
cdfeb715 7443 }
7444 }
7445 }
a0c938f0 7446
cdfeb715 7447 /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */
c2f47e15 7448 if (fcode == BUILT_IN_POW
7449 || fcode == BUILT_IN_POWF
cdfeb715 7450 || fcode == BUILT_IN_POWL)
a0c938f0 7451 {
c2f47e15 7452 tree arg00 = CALL_EXPR_ARG (arg, 0);
7453 tree arg01 = CALL_EXPR_ARG (arg, 1);
cdfeb715 7454 if (tree_expr_nonnegative_p (arg00))
7455 {
c2f47e15 7456 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7457 const REAL_VALUE_TYPE dconstroot
7458 = real_value_truncate (TYPE_MODE (type), dconstthird);
49d00087 7459 tree narg01 = fold_build2 (MULT_EXPR, type, arg01,
7460 build_real (type, dconstroot));
c2f47e15 7461 return build_call_expr (powfn, 2, arg00, narg01);
cdfeb715 7462 }
7463 }
e6e27594 7464 }
7465 return NULL_TREE;
7466}
7467
c2f47e15 7468/* Fold function call to builtin cos, cosf, or cosl with argument ARG.
7469 TYPE is the type of the return value. Return NULL_TREE if no
7470 simplification can be made. */
7471
e6e27594 7472static tree
c2f47e15 7473fold_builtin_cos (tree arg, tree type, tree fndecl)
e6e27594 7474{
e6ab33d8 7475 tree res, narg;
e6e27594 7476
c2f47e15 7477 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7478 return NULL_TREE;
7479
bffb7645 7480 /* Calculate the result when the argument is a constant. */
728bac60 7481 if ((res = do_mpfr_arg1 (arg, type, mpfr_cos, NULL, NULL, 0)))
bffb7645 7482 return res;
7483
e6e27594 7484 /* Optimize cos(-x) into cos (x). */
e6ab33d8 7485 if ((narg = fold_strip_sign_ops (arg)))
c2f47e15 7486 return build_call_expr (fndecl, 1, narg);
e6e27594 7487
7488 return NULL_TREE;
7489}
7490
c2f47e15 7491/* Fold function call to builtin cosh, coshf, or coshl with argument ARG.
7492 Return NULL_TREE if no simplification can be made. */
7493
cacdc1af 7494static tree
c2f47e15 7495fold_builtin_cosh (tree arg, tree type, tree fndecl)
cacdc1af 7496{
c2f47e15 7497 if (validate_arg (arg, REAL_TYPE))
cacdc1af 7498 {
cacdc1af 7499 tree res, narg;
7500
7501 /* Calculate the result when the argument is a constant. */
7502 if ((res = do_mpfr_arg1 (arg, type, mpfr_cosh, NULL, NULL, 0)))
7503 return res;
7504
7505 /* Optimize cosh(-x) into cosh (x). */
7506 if ((narg = fold_strip_sign_ops (arg)))
c2f47e15 7507 return build_call_expr (fndecl, 1, narg);
cacdc1af 7508 }
7509
7510 return NULL_TREE;
7511}
7512
c2f47e15 7513/* Fold function call to builtin tan, tanf, or tanl with argument ARG.
7514 Return NULL_TREE if no simplification can be made. */
7515
e6e27594 7516static tree
c2f47e15 7517fold_builtin_tan (tree arg, tree type)
e6e27594 7518{
7519 enum built_in_function fcode;
29f4cd78 7520 tree res;
e6e27594 7521
c2f47e15 7522 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7523 return NULL_TREE;
7524
bffb7645 7525 /* Calculate the result when the argument is a constant. */
728bac60 7526 if ((res = do_mpfr_arg1 (arg, type, mpfr_tan, NULL, NULL, 0)))
bffb7645 7527 return res;
7528
e6e27594 7529 /* Optimize tan(atan(x)) = x. */
7530 fcode = builtin_mathfn_code (arg);
7531 if (flag_unsafe_math_optimizations
7532 && (fcode == BUILT_IN_ATAN
7533 || fcode == BUILT_IN_ATANF
7534 || fcode == BUILT_IN_ATANL))
c2f47e15 7535 return CALL_EXPR_ARG (arg, 0);
e6e27594 7536
7537 return NULL_TREE;
7538}
7539
d735c391 7540/* Fold function call to builtin sincos, sincosf, or sincosl. Return
7541 NULL_TREE if no simplification can be made. */
7542
7543static tree
c2f47e15 7544fold_builtin_sincos (tree arg0, tree arg1, tree arg2)
d735c391 7545{
c2f47e15 7546 tree type;
d735c391 7547 tree res, fn, call;
7548
c2f47e15 7549 if (!validate_arg (arg0, REAL_TYPE)
7550 || !validate_arg (arg1, POINTER_TYPE)
7551 || !validate_arg (arg2, POINTER_TYPE))
d735c391 7552 return NULL_TREE;
7553
d735c391 7554 type = TREE_TYPE (arg0);
d735c391 7555
7556 /* Calculate the result when the argument is a constant. */
7557 if ((res = do_mpfr_sincos (arg0, arg1, arg2)))
7558 return res;
7559
7560 /* Canonicalize sincos to cexpi. */
2a6b4c77 7561 if (!TARGET_C99_FUNCTIONS)
7562 return NULL_TREE;
d735c391 7563 fn = mathfn_built_in (type, BUILT_IN_CEXPI);
7564 if (!fn)
7565 return NULL_TREE;
7566
c2f47e15 7567 call = build_call_expr (fn, 1, arg0);
d735c391 7568 call = builtin_save_expr (call);
7569
7570 return build2 (COMPOUND_EXPR, type,
7571 build2 (MODIFY_EXPR, void_type_node,
7572 build_fold_indirect_ref (arg1),
7573 build1 (IMAGPART_EXPR, type, call)),
7574 build2 (MODIFY_EXPR, void_type_node,
7575 build_fold_indirect_ref (arg2),
7576 build1 (REALPART_EXPR, type, call)));
7577}
7578
c5bb2c4b 7579/* Fold function call to builtin cexp, cexpf, or cexpl. Return
7580 NULL_TREE if no simplification can be made. */
7581
7582static tree
c2f47e15 7583fold_builtin_cexp (tree arg0, tree type)
c5bb2c4b 7584{
c2f47e15 7585 tree rtype;
c5bb2c4b 7586 tree realp, imagp, ifn;
7587
c2f47e15 7588 if (!validate_arg (arg0, COMPLEX_TYPE))
c5bb2c4b 7589 return NULL_TREE;
7590
c5bb2c4b 7591 rtype = TREE_TYPE (TREE_TYPE (arg0));
7592
7593 /* In case we can figure out the real part of arg0 and it is constant zero
7594 fold to cexpi. */
2a6b4c77 7595 if (!TARGET_C99_FUNCTIONS)
7596 return NULL_TREE;
c5bb2c4b 7597 ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI);
7598 if (!ifn)
7599 return NULL_TREE;
7600
7601 if ((realp = fold_unary (REALPART_EXPR, rtype, arg0))
7602 && real_zerop (realp))
7603 {
7604 tree narg = fold_build1 (IMAGPART_EXPR, rtype, arg0);
c2f47e15 7605 return build_call_expr (ifn, 1, narg);
c5bb2c4b 7606 }
7607
7608 /* In case we can easily decompose real and imaginary parts split cexp
7609 to exp (r) * cexpi (i). */
7610 if (flag_unsafe_math_optimizations
7611 && realp)
7612 {
7613 tree rfn, rcall, icall;
7614
7615 rfn = mathfn_built_in (rtype, BUILT_IN_EXP);
7616 if (!rfn)
7617 return NULL_TREE;
7618
7619 imagp = fold_unary (IMAGPART_EXPR, rtype, arg0);
7620 if (!imagp)
7621 return NULL_TREE;
7622
c2f47e15 7623 icall = build_call_expr (ifn, 1, imagp);
c5bb2c4b 7624 icall = builtin_save_expr (icall);
c2f47e15 7625 rcall = build_call_expr (rfn, 1, realp);
c5bb2c4b 7626 rcall = builtin_save_expr (rcall);
7627 return build2 (COMPLEX_EXPR, type,
7628 build2 (MULT_EXPR, rtype,
7629 rcall,
7630 build1 (REALPART_EXPR, rtype, icall)),
7631 build2 (MULT_EXPR, rtype,
7632 rcall,
7633 build1 (IMAGPART_EXPR, rtype, icall)));
7634 }
7635
7636 return NULL_TREE;
7637}
7638
c2f47e15 7639/* Fold function call to builtin trunc, truncf or truncl with argument ARG.
7640 Return NULL_TREE if no simplification can be made. */
277f8dd2 7641
7642static tree
c2f47e15 7643fold_builtin_trunc (tree fndecl, tree arg)
277f8dd2 7644{
c2f47e15 7645 if (!validate_arg (arg, REAL_TYPE))
7646 return NULL_TREE;
277f8dd2 7647
7648 /* Optimize trunc of constant value. */
f96bd2bf 7649 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7650 {
7651 REAL_VALUE_TYPE r, x;
2426241c 7652 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7653
7654 x = TREE_REAL_CST (arg);
7655 real_trunc (&r, TYPE_MODE (type), &x);
7656 return build_real (type, r);
7657 }
7658
c2f47e15 7659 return fold_trunc_transparent_mathfn (fndecl, arg);
277f8dd2 7660}
7661
c2f47e15 7662/* Fold function call to builtin floor, floorf or floorl with argument ARG.
7663 Return NULL_TREE if no simplification can be made. */
277f8dd2 7664
7665static tree
c2f47e15 7666fold_builtin_floor (tree fndecl, tree arg)
277f8dd2 7667{
c2f47e15 7668 if (!validate_arg (arg, REAL_TYPE))
7669 return NULL_TREE;
277f8dd2 7670
7671 /* Optimize floor of constant value. */
f96bd2bf 7672 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7673 {
7674 REAL_VALUE_TYPE x;
7675
7676 x = TREE_REAL_CST (arg);
7677 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7678 {
2426241c 7679 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7680 REAL_VALUE_TYPE r;
7681
7682 real_floor (&r, TYPE_MODE (type), &x);
7683 return build_real (type, r);
7684 }
7685 }
7686
acc2b92e 7687 /* Fold floor (x) where x is nonnegative to trunc (x). */
7688 if (tree_expr_nonnegative_p (arg))
30fe8286 7689 {
7690 tree truncfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_TRUNC);
7691 if (truncfn)
c2f47e15 7692 return build_call_expr (truncfn, 1, arg);
30fe8286 7693 }
acc2b92e 7694
c2f47e15 7695 return fold_trunc_transparent_mathfn (fndecl, arg);
277f8dd2 7696}
7697
c2f47e15 7698/* Fold function call to builtin ceil, ceilf or ceill with argument ARG.
7699 Return NULL_TREE if no simplification can be made. */
277f8dd2 7700
7701static tree
c2f47e15 7702fold_builtin_ceil (tree fndecl, tree arg)
277f8dd2 7703{
c2f47e15 7704 if (!validate_arg (arg, REAL_TYPE))
7705 return NULL_TREE;
277f8dd2 7706
7707 /* Optimize ceil of constant value. */
f96bd2bf 7708 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7709 {
7710 REAL_VALUE_TYPE x;
7711
7712 x = TREE_REAL_CST (arg);
7713 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7714 {
2426241c 7715 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7716 REAL_VALUE_TYPE r;
7717
7718 real_ceil (&r, TYPE_MODE (type), &x);
7719 return build_real (type, r);
7720 }
7721 }
7722
c2f47e15 7723 return fold_trunc_transparent_mathfn (fndecl, arg);
277f8dd2 7724}
7725
c2f47e15 7726/* Fold function call to builtin round, roundf or roundl with argument ARG.
7727 Return NULL_TREE if no simplification can be made. */
89ab3887 7728
7729static tree
c2f47e15 7730fold_builtin_round (tree fndecl, tree arg)
89ab3887 7731{
c2f47e15 7732 if (!validate_arg (arg, REAL_TYPE))
7733 return NULL_TREE;
89ab3887 7734
34f17811 7735 /* Optimize round of constant value. */
f96bd2bf 7736 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
89ab3887 7737 {
7738 REAL_VALUE_TYPE x;
7739
7740 x = TREE_REAL_CST (arg);
7741 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7742 {
2426241c 7743 tree type = TREE_TYPE (TREE_TYPE (fndecl));
89ab3887 7744 REAL_VALUE_TYPE r;
7745
7746 real_round (&r, TYPE_MODE (type), &x);
7747 return build_real (type, r);
7748 }
7749 }
7750
c2f47e15 7751 return fold_trunc_transparent_mathfn (fndecl, arg);
89ab3887 7752}
7753
34f17811 7754/* Fold function call to builtin lround, lroundf or lroundl (or the
c2f47e15 7755 corresponding long long versions) and other rounding functions. ARG
7756 is the argument to the call. Return NULL_TREE if no simplification
7757 can be made. */
34f17811 7758
7759static tree
c2f47e15 7760fold_builtin_int_roundingfn (tree fndecl, tree arg)
34f17811 7761{
c2f47e15 7762 if (!validate_arg (arg, REAL_TYPE))
7763 return NULL_TREE;
34f17811 7764
7765 /* Optimize lround of constant value. */
f96bd2bf 7766 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
34f17811 7767 {
7768 const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
7769
7770 if (! REAL_VALUE_ISNAN (x) && ! REAL_VALUE_ISINF (x))
7771 {
2426241c 7772 tree itype = TREE_TYPE (TREE_TYPE (fndecl));
ca9b061d 7773 tree ftype = TREE_TYPE (arg);
7774 unsigned HOST_WIDE_INT lo2;
34f17811 7775 HOST_WIDE_INT hi, lo;
7776 REAL_VALUE_TYPE r;
7777
ad52b9b7 7778 switch (DECL_FUNCTION_CODE (fndecl))
7779 {
4f35b1fc 7780 CASE_FLT_FN (BUILT_IN_LFLOOR):
7781 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 7782 real_floor (&r, TYPE_MODE (ftype), &x);
7783 break;
7784
4f35b1fc 7785 CASE_FLT_FN (BUILT_IN_LCEIL):
7786 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 7787 real_ceil (&r, TYPE_MODE (ftype), &x);
7788 break;
7789
4f35b1fc 7790 CASE_FLT_FN (BUILT_IN_LROUND):
7791 CASE_FLT_FN (BUILT_IN_LLROUND):
ad52b9b7 7792 real_round (&r, TYPE_MODE (ftype), &x);
7793 break;
7794
7795 default:
7796 gcc_unreachable ();
7797 }
7798
34f17811 7799 REAL_VALUE_TO_INT (&lo, &hi, r);
ca9b061d 7800 if (!fit_double_type (lo, hi, &lo2, &hi, itype))
7801 return build_int_cst_wide (itype, lo2, hi);
34f17811 7802 }
7803 }
7804
acc2b92e 7805 switch (DECL_FUNCTION_CODE (fndecl))
7806 {
7807 CASE_FLT_FN (BUILT_IN_LFLOOR):
7808 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7809 /* Fold lfloor (x) where x is nonnegative to FIX_TRUNC (x). */
7810 if (tree_expr_nonnegative_p (arg))
7811 return fold_build1 (FIX_TRUNC_EXPR, TREE_TYPE (TREE_TYPE (fndecl)),
7812 arg);
7813 break;
7814 default:;
7815 }
7816
c2f47e15 7817 return fold_fixed_mathfn (fndecl, arg);
34f17811 7818}
7819
70fb4c07 7820/* Fold function call to builtin ffs, clz, ctz, popcount and parity
c2f47e15 7821 and their long and long long variants (i.e. ffsl and ffsll). ARG is
7822 the argument to the call. Return NULL_TREE if no simplification can
7823 be made. */
70fb4c07 7824
7825static tree
c2f47e15 7826fold_builtin_bitop (tree fndecl, tree arg)
70fb4c07 7827{
c2f47e15 7828 if (!validate_arg (arg, INTEGER_TYPE))
70fb4c07 7829 return NULL_TREE;
7830
7831 /* Optimize for constant argument. */
f96bd2bf 7832 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
70fb4c07 7833 {
7834 HOST_WIDE_INT hi, width, result;
7835 unsigned HOST_WIDE_INT lo;
7c446c95 7836 tree type;
70fb4c07 7837
7838 type = TREE_TYPE (arg);
7839 width = TYPE_PRECISION (type);
7840 lo = TREE_INT_CST_LOW (arg);
7841
7842 /* Clear all the bits that are beyond the type's precision. */
7843 if (width > HOST_BITS_PER_WIDE_INT)
7844 {
7845 hi = TREE_INT_CST_HIGH (arg);
7846 if (width < 2 * HOST_BITS_PER_WIDE_INT)
7847 hi &= ~((HOST_WIDE_INT) (-1) >> (width - HOST_BITS_PER_WIDE_INT));
7848 }
7849 else
7850 {
7851 hi = 0;
7852 if (width < HOST_BITS_PER_WIDE_INT)
7853 lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
7854 }
7855
7856 switch (DECL_FUNCTION_CODE (fndecl))
7857 {
4f35b1fc 7858 CASE_INT_FN (BUILT_IN_FFS):
70fb4c07 7859 if (lo != 0)
7860 result = exact_log2 (lo & -lo) + 1;
7861 else if (hi != 0)
7862 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi) + 1;
7863 else
7864 result = 0;
7865 break;
7866
4f35b1fc 7867 CASE_INT_FN (BUILT_IN_CLZ):
70fb4c07 7868 if (hi != 0)
7869 result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
7870 else if (lo != 0)
7871 result = width - floor_log2 (lo) - 1;
7872 else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
7873 result = width;
7874 break;
7875
4f35b1fc 7876 CASE_INT_FN (BUILT_IN_CTZ):
70fb4c07 7877 if (lo != 0)
7878 result = exact_log2 (lo & -lo);
7879 else if (hi != 0)
7880 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi);
7881 else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
7882 result = width;
7883 break;
7884
4f35b1fc 7885 CASE_INT_FN (BUILT_IN_POPCOUNT):
70fb4c07 7886 result = 0;
7887 while (lo)
7888 result++, lo &= lo - 1;
7889 while (hi)
7890 result++, hi &= hi - 1;
7891 break;
7892
4f35b1fc 7893 CASE_INT_FN (BUILT_IN_PARITY):
70fb4c07 7894 result = 0;
7895 while (lo)
7896 result++, lo &= lo - 1;
7897 while (hi)
7898 result++, hi &= hi - 1;
7899 result &= 1;
7900 break;
7901
7902 default:
64db345d 7903 gcc_unreachable ();
70fb4c07 7904 }
7905
2426241c 7906 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
70fb4c07 7907 }
7908
7909 return NULL_TREE;
7910}
7911
42791117 7912/* Fold function call to builtin_bswap and the long and long long
7913 variants. Return NULL_TREE if no simplification can be made. */
7914static tree
c2f47e15 7915fold_builtin_bswap (tree fndecl, tree arg)
42791117 7916{
c2f47e15 7917 if (! validate_arg (arg, INTEGER_TYPE))
7918 return NULL_TREE;
42791117 7919
7920 /* Optimize constant value. */
f96bd2bf 7921 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
42791117 7922 {
7923 HOST_WIDE_INT hi, width, r_hi = 0;
7924 unsigned HOST_WIDE_INT lo, r_lo = 0;
7925 tree type;
7926
7927 type = TREE_TYPE (arg);
7928 width = TYPE_PRECISION (type);
7929 lo = TREE_INT_CST_LOW (arg);
7930 hi = TREE_INT_CST_HIGH (arg);
7931
7932 switch (DECL_FUNCTION_CODE (fndecl))
7933 {
7934 case BUILT_IN_BSWAP32:
7935 case BUILT_IN_BSWAP64:
7936 {
7937 int s;
7938
7939 for (s = 0; s < width; s += 8)
7940 {
7941 int d = width - s - 8;
7942 unsigned HOST_WIDE_INT byte;
7943
7944 if (s < HOST_BITS_PER_WIDE_INT)
7945 byte = (lo >> s) & 0xff;
7946 else
7947 byte = (hi >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff;
7948
7949 if (d < HOST_BITS_PER_WIDE_INT)
7950 r_lo |= byte << d;
7951 else
7952 r_hi |= byte << (d - HOST_BITS_PER_WIDE_INT);
7953 }
7954 }
7955
7956 break;
7957
7958 default:
7959 gcc_unreachable ();
7960 }
7961
7962 if (width < HOST_BITS_PER_WIDE_INT)
7963 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), r_lo);
7964 else
7965 return build_int_cst_wide (TREE_TYPE (TREE_TYPE (fndecl)), r_lo, r_hi);
7966 }
7967
7968 return NULL_TREE;
7969}
c2f47e15 7970
8918c507 7971/* Return true if EXPR is the real constant contained in VALUE. */
7972
7973static bool
7974real_dconstp (tree expr, const REAL_VALUE_TYPE *value)
7975{
7976 STRIP_NOPS (expr);
7977
7978 return ((TREE_CODE (expr) == REAL_CST
f96bd2bf 7979 && !TREE_OVERFLOW (expr)
a0c938f0 7980 && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), *value))
7981 || (TREE_CODE (expr) == COMPLEX_CST
7982 && real_dconstp (TREE_REALPART (expr), value)
7983 && real_zerop (TREE_IMAGPART (expr))));
8918c507 7984}
7985
7986/* A subroutine of fold_builtin to fold the various logarithmic
29f4cd78 7987 functions. Return NULL_TREE if no simplification can me made.
7988 FUNC is the corresponding MPFR logarithm function. */
8918c507 7989
7990static tree
c2f47e15 7991fold_builtin_logarithm (tree fndecl, tree arg,
29f4cd78 7992 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 7993{
c2f47e15 7994 if (validate_arg (arg, REAL_TYPE))
8918c507 7995 {
8918c507 7996 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 7997 tree res;
8918c507 7998 const enum built_in_function fcode = builtin_mathfn_code (arg);
0862b7e9 7999
29f4cd78 8000 /* Optimize log(e) = 1.0. We're never passed an exact 'e',
8001 instead we'll look for 'e' truncated to MODE. So only do
8002 this if flag_unsafe_math_optimizations is set. */
8003 if (flag_unsafe_math_optimizations && func == mpfr_log)
8004 {
8005 const REAL_VALUE_TYPE e_truncated =
8006 real_value_truncate (TYPE_MODE (type), dconste);
8007 if (real_dconstp (arg, &e_truncated))
1f5cb383 8008 return build_real (type, dconst1);
8009 }
0862b7e9 8010
29f4cd78 8011 /* Calculate the result when the argument is a constant. */
8012 if ((res = do_mpfr_arg1 (arg, type, func, &dconst0, NULL, false)))
8013 return res;
8014
8918c507 8015 /* Special case, optimize logN(expN(x)) = x. */
8016 if (flag_unsafe_math_optimizations
29f4cd78 8017 && ((func == mpfr_log
8918c507 8018 && (fcode == BUILT_IN_EXP
8019 || fcode == BUILT_IN_EXPF
8020 || fcode == BUILT_IN_EXPL))
29f4cd78 8021 || (func == mpfr_log2
8918c507 8022 && (fcode == BUILT_IN_EXP2
8023 || fcode == BUILT_IN_EXP2F
8024 || fcode == BUILT_IN_EXP2L))
29f4cd78 8025 || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode)))))
c2f47e15 8026 return fold_convert (type, CALL_EXPR_ARG (arg, 0));
8918c507 8027
ca273d4a 8028 /* Optimize logN(func()) for various exponential functions. We
a0c938f0 8029 want to determine the value "x" and the power "exponent" in
8030 order to transform logN(x**exponent) into exponent*logN(x). */
8918c507 8031 if (flag_unsafe_math_optimizations)
a0c938f0 8032 {
8918c507 8033 tree exponent = 0, x = 0;
0862b7e9 8034
8918c507 8035 switch (fcode)
8036 {
4f35b1fc 8037 CASE_FLT_FN (BUILT_IN_EXP):
8918c507 8038 /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
8918c507 8039 x = build_real (type,
8040 real_value_truncate (TYPE_MODE (type), dconste));
c2f47e15 8041 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8042 break;
4f35b1fc 8043 CASE_FLT_FN (BUILT_IN_EXP2):
8918c507 8044 /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */
8045 x = build_real (type, dconst2);
c2f47e15 8046 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8047 break;
4f35b1fc 8048 CASE_FLT_FN (BUILT_IN_EXP10):
8049 CASE_FLT_FN (BUILT_IN_POW10):
8918c507 8050 /* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */
8051 x = build_real (type, dconst10);
c2f47e15 8052 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8053 break;
4f35b1fc 8054 CASE_FLT_FN (BUILT_IN_SQRT):
8918c507 8055 /* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */
c2f47e15 8056 x = CALL_EXPR_ARG (arg, 0);
8918c507 8057 exponent = build_real (type, dconsthalf);
8058 break;
4f35b1fc 8059 CASE_FLT_FN (BUILT_IN_CBRT):
8918c507 8060 /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */
c2f47e15 8061 x = CALL_EXPR_ARG (arg, 0);
8918c507 8062 exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
8063 dconstthird));
8064 break;
4f35b1fc 8065 CASE_FLT_FN (BUILT_IN_POW):
8918c507 8066 /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x). */
c2f47e15 8067 x = CALL_EXPR_ARG (arg, 0);
8068 exponent = CALL_EXPR_ARG (arg, 1);
8918c507 8069 break;
8070 default:
8071 break;
8072 }
8073
8074 /* Now perform the optimization. */
8075 if (x && exponent)
8076 {
c2f47e15 8077 tree logfn = build_call_expr (fndecl, 1, x);
49d00087 8078 return fold_build2 (MULT_EXPR, type, exponent, logfn);
8918c507 8079 }
8080 }
8081 }
8082
c2f47e15 8083 return NULL_TREE;
8918c507 8084}
0862b7e9 8085
f0c477f2 8086/* Fold a builtin function call to hypot, hypotf, or hypotl. Return
8087 NULL_TREE if no simplification can be made. */
8088
8089static tree
c2f47e15 8090fold_builtin_hypot (tree fndecl, tree arg0, tree arg1, tree type)
f0c477f2 8091{
e6ab33d8 8092 tree res, narg0, narg1;
f0c477f2 8093
c2f47e15 8094 if (!validate_arg (arg0, REAL_TYPE)
8095 || !validate_arg (arg1, REAL_TYPE))
f0c477f2 8096 return NULL_TREE;
8097
8098 /* Calculate the result when the argument is a constant. */
8099 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot)))
8100 return res;
8101
6c95f21c 8102 /* If either argument to hypot has a negate or abs, strip that off.
8103 E.g. hypot(-x,fabs(y)) -> hypot(x,y). */
e6ab33d8 8104 narg0 = fold_strip_sign_ops (arg0);
8105 narg1 = fold_strip_sign_ops (arg1);
8106 if (narg0 || narg1)
8107 {
c2f47e15 8108 return build_call_expr (fndecl, 2, narg0 ? narg0 : arg0,
8109 narg1 ? narg1 : arg1);
6c95f21c 8110 }
8111
f0c477f2 8112 /* If either argument is zero, hypot is fabs of the other. */
8113 if (real_zerop (arg0))
8114 return fold_build1 (ABS_EXPR, type, arg1);
8115 else if (real_zerop (arg1))
8116 return fold_build1 (ABS_EXPR, type, arg0);
8117
6c95f21c 8118 /* hypot(x,x) -> fabs(x)*sqrt(2). */
8119 if (flag_unsafe_math_optimizations
8120 && operand_equal_p (arg0, arg1, OEP_PURE_SAME))
f0c477f2 8121 {
2e7ca27b 8122 const REAL_VALUE_TYPE sqrt2_trunc
8123 = real_value_truncate (TYPE_MODE (type), dconstsqrt2);
6c95f21c 8124 return fold_build2 (MULT_EXPR, type,
8125 fold_build1 (ABS_EXPR, type, arg0),
2e7ca27b 8126 build_real (type, sqrt2_trunc));
f0c477f2 8127 }
8128
f0c477f2 8129 return NULL_TREE;
8130}
8131
8132
e6e27594 8133/* Fold a builtin function call to pow, powf, or powl. Return
8134 NULL_TREE if no simplification can be made. */
8135static tree
c2f47e15 8136fold_builtin_pow (tree fndecl, tree arg0, tree arg1, tree type)
e6e27594 8137{
f0c477f2 8138 tree res;
e6e27594 8139
c2f47e15 8140 if (!validate_arg (arg0, REAL_TYPE)
8141 || !validate_arg (arg1, REAL_TYPE))
e6e27594 8142 return NULL_TREE;
8143
f0c477f2 8144 /* Calculate the result when the argument is a constant. */
8145 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_pow)))
8146 return res;
8147
e6e27594 8148 /* Optimize pow(1.0,y) = 1.0. */
8149 if (real_onep (arg0))
8150 return omit_one_operand (type, build_real (type, dconst1), arg1);
8151
8152 if (TREE_CODE (arg1) == REAL_CST
f96bd2bf 8153 && !TREE_OVERFLOW (arg1))
e6e27594 8154 {
198d9bbe 8155 REAL_VALUE_TYPE cint;
e6e27594 8156 REAL_VALUE_TYPE c;
198d9bbe 8157 HOST_WIDE_INT n;
8158
e6e27594 8159 c = TREE_REAL_CST (arg1);
8160
8161 /* Optimize pow(x,0.0) = 1.0. */
8162 if (REAL_VALUES_EQUAL (c, dconst0))
8163 return omit_one_operand (type, build_real (type, dconst1),
8164 arg0);
8165
8166 /* Optimize pow(x,1.0) = x. */
8167 if (REAL_VALUES_EQUAL (c, dconst1))
8168 return arg0;
8169
8170 /* Optimize pow(x,-1.0) = 1.0/x. */
8171 if (REAL_VALUES_EQUAL (c, dconstm1))
49d00087 8172 return fold_build2 (RDIV_EXPR, type,
8173 build_real (type, dconst1), arg0);
e6e27594 8174
8175 /* Optimize pow(x,0.5) = sqrt(x). */
8176 if (flag_unsafe_math_optimizations
8177 && REAL_VALUES_EQUAL (c, dconsthalf))
8178 {
8179 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
8180
8181 if (sqrtfn != NULL_TREE)
c2f47e15 8182 return build_call_expr (sqrtfn, 1, arg0);
e6e27594 8183 }
8184
feb5b3eb 8185 /* Optimize pow(x,1.0/3.0) = cbrt(x). */
8186 if (flag_unsafe_math_optimizations)
8187 {
8188 const REAL_VALUE_TYPE dconstroot
8189 = real_value_truncate (TYPE_MODE (type), dconstthird);
8190
8191 if (REAL_VALUES_EQUAL (c, dconstroot))
8192 {
8193 tree cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT);
8194 if (cbrtfn != NULL_TREE)
c2f47e15 8195 return build_call_expr (cbrtfn, 1, arg0);
feb5b3eb 8196 }
8197 }
8198
198d9bbe 8199 /* Check for an integer exponent. */
8200 n = real_to_integer (&c);
8201 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
8202 if (real_identical (&c, &cint))
e6e27594 8203 {
198d9bbe 8204 /* Attempt to evaluate pow at compile-time. */
8205 if (TREE_CODE (arg0) == REAL_CST
f96bd2bf 8206 && !TREE_OVERFLOW (arg0))
e6e27594 8207 {
8208 REAL_VALUE_TYPE x;
8209 bool inexact;
8210
8211 x = TREE_REAL_CST (arg0);
8212 inexact = real_powi (&x, TYPE_MODE (type), &x, n);
8213 if (flag_unsafe_math_optimizations || !inexact)
8214 return build_real (type, x);
8215 }
198d9bbe 8216
8217 /* Strip sign ops from even integer powers. */
8218 if ((n & 1) == 0 && flag_unsafe_math_optimizations)
8219 {
8220 tree narg0 = fold_strip_sign_ops (arg0);
8221 if (narg0)
c2f47e15 8222 return build_call_expr (fndecl, 2, narg0, arg1);
198d9bbe 8223 }
e6e27594 8224 }
8225 }
8226
cdfeb715 8227 if (flag_unsafe_math_optimizations)
e6e27594 8228 {
cdfeb715 8229 const enum built_in_function fcode = builtin_mathfn_code (arg0);
e6e27594 8230
cdfeb715 8231 /* Optimize pow(expN(x),y) = expN(x*y). */
8232 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 8233 {
c2f47e15 8234 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
8235 tree arg = CALL_EXPR_ARG (arg0, 0);
49d00087 8236 arg = fold_build2 (MULT_EXPR, type, arg, arg1);
c2f47e15 8237 return build_call_expr (expfn, 1, arg);
cdfeb715 8238 }
e6e27594 8239
cdfeb715 8240 /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
8241 if (BUILTIN_SQRT_P (fcode))
a0c938f0 8242 {
c2f47e15 8243 tree narg0 = CALL_EXPR_ARG (arg0, 0);
49d00087 8244 tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
8245 build_real (type, dconsthalf));
c2f47e15 8246 return build_call_expr (fndecl, 2, narg0, narg1);
cdfeb715 8247 }
8248
8249 /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */
8250 if (BUILTIN_CBRT_P (fcode))
a0c938f0 8251 {
c2f47e15 8252 tree arg = CALL_EXPR_ARG (arg0, 0);
cdfeb715 8253 if (tree_expr_nonnegative_p (arg))
8254 {
8255 const REAL_VALUE_TYPE dconstroot
8256 = real_value_truncate (TYPE_MODE (type), dconstthird);
49d00087 8257 tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
8258 build_real (type, dconstroot));
c2f47e15 8259 return build_call_expr (fndecl, 2, arg, narg1);
cdfeb715 8260 }
8261 }
a0c938f0 8262
cdfeb715 8263 /* Optimize pow(pow(x,y),z) = pow(x,y*z). */
c2f47e15 8264 if (fcode == BUILT_IN_POW
8265 || fcode == BUILT_IN_POWF
8266 || fcode == BUILT_IN_POWL)
a0c938f0 8267 {
c2f47e15 8268 tree arg00 = CALL_EXPR_ARG (arg0, 0);
8269 tree arg01 = CALL_EXPR_ARG (arg0, 1);
49d00087 8270 tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1);
c2f47e15 8271 return build_call_expr (fndecl, 2, arg00, narg1);
cdfeb715 8272 }
e6e27594 8273 }
cdfeb715 8274
e6e27594 8275 return NULL_TREE;
8276}
8277
c2f47e15 8278/* Fold a builtin function call to powi, powif, or powil with argument ARG.
8279 Return NULL_TREE if no simplification can be made. */
b4d0c20c 8280static tree
c2f47e15 8281fold_builtin_powi (tree fndecl ATTRIBUTE_UNUSED,
8282 tree arg0, tree arg1, tree type)
b4d0c20c 8283{
c2f47e15 8284 if (!validate_arg (arg0, REAL_TYPE)
8285 || !validate_arg (arg1, INTEGER_TYPE))
b4d0c20c 8286 return NULL_TREE;
8287
8288 /* Optimize pow(1.0,y) = 1.0. */
8289 if (real_onep (arg0))
8290 return omit_one_operand (type, build_real (type, dconst1), arg1);
8291
8292 if (host_integerp (arg1, 0))
8293 {
8294 HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
8295
8296 /* Evaluate powi at compile-time. */
8297 if (TREE_CODE (arg0) == REAL_CST
f96bd2bf 8298 && !TREE_OVERFLOW (arg0))
b4d0c20c 8299 {
8300 REAL_VALUE_TYPE x;
8301 x = TREE_REAL_CST (arg0);
8302 real_powi (&x, TYPE_MODE (type), &x, c);
8303 return build_real (type, x);
8304 }
8305
8306 /* Optimize pow(x,0) = 1.0. */
8307 if (c == 0)
8308 return omit_one_operand (type, build_real (type, dconst1),
8309 arg0);
8310
8311 /* Optimize pow(x,1) = x. */
8312 if (c == 1)
8313 return arg0;
8314
8315 /* Optimize pow(x,-1) = 1.0/x. */
8316 if (c == -1)
49d00087 8317 return fold_build2 (RDIV_EXPR, type,
8318 build_real (type, dconst1), arg0);
b4d0c20c 8319 }
8320
8321 return NULL_TREE;
8322}
8323
8918c507 8324/* A subroutine of fold_builtin to fold the various exponent
c2f47e15 8325 functions. Return NULL_TREE if no simplification can be made.
debf9994 8326 FUNC is the corresponding MPFR exponent function. */
8918c507 8327
8328static tree
c2f47e15 8329fold_builtin_exponent (tree fndecl, tree arg,
debf9994 8330 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8331{
c2f47e15 8332 if (validate_arg (arg, REAL_TYPE))
8918c507 8333 {
8918c507 8334 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8335 tree res;
debf9994 8336
8337 /* Calculate the result when the argument is a constant. */
728bac60 8338 if ((res = do_mpfr_arg1 (arg, type, func, NULL, NULL, 0)))
debf9994 8339 return res;
8918c507 8340
8341 /* Optimize expN(logN(x)) = x. */
8342 if (flag_unsafe_math_optimizations)
a0c938f0 8343 {
8918c507 8344 const enum built_in_function fcode = builtin_mathfn_code (arg);
8345
debf9994 8346 if ((func == mpfr_exp
8918c507 8347 && (fcode == BUILT_IN_LOG
8348 || fcode == BUILT_IN_LOGF
8349 || fcode == BUILT_IN_LOGL))
debf9994 8350 || (func == mpfr_exp2
8918c507 8351 && (fcode == BUILT_IN_LOG2
8352 || fcode == BUILT_IN_LOG2F
8353 || fcode == BUILT_IN_LOG2L))
debf9994 8354 || (func == mpfr_exp10
8918c507 8355 && (fcode == BUILT_IN_LOG10
8356 || fcode == BUILT_IN_LOG10F
8357 || fcode == BUILT_IN_LOG10L)))
c2f47e15 8358 return fold_convert (type, CALL_EXPR_ARG (arg, 0));
8918c507 8359 }
8360 }
8361
c2f47e15 8362 return NULL_TREE;
8918c507 8363}
8364
e973ffcc 8365/* Return true if VAR is a VAR_DECL or a component thereof. */
8366
8367static bool
8368var_decl_component_p (tree var)
8369{
8370 tree inner = var;
8371 while (handled_component_p (inner))
8372 inner = TREE_OPERAND (inner, 0);
8373 return SSA_VAR_P (inner);
8374}
8375
4f46f2b9 8376/* Fold function call to builtin memset. Return
9c8a1629 8377 NULL_TREE if no simplification can be made. */
8378
8379static tree
c2f47e15 8380fold_builtin_memset (tree dest, tree c, tree len, tree type, bool ignore)
9c8a1629 8381{
c2f47e15 8382 tree var, ret;
4f46f2b9 8383 unsigned HOST_WIDE_INT length, cval;
9c8a1629 8384
c2f47e15 8385 if (! validate_arg (dest, POINTER_TYPE)
8386 || ! validate_arg (c, INTEGER_TYPE)
8387 || ! validate_arg (len, INTEGER_TYPE))
8388 return NULL_TREE;
9c8a1629 8389
4f46f2b9 8390 if (! host_integerp (len, 1))
c2f47e15 8391 return NULL_TREE;
4f46f2b9 8392
9c8a1629 8393 /* If the LEN parameter is zero, return DEST. */
8394 if (integer_zerop (len))
4f46f2b9 8395 return omit_one_operand (type, dest, c);
9c8a1629 8396
4f46f2b9 8397 if (! host_integerp (c, 1) || TREE_SIDE_EFFECTS (dest))
c2f47e15 8398 return NULL_TREE;
9c8a1629 8399
4f46f2b9 8400 var = dest;
8401 STRIP_NOPS (var);
8402 if (TREE_CODE (var) != ADDR_EXPR)
c2f47e15 8403 return NULL_TREE;
4f46f2b9 8404
8405 var = TREE_OPERAND (var, 0);
8406 if (TREE_THIS_VOLATILE (var))
c2f47e15 8407 return NULL_TREE;
4f46f2b9 8408
8409 if (!INTEGRAL_TYPE_P (TREE_TYPE (var))
8410 && !POINTER_TYPE_P (TREE_TYPE (var)))
c2f47e15 8411 return NULL_TREE;
4f46f2b9 8412
e973ffcc 8413 if (! var_decl_component_p (var))
c2f47e15 8414 return NULL_TREE;
e973ffcc 8415
4f46f2b9 8416 length = tree_low_cst (len, 1);
8417 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (var))) != length
8418 || get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
8419 < (int) length)
c2f47e15 8420 return NULL_TREE;
4f46f2b9 8421
8422 if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT)
c2f47e15 8423 return NULL_TREE;
4f46f2b9 8424
8425 if (integer_zerop (c))
8426 cval = 0;
8427 else
8428 {
8429 if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64)
c2f47e15 8430 return NULL_TREE;
4f46f2b9 8431
8432 cval = tree_low_cst (c, 1);
8433 cval &= 0xff;
8434 cval |= cval << 8;
8435 cval |= cval << 16;
8436 cval |= (cval << 31) << 1;
8437 }
8438
8439 ret = build_int_cst_type (TREE_TYPE (var), cval);
41076ef6 8440 ret = build2 (MODIFY_EXPR, TREE_TYPE (var), var, ret);
4f46f2b9 8441 if (ignore)
8442 return ret;
8443
8444 return omit_one_operand (type, dest, ret);
9c8a1629 8445}
8446
4f46f2b9 8447/* Fold function call to builtin memset. Return
9c8a1629 8448 NULL_TREE if no simplification can be made. */
8449
8450static tree
c2f47e15 8451fold_builtin_bzero (tree dest, tree size, bool ignore)
9c8a1629 8452{
c2f47e15 8453 if (! validate_arg (dest, POINTER_TYPE)
8454 || ! validate_arg (size, INTEGER_TYPE))
8455 return NULL_TREE;
9c8a1629 8456
4f46f2b9 8457 if (!ignore)
c2f47e15 8458 return NULL_TREE;
a0c938f0 8459
4f46f2b9 8460 /* New argument list transforming bzero(ptr x, int y) to
8461 memset(ptr x, int 0, size_t y). This is done this way
8462 so that if it isn't expanded inline, we fallback to
8463 calling bzero instead of memset. */
8464
c2f47e15 8465 return fold_builtin_memset (dest, integer_zero_node,
8466 fold_convert (sizetype, size),
8467 void_type_node, ignore);
9c8a1629 8468}
8469
4f46f2b9 8470/* Fold function call to builtin mem{{,p}cpy,move}. Return
8471 NULL_TREE if no simplification can be made.
8472 If ENDP is 0, return DEST (like memcpy).
8473 If ENDP is 1, return DEST+LEN (like mempcpy).
8474 If ENDP is 2, return DEST+LEN-1 (like stpcpy).
8475 If ENDP is 3, return DEST, additionally *SRC and *DEST may overlap
8476 (memmove). */
9c8a1629 8477
8478static tree
c2f47e15 8479fold_builtin_memory_op (tree dest, tree src, tree len, tree type, bool ignore, int endp)
9c8a1629 8480{
c2f47e15 8481 tree destvar, srcvar, expr;
9c8a1629 8482
c2f47e15 8483 if (! validate_arg (dest, POINTER_TYPE)
8484 || ! validate_arg (src, POINTER_TYPE)
8485 || ! validate_arg (len, INTEGER_TYPE))
8486 return NULL_TREE;
9c8a1629 8487
8488 /* If the LEN parameter is zero, return DEST. */
8489 if (integer_zerop (len))
7e72af53 8490 return omit_one_operand (type, dest, src);
9c8a1629 8491
4f46f2b9 8492 /* If SRC and DEST are the same (and not volatile), return
8493 DEST{,+LEN,+LEN-1}. */
9c8a1629 8494 if (operand_equal_p (src, dest, 0))
4f46f2b9 8495 expr = len;
8496 else
8497 {
5a84fdd6 8498 tree srctype, desttype;
3b1757a2 8499 if (endp == 3)
8500 {
5a84fdd6 8501 int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
8502 int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
8503
3b1757a2 8504 /* Both DEST and SRC must be pointer types.
8505 ??? This is what old code did. Is the testing for pointer types
8506 really mandatory?
8507
8508 If either SRC is readonly or length is 1, we can use memcpy. */
8509 if (dest_align && src_align
8510 && (readonly_data_expr (src)
5a84fdd6 8511 || (host_integerp (len, 1)
b4fc673b 8512 && (MIN (src_align, dest_align) / BITS_PER_UNIT >=
5a84fdd6 8513 tree_low_cst (len, 1)))))
3b1757a2 8514 {
8515 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8516 if (!fn)
c2f47e15 8517 return NULL_TREE;
8518 return build_call_expr (fn, 3, dest, src, len);
3b1757a2 8519 }
c2f47e15 8520 return NULL_TREE;
3b1757a2 8521 }
4f46f2b9 8522
5a84fdd6 8523 if (!host_integerp (len, 0))
c2f47e15 8524 return NULL_TREE;
5a84fdd6 8525 /* FIXME:
8526 This logic lose for arguments like (type *)malloc (sizeof (type)),
8527 since we strip the casts of up to VOID return value from malloc.
8528 Perhaps we ought to inherit type from non-VOID argument here? */
8529 STRIP_NOPS (src);
8530 STRIP_NOPS (dest);
8531 srctype = TREE_TYPE (TREE_TYPE (src));
8532 desttype = TREE_TYPE (TREE_TYPE (dest));
8533 if (!srctype || !desttype
8534 || !TYPE_SIZE_UNIT (srctype)
8535 || !TYPE_SIZE_UNIT (desttype)
8536 || TREE_CODE (TYPE_SIZE_UNIT (srctype)) != INTEGER_CST
8537 || TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST
92552a26 8538 || !tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len)
8539 || !tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
c2f47e15 8540 return NULL_TREE;
4f46f2b9 8541
5a84fdd6 8542 if (get_pointer_alignment (dest, BIGGEST_ALIGNMENT)
8543 < (int) TYPE_ALIGN (desttype)
8544 || (get_pointer_alignment (src, BIGGEST_ALIGNMENT)
8545 < (int) TYPE_ALIGN (srctype)))
c2f47e15 8546 return NULL_TREE;
e973ffcc 8547
5a84fdd6 8548 if (!ignore)
8549 dest = builtin_save_expr (dest);
4f46f2b9 8550
5a84fdd6 8551 srcvar = build_fold_indirect_ref (src);
4f46f2b9 8552 if (TREE_THIS_VOLATILE (srcvar))
c2f47e15 8553 return NULL_TREE;
92552a26 8554 if (!tree_int_cst_equal (lang_hooks.expr_size (srcvar), len))
c2f47e15 8555 return NULL_TREE;
5a84fdd6 8556 /* With memcpy, it is possible to bypass aliasing rules, so without
8557 this check i. e. execute/20060930-2.c would be misoptimized, because
8558 it use conflicting alias set to hold argument for the memcpy call.
8559 This check is probably unnecesary with -fno-strict-aliasing.
8560 Similarly for destvar. See also PR29286. */
8561 if (!var_decl_component_p (srcvar)
8562 /* Accept: memcpy (*char_var, "test", 1); that simplify
8563 to char_var='t'; */
8564 || is_gimple_min_invariant (srcvar)
8565 || readonly_data_expr (src))
c2f47e15 8566 return NULL_TREE;
4f46f2b9 8567
5a84fdd6 8568 destvar = build_fold_indirect_ref (dest);
8569 if (TREE_THIS_VOLATILE (destvar))
c2f47e15 8570 return NULL_TREE;
92552a26 8571 if (!tree_int_cst_equal (lang_hooks.expr_size (destvar), len))
c2f47e15 8572 return NULL_TREE;
5a84fdd6 8573 if (!var_decl_component_p (destvar))
c2f47e15 8574 return NULL_TREE;
4f46f2b9 8575
5a84fdd6 8576 if (srctype == desttype
2d04fd8d 8577 || (gimple_in_ssa_p (cfun)
5a84fdd6 8578 && tree_ssa_useless_type_conversion_1 (desttype, srctype)))
8579 expr = srcvar;
8580 else if ((INTEGRAL_TYPE_P (TREE_TYPE (srcvar))
4f46f2b9 8581 || POINTER_TYPE_P (TREE_TYPE (srcvar)))
8582 && (INTEGRAL_TYPE_P (TREE_TYPE (destvar))
8583 || POINTER_TYPE_P (TREE_TYPE (destvar))))
8584 expr = fold_convert (TREE_TYPE (destvar), srcvar);
8585 else
8586 expr = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (destvar), srcvar);
41076ef6 8587 expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, expr);
4f46f2b9 8588 }
8589
8590 if (ignore)
8591 return expr;
8592
8593 if (endp == 0 || endp == 3)
8594 return omit_one_operand (type, dest, expr);
8595
8596 if (expr == len)
c2f47e15 8597 expr = NULL_TREE;
4f46f2b9 8598
8599 if (endp == 2)
8600 len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len,
8601 ssize_int (1));
8602
8603 len = fold_convert (TREE_TYPE (dest), len);
8604 dest = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
8605 dest = fold_convert (type, dest);
8606 if (expr)
8607 dest = omit_one_operand (type, dest, expr);
8608 return dest;
8609}
8610
c2f47e15 8611/* Fold function call to builtin strcpy with arguments DEST and SRC.
8612 If LEN is not NULL, it represents the length of the string to be
8613 copied. Return NULL_TREE if no simplification can be made. */
9c8a1629 8614
f0613857 8615tree
c2f47e15 8616fold_builtin_strcpy (tree fndecl, tree dest, tree src, tree len)
9c8a1629 8617{
c2f47e15 8618 tree fn;
9c8a1629 8619
c2f47e15 8620 if (!validate_arg (dest, POINTER_TYPE)
8621 || !validate_arg (src, POINTER_TYPE))
8622 return NULL_TREE;
9c8a1629 8623
8624 /* If SRC and DEST are the same (and not volatile), return DEST. */
8625 if (operand_equal_p (src, dest, 0))
2426241c 8626 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
9c8a1629 8627
f0613857 8628 if (optimize_size)
c2f47e15 8629 return NULL_TREE;
f0613857 8630
8631 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8632 if (!fn)
c2f47e15 8633 return NULL_TREE;
f0613857 8634
8635 if (!len)
8636 {
8637 len = c_strlen (src, 1);
8638 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 8639 return NULL_TREE;
f0613857 8640 }
8641
8642 len = size_binop (PLUS_EXPR, len, ssize_int (1));
2426241c 8643 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
c2f47e15 8644 build_call_expr (fn, 3, dest, src, len));
9c8a1629 8645}
8646
c2f47e15 8647/* Fold function call to builtin strncpy with arguments DEST, SRC, and LEN.
8648 If SLEN is not NULL, it represents the length of the source string.
8649 Return NULL_TREE if no simplification can be made. */
9c8a1629 8650
f0613857 8651tree
c2f47e15 8652fold_builtin_strncpy (tree fndecl, tree dest, tree src, tree len, tree slen)
9c8a1629 8653{
c2f47e15 8654 tree fn;
9c8a1629 8655
c2f47e15 8656 if (!validate_arg (dest, POINTER_TYPE)
8657 || !validate_arg (src, POINTER_TYPE)
8658 || !validate_arg (len, INTEGER_TYPE))
8659 return NULL_TREE;
9c8a1629 8660
8661 /* If the LEN parameter is zero, return DEST. */
8662 if (integer_zerop (len))
2426241c 8663 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
9c8a1629 8664
19226313 8665 /* We can't compare slen with len as constants below if len is not a
8666 constant. */
8667 if (len == 0 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 8668 return NULL_TREE;
19226313 8669
f0613857 8670 if (!slen)
8671 slen = c_strlen (src, 1);
8672
8673 /* Now, we must be passed a constant src ptr parameter. */
8674 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
c2f47e15 8675 return NULL_TREE;
f0613857 8676
8677 slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
8678
8679 /* We do not support simplification of this case, though we do
8680 support it when expanding trees into RTL. */
8681 /* FIXME: generate a call to __builtin_memset. */
8682 if (tree_int_cst_lt (slen, len))
c2f47e15 8683 return NULL_TREE;
f0613857 8684
8685 /* OK transform into builtin memcpy. */
8686 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8687 if (!fn)
c2f47e15 8688 return NULL_TREE;
2426241c 8689 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
c2f47e15 8690 build_call_expr (fn, 3, dest, src, len));
9c8a1629 8691}
8692
7959b13b 8693/* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the
8694 arguments to the call, and TYPE is its return type.
8695 Return NULL_TREE if no simplification can be made. */
8696
8697static tree
8698fold_builtin_memchr (tree arg1, tree arg2, tree len, tree type)
8699{
8700 if (!validate_arg (arg1, POINTER_TYPE)
8701 || !validate_arg (arg2, INTEGER_TYPE)
8702 || !validate_arg (len, INTEGER_TYPE))
8703 return NULL_TREE;
8704 else
8705 {
8706 const char *p1;
8707
8708 if (TREE_CODE (arg2) != INTEGER_CST
8709 || !host_integerp (len, 1))
8710 return NULL_TREE;
8711
8712 p1 = c_getstr (arg1);
8713 if (p1 && compare_tree_int (len, strlen (p1) + 1) <= 0)
8714 {
8715 char c;
8716 const char *r;
8717 tree tem;
8718
8719 if (target_char_cast (arg2, &c))
8720 return NULL_TREE;
8721
8722 r = memchr (p1, c, tree_low_cst (len, 1));
8723
8724 if (r == NULL)
8725 return build_int_cst (TREE_TYPE (arg1), 0);
8726
8727 tem = fold_build2 (PLUS_EXPR, TREE_TYPE (arg1), arg1,
8728 build_int_cst (TREE_TYPE (arg1), r - p1));
8729 return fold_convert (type, tem);
8730 }
8731 return NULL_TREE;
8732 }
8733}
8734
c2f47e15 8735/* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
8736 Return NULL_TREE if no simplification can be made. */
9c8a1629 8737
8738static tree
c2f47e15 8739fold_builtin_memcmp (tree arg1, tree arg2, tree len)
9c8a1629 8740{
c4fef134 8741 const char *p1, *p2;
9c8a1629 8742
c2f47e15 8743 if (!validate_arg (arg1, POINTER_TYPE)
8744 || !validate_arg (arg2, POINTER_TYPE)
8745 || !validate_arg (len, INTEGER_TYPE))
8746 return NULL_TREE;
9c8a1629 8747
8748 /* If the LEN parameter is zero, return zero. */
8749 if (integer_zerop (len))
c4fef134 8750 return omit_two_operands (integer_type_node, integer_zero_node,
8751 arg1, arg2);
9c8a1629 8752
8753 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8754 if (operand_equal_p (arg1, arg2, 0))
c4fef134 8755 return omit_one_operand (integer_type_node, integer_zero_node, len);
8756
8757 p1 = c_getstr (arg1);
8758 p2 = c_getstr (arg2);
8759
8760 /* If all arguments are constant, and the value of len is not greater
8761 than the lengths of arg1 and arg2, evaluate at compile-time. */
8762 if (host_integerp (len, 1) && p1 && p2
8763 && compare_tree_int (len, strlen (p1) + 1) <= 0
8764 && compare_tree_int (len, strlen (p2) + 1) <= 0)
8765 {
8766 const int r = memcmp (p1, p2, tree_low_cst (len, 1));
8767
8768 if (r > 0)
8769 return integer_one_node;
8770 else if (r < 0)
8771 return integer_minus_one_node;
8772 else
8773 return integer_zero_node;
8774 }
8775
8776 /* If len parameter is one, return an expression corresponding to
8777 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
8778 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
8779 {
8780 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8781 tree cst_uchar_ptr_node
8782 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8783
c4fef134 8784 tree ind1 = fold_convert (integer_type_node,
8785 build1 (INDIRECT_REF, cst_uchar_node,
8786 fold_convert (cst_uchar_ptr_node,
8787 arg1)));
8788 tree ind2 = fold_convert (integer_type_node,
8789 build1 (INDIRECT_REF, cst_uchar_node,
8790 fold_convert (cst_uchar_ptr_node,
8791 arg2)));
49d00087 8792 return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
c4fef134 8793 }
9c8a1629 8794
c2f47e15 8795 return NULL_TREE;
9c8a1629 8796}
8797
c2f47e15 8798/* Fold function call to builtin strcmp with arguments ARG1 and ARG2.
8799 Return NULL_TREE if no simplification can be made. */
9c8a1629 8800
8801static tree
c2f47e15 8802fold_builtin_strcmp (tree arg1, tree arg2)
9c8a1629 8803{
9c8a1629 8804 const char *p1, *p2;
8805
c2f47e15 8806 if (!validate_arg (arg1, POINTER_TYPE)
8807 || !validate_arg (arg2, POINTER_TYPE))
8808 return NULL_TREE;
9c8a1629 8809
8810 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8811 if (operand_equal_p (arg1, arg2, 0))
c4fef134 8812 return integer_zero_node;
9c8a1629 8813
8814 p1 = c_getstr (arg1);
8815 p2 = c_getstr (arg2);
8816
8817 if (p1 && p2)
8818 {
9c8a1629 8819 const int i = strcmp (p1, p2);
8820 if (i < 0)
c4fef134 8821 return integer_minus_one_node;
9c8a1629 8822 else if (i > 0)
c4fef134 8823 return integer_one_node;
9c8a1629 8824 else
c4fef134 8825 return integer_zero_node;
8826 }
8827
8828 /* If the second arg is "", return *(const unsigned char*)arg1. */
8829 if (p2 && *p2 == '\0')
8830 {
8831 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8832 tree cst_uchar_ptr_node
8833 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8834
c4fef134 8835 return fold_convert (integer_type_node,
8836 build1 (INDIRECT_REF, cst_uchar_node,
8837 fold_convert (cst_uchar_ptr_node,
8838 arg1)));
8839 }
8840
8841 /* If the first arg is "", return -*(const unsigned char*)arg2. */
8842 if (p1 && *p1 == '\0')
8843 {
8844 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8845 tree cst_uchar_ptr_node
8846 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8847
c4fef134 8848 tree temp = fold_convert (integer_type_node,
8849 build1 (INDIRECT_REF, cst_uchar_node,
8850 fold_convert (cst_uchar_ptr_node,
8851 arg2)));
49d00087 8852 return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
9c8a1629 8853 }
8854
c2f47e15 8855 return NULL_TREE;
9c8a1629 8856}
8857
c2f47e15 8858/* Fold function call to builtin strncmp with arguments ARG1, ARG2, and LEN.
8859 Return NULL_TREE if no simplification can be made. */
9c8a1629 8860
8861static tree
c2f47e15 8862fold_builtin_strncmp (tree arg1, tree arg2, tree len)
9c8a1629 8863{
9c8a1629 8864 const char *p1, *p2;
8865
c2f47e15 8866 if (!validate_arg (arg1, POINTER_TYPE)
8867 || !validate_arg (arg2, POINTER_TYPE)
8868 || !validate_arg (len, INTEGER_TYPE))
8869 return NULL_TREE;
9c8a1629 8870
8871 /* If the LEN parameter is zero, return zero. */
8872 if (integer_zerop (len))
c4fef134 8873 return omit_two_operands (integer_type_node, integer_zero_node,
8874 arg1, arg2);
9c8a1629 8875
8876 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8877 if (operand_equal_p (arg1, arg2, 0))
c4fef134 8878 return omit_one_operand (integer_type_node, integer_zero_node, len);
9c8a1629 8879
8880 p1 = c_getstr (arg1);
8881 p2 = c_getstr (arg2);
8882
8883 if (host_integerp (len, 1) && p1 && p2)
8884 {
9c8a1629 8885 const int i = strncmp (p1, p2, tree_low_cst (len, 1));
c4fef134 8886 if (i > 0)
8887 return integer_one_node;
8888 else if (i < 0)
8889 return integer_minus_one_node;
9c8a1629 8890 else
c4fef134 8891 return integer_zero_node;
8892 }
8893
8894 /* If the second arg is "", and the length is greater than zero,
8895 return *(const unsigned char*)arg1. */
8896 if (p2 && *p2 == '\0'
8897 && TREE_CODE (len) == INTEGER_CST
8898 && tree_int_cst_sgn (len) == 1)
8899 {
8900 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8901 tree cst_uchar_ptr_node
8902 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8903
c4fef134 8904 return fold_convert (integer_type_node,
8905 build1 (INDIRECT_REF, cst_uchar_node,
8906 fold_convert (cst_uchar_ptr_node,
8907 arg1)));
8908 }
8909
8910 /* If the first arg is "", and the length is greater than zero,
8911 return -*(const unsigned char*)arg2. */
8912 if (p1 && *p1 == '\0'
8913 && TREE_CODE (len) == INTEGER_CST
8914 && tree_int_cst_sgn (len) == 1)
8915 {
8916 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8917 tree cst_uchar_ptr_node
8918 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8919
c4fef134 8920 tree temp = fold_convert (integer_type_node,
8921 build1 (INDIRECT_REF, cst_uchar_node,
8922 fold_convert (cst_uchar_ptr_node,
8923 arg2)));
49d00087 8924 return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
c4fef134 8925 }
8926
8927 /* If len parameter is one, return an expression corresponding to
8928 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
8929 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
8930 {
8931 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8932 tree cst_uchar_ptr_node
8933 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8934
c4fef134 8935 tree ind1 = fold_convert (integer_type_node,
8936 build1 (INDIRECT_REF, cst_uchar_node,
8937 fold_convert (cst_uchar_ptr_node,
8938 arg1)));
8939 tree ind2 = fold_convert (integer_type_node,
8940 build1 (INDIRECT_REF, cst_uchar_node,
8941 fold_convert (cst_uchar_ptr_node,
8942 arg2)));
49d00087 8943 return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
9c8a1629 8944 }
8945
c2f47e15 8946 return NULL_TREE;
9c8a1629 8947}
8948
c2f47e15 8949/* Fold function call to builtin signbit, signbitf or signbitl with argument
8950 ARG. Return NULL_TREE if no simplification can be made. */
27f261ef 8951
8952static tree
c2f47e15 8953fold_builtin_signbit (tree arg, tree type)
27f261ef 8954{
c2f47e15 8955 tree temp;
27f261ef 8956
c2f47e15 8957 if (!validate_arg (arg, REAL_TYPE))
27f261ef 8958 return NULL_TREE;
8959
27f261ef 8960 /* If ARG is a compile-time constant, determine the result. */
8961 if (TREE_CODE (arg) == REAL_CST
f96bd2bf 8962 && !TREE_OVERFLOW (arg))
27f261ef 8963 {
8964 REAL_VALUE_TYPE c;
8965
8966 c = TREE_REAL_CST (arg);
8967 temp = REAL_VALUE_NEGATIVE (c) ? integer_one_node : integer_zero_node;
2426241c 8968 return fold_convert (type, temp);
27f261ef 8969 }
8970
8971 /* If ARG is non-negative, the result is always zero. */
8972 if (tree_expr_nonnegative_p (arg))
2426241c 8973 return omit_one_operand (type, integer_zero_node, arg);
27f261ef 8974
8975 /* If ARG's format doesn't have signed zeros, return "arg < 0.0". */
8976 if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
49d00087 8977 return fold_build2 (LT_EXPR, type, arg,
8978 build_real (TREE_TYPE (arg), dconst0));
27f261ef 8979
8980 return NULL_TREE;
8981}
8982
c2f47e15 8983/* Fold function call to builtin copysign, copysignf or copysignl with
8984 arguments ARG1 and ARG2. Return NULL_TREE if no simplification can
8985 be made. */
467214fd 8986
8987static tree
c2f47e15 8988fold_builtin_copysign (tree fndecl, tree arg1, tree arg2, tree type)
467214fd 8989{
c2f47e15 8990 tree tem;
467214fd 8991
c2f47e15 8992 if (!validate_arg (arg1, REAL_TYPE)
8993 || !validate_arg (arg2, REAL_TYPE))
467214fd 8994 return NULL_TREE;
8995
467214fd 8996 /* copysign(X,X) is X. */
8997 if (operand_equal_p (arg1, arg2, 0))
8998 return fold_convert (type, arg1);
8999
9000 /* If ARG1 and ARG2 are compile-time constants, determine the result. */
9001 if (TREE_CODE (arg1) == REAL_CST
9002 && TREE_CODE (arg2) == REAL_CST
f96bd2bf 9003 && !TREE_OVERFLOW (arg1)
9004 && !TREE_OVERFLOW (arg2))
467214fd 9005 {
9006 REAL_VALUE_TYPE c1, c2;
9007
9008 c1 = TREE_REAL_CST (arg1);
9009 c2 = TREE_REAL_CST (arg2);
749680e2 9010 /* c1.sign := c2.sign. */
467214fd 9011 real_copysign (&c1, &c2);
9012 return build_real (type, c1);
467214fd 9013 }
9014
9015 /* copysign(X, Y) is fabs(X) when Y is always non-negative.
9016 Remember to evaluate Y for side-effects. */
9017 if (tree_expr_nonnegative_p (arg2))
9018 return omit_one_operand (type,
49d00087 9019 fold_build1 (ABS_EXPR, type, arg1),
467214fd 9020 arg2);
9021
198d9bbe 9022 /* Strip sign changing operations for the first argument. */
9023 tem = fold_strip_sign_ops (arg1);
9024 if (tem)
c2f47e15 9025 return build_call_expr (fndecl, 2, tem, arg2);
198d9bbe 9026
467214fd 9027 return NULL_TREE;
9028}
9029
c2f47e15 9030/* Fold a call to builtin isascii with argument ARG. */
d49367d4 9031
9032static tree
c2f47e15 9033fold_builtin_isascii (tree arg)
d49367d4 9034{
c2f47e15 9035 if (!validate_arg (arg, INTEGER_TYPE))
9036 return NULL_TREE;
d49367d4 9037 else
9038 {
9039 /* Transform isascii(c) -> ((c & ~0x7f) == 0). */
7c446c95 9040 arg = build2 (BIT_AND_EXPR, integer_type_node, arg,
9041 build_int_cst (NULL_TREE,
7016c612 9042 ~ (unsigned HOST_WIDE_INT) 0x7f));
f2532264 9043 return fold_build2 (EQ_EXPR, integer_type_node,
9044 arg, integer_zero_node);
d49367d4 9045 }
9046}
9047
c2f47e15 9048/* Fold a call to builtin toascii with argument ARG. */
d49367d4 9049
9050static tree
c2f47e15 9051fold_builtin_toascii (tree arg)
d49367d4 9052{
c2f47e15 9053 if (!validate_arg (arg, INTEGER_TYPE))
9054 return NULL_TREE;
9055
9056 /* Transform toascii(c) -> (c & 0x7f). */
9057 return fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
9058 build_int_cst (NULL_TREE, 0x7f));
d49367d4 9059}
9060
c2f47e15 9061/* Fold a call to builtin isdigit with argument ARG. */
df1cf42e 9062
9063static tree
c2f47e15 9064fold_builtin_isdigit (tree arg)
df1cf42e 9065{
c2f47e15 9066 if (!validate_arg (arg, INTEGER_TYPE))
9067 return NULL_TREE;
df1cf42e 9068 else
9069 {
9070 /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */
624d37a6 9071 /* According to the C standard, isdigit is unaffected by locale.
9072 However, it definitely is affected by the target character set. */
624d37a6 9073 unsigned HOST_WIDE_INT target_digit0
9074 = lang_hooks.to_target_charset ('0');
9075
9076 if (target_digit0 == 0)
9077 return NULL_TREE;
9078
c2f47e15 9079 arg = fold_convert (unsigned_type_node, arg);
05abc81b 9080 arg = build2 (MINUS_EXPR, unsigned_type_node, arg,
624d37a6 9081 build_int_cst (unsigned_type_node, target_digit0));
f2532264 9082 return fold_build2 (LE_EXPR, integer_type_node, arg,
9083 build_int_cst (unsigned_type_node, 9));
df1cf42e 9084 }
9085}
27f261ef 9086
c2f47e15 9087/* Fold a call to fabs, fabsf or fabsl with argument ARG. */
d1aade50 9088
9089static tree
c2f47e15 9090fold_builtin_fabs (tree arg, tree type)
d1aade50 9091{
c2f47e15 9092 if (!validate_arg (arg, REAL_TYPE))
9093 return NULL_TREE;
d1aade50 9094
9829e110 9095 arg = fold_convert (type, arg);
d1aade50 9096 if (TREE_CODE (arg) == REAL_CST)
9097 return fold_abs_const (arg, type);
49d00087 9098 return fold_build1 (ABS_EXPR, type, arg);
d1aade50 9099}
9100
c2f47e15 9101/* Fold a call to abs, labs, llabs or imaxabs with argument ARG. */
d1aade50 9102
9103static tree
c2f47e15 9104fold_builtin_abs (tree arg, tree type)
d1aade50 9105{
c2f47e15 9106 if (!validate_arg (arg, INTEGER_TYPE))
9107 return NULL_TREE;
d1aade50 9108
9829e110 9109 arg = fold_convert (type, arg);
d1aade50 9110 if (TREE_CODE (arg) == INTEGER_CST)
9111 return fold_abs_const (arg, type);
49d00087 9112 return fold_build1 (ABS_EXPR, type, arg);
d1aade50 9113}
9114
d4a43a03 9115/* Fold a call to builtin fmin or fmax. */
9116
9117static tree
c2f47e15 9118fold_builtin_fmin_fmax (tree arg0, tree arg1, tree type, bool max)
d4a43a03 9119{
c2f47e15 9120 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, REAL_TYPE))
d4a43a03 9121 {
d4a43a03 9122 /* Calculate the result when the argument is a constant. */
9123 tree res = do_mpfr_arg2 (arg0, arg1, type, (max ? mpfr_max : mpfr_min));
9124
9125 if (res)
9126 return res;
9127
61fe3555 9128 /* If either argument is NaN, return the other one. Avoid the
9129 transformation if we get (and honor) a signalling NaN. Using
9130 omit_one_operand() ensures we create a non-lvalue. */
9131 if (TREE_CODE (arg0) == REAL_CST
9132 && real_isnan (&TREE_REAL_CST (arg0))
9133 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
9134 || ! TREE_REAL_CST (arg0).signalling))
9135 return omit_one_operand (type, arg1, arg0);
9136 if (TREE_CODE (arg1) == REAL_CST
9137 && real_isnan (&TREE_REAL_CST (arg1))
9138 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
9139 || ! TREE_REAL_CST (arg1).signalling))
9140 return omit_one_operand (type, arg0, arg1);
9141
d4a43a03 9142 /* Transform fmin/fmax(x,x) -> x. */
9143 if (operand_equal_p (arg0, arg1, OEP_PURE_SAME))
9144 return omit_one_operand (type, arg0, arg1);
9145
9146 /* Convert fmin/fmax to MIN_EXPR/MAX_EXPR. C99 requires these
9147 functions to return the numeric arg if the other one is NaN.
9148 These tree codes don't honor that, so only transform if
9149 -ffinite-math-only is set. C99 doesn't require -0.0 to be
9150 handled, so we don't have to worry about it either. */
9151 if (flag_finite_math_only)
9152 return fold_build2 ((max ? MAX_EXPR : MIN_EXPR), type,
9153 fold_convert (type, arg0),
9154 fold_convert (type, arg1));
9155 }
9156 return NULL_TREE;
9157}
9158
abe4dcf6 9159/* Fold a call to builtin carg(a+bi) -> atan2(b,a). */
9160
9161static tree
c2f47e15 9162fold_builtin_carg (tree arg, tree type)
abe4dcf6 9163{
c2f47e15 9164 if (validate_arg (arg, COMPLEX_TYPE))
abe4dcf6 9165 {
9166 tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
9167
9168 if (atan2_fn)
9169 {
c2f47e15 9170 tree new_arg = builtin_save_expr (arg);
9171 tree r_arg = fold_build1 (REALPART_EXPR, type, new_arg);
9172 tree i_arg = fold_build1 (IMAGPART_EXPR, type, new_arg);
9173 return build_call_expr (atan2_fn, 2, i_arg, r_arg);
abe4dcf6 9174 }
9175 }
9176
9177 return NULL_TREE;
9178}
9179
cb2b9385 9180/* Fold a call to builtin logb/ilogb. */
9181
9182static tree
9183fold_builtin_logb (tree arg, tree rettype)
9184{
9185 if (! validate_arg (arg, REAL_TYPE))
9186 return NULL_TREE;
9187
9188 STRIP_NOPS (arg);
9189
9190 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9191 {
9192 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
9193
9194 switch (value->cl)
9195 {
9196 case rvc_nan:
9197 case rvc_inf:
9198 /* If arg is Inf or NaN and we're logb, return it. */
9199 if (TREE_CODE (rettype) == REAL_TYPE)
9200 return fold_convert (rettype, arg);
9201 /* Fall through... */
9202 case rvc_zero:
9203 /* Zero may set errno and/or raise an exception for logb, also
9204 for ilogb we don't know FP_ILOGB0. */
9205 return NULL_TREE;
9206 case rvc_normal:
9207 /* For normal numbers, proceed iff radix == 2. In GCC,
9208 normalized significands are in the range [0.5, 1.0). We
9209 want the exponent as if they were [1.0, 2.0) so get the
9210 exponent and subtract 1. */
9211 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
9212 return fold_convert (rettype, build_int_cst (NULL_TREE,
9213 REAL_EXP (value)-1));
9214 break;
9215 }
9216 }
9217
9218 return NULL_TREE;
9219}
9220
9221/* Fold a call to builtin significand, if radix == 2. */
9222
9223static tree
9224fold_builtin_significand (tree arg, tree rettype)
9225{
9226 if (! validate_arg (arg, REAL_TYPE))
9227 return NULL_TREE;
9228
9229 STRIP_NOPS (arg);
9230
9231 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9232 {
9233 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
9234
9235 switch (value->cl)
9236 {
9237 case rvc_zero:
9238 case rvc_nan:
9239 case rvc_inf:
9240 /* If arg is +-0, +-Inf or +-NaN, then return it. */
9241 return fold_convert (rettype, arg);
9242 case rvc_normal:
9243 /* For normal numbers, proceed iff radix == 2. */
9244 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
9245 {
9246 REAL_VALUE_TYPE result = *value;
9247 /* In GCC, normalized significands are in the range [0.5,
9248 1.0). We want them to be [1.0, 2.0) so set the
9249 exponent to 1. */
9250 SET_REAL_EXP (&result, 1);
9251 return build_real (rettype, result);
9252 }
9253 break;
9254 }
9255 }
9256
9257 return NULL_TREE;
9258}
9259
3838b9ae 9260/* Fold a call to builtin frexp, we can assume the base is 2. */
9261
9262static tree
9263fold_builtin_frexp (tree arg0, tree arg1, tree rettype)
9264{
9265 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9266 return NULL_TREE;
9267
9268 STRIP_NOPS (arg0);
9269
9270 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9271 return NULL_TREE;
9272
9273 arg1 = build_fold_indirect_ref (arg1);
9274
9275 /* Proceed if a valid pointer type was passed in. */
9276 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
9277 {
9278 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9279 tree frac, exp;
9280
9281 switch (value->cl)
9282 {
9283 case rvc_zero:
9284 /* For +-0, return (*exp = 0, +-0). */
9285 exp = integer_zero_node;
9286 frac = arg0;
9287 break;
9288 case rvc_nan:
9289 case rvc_inf:
9290 /* For +-NaN or +-Inf, *exp is unspecified, return arg0. */
9291 return omit_one_operand (rettype, arg0, arg1);
9292 case rvc_normal:
9293 {
9294 /* Since the frexp function always expects base 2, and in
9295 GCC normalized significands are already in the range
9296 [0.5, 1.0), we have exactly what frexp wants. */
9297 REAL_VALUE_TYPE frac_rvt = *value;
9298 SET_REAL_EXP (&frac_rvt, 0);
9299 frac = build_real (rettype, frac_rvt);
9300 exp = build_int_cst (NULL_TREE, REAL_EXP (value));
9301 }
9302 break;
9303 default:
9304 gcc_unreachable ();
9305 }
9306
9307 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
9308 arg1 = fold_build2 (MODIFY_EXPR, rettype, arg1, exp);
9309 TREE_SIDE_EFFECTS (arg1) = 1;
9310 return fold_build2 (COMPOUND_EXPR, rettype, arg1, frac);
9311 }
9312
9313 return NULL_TREE;
9314}
9315
7587301b 9316/* Fold a call to builtin ldexp or scalbn/scalbln. If LDEXP is true
9317 then we can assume the base is two. If it's false, then we have to
9318 check the mode of the TYPE parameter in certain cases. */
9319
9320static tree
9321fold_builtin_load_exponent (tree arg0, tree arg1, tree type, bool ldexp)
9322{
9323 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, INTEGER_TYPE))
9324 {
9325 STRIP_NOPS (arg0);
9326 STRIP_NOPS (arg1);
9327
9328 /* If arg0 is 0, Inf or NaN, or if arg1 is 0, then return arg0. */
9329 if (real_zerop (arg0) || integer_zerop (arg1)
9330 || (TREE_CODE (arg0) == REAL_CST
9331 && (real_isnan (&TREE_REAL_CST (arg0))
9332 || real_isinf (&TREE_REAL_CST (arg0)))))
9333 return omit_one_operand (type, arg0, arg1);
9334
9335 /* If both arguments are constant, then try to evaluate it. */
9336 if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2)
9337 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
9338 && host_integerp (arg1, 0))
9339 {
9340 /* Bound the maximum adjustment to twice the range of the
9341 mode's valid exponents. Use abs to ensure the range is
9342 positive as a sanity check. */
9343 const long max_exp_adj = 2 *
9344 labs (REAL_MODE_FORMAT (TYPE_MODE (type))->emax
9345 - REAL_MODE_FORMAT (TYPE_MODE (type))->emin);
9346
9347 /* Get the user-requested adjustment. */
9348 const HOST_WIDE_INT req_exp_adj = tree_low_cst (arg1, 0);
9349
9350 /* The requested adjustment must be inside this range. This
9351 is a preliminary cap to avoid things like overflow, we
9352 may still fail to compute the result for other reasons. */
9353 if (-max_exp_adj < req_exp_adj && req_exp_adj < max_exp_adj)
9354 {
9355 REAL_VALUE_TYPE initial_result;
9356
9357 real_ldexp (&initial_result, &TREE_REAL_CST (arg0), req_exp_adj);
9358
9359 /* Ensure we didn't overflow. */
9360 if (! real_isinf (&initial_result))
9361 {
9362 const REAL_VALUE_TYPE trunc_result
9363 = real_value_truncate (TYPE_MODE (type), initial_result);
9364
9365 /* Only proceed if the target mode can hold the
9366 resulting value. */
9367 if (REAL_VALUES_EQUAL (initial_result, trunc_result))
9368 return build_real (type, trunc_result);
9369 }
9370 }
9371 }
9372 }
9373
9374 return NULL_TREE;
9375}
9376
ebf8b4f5 9377/* Fold a call to builtin modf. */
9378
9379static tree
9380fold_builtin_modf (tree arg0, tree arg1, tree rettype)
9381{
9382 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9383 return NULL_TREE;
9384
9385 STRIP_NOPS (arg0);
9386
9387 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9388 return NULL_TREE;
9389
9390 arg1 = build_fold_indirect_ref (arg1);
9391
9392 /* Proceed if a valid pointer type was passed in. */
9393 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
9394 {
9395 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9396 REAL_VALUE_TYPE trunc, frac;
9397
9398 switch (value->cl)
9399 {
9400 case rvc_nan:
9401 case rvc_zero:
9402 /* For +-NaN or +-0, return (*arg1 = arg0, arg0). */
9403 trunc = frac = *value;
9404 break;
9405 case rvc_inf:
9406 /* For +-Inf, return (*arg1 = arg0, +-0). */
9407 frac = dconst0;
9408 frac.sign = value->sign;
9409 trunc = *value;
9410 break;
9411 case rvc_normal:
9412 /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)). */
9413 real_trunc (&trunc, VOIDmode, value);
9414 real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
9415 /* If the original number was negative and already
9416 integral, then the fractional part is -0.0. */
9417 if (value->sign && frac.cl == rvc_zero)
9418 frac.sign = value->sign;
9419 break;
9420 }
9421
9422 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
9423 arg1 = fold_build2 (MODIFY_EXPR, rettype, arg1,
9424 build_real (rettype, trunc));
9425 TREE_SIDE_EFFECTS (arg1) = 1;
9426 return fold_build2 (COMPOUND_EXPR, rettype, arg1,
9427 build_real (rettype, frac));
9428 }
9429
9430 return NULL_TREE;
9431}
9432
726069ba 9433/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
c2f47e15 9434 ARG is the argument for the call. */
726069ba 9435
9436static tree
c2f47e15 9437fold_builtin_classify (tree fndecl, tree arg, int builtin_index)
726069ba 9438{
726069ba 9439 tree type = TREE_TYPE (TREE_TYPE (fndecl));
726069ba 9440 REAL_VALUE_TYPE r;
9441
c2f47e15 9442 if (!validate_arg (arg, REAL_TYPE))
726069ba 9443 {
c2f47e15 9444 error ("non-floating-point argument to function %qs",
9445 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
9446 return error_mark_node;
726069ba 9447 }
9448
726069ba 9449 switch (builtin_index)
9450 {
9451 case BUILT_IN_ISINF:
b70bfd00 9452 if (!HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
a0c938f0 9453 return omit_one_operand (type, integer_zero_node, arg);
726069ba 9454
9455 if (TREE_CODE (arg) == REAL_CST)
9456 {
9457 r = TREE_REAL_CST (arg);
9458 if (real_isinf (&r))
9459 return real_compare (GT_EXPR, &r, &dconst0)
9460 ? integer_one_node : integer_minus_one_node;
9461 else
9462 return integer_zero_node;
9463 }
9464
9465 return NULL_TREE;
9466
f23e5f4e 9467 case BUILT_IN_FINITE:
b70bfd00 9468 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
9469 && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
34709e02 9470 return omit_one_operand (type, integer_one_node, arg);
726069ba 9471
9472 if (TREE_CODE (arg) == REAL_CST)
9473 {
9474 r = TREE_REAL_CST (arg);
9475 return real_isinf (&r) || real_isnan (&r)
9476 ? integer_zero_node : integer_one_node;
9477 }
9478
9479 return NULL_TREE;
9480
9481 case BUILT_IN_ISNAN:
b70bfd00 9482 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))))
a0c938f0 9483 return omit_one_operand (type, integer_zero_node, arg);
726069ba 9484
9485 if (TREE_CODE (arg) == REAL_CST)
9486 {
9487 r = TREE_REAL_CST (arg);
9488 return real_isnan (&r) ? integer_one_node : integer_zero_node;
9489 }
9490
9491 arg = builtin_save_expr (arg);
49d00087 9492 return fold_build2 (UNORDERED_EXPR, type, arg, arg);
726069ba 9493
9494 default:
64db345d 9495 gcc_unreachable ();
726069ba 9496 }
9497}
9498
9bc9f15f 9499/* Fold a call to an unordered comparison function such as
d5019fe8 9500 __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function
c2f47e15 9501 being called and ARG0 and ARG1 are the arguments for the call.
726069ba 9502 UNORDERED_CODE and ORDERED_CODE are comparison codes that give
9503 the opposite of the desired result. UNORDERED_CODE is used
9504 for modes that can hold NaNs and ORDERED_CODE is used for
9505 the rest. */
9bc9f15f 9506
9507static tree
c2f47e15 9508fold_builtin_unordered_cmp (tree fndecl, tree arg0, tree arg1,
9bc9f15f 9509 enum tree_code unordered_code,
9510 enum tree_code ordered_code)
9511{
859f903a 9512 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9bc9f15f 9513 enum tree_code code;
6978db0d 9514 tree type0, type1;
9515 enum tree_code code0, code1;
9516 tree cmp_type = NULL_TREE;
9bc9f15f 9517
6978db0d 9518 type0 = TREE_TYPE (arg0);
9519 type1 = TREE_TYPE (arg1);
a0c938f0 9520
6978db0d 9521 code0 = TREE_CODE (type0);
9522 code1 = TREE_CODE (type1);
a0c938f0 9523
6978db0d 9524 if (code0 == REAL_TYPE && code1 == REAL_TYPE)
9525 /* Choose the wider of two real types. */
9526 cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
9527 ? type0 : type1;
9528 else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
9529 cmp_type = type0;
9530 else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
9531 cmp_type = type1;
859f903a 9532 else
9533 {
6978db0d 9534 error ("non-floating-point argument to function %qs",
9535 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
9536 return error_mark_node;
859f903a 9537 }
a0c938f0 9538
6978db0d 9539 arg0 = fold_convert (cmp_type, arg0);
9540 arg1 = fold_convert (cmp_type, arg1);
859f903a 9541
9542 if (unordered_code == UNORDERED_EXPR)
9543 {
b70bfd00 9544 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
859f903a 9545 return omit_two_operands (type, integer_zero_node, arg0, arg1);
49d00087 9546 return fold_build2 (UNORDERED_EXPR, type, arg0, arg1);
859f903a 9547 }
9bc9f15f 9548
b70bfd00 9549 code = HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
9550 : ordered_code;
49d00087 9551 return fold_build1 (TRUTH_NOT_EXPR, type,
9552 fold_build2 (code, type, arg0, arg1));
9bc9f15f 9553}
9554
c2f47e15 9555/* Fold a call to built-in function FNDECL with 0 arguments.
9556 IGNORE is true if the result of the function call is ignored. This
9557 function returns NULL_TREE if no simplification was possible. */
650e4c94 9558
4ee9c684 9559static tree
c2f47e15 9560fold_builtin_0 (tree fndecl, bool ignore ATTRIBUTE_UNUSED)
650e4c94 9561{
e9f80ff5 9562 tree type = TREE_TYPE (TREE_TYPE (fndecl));
c2f47e15 9563 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
189b3398 9564 switch (fcode)
650e4c94 9565 {
c2f47e15 9566 CASE_FLT_FN (BUILT_IN_INF):
9567 case BUILT_IN_INFD32:
9568 case BUILT_IN_INFD64:
9569 case BUILT_IN_INFD128:
9570 return fold_builtin_inf (type, true);
7c2f0500 9571
c2f47e15 9572 CASE_FLT_FN (BUILT_IN_HUGE_VAL):
9573 return fold_builtin_inf (type, false);
7c2f0500 9574
c2f47e15 9575 case BUILT_IN_CLASSIFY_TYPE:
9576 return fold_builtin_classify_type (NULL_TREE);
7c2f0500 9577
c2f47e15 9578 default:
9579 break;
9580 }
9581 return NULL_TREE;
9582}
7c2f0500 9583
c2f47e15 9584/* Fold a call to built-in function FNDECL with 1 argument, ARG0.
9585 IGNORE is true if the result of the function call is ignored. This
9586 function returns NULL_TREE if no simplification was possible. */
7c2f0500 9587
c2f47e15 9588static tree
9589fold_builtin_1 (tree fndecl, tree arg0, bool ignore)
9590{
9591 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9592 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9593 switch (fcode)
9594 {
7c2f0500 9595
650e4c94 9596 case BUILT_IN_CONSTANT_P:
7c2f0500 9597 {
c2f47e15 9598 tree val = fold_builtin_constant_p (arg0);
7c2f0500 9599
7c2f0500 9600 /* Gimplification will pull the CALL_EXPR for the builtin out of
9601 an if condition. When not optimizing, we'll not CSE it back.
9602 To avoid link error types of regressions, return false now. */
9603 if (!val && !optimize)
9604 val = integer_zero_node;
9605
9606 return val;
9607 }
650e4c94 9608
539a3a92 9609 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 9610 return fold_builtin_classify_type (arg0);
539a3a92 9611
650e4c94 9612 case BUILT_IN_STRLEN:
c2f47e15 9613 return fold_builtin_strlen (arg0);
650e4c94 9614
4f35b1fc 9615 CASE_FLT_FN (BUILT_IN_FABS):
c2f47e15 9616 return fold_builtin_fabs (arg0, type);
d1aade50 9617
9618 case BUILT_IN_ABS:
9619 case BUILT_IN_LABS:
9620 case BUILT_IN_LLABS:
9621 case BUILT_IN_IMAXABS:
c2f47e15 9622 return fold_builtin_abs (arg0, type);
c63f4ad3 9623
4f35b1fc 9624 CASE_FLT_FN (BUILT_IN_CONJ):
c2f47e15 9625 if (validate_arg (arg0, COMPLEX_TYPE))
9626 return fold_build1 (CONJ_EXPR, type, arg0);
9627 break;
36d3581d 9628
4f35b1fc 9629 CASE_FLT_FN (BUILT_IN_CREAL):
c2f47e15 9630 if (validate_arg (arg0, COMPLEX_TYPE))
9631 return non_lvalue (fold_build1 (REALPART_EXPR, type, arg0));;
9632 break;
36d3581d 9633
4f35b1fc 9634 CASE_FLT_FN (BUILT_IN_CIMAG):
c2f47e15 9635 if (validate_arg (arg0, COMPLEX_TYPE))
9636 return non_lvalue (fold_build1 (IMAGPART_EXPR, type, arg0));
9637 break;
36d3581d 9638
503733d5 9639 CASE_FLT_FN (BUILT_IN_CCOS):
9640 CASE_FLT_FN (BUILT_IN_CCOSH):
9641 /* These functions are "even", i.e. f(x) == f(-x). */
c2f47e15 9642 if (validate_arg (arg0, COMPLEX_TYPE))
9643 {
9644 tree narg = fold_strip_sign_ops (arg0);
503733d5 9645 if (narg)
c2f47e15 9646 return build_call_expr (fndecl, 1, narg);
503733d5 9647 }
c2f47e15 9648 break;
503733d5 9649
4f35b1fc 9650 CASE_FLT_FN (BUILT_IN_CABS):
c2f47e15 9651 return fold_builtin_cabs (arg0, type, fndecl);
c63f4ad3 9652
abe4dcf6 9653 CASE_FLT_FN (BUILT_IN_CARG):
c2f47e15 9654 return fold_builtin_carg (arg0, type);
abe4dcf6 9655
4f35b1fc 9656 CASE_FLT_FN (BUILT_IN_SQRT):
c2f47e15 9657 return fold_builtin_sqrt (arg0, type);
805e22b2 9658
4f35b1fc 9659 CASE_FLT_FN (BUILT_IN_CBRT):
c2f47e15 9660 return fold_builtin_cbrt (arg0, type);
3bc5c41b 9661
728bac60 9662 CASE_FLT_FN (BUILT_IN_ASIN):
c2f47e15 9663 if (validate_arg (arg0, REAL_TYPE))
9664 return do_mpfr_arg1 (arg0, type, mpfr_asin,
728bac60 9665 &dconstm1, &dconst1, true);
9666 break;
9667
9668 CASE_FLT_FN (BUILT_IN_ACOS):
c2f47e15 9669 if (validate_arg (arg0, REAL_TYPE))
9670 return do_mpfr_arg1 (arg0, type, mpfr_acos,
728bac60 9671 &dconstm1, &dconst1, true);
9672 break;
9673
9674 CASE_FLT_FN (BUILT_IN_ATAN):
c2f47e15 9675 if (validate_arg (arg0, REAL_TYPE))
9676 return do_mpfr_arg1 (arg0, type, mpfr_atan, NULL, NULL, 0);
728bac60 9677 break;
9678
9679 CASE_FLT_FN (BUILT_IN_ASINH):
c2f47e15 9680 if (validate_arg (arg0, REAL_TYPE))
9681 return do_mpfr_arg1 (arg0, type, mpfr_asinh, NULL, NULL, 0);
728bac60 9682 break;
9683
9684 CASE_FLT_FN (BUILT_IN_ACOSH):
c2f47e15 9685 if (validate_arg (arg0, REAL_TYPE))
9686 return do_mpfr_arg1 (arg0, type, mpfr_acosh,
728bac60 9687 &dconst1, NULL, true);
9688 break;
9689
9690 CASE_FLT_FN (BUILT_IN_ATANH):
c2f47e15 9691 if (validate_arg (arg0, REAL_TYPE))
9692 return do_mpfr_arg1 (arg0, type, mpfr_atanh,
728bac60 9693 &dconstm1, &dconst1, false);
9694 break;
9695
4f35b1fc 9696 CASE_FLT_FN (BUILT_IN_SIN):
c2f47e15 9697 if (validate_arg (arg0, REAL_TYPE))
9698 return do_mpfr_arg1 (arg0, type, mpfr_sin, NULL, NULL, 0);
728bac60 9699 break;
77e89269 9700
4f35b1fc 9701 CASE_FLT_FN (BUILT_IN_COS):
c2f47e15 9702 return fold_builtin_cos (arg0, type, fndecl);
9703 break;
77e89269 9704
728bac60 9705 CASE_FLT_FN (BUILT_IN_TAN):
c2f47e15 9706 return fold_builtin_tan (arg0, type);
d735c391 9707
c5bb2c4b 9708 CASE_FLT_FN (BUILT_IN_CEXP):
c2f47e15 9709 return fold_builtin_cexp (arg0, type);
c5bb2c4b 9710
d735c391 9711 CASE_FLT_FN (BUILT_IN_CEXPI):
c2f47e15 9712 if (validate_arg (arg0, REAL_TYPE))
9713 return do_mpfr_sincos (arg0, NULL_TREE, NULL_TREE);
9714 break;
d92f994c 9715
728bac60 9716 CASE_FLT_FN (BUILT_IN_SINH):
c2f47e15 9717 if (validate_arg (arg0, REAL_TYPE))
9718 return do_mpfr_arg1 (arg0, type, mpfr_sinh, NULL, NULL, 0);
728bac60 9719 break;
9720
9721 CASE_FLT_FN (BUILT_IN_COSH):
c2f47e15 9722 return fold_builtin_cosh (arg0, type, fndecl);
728bac60 9723
9724 CASE_FLT_FN (BUILT_IN_TANH):
c2f47e15 9725 if (validate_arg (arg0, REAL_TYPE))
9726 return do_mpfr_arg1 (arg0, type, mpfr_tanh, NULL, NULL, 0);
728bac60 9727 break;
9728
29f4cd78 9729 CASE_FLT_FN (BUILT_IN_ERF):
c2f47e15 9730 if (validate_arg (arg0, REAL_TYPE))
9731 return do_mpfr_arg1 (arg0, type, mpfr_erf, NULL, NULL, 0);
29f4cd78 9732 break;
9733
9734 CASE_FLT_FN (BUILT_IN_ERFC):
c2f47e15 9735 if (validate_arg (arg0, REAL_TYPE))
9736 return do_mpfr_arg1 (arg0, type, mpfr_erfc, NULL, NULL, 0);
29f4cd78 9737 break;
9738
32dba52b 9739 CASE_FLT_FN (BUILT_IN_TGAMMA):
c2f47e15 9740 if (validate_arg (arg0, REAL_TYPE))
9741 return do_mpfr_arg1 (arg0, type, mpfr_gamma, NULL, NULL, 0);
32dba52b 9742 break;
9743
4f35b1fc 9744 CASE_FLT_FN (BUILT_IN_EXP):
c2f47e15 9745 return fold_builtin_exponent (fndecl, arg0, mpfr_exp);
467214fd 9746
4f35b1fc 9747 CASE_FLT_FN (BUILT_IN_EXP2):
c2f47e15 9748 return fold_builtin_exponent (fndecl, arg0, mpfr_exp2);
467214fd 9749
4f35b1fc 9750 CASE_FLT_FN (BUILT_IN_EXP10):
9751 CASE_FLT_FN (BUILT_IN_POW10):
c2f47e15 9752 return fold_builtin_exponent (fndecl, arg0, mpfr_exp10);
467214fd 9753
29f4cd78 9754 CASE_FLT_FN (BUILT_IN_EXPM1):
c2f47e15 9755 if (validate_arg (arg0, REAL_TYPE))
9756 return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0);
29f4cd78 9757 break;
9758
4f35b1fc 9759 CASE_FLT_FN (BUILT_IN_LOG):
c2f47e15 9760 return fold_builtin_logarithm (fndecl, arg0, mpfr_log);
467214fd 9761
4f35b1fc 9762 CASE_FLT_FN (BUILT_IN_LOG2):
c2f47e15 9763 return fold_builtin_logarithm (fndecl, arg0, mpfr_log2);
467214fd 9764
4f35b1fc 9765 CASE_FLT_FN (BUILT_IN_LOG10):
c2f47e15 9766 return fold_builtin_logarithm (fndecl, arg0, mpfr_log10);
29f4cd78 9767
9768 CASE_FLT_FN (BUILT_IN_LOG1P):
c2f47e15 9769 if (validate_arg (arg0, REAL_TYPE))
9770 return do_mpfr_arg1 (arg0, type, mpfr_log1p,
29f4cd78 9771 &dconstm1, NULL, false);
9772 break;
805e22b2 9773
65dd1378 9774#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
9775 CASE_FLT_FN (BUILT_IN_J0):
9776 if (validate_arg (arg0, REAL_TYPE))
9777 return do_mpfr_arg1 (arg0, type, mpfr_j0,
9778 NULL, NULL, 0);
9779 break;
9780
9781 CASE_FLT_FN (BUILT_IN_J1):
9782 if (validate_arg (arg0, REAL_TYPE))
9783 return do_mpfr_arg1 (arg0, type, mpfr_j1,
9784 NULL, NULL, 0);
9785 break;
6ff9eeff 9786
9787 CASE_FLT_FN (BUILT_IN_Y0):
9788 if (validate_arg (arg0, REAL_TYPE))
9789 return do_mpfr_arg1 (arg0, type, mpfr_y0,
9790 &dconst0, NULL, false);
9791 break;
9792
9793 CASE_FLT_FN (BUILT_IN_Y1):
9794 if (validate_arg (arg0, REAL_TYPE))
9795 return do_mpfr_arg1 (arg0, type, mpfr_y1,
9796 &dconst0, NULL, false);
9797 break;
65dd1378 9798#endif
9799
4f35b1fc 9800 CASE_FLT_FN (BUILT_IN_NAN):
c4503c0a 9801 case BUILT_IN_NAND32:
9802 case BUILT_IN_NAND64:
9803 case BUILT_IN_NAND128:
c2f47e15 9804 return fold_builtin_nan (arg0, type, true);
b0db7939 9805
4f35b1fc 9806 CASE_FLT_FN (BUILT_IN_NANS):
c2f47e15 9807 return fold_builtin_nan (arg0, type, false);
b0db7939 9808
4f35b1fc 9809 CASE_FLT_FN (BUILT_IN_FLOOR):
c2f47e15 9810 return fold_builtin_floor (fndecl, arg0);
277f8dd2 9811
4f35b1fc 9812 CASE_FLT_FN (BUILT_IN_CEIL):
c2f47e15 9813 return fold_builtin_ceil (fndecl, arg0);
277f8dd2 9814
4f35b1fc 9815 CASE_FLT_FN (BUILT_IN_TRUNC):
c2f47e15 9816 return fold_builtin_trunc (fndecl, arg0);
277f8dd2 9817
4f35b1fc 9818 CASE_FLT_FN (BUILT_IN_ROUND):
c2f47e15 9819 return fold_builtin_round (fndecl, arg0);
89ab3887 9820
4f35b1fc 9821 CASE_FLT_FN (BUILT_IN_NEARBYINT):
9822 CASE_FLT_FN (BUILT_IN_RINT):
c2f47e15 9823 return fold_trunc_transparent_mathfn (fndecl, arg0);
6528f4f4 9824
4f35b1fc 9825 CASE_FLT_FN (BUILT_IN_LCEIL):
9826 CASE_FLT_FN (BUILT_IN_LLCEIL):
9827 CASE_FLT_FN (BUILT_IN_LFLOOR):
9828 CASE_FLT_FN (BUILT_IN_LLFLOOR):
a0c938f0 9829 CASE_FLT_FN (BUILT_IN_LROUND):
4f35b1fc 9830 CASE_FLT_FN (BUILT_IN_LLROUND):
c2f47e15 9831 return fold_builtin_int_roundingfn (fndecl, arg0);
34f17811 9832
4f35b1fc 9833 CASE_FLT_FN (BUILT_IN_LRINT):
9834 CASE_FLT_FN (BUILT_IN_LLRINT):
c2f47e15 9835 return fold_fixed_mathfn (fndecl, arg0);
9ed65c7f 9836
42791117 9837 case BUILT_IN_BSWAP32:
9838 case BUILT_IN_BSWAP64:
c2f47e15 9839 return fold_builtin_bswap (fndecl, arg0);
42791117 9840
4f35b1fc 9841 CASE_INT_FN (BUILT_IN_FFS):
9842 CASE_INT_FN (BUILT_IN_CLZ):
9843 CASE_INT_FN (BUILT_IN_CTZ):
9844 CASE_INT_FN (BUILT_IN_POPCOUNT):
9845 CASE_INT_FN (BUILT_IN_PARITY):
c2f47e15 9846 return fold_builtin_bitop (fndecl, arg0);
9c8a1629 9847
4f35b1fc 9848 CASE_FLT_FN (BUILT_IN_SIGNBIT):
c2f47e15 9849 return fold_builtin_signbit (arg0, type);
27f261ef 9850
cb2b9385 9851 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
9852 return fold_builtin_significand (arg0, type);
9853
9854 CASE_FLT_FN (BUILT_IN_ILOGB):
9855 CASE_FLT_FN (BUILT_IN_LOGB):
9856 return fold_builtin_logb (arg0, type);
9857
d49367d4 9858 case BUILT_IN_ISASCII:
c2f47e15 9859 return fold_builtin_isascii (arg0);
d49367d4 9860
9861 case BUILT_IN_TOASCII:
c2f47e15 9862 return fold_builtin_toascii (arg0);
d49367d4 9863
df1cf42e 9864 case BUILT_IN_ISDIGIT:
c2f47e15 9865 return fold_builtin_isdigit (arg0);
467214fd 9866
4f35b1fc 9867 CASE_FLT_FN (BUILT_IN_FINITE):
c4503c0a 9868 case BUILT_IN_FINITED32:
9869 case BUILT_IN_FINITED64:
9870 case BUILT_IN_FINITED128:
c2f47e15 9871 return fold_builtin_classify (fndecl, arg0, BUILT_IN_FINITE);
726069ba 9872
4f35b1fc 9873 CASE_FLT_FN (BUILT_IN_ISINF):
c4503c0a 9874 case BUILT_IN_ISINFD32:
9875 case BUILT_IN_ISINFD64:
9876 case BUILT_IN_ISINFD128:
c2f47e15 9877 return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISINF);
726069ba 9878
4f35b1fc 9879 CASE_FLT_FN (BUILT_IN_ISNAN):
c4503c0a 9880 case BUILT_IN_ISNAND32:
9881 case BUILT_IN_ISNAND64:
9882 case BUILT_IN_ISNAND128:
c2f47e15 9883 return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISNAN);
9884
9885 case BUILT_IN_PRINTF:
9886 case BUILT_IN_PRINTF_UNLOCKED:
9887 case BUILT_IN_VPRINTF:
9888 return fold_builtin_printf (fndecl, arg0, NULL_TREE, ignore, fcode);
9889
9890 default:
9891 break;
9892 }
9893
9894 return NULL_TREE;
9895
9896}
9897
9898/* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1.
9899 IGNORE is true if the result of the function call is ignored. This
9900 function returns NULL_TREE if no simplification was possible. */
9901
9902static tree
9903fold_builtin_2 (tree fndecl, tree arg0, tree arg1, bool ignore)
9904{
9905 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9906 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9907
9908 switch (fcode)
9909 {
65dd1378 9910#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
9911 CASE_FLT_FN (BUILT_IN_JN):
9912 if (validate_arg (arg0, INTEGER_TYPE)
9913 && validate_arg (arg1, REAL_TYPE))
9914 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_jn, NULL, 0);
9915 break;
6ff9eeff 9916
9917 CASE_FLT_FN (BUILT_IN_YN):
9918 if (validate_arg (arg0, INTEGER_TYPE)
9919 && validate_arg (arg1, REAL_TYPE))
9920 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_yn,
9921 &dconst0, false);
9922 break;
65dd1378 9923#endif
c2f47e15 9924
9925 CASE_FLT_FN (BUILT_IN_ATAN2):
9926 if (validate_arg (arg0, REAL_TYPE)
9927 && validate_arg(arg1, REAL_TYPE))
9928 return do_mpfr_arg2 (arg0, arg1, type, mpfr_atan2);
9929 break;
9930
9931 CASE_FLT_FN (BUILT_IN_FDIM):
9932 if (validate_arg (arg0, REAL_TYPE)
9933 && validate_arg(arg1, REAL_TYPE))
9934 return do_mpfr_arg2 (arg0, arg1, type, mpfr_dim);
9935 break;
9936
9937 CASE_FLT_FN (BUILT_IN_HYPOT):
9938 return fold_builtin_hypot (fndecl, arg0, arg1, type);
9939
7587301b 9940 CASE_FLT_FN (BUILT_IN_LDEXP):
9941 return fold_builtin_load_exponent (arg0, arg1, type, /*ldexp=*/true);
9942 CASE_FLT_FN (BUILT_IN_SCALBN):
9943 CASE_FLT_FN (BUILT_IN_SCALBLN):
9944 return fold_builtin_load_exponent (arg0, arg1, type, /*ldexp=*/false);
9945
3838b9ae 9946 CASE_FLT_FN (BUILT_IN_FREXP):
9947 return fold_builtin_frexp (arg0, arg1, type);
9948
ebf8b4f5 9949 CASE_FLT_FN (BUILT_IN_MODF):
9950 return fold_builtin_modf (arg0, arg1, type);
9951
c2f47e15 9952 case BUILT_IN_BZERO:
9953 return fold_builtin_bzero (arg0, arg1, ignore);
9954
9955 case BUILT_IN_FPUTS:
9956 return fold_builtin_fputs (arg0, arg1, ignore, false, NULL_TREE);
9957
9958 case BUILT_IN_FPUTS_UNLOCKED:
9959 return fold_builtin_fputs (arg0, arg1, ignore, true, NULL_TREE);
9960
9961 case BUILT_IN_STRSTR:
9962 return fold_builtin_strstr (arg0, arg1, type);
9963
9964 case BUILT_IN_STRCAT:
9965 return fold_builtin_strcat (arg0, arg1);
9966
9967 case BUILT_IN_STRSPN:
9968 return fold_builtin_strspn (arg0, arg1);
9969
9970 case BUILT_IN_STRCSPN:
9971 return fold_builtin_strcspn (arg0, arg1);
9972
9973 case BUILT_IN_STRCHR:
9974 case BUILT_IN_INDEX:
9975 return fold_builtin_strchr (arg0, arg1, type);
9976
9977 case BUILT_IN_STRRCHR:
9978 case BUILT_IN_RINDEX:
9979 return fold_builtin_strrchr (arg0, arg1, type);
9980
9981 case BUILT_IN_STRCPY:
9982 return fold_builtin_strcpy (fndecl, arg0, arg1, NULL_TREE);
9983
9984 case BUILT_IN_STRCMP:
9985 return fold_builtin_strcmp (arg0, arg1);
9986
9987 case BUILT_IN_STRPBRK:
9988 return fold_builtin_strpbrk (arg0, arg1, type);
9989
9990 case BUILT_IN_EXPECT:
9991 return fold_builtin_expect (arg0);
9992
9993 CASE_FLT_FN (BUILT_IN_POW):
9994 return fold_builtin_pow (fndecl, arg0, arg1, type);
9995
9996 CASE_FLT_FN (BUILT_IN_POWI):
9997 return fold_builtin_powi (fndecl, arg0, arg1, type);
9998
9999 CASE_FLT_FN (BUILT_IN_COPYSIGN):
10000 return fold_builtin_copysign (fndecl, arg0, arg1, type);
10001
10002 CASE_FLT_FN (BUILT_IN_FMIN):
10003 return fold_builtin_fmin_fmax (arg0, arg1, type, /*max=*/false);
10004
10005 CASE_FLT_FN (BUILT_IN_FMAX):
10006 return fold_builtin_fmin_fmax (arg0, arg1, type, /*max=*/true);
726069ba 10007
9bc9f15f 10008 case BUILT_IN_ISGREATER:
c2f47e15 10009 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNLE_EXPR, LE_EXPR);
9bc9f15f 10010 case BUILT_IN_ISGREATEREQUAL:
c2f47e15 10011 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNLT_EXPR, LT_EXPR);
9bc9f15f 10012 case BUILT_IN_ISLESS:
c2f47e15 10013 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNGE_EXPR, GE_EXPR);
9bc9f15f 10014 case BUILT_IN_ISLESSEQUAL:
c2f47e15 10015 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNGT_EXPR, GT_EXPR);
9bc9f15f 10016 case BUILT_IN_ISLESSGREATER:
c2f47e15 10017 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNEQ_EXPR, EQ_EXPR);
9bc9f15f 10018 case BUILT_IN_ISUNORDERED:
c2f47e15 10019 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNORDERED_EXPR,
d5019fe8 10020 NOP_EXPR);
9bc9f15f 10021
7c2f0500 10022 /* We do the folding for va_start in the expander. */
10023 case BUILT_IN_VA_START:
10024 break;
f0613857 10025
c2f47e15 10026 case BUILT_IN_SPRINTF:
10027 return fold_builtin_sprintf (arg0, arg1, NULL_TREE, ignore);
10028
0a39fd54 10029 case BUILT_IN_OBJECT_SIZE:
c2f47e15 10030 return fold_builtin_object_size (arg0, arg1);
0a39fd54 10031
10032 case BUILT_IN_PRINTF:
10033 case BUILT_IN_PRINTF_UNLOCKED:
10034 case BUILT_IN_VPRINTF:
c2f47e15 10035 return fold_builtin_printf (fndecl, arg0, arg1, ignore, fcode);
10036
0a39fd54 10037 case BUILT_IN_PRINTF_CHK:
10038 case BUILT_IN_VPRINTF_CHK:
c2f47e15 10039 if (!validate_arg (arg0, INTEGER_TYPE)
10040 || TREE_SIDE_EFFECTS (arg0))
10041 return NULL_TREE;
10042 else
10043 return fold_builtin_printf (fndecl, arg1, NULL_TREE, ignore, fcode);
10044 break;
0a39fd54 10045
10046 case BUILT_IN_FPRINTF:
10047 case BUILT_IN_FPRINTF_UNLOCKED:
10048 case BUILT_IN_VFPRINTF:
c2f47e15 10049 return fold_builtin_fprintf (fndecl, arg0, arg1, NULL_TREE,
10050 ignore, fcode);
10051
10052 default:
10053 break;
10054 }
10055 return NULL_TREE;
10056}
10057
10058/* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
10059 and ARG2. IGNORE is true if the result of the function call is ignored.
10060 This function returns NULL_TREE if no simplification was possible. */
10061
10062static tree
10063fold_builtin_3 (tree fndecl, tree arg0, tree arg1, tree arg2, bool ignore)
10064{
10065 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10066 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10067 switch (fcode)
10068 {
10069
10070 CASE_FLT_FN (BUILT_IN_SINCOS):
10071 return fold_builtin_sincos (arg0, arg1, arg2);
10072
10073 CASE_FLT_FN (BUILT_IN_FMA):
10074 if (validate_arg (arg0, REAL_TYPE)
10075 && validate_arg(arg1, REAL_TYPE)
10076 && validate_arg(arg2, REAL_TYPE))
10077 return do_mpfr_arg3 (arg0, arg1, arg2, type, mpfr_fma);
10078 break;
10079
10080 case BUILT_IN_MEMSET:
10081 return fold_builtin_memset (arg0, arg1, arg2, type, ignore);
10082
10083 case BUILT_IN_BCOPY:
10084 return fold_builtin_memory_op (arg1, arg0, arg2, void_type_node, true, /*endp=*/3);
10085
10086 case BUILT_IN_MEMCPY:
10087 return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/0);
10088
10089 case BUILT_IN_MEMPCPY:
10090 return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/1);
10091
10092 case BUILT_IN_MEMMOVE:
10093 return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/3);
10094
10095 case BUILT_IN_STRNCAT:
10096 return fold_builtin_strncat (arg0, arg1, arg2);
10097
10098 case BUILT_IN_STRNCPY:
10099 return fold_builtin_strncpy (fndecl, arg0, arg1, arg2, NULL_TREE);
10100
10101 case BUILT_IN_STRNCMP:
10102 return fold_builtin_strncmp (arg0, arg1, arg2);
10103
7959b13b 10104 case BUILT_IN_MEMCHR:
10105 return fold_builtin_memchr (arg0, arg1, arg2, type);
10106
c2f47e15 10107 case BUILT_IN_BCMP:
10108 case BUILT_IN_MEMCMP:
10109 return fold_builtin_memcmp (arg0, arg1, arg2);;
10110
10111 case BUILT_IN_SPRINTF:
10112 return fold_builtin_sprintf (arg0, arg1, arg2, ignore);
10113
10114 case BUILT_IN_STRCPY_CHK:
10115 case BUILT_IN_STPCPY_CHK:
10116 return fold_builtin_stxcpy_chk (fndecl, arg0, arg1, arg2, NULL_TREE,
10117 ignore, fcode);
10118
10119 case BUILT_IN_STRCAT_CHK:
10120 return fold_builtin_strcat_chk (fndecl, arg0, arg1, arg2);
10121
10122 case BUILT_IN_PRINTF_CHK:
10123 case BUILT_IN_VPRINTF_CHK:
10124 if (!validate_arg (arg0, INTEGER_TYPE)
10125 || TREE_SIDE_EFFECTS (arg0))
10126 return NULL_TREE;
10127 else
10128 return fold_builtin_printf (fndecl, arg1, arg2, ignore, fcode);
10129 break;
10130
10131 case BUILT_IN_FPRINTF:
10132 case BUILT_IN_FPRINTF_UNLOCKED:
10133 case BUILT_IN_VFPRINTF:
10134 return fold_builtin_fprintf (fndecl, arg0, arg1, arg2, ignore, fcode);
10135
0a39fd54 10136 case BUILT_IN_FPRINTF_CHK:
10137 case BUILT_IN_VFPRINTF_CHK:
c2f47e15 10138 if (!validate_arg (arg1, INTEGER_TYPE)
10139 || TREE_SIDE_EFFECTS (arg1))
10140 return NULL_TREE;
10141 else
10142 return fold_builtin_fprintf (fndecl, arg0, arg2, NULL_TREE,
10143 ignore, fcode);
0a39fd54 10144
650e4c94 10145 default:
10146 break;
10147 }
c2f47e15 10148 return NULL_TREE;
10149}
650e4c94 10150
c2f47e15 10151/* Fold a call to built-in function FNDECL with 4 arguments, ARG0, ARG1,
10152 ARG2, and ARG3. IGNORE is true if the result of the function call is
10153 ignored. This function returns NULL_TREE if no simplification was
10154 possible. */
10155
10156static tree
10157fold_builtin_4 (tree fndecl, tree arg0, tree arg1, tree arg2, tree arg3,
10158 bool ignore)
10159{
10160 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10161
10162 switch (fcode)
10163 {
10164 case BUILT_IN_MEMCPY_CHK:
10165 case BUILT_IN_MEMPCPY_CHK:
10166 case BUILT_IN_MEMMOVE_CHK:
10167 case BUILT_IN_MEMSET_CHK:
10168 return fold_builtin_memory_chk (fndecl, arg0, arg1, arg2, arg3,
10169 NULL_TREE, ignore,
10170 DECL_FUNCTION_CODE (fndecl));
10171
10172 case BUILT_IN_STRNCPY_CHK:
10173 return fold_builtin_strncpy_chk (arg0, arg1, arg2, arg3, NULL_TREE);
10174
10175 case BUILT_IN_STRNCAT_CHK:
10176 return fold_builtin_strncat_chk (fndecl, arg0, arg1, arg2, arg3);
10177
10178 case BUILT_IN_FPRINTF_CHK:
10179 case BUILT_IN_VFPRINTF_CHK:
10180 if (!validate_arg (arg1, INTEGER_TYPE)
10181 || TREE_SIDE_EFFECTS (arg1))
10182 return NULL_TREE;
10183 else
10184 return fold_builtin_fprintf (fndecl, arg0, arg2, arg3,
10185 ignore, fcode);
10186 break;
10187
10188 default:
10189 break;
10190 }
10191 return NULL_TREE;
10192}
10193
10194/* Fold a call to built-in function FNDECL. ARGS is an array of NARGS
10195 arguments, where NARGS <= 4. IGNORE is true if the result of the
10196 function call is ignored. This function returns NULL_TREE if no
10197 simplification was possible. Note that this only folds builtins with
10198 fixed argument patterns. Foldings that do varargs-to-varargs
10199 transformations, or that match calls with more than 4 arguments,
10200 need to be handled with fold_builtin_varargs instead. */
10201
10202#define MAX_ARGS_TO_FOLD_BUILTIN 4
10203
10204static tree
10205fold_builtin_n (tree fndecl, tree *args, int nargs, bool ignore)
10206{
10207 tree ret = NULL_TREE;
10208 switch (nargs)
10209 {
10210 case 0:
10211 ret = fold_builtin_0 (fndecl, ignore);
10212 break;
10213 case 1:
10214 ret = fold_builtin_1 (fndecl, args[0], ignore);
10215 break;
10216 case 2:
10217 ret = fold_builtin_2 (fndecl, args[0], args[1], ignore);
10218 break;
10219 case 3:
10220 ret = fold_builtin_3 (fndecl, args[0], args[1], args[2], ignore);
10221 break;
10222 case 4:
10223 ret = fold_builtin_4 (fndecl, args[0], args[1], args[2], args[3],
10224 ignore);
10225 break;
10226 default:
10227 break;
10228 }
10229 if (ret)
10230 {
10231 ret = build1 (NOP_EXPR, GENERIC_TREE_TYPE (ret), ret);
10232 TREE_NO_WARNING (ret) = 1;
10233 return ret;
10234 }
10235 return NULL_TREE;
10236}
10237
10238/* Builtins with folding operations that operate on "..." arguments
10239 need special handling; we need to store the arguments in a convenient
10240 data structure before attempting any folding. Fortunately there are
10241 only a few builtins that fall into this category. FNDECL is the
10242 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
10243 result of the function call is ignored. */
10244
10245static tree
10246fold_builtin_varargs (tree fndecl, tree exp, bool ignore ATTRIBUTE_UNUSED)
10247{
10248 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10249 tree ret = NULL_TREE;
10250
10251 switch (fcode)
10252 {
10253 case BUILT_IN_SPRINTF_CHK:
10254 case BUILT_IN_VSPRINTF_CHK:
10255 ret = fold_builtin_sprintf_chk (exp, fcode);
10256 break;
10257
10258 case BUILT_IN_SNPRINTF_CHK:
10259 case BUILT_IN_VSNPRINTF_CHK:
10260 ret = fold_builtin_snprintf_chk (exp, NULL_TREE, fcode);
10261
10262 default:
10263 break;
10264 }
10265 if (ret)
10266 {
10267 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
10268 TREE_NO_WARNING (ret) = 1;
10269 return ret;
10270 }
10271 return NULL_TREE;
650e4c94 10272}
7e15618b 10273
4ee9c684 10274/* A wrapper function for builtin folding that prevents warnings for
491e04ef 10275 "statement without effect" and the like, caused by removing the
4ee9c684 10276 call node earlier than the warning is generated. */
10277
10278tree
c2f47e15 10279fold_call_expr (tree exp, bool ignore)
4ee9c684 10280{
c2f47e15 10281 tree ret = NULL_TREE;
10282 tree fndecl = get_callee_fndecl (exp);
10283 if (fndecl
10284 && TREE_CODE (fndecl) == FUNCTION_DECL
10285 && DECL_BUILT_IN (fndecl))
4ee9c684 10286 {
c2f47e15 10287 /* FIXME: Don't use a list in this interface. */
10288 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
10289 return targetm.fold_builtin (fndecl, CALL_EXPR_ARGS (exp), ignore);
10290 else
10291 {
10292 int nargs = call_expr_nargs (exp);
10293 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
10294 {
10295 tree *args = CALL_EXPR_ARGP (exp);
10296 ret = fold_builtin_n (fndecl, args, nargs, ignore);
10297 }
10298 if (!ret)
10299 ret = fold_builtin_varargs (fndecl, exp, ignore);
10300 if (ret)
10301 {
10302 /* Propagate location information from original call to
10303 expansion of builtin. Otherwise things like
10304 maybe_emit_chk_warning, that operate on the expansion
10305 of a builtin, will use the wrong location information. */
10306 if (CAN_HAVE_LOCATION_P (exp) && EXPR_HAS_LOCATION (exp))
10307 {
10308 tree realret = ret;
10309 if (TREE_CODE (ret) == NOP_EXPR)
10310 realret = TREE_OPERAND (ret, 0);
10311 if (CAN_HAVE_LOCATION_P (realret)
10312 && !EXPR_HAS_LOCATION (realret))
10313 SET_EXPR_LOCATION (realret, EXPR_LOCATION (exp));
10314 }
10315 return ret;
10316 }
10317 }
4ee9c684 10318 }
c2f47e15 10319 return NULL_TREE;
10320}
10321
10322/* Conveniently construct a function call expression. FNDECL names the
10323 function to be called and ARGLIST is a TREE_LIST of arguments. */
10324
10325tree
10326build_function_call_expr (tree fndecl, tree arglist)
10327{
10328 tree fntype = TREE_TYPE (fndecl);
10329 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
d01f58f9 10330 int n = list_length (arglist);
10331 tree *argarray = (tree *) alloca (n * sizeof (tree));
10332 int i;
10333
10334 for (i = 0; i < n; i++, arglist = TREE_CHAIN (arglist))
10335 argarray[i] = TREE_VALUE (arglist);
10336 return fold_builtin_call_array (TREE_TYPE (fntype), fn, n, argarray);
c2f47e15 10337}
10338
10339/* Conveniently construct a function call expression. FNDECL names the
10340 function to be called, N is the number of arguments, and the "..."
10341 parameters are the argument expressions. */
10342
10343tree
10344build_call_expr (tree fndecl, int n, ...)
10345{
10346 va_list ap;
c2f47e15 10347 tree fntype = TREE_TYPE (fndecl);
10348 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
d01f58f9 10349 tree *argarray = (tree *) alloca (n * sizeof (tree));
10350 int i;
c2f47e15 10351
10352 va_start (ap, n);
d01f58f9 10353 for (i = 0; i < n; i++)
10354 argarray[i] = va_arg (ap, tree);
c2f47e15 10355 va_end (ap);
d01f58f9 10356 return fold_builtin_call_array (TREE_TYPE (fntype), fn, n, argarray);
4ee9c684 10357}
10358
c2f47e15 10359/* Construct a CALL_EXPR with type TYPE with FN as the function expression.
d01f58f9 10360 N arguments are passed in the array ARGARRAY. */
805e22b2 10361
10362tree
d01f58f9 10363fold_builtin_call_array (tree type,
10364 tree fn,
10365 int n,
10366 tree *argarray)
7e15618b 10367{
c2f47e15 10368 tree ret = NULL_TREE;
10369 int i;
10370 tree exp;
10371
10372 if (TREE_CODE (fn) == ADDR_EXPR)
10373 {
10374 tree fndecl = TREE_OPERAND (fn, 0);
10375 if (TREE_CODE (fndecl) == FUNCTION_DECL
10376 && DECL_BUILT_IN (fndecl))
10377 {
10378 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
10379 {
10380 tree arglist = NULL_TREE;
d01f58f9 10381 for (i = n - 1; i >= 0; i--)
10382 arglist = tree_cons (NULL_TREE, argarray[i], arglist);
c2f47e15 10383 ret = targetm.fold_builtin (fndecl, arglist, false);
10384 if (ret)
10385 return ret;
10386 }
10387 else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
10388 {
10389 /* First try the transformations that don't require consing up
10390 an exp. */
d01f58f9 10391 ret = fold_builtin_n (fndecl, argarray, n, false);
c2f47e15 10392 if (ret)
10393 return ret;
10394 }
10395
10396 /* If we got this far, we need to build an exp. */
d01f58f9 10397 exp = build_call_array (type, fn, n, argarray);
c2f47e15 10398 ret = fold_builtin_varargs (fndecl, exp, false);
10399 return ret ? ret : exp;
10400 }
10401 }
10402
d01f58f9 10403 return build_call_array (type, fn, n, argarray);
c2f47e15 10404}
10405
10406/* Construct a new CALL_EXPR using the tail of the argument list of EXP
10407 along with N new arguments specified as the "..." parameters. SKIP
10408 is the number of arguments in EXP to be omitted. This function is used
10409 to do varargs-to-varargs transformations. */
10410
10411static tree
10412rewrite_call_expr (tree exp, int skip, tree fndecl, int n, ...)
10413{
10414 int oldnargs = call_expr_nargs (exp);
10415 int nargs = oldnargs - skip + n;
10416 tree fntype = TREE_TYPE (fndecl);
10417 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
10418 tree *buffer;
10419
10420 if (n > 0)
10421 {
10422 int i, j;
10423 va_list ap;
7e15618b 10424
c2f47e15 10425 buffer = alloca (nargs * sizeof (tree));
10426 va_start (ap, n);
10427 for (i = 0; i < n; i++)
10428 buffer[i] = va_arg (ap, tree);
10429 va_end (ap);
10430 for (j = skip; j < oldnargs; j++, i++)
10431 buffer[i] = CALL_EXPR_ARG (exp, j);
10432 }
10433 else
10434 buffer = CALL_EXPR_ARGP (exp) + skip;
10435
10436 return fold (build_call_array (TREE_TYPE (exp), fn, nargs, buffer));
10437}
10438
10439/* Validate a single argument ARG against a tree code CODE representing
10440 a type. */
10441
10442static bool
10443validate_arg (tree arg, enum tree_code code)
10444{
10445 if (!arg)
10446 return false;
10447 else if (code == POINTER_TYPE)
10448 return POINTER_TYPE_P (TREE_TYPE (arg));
10449 return code == TREE_CODE (TREE_TYPE (arg));
7e15618b 10450}
0eb671f7 10451
10452/* This function validates the types of a function call argument list
c2f47e15 10453 against a specified list of tree_codes. If the last specifier is a 0,
10454 that represents an ellipses, otherwise the last specifier must be a
10455 VOID_TYPE. */
27d0c333 10456
c2f47e15 10457bool
10458validate_arglist (tree callexpr, ...)
0eb671f7 10459{
0eb671f7 10460 enum tree_code code;
c2f47e15 10461 bool res = 0;
ee582a61 10462 va_list ap;
c2f47e15 10463 call_expr_arg_iterator iter;
10464 tree arg;
aecda0d6 10465
c2f47e15 10466 va_start (ap, callexpr);
10467 init_call_expr_arg_iterator (callexpr, &iter);
0eb671f7 10468
f0ce3b1f 10469 do
0eb671f7 10470 {
f0ce3b1f 10471 code = va_arg (ap, enum tree_code);
10472 switch (code)
10473 {
10474 case 0:
10475 /* This signifies an ellipses, any further arguments are all ok. */
c2f47e15 10476 res = true;
f0ce3b1f 10477 goto end;
10478 case VOID_TYPE:
10479 /* This signifies an endlink, if no arguments remain, return
10480 true, otherwise return false. */
c2f47e15 10481 res = !more_call_expr_args_p (&iter);
f0ce3b1f 10482 goto end;
10483 default:
10484 /* If no parameters remain or the parameter's code does not
10485 match the specified code, return false. Otherwise continue
10486 checking any remaining arguments. */
c2f47e15 10487 arg = next_call_expr_arg (&iter);
10488 if (!validate_arg (arg, code))
f0ce3b1f 10489 goto end;
10490 break;
10491 }
0eb671f7 10492 }
f0ce3b1f 10493 while (1);
0903457a 10494
10495 /* We need gotos here since we can only have one VA_CLOSE in a
10496 function. */
10497 end: ;
ee582a61 10498 va_end (ap);
0903457a 10499
10500 return res;
0eb671f7 10501}
fc2a2dcb 10502
fc2a2dcb 10503/* Default target-specific builtin expander that does nothing. */
10504
10505rtx
aecda0d6 10506default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
10507 rtx target ATTRIBUTE_UNUSED,
10508 rtx subtarget ATTRIBUTE_UNUSED,
10509 enum machine_mode mode ATTRIBUTE_UNUSED,
10510 int ignore ATTRIBUTE_UNUSED)
fc2a2dcb 10511{
10512 return NULL_RTX;
10513}
c7926a82 10514
01537105 10515/* Returns true is EXP represents data that would potentially reside
10516 in a readonly section. */
10517
10518static bool
10519readonly_data_expr (tree exp)
10520{
10521 STRIP_NOPS (exp);
10522
9ff0637e 10523 if (TREE_CODE (exp) != ADDR_EXPR)
10524 return false;
10525
10526 exp = get_base_address (TREE_OPERAND (exp, 0));
10527 if (!exp)
10528 return false;
10529
10530 /* Make sure we call decl_readonly_section only for trees it
10531 can handle (since it returns true for everything it doesn't
10532 understand). */
491e04ef 10533 if (TREE_CODE (exp) == STRING_CST
9ff0637e 10534 || TREE_CODE (exp) == CONSTRUCTOR
10535 || (TREE_CODE (exp) == VAR_DECL && TREE_STATIC (exp)))
10536 return decl_readonly_section (exp, 0);
01537105 10537 else
10538 return false;
10539}
4ee9c684 10540
c2f47e15 10541/* Simplify a call to the strstr builtin. S1 and S2 are the arguments
10542 to the call, and TYPE is its return type.
4ee9c684 10543
c2f47e15 10544 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10545 simplified form of the call as a tree.
10546
10547 The simplified form may be a constant or other expression which
10548 computes the same value, but in a more efficient manner (including
10549 calls to other builtin functions).
10550
10551 The call may contain arguments which need to be evaluated, but
10552 which are not useful to determine the result of the call. In
10553 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10554 COMPOUND_EXPR will be an argument which must be evaluated.
10555 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10556 COMPOUND_EXPR in the chain will contain the tree for the simplified
10557 form of the builtin function call. */
10558
10559static tree
c2f47e15 10560fold_builtin_strstr (tree s1, tree s2, tree type)
4ee9c684 10561{
c2f47e15 10562 if (!validate_arg (s1, POINTER_TYPE)
10563 || !validate_arg (s2, POINTER_TYPE))
10564 return NULL_TREE;
4ee9c684 10565 else
10566 {
4ee9c684 10567 tree fn;
10568 const char *p1, *p2;
10569
10570 p2 = c_getstr (s2);
10571 if (p2 == NULL)
c2f47e15 10572 return NULL_TREE;
4ee9c684 10573
10574 p1 = c_getstr (s1);
10575 if (p1 != NULL)
10576 {
10577 const char *r = strstr (p1, p2);
daa1d5f5 10578 tree tem;
4ee9c684 10579
4ee9c684 10580 if (r == NULL)
779b4c41 10581 return build_int_cst (TREE_TYPE (s1), 0);
c0c67e38 10582
10583 /* Return an offset into the constant string argument. */
49d00087 10584 tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
10585 s1, build_int_cst (TREE_TYPE (s1), r - p1));
daa1d5f5 10586 return fold_convert (type, tem);
4ee9c684 10587 }
10588
7efa231c 10589 /* The argument is const char *, and the result is char *, so we need
10590 a type conversion here to avoid a warning. */
4ee9c684 10591 if (p2[0] == '\0')
7efa231c 10592 return fold_convert (type, s1);
4ee9c684 10593
10594 if (p2[1] != '\0')
c2f47e15 10595 return NULL_TREE;
4ee9c684 10596
10597 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
10598 if (!fn)
c2f47e15 10599 return NULL_TREE;
4ee9c684 10600
10601 /* New argument list transforming strstr(s1, s2) to
10602 strchr(s1, s2[0]). */
c2f47e15 10603 return build_call_expr (fn, 2, s1, build_int_cst (NULL_TREE, p2[0]));
4ee9c684 10604 }
10605}
10606
c2f47e15 10607/* Simplify a call to the strchr builtin. S1 and S2 are the arguments to
10608 the call, and TYPE is its return type.
4ee9c684 10609
c2f47e15 10610 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10611 simplified form of the call as a tree.
10612
10613 The simplified form may be a constant or other expression which
10614 computes the same value, but in a more efficient manner (including
10615 calls to other builtin functions).
10616
10617 The call may contain arguments which need to be evaluated, but
10618 which are not useful to determine the result of the call. In
10619 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10620 COMPOUND_EXPR will be an argument which must be evaluated.
10621 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10622 COMPOUND_EXPR in the chain will contain the tree for the simplified
10623 form of the builtin function call. */
10624
10625static tree
c2f47e15 10626fold_builtin_strchr (tree s1, tree s2, tree type)
4ee9c684 10627{
c2f47e15 10628 if (!validate_arg (s1, POINTER_TYPE)
10629 || !validate_arg (s2, INTEGER_TYPE))
10630 return NULL_TREE;
4ee9c684 10631 else
10632 {
4ee9c684 10633 const char *p1;
10634
10635 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 10636 return NULL_TREE;
4ee9c684 10637
10638 p1 = c_getstr (s1);
10639 if (p1 != NULL)
10640 {
10641 char c;
10642 const char *r;
daa1d5f5 10643 tree tem;
4ee9c684 10644
10645 if (target_char_cast (s2, &c))
c2f47e15 10646 return NULL_TREE;
4ee9c684 10647
10648 r = strchr (p1, c);
10649
10650 if (r == NULL)
779b4c41 10651 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 10652
10653 /* Return an offset into the constant string argument. */
49d00087 10654 tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
10655 s1, build_int_cst (TREE_TYPE (s1), r - p1));
daa1d5f5 10656 return fold_convert (type, tem);
4ee9c684 10657 }
c2f47e15 10658 return NULL_TREE;
4ee9c684 10659 }
10660}
10661
c2f47e15 10662/* Simplify a call to the strrchr builtin. S1 and S2 are the arguments to
10663 the call, and TYPE is its return type.
4ee9c684 10664
c2f47e15 10665 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10666 simplified form of the call as a tree.
10667
10668 The simplified form may be a constant or other expression which
10669 computes the same value, but in a more efficient manner (including
10670 calls to other builtin functions).
10671
10672 The call may contain arguments which need to be evaluated, but
10673 which are not useful to determine the result of the call. In
10674 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10675 COMPOUND_EXPR will be an argument which must be evaluated.
10676 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10677 COMPOUND_EXPR in the chain will contain the tree for the simplified
10678 form of the builtin function call. */
10679
10680static tree
c2f47e15 10681fold_builtin_strrchr (tree s1, tree s2, tree type)
4ee9c684 10682{
c2f47e15 10683 if (!validate_arg (s1, POINTER_TYPE)
10684 || !validate_arg (s2, INTEGER_TYPE))
10685 return NULL_TREE;
4ee9c684 10686 else
10687 {
4ee9c684 10688 tree fn;
10689 const char *p1;
10690
10691 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 10692 return NULL_TREE;
4ee9c684 10693
10694 p1 = c_getstr (s1);
10695 if (p1 != NULL)
10696 {
10697 char c;
10698 const char *r;
daa1d5f5 10699 tree tem;
4ee9c684 10700
10701 if (target_char_cast (s2, &c))
c2f47e15 10702 return NULL_TREE;
4ee9c684 10703
10704 r = strrchr (p1, c);
10705
10706 if (r == NULL)
779b4c41 10707 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 10708
10709 /* Return an offset into the constant string argument. */
49d00087 10710 tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
10711 s1, build_int_cst (TREE_TYPE (s1), r - p1));
daa1d5f5 10712 return fold_convert (type, tem);
4ee9c684 10713 }
10714
10715 if (! integer_zerop (s2))
c2f47e15 10716 return NULL_TREE;
4ee9c684 10717
10718 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
10719 if (!fn)
c2f47e15 10720 return NULL_TREE;
4ee9c684 10721
10722 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
c2f47e15 10723 return build_call_expr (fn, 2, s1, s2);
4ee9c684 10724 }
10725}
10726
c2f47e15 10727/* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments
10728 to the call, and TYPE is its return type.
4ee9c684 10729
c2f47e15 10730 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10731 simplified form of the call as a tree.
10732
10733 The simplified form may be a constant or other expression which
10734 computes the same value, but in a more efficient manner (including
10735 calls to other builtin functions).
10736
10737 The call may contain arguments which need to be evaluated, but
10738 which are not useful to determine the result of the call. In
10739 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10740 COMPOUND_EXPR will be an argument which must be evaluated.
10741 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10742 COMPOUND_EXPR in the chain will contain the tree for the simplified
10743 form of the builtin function call. */
10744
10745static tree
c2f47e15 10746fold_builtin_strpbrk (tree s1, tree s2, tree type)
4ee9c684 10747{
c2f47e15 10748 if (!validate_arg (s1, POINTER_TYPE)
10749 || !validate_arg (s2, POINTER_TYPE))
10750 return NULL_TREE;
4ee9c684 10751 else
10752 {
4ee9c684 10753 tree fn;
10754 const char *p1, *p2;
10755
10756 p2 = c_getstr (s2);
10757 if (p2 == NULL)
c2f47e15 10758 return NULL_TREE;
4ee9c684 10759
10760 p1 = c_getstr (s1);
10761 if (p1 != NULL)
10762 {
10763 const char *r = strpbrk (p1, p2);
daa1d5f5 10764 tree tem;
4ee9c684 10765
10766 if (r == NULL)
779b4c41 10767 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 10768
10769 /* Return an offset into the constant string argument. */
49d00087 10770 tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
10771 s1, build_int_cst (TREE_TYPE (s1), r - p1));
daa1d5f5 10772 return fold_convert (type, tem);
4ee9c684 10773 }
10774
10775 if (p2[0] == '\0')
05abc81b 10776 /* strpbrk(x, "") == NULL.
10777 Evaluate and ignore s1 in case it had side-effects. */
10778 return omit_one_operand (TREE_TYPE (s1), integer_zero_node, s1);
4ee9c684 10779
10780 if (p2[1] != '\0')
c2f47e15 10781 return NULL_TREE; /* Really call strpbrk. */
4ee9c684 10782
10783 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
10784 if (!fn)
c2f47e15 10785 return NULL_TREE;
4ee9c684 10786
10787 /* New argument list transforming strpbrk(s1, s2) to
10788 strchr(s1, s2[0]). */
c2f47e15 10789 return build_call_expr (fn, 2, s1, build_int_cst (NULL_TREE, p2[0]));
4ee9c684 10790 }
10791}
10792
c2f47e15 10793/* Simplify a call to the strcat builtin. DST and SRC are the arguments
10794 to the call.
4ee9c684 10795
c2f47e15 10796 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10797 simplified form of the call as a tree.
10798
10799 The simplified form may be a constant or other expression which
10800 computes the same value, but in a more efficient manner (including
10801 calls to other builtin functions).
10802
10803 The call may contain arguments which need to be evaluated, but
10804 which are not useful to determine the result of the call. In
10805 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10806 COMPOUND_EXPR will be an argument which must be evaluated.
10807 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10808 COMPOUND_EXPR in the chain will contain the tree for the simplified
10809 form of the builtin function call. */
10810
10811static tree
c2f47e15 10812fold_builtin_strcat (tree dst, tree src)
4ee9c684 10813{
c2f47e15 10814 if (!validate_arg (dst, POINTER_TYPE)
10815 || !validate_arg (src, POINTER_TYPE))
10816 return NULL_TREE;
4ee9c684 10817 else
10818 {
4ee9c684 10819 const char *p = c_getstr (src);
10820
10821 /* If the string length is zero, return the dst parameter. */
10822 if (p && *p == '\0')
10823 return dst;
10824
c2f47e15 10825 return NULL_TREE;
4ee9c684 10826 }
10827}
10828
c2f47e15 10829/* Simplify a call to the strncat builtin. DST, SRC, and LEN are the
10830 arguments to the call.
4ee9c684 10831
c2f47e15 10832 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10833 simplified form of the call as a tree.
10834
10835 The simplified form may be a constant or other expression which
10836 computes the same value, but in a more efficient manner (including
10837 calls to other builtin functions).
10838
10839 The call may contain arguments which need to be evaluated, but
10840 which are not useful to determine the result of the call. In
10841 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10842 COMPOUND_EXPR will be an argument which must be evaluated.
10843 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10844 COMPOUND_EXPR in the chain will contain the tree for the simplified
10845 form of the builtin function call. */
10846
10847static tree
c2f47e15 10848fold_builtin_strncat (tree dst, tree src, tree len)
4ee9c684 10849{
c2f47e15 10850 if (!validate_arg (dst, POINTER_TYPE)
10851 || !validate_arg (src, POINTER_TYPE)
10852 || !validate_arg (len, INTEGER_TYPE))
10853 return NULL_TREE;
4ee9c684 10854 else
10855 {
4ee9c684 10856 const char *p = c_getstr (src);
10857
10858 /* If the requested length is zero, or the src parameter string
0a39fd54 10859 length is zero, return the dst parameter. */
4ee9c684 10860 if (integer_zerop (len) || (p && *p == '\0'))
a0c938f0 10861 return omit_two_operands (TREE_TYPE (dst), dst, src, len);
4ee9c684 10862
10863 /* If the requested len is greater than or equal to the string
a0c938f0 10864 length, call strcat. */
4ee9c684 10865 if (TREE_CODE (len) == INTEGER_CST && p
10866 && compare_tree_int (len, strlen (p)) >= 0)
10867 {
4ee9c684 10868 tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
10869
10870 /* If the replacement _DECL isn't initialized, don't do the
10871 transformation. */
10872 if (!fn)
c2f47e15 10873 return NULL_TREE;
4ee9c684 10874
c2f47e15 10875 return build_call_expr (fn, 2, dst, src);
4ee9c684 10876 }
c2f47e15 10877 return NULL_TREE;
4ee9c684 10878 }
10879}
10880
c2f47e15 10881/* Simplify a call to the strspn builtin. S1 and S2 are the arguments
10882 to the call.
4ee9c684 10883
c2f47e15 10884 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10885 simplified form of the call as a tree.
10886
10887 The simplified form may be a constant or other expression which
10888 computes the same value, but in a more efficient manner (including
10889 calls to other builtin functions).
10890
10891 The call may contain arguments which need to be evaluated, but
10892 which are not useful to determine the result of the call. In
10893 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10894 COMPOUND_EXPR will be an argument which must be evaluated.
10895 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10896 COMPOUND_EXPR in the chain will contain the tree for the simplified
10897 form of the builtin function call. */
10898
10899static tree
c2f47e15 10900fold_builtin_strspn (tree s1, tree s2)
4ee9c684 10901{
c2f47e15 10902 if (!validate_arg (s1, POINTER_TYPE)
10903 || !validate_arg (s2, POINTER_TYPE))
10904 return NULL_TREE;
4ee9c684 10905 else
10906 {
4ee9c684 10907 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
10908
10909 /* If both arguments are constants, evaluate at compile-time. */
10910 if (p1 && p2)
10911 {
10912 const size_t r = strspn (p1, p2);
10913 return size_int (r);
10914 }
10915
c2f47e15 10916 /* If either argument is "", return NULL_TREE. */
4ee9c684 10917 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9bc9f15f 10918 /* Evaluate and ignore both arguments in case either one has
10919 side-effects. */
10920 return omit_two_operands (integer_type_node, integer_zero_node,
10921 s1, s2);
c2f47e15 10922 return NULL_TREE;
4ee9c684 10923 }
10924}
10925
c2f47e15 10926/* Simplify a call to the strcspn builtin. S1 and S2 are the arguments
10927 to the call.
4ee9c684 10928
c2f47e15 10929 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10930 simplified form of the call as a tree.
10931
10932 The simplified form may be a constant or other expression which
10933 computes the same value, but in a more efficient manner (including
10934 calls to other builtin functions).
10935
10936 The call may contain arguments which need to be evaluated, but
10937 which are not useful to determine the result of the call. In
10938 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10939 COMPOUND_EXPR will be an argument which must be evaluated.
10940 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10941 COMPOUND_EXPR in the chain will contain the tree for the simplified
10942 form of the builtin function call. */
10943
10944static tree
c2f47e15 10945fold_builtin_strcspn (tree s1, tree s2)
4ee9c684 10946{
c2f47e15 10947 if (!validate_arg (s1, POINTER_TYPE)
10948 || !validate_arg (s2, POINTER_TYPE))
10949 return NULL_TREE;
4ee9c684 10950 else
10951 {
4ee9c684 10952 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
10953
10954 /* If both arguments are constants, evaluate at compile-time. */
10955 if (p1 && p2)
10956 {
10957 const size_t r = strcspn (p1, p2);
10958 return size_int (r);
10959 }
10960
c2f47e15 10961 /* If the first argument is "", return NULL_TREE. */
4ee9c684 10962 if (p1 && *p1 == '\0')
10963 {
10964 /* Evaluate and ignore argument s2 in case it has
10965 side-effects. */
05abc81b 10966 return omit_one_operand (integer_type_node,
10967 integer_zero_node, s2);
4ee9c684 10968 }
10969
10970 /* If the second argument is "", return __builtin_strlen(s1). */
10971 if (p2 && *p2 == '\0')
10972 {
c2f47e15 10973 tree fn = implicit_built_in_decls[BUILT_IN_STRLEN];
4ee9c684 10974
10975 /* If the replacement _DECL isn't initialized, don't do the
10976 transformation. */
10977 if (!fn)
c2f47e15 10978 return NULL_TREE;
4ee9c684 10979
c2f47e15 10980 return build_call_expr (fn, 1, s1);
4ee9c684 10981 }
c2f47e15 10982 return NULL_TREE;
4ee9c684 10983 }
10984}
10985
c2f47e15 10986/* Fold a call to the fputs builtin. ARG0 and ARG1 are the arguments
10987 to the call. IGNORE is true if the value returned
f0613857 10988 by the builtin will be ignored. UNLOCKED is true is true if this
10989 actually a call to fputs_unlocked. If LEN in non-NULL, it represents
10990 the known length of the string. Return NULL_TREE if no simplification
10991 was possible. */
4ee9c684 10992
10993tree
c2f47e15 10994fold_builtin_fputs (tree arg0, tree arg1, bool ignore, bool unlocked, tree len)
4ee9c684 10995{
6d77ed92 10996 /* If we're using an unlocked function, assume the other unlocked
10997 functions exist explicitly. */
10998 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
4ee9c684 10999 : implicit_built_in_decls[BUILT_IN_FPUTC];
6d77ed92 11000 tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
4ee9c684 11001 : implicit_built_in_decls[BUILT_IN_FWRITE];
11002
c403edd4 11003 /* If the return value is used, don't do the transformation. */
11004 if (!ignore)
c2f47e15 11005 return NULL_TREE;
4ee9c684 11006
11007 /* Verify the arguments in the original call. */
c2f47e15 11008 if (!validate_arg (arg0, POINTER_TYPE)
11009 || !validate_arg (arg1, POINTER_TYPE))
11010 return NULL_TREE;
4ee9c684 11011
f0613857 11012 if (! len)
c2f47e15 11013 len = c_strlen (arg0, 0);
4ee9c684 11014
11015 /* Get the length of the string passed to fputs. If the length
11016 can't be determined, punt. */
11017 if (!len
11018 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 11019 return NULL_TREE;
4ee9c684 11020
11021 switch (compare_tree_int (len, 1))
11022 {
11023 case -1: /* length is 0, delete the call entirely . */
c2f47e15 11024 return omit_one_operand (integer_type_node, integer_zero_node, arg1);;
05abc81b 11025
4ee9c684 11026 case 0: /* length is 1, call fputc. */
11027 {
c2f47e15 11028 const char *p = c_getstr (arg0);
4ee9c684 11029
11030 if (p != NULL)
11031 {
c2f47e15 11032 if (fn_fputc)
11033 return build_call_expr (fn_fputc, 2,
11034 build_int_cst (NULL_TREE, p[0]), arg1);
11035 else
11036 return NULL_TREE;
4ee9c684 11037 }
11038 }
11039 /* FALLTHROUGH */
11040 case 1: /* length is greater than 1, call fwrite. */
11041 {
0bed3869 11042 /* If optimizing for size keep fputs. */
4ee9c684 11043 if (optimize_size)
c2f47e15 11044 return NULL_TREE;
4ee9c684 11045 /* New argument list transforming fputs(string, stream) to
11046 fwrite(string, 1, len, stream). */
c2f47e15 11047 if (fn_fwrite)
11048 return build_call_expr (fn_fwrite, 4, arg0, size_one_node, len, arg1);
11049 else
11050 return NULL_TREE;
4ee9c684 11051 }
11052 default:
64db345d 11053 gcc_unreachable ();
4ee9c684 11054 }
c2f47e15 11055 return NULL_TREE;
4ee9c684 11056}
11057
c2f47e15 11058/* Fold the next_arg or va_start call EXP. Returns true if there was an error
743b0c6a 11059 produced. False otherwise. This is done so that we don't output the error
11060 or warning twice or three times. */
11061bool
c2f47e15 11062fold_builtin_next_arg (tree exp, bool va_start_p)
4ee9c684 11063{
11064 tree fntype = TREE_TYPE (current_function_decl);
c2f47e15 11065 int nargs = call_expr_nargs (exp);
11066 tree arg;
4ee9c684 11067
11068 if (TYPE_ARG_TYPES (fntype) == 0
11069 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
11070 == void_type_node))
743b0c6a 11071 {
11072 error ("%<va_start%> used in function with fixed args");
11073 return true;
11074 }
c2f47e15 11075
11076 if (va_start_p)
79012a9d 11077 {
c2f47e15 11078 if (va_start_p && (nargs != 2))
11079 {
11080 error ("wrong number of arguments to function %<va_start%>");
11081 return true;
11082 }
11083 arg = CALL_EXPR_ARG (exp, 1);
79012a9d 11084 }
11085 /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
11086 when we checked the arguments and if needed issued a warning. */
c2f47e15 11087 else
4ee9c684 11088 {
c2f47e15 11089 if (nargs == 0)
11090 {
11091 /* Evidently an out of date version of <stdarg.h>; can't validate
11092 va_start's second argument, but can still work as intended. */
11093 warning (0, "%<__builtin_next_arg%> called without an argument");
11094 return true;
11095 }
11096 else if (nargs > 1)
a0c938f0 11097 {
c2f47e15 11098 error ("wrong number of arguments to function %<__builtin_next_arg%>");
a0c938f0 11099 return true;
11100 }
c2f47e15 11101 arg = CALL_EXPR_ARG (exp, 0);
11102 }
11103
11104 /* We destructively modify the call to be __builtin_va_start (ap, 0)
11105 or __builtin_next_arg (0) the first time we see it, after checking
11106 the arguments and if needed issuing a warning. */
11107 if (!integer_zerop (arg))
11108 {
11109 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
79012a9d 11110
4ee9c684 11111 /* Strip off all nops for the sake of the comparison. This
11112 is not quite the same as STRIP_NOPS. It does more.
11113 We must also strip off INDIRECT_EXPR for C++ reference
11114 parameters. */
11115 while (TREE_CODE (arg) == NOP_EXPR
11116 || TREE_CODE (arg) == CONVERT_EXPR
11117 || TREE_CODE (arg) == NON_LVALUE_EXPR
11118 || TREE_CODE (arg) == INDIRECT_REF)
11119 arg = TREE_OPERAND (arg, 0);
11120 if (arg != last_parm)
a0c938f0 11121 {
b08cf617 11122 /* FIXME: Sometimes with the tree optimizers we can get the
11123 not the last argument even though the user used the last
11124 argument. We just warn and set the arg to be the last
11125 argument so that we will get wrong-code because of
11126 it. */
c3ceba8e 11127 warning (0, "second parameter of %<va_start%> not last named argument");
743b0c6a 11128 }
79012a9d 11129 /* We want to verify the second parameter just once before the tree
a0c938f0 11130 optimizers are run and then avoid keeping it in the tree,
11131 as otherwise we could warn even for correct code like:
11132 void foo (int i, ...)
11133 { va_list ap; i++; va_start (ap, i); va_end (ap); } */
c2f47e15 11134 if (va_start_p)
11135 CALL_EXPR_ARG (exp, 1) = integer_zero_node;
11136 else
11137 CALL_EXPR_ARG (exp, 0) = integer_zero_node;
743b0c6a 11138 }
11139 return false;
4ee9c684 11140}
11141
11142
c2f47e15 11143/* Simplify a call to the sprintf builtin with arguments DEST, FMT, and ORIG.
11144 ORIG may be null if this is a 2-argument call. We don't attempt to
11145 simplify calls with more than 3 arguments.
4ee9c684 11146
c2f47e15 11147 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11148 simplified form of the call as a tree. If IGNORED is true, it means that
11149 the caller does not use the returned value of the function. */
11150
11151static tree
c2f47e15 11152fold_builtin_sprintf (tree dest, tree fmt, tree orig, int ignored)
4ee9c684 11153{
c2f47e15 11154 tree call, retval;
4ee9c684 11155 const char *fmt_str = NULL;
11156
11157 /* Verify the required arguments in the original call. We deal with two
11158 types of sprintf() calls: 'sprintf (str, fmt)' and
11159 'sprintf (dest, "%s", orig)'. */
c2f47e15 11160 if (!validate_arg (dest, POINTER_TYPE)
11161 || !validate_arg (fmt, POINTER_TYPE))
11162 return NULL_TREE;
11163 if (orig && !validate_arg (orig, POINTER_TYPE))
4ee9c684 11164 return NULL_TREE;
4ee9c684 11165
11166 /* Check whether the format is a literal string constant. */
11167 fmt_str = c_getstr (fmt);
11168 if (fmt_str == NULL)
11169 return NULL_TREE;
11170
11171 call = NULL_TREE;
11172 retval = NULL_TREE;
11173
d4473c84 11174 if (!init_target_chars ())
c2f47e15 11175 return NULL_TREE;
99eabcc1 11176
4ee9c684 11177 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 11178 if (strchr (fmt_str, target_percent) == NULL)
4ee9c684 11179 {
11180 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11181
11182 if (!fn)
11183 return NULL_TREE;
11184
72dfb3f2 11185 /* Don't optimize sprintf (buf, "abc", ptr++). */
c2f47e15 11186 if (orig)
72dfb3f2 11187 return NULL_TREE;
11188
4ee9c684 11189 /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
11190 'format' is known to contain no % formats. */
c2f47e15 11191 call = build_call_expr (fn, 2, dest, fmt);
4ee9c684 11192 if (!ignored)
7016c612 11193 retval = build_int_cst (NULL_TREE, strlen (fmt_str));
4ee9c684 11194 }
11195
11196 /* If the format is "%s", use strcpy if the result isn't used. */
99eabcc1 11197 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
4ee9c684 11198 {
c2f47e15 11199 tree fn;
4ee9c684 11200 fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11201
11202 if (!fn)
11203 return NULL_TREE;
11204
72dfb3f2 11205 /* Don't crash on sprintf (str1, "%s"). */
c2f47e15 11206 if (!orig)
72dfb3f2 11207 return NULL_TREE;
11208
4ee9c684 11209 /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2). */
4ee9c684 11210 if (!ignored)
11211 {
11212 retval = c_strlen (orig, 1);
11213 if (!retval || TREE_CODE (retval) != INTEGER_CST)
11214 return NULL_TREE;
11215 }
c2f47e15 11216 call = build_call_expr (fn, 2, dest, orig);
4ee9c684 11217 }
11218
11219 if (call && retval)
11220 {
e3b560a6 11221 retval = fold_convert
4ee9c684 11222 (TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])),
11223 retval);
05abc81b 11224 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
4ee9c684 11225 }
11226 else
11227 return call;
11228}
0a39fd54 11229
c2f47e15 11230/* Expand a call EXP to __builtin_object_size. */
0a39fd54 11231
11232rtx
11233expand_builtin_object_size (tree exp)
11234{
11235 tree ost;
11236 int object_size_type;
11237 tree fndecl = get_callee_fndecl (exp);
0a39fd54 11238 location_t locus = EXPR_LOCATION (exp);
11239
c2f47e15 11240 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
0a39fd54 11241 {
11242 error ("%Hfirst argument of %D must be a pointer, second integer constant",
11243 &locus, fndecl);
11244 expand_builtin_trap ();
11245 return const0_rtx;
11246 }
11247
c2f47e15 11248 ost = CALL_EXPR_ARG (exp, 1);
0a39fd54 11249 STRIP_NOPS (ost);
11250
11251 if (TREE_CODE (ost) != INTEGER_CST
11252 || tree_int_cst_sgn (ost) < 0
11253 || compare_tree_int (ost, 3) > 0)
11254 {
11255 error ("%Hlast argument of %D is not integer constant between 0 and 3",
11256 &locus, fndecl);
11257 expand_builtin_trap ();
11258 return const0_rtx;
11259 }
11260
11261 object_size_type = tree_low_cst (ost, 0);
11262
11263 return object_size_type < 2 ? constm1_rtx : const0_rtx;
11264}
11265
11266/* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
11267 FCODE is the BUILT_IN_* to use.
c2f47e15 11268 Return NULL_RTX if we failed; the caller should emit a normal call,
0a39fd54 11269 otherwise try to get the result in TARGET, if convenient (and in
11270 mode MODE if that's convenient). */
11271
11272static rtx
11273expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
11274 enum built_in_function fcode)
11275{
0a39fd54 11276 tree dest, src, len, size;
11277
c2f47e15 11278 if (!validate_arglist (exp,
0a39fd54 11279 POINTER_TYPE,
11280 fcode == BUILT_IN_MEMSET_CHK
11281 ? INTEGER_TYPE : POINTER_TYPE,
11282 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
c2f47e15 11283 return NULL_RTX;
0a39fd54 11284
c2f47e15 11285 dest = CALL_EXPR_ARG (exp, 0);
11286 src = CALL_EXPR_ARG (exp, 1);
11287 len = CALL_EXPR_ARG (exp, 2);
11288 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11289
11290 if (! host_integerp (size, 1))
c2f47e15 11291 return NULL_RTX;
0a39fd54 11292
11293 if (host_integerp (len, 1) || integer_all_onesp (size))
11294 {
11295 tree fn;
11296
11297 if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
11298 {
11299 location_t locus = EXPR_LOCATION (exp);
11300 warning (0, "%Hcall to %D will always overflow destination buffer",
11301 &locus, get_callee_fndecl (exp));
c2f47e15 11302 return NULL_RTX;
0a39fd54 11303 }
11304
0a39fd54 11305 fn = NULL_TREE;
11306 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
11307 mem{cpy,pcpy,move,set} is available. */
11308 switch (fcode)
11309 {
11310 case BUILT_IN_MEMCPY_CHK:
11311 fn = built_in_decls[BUILT_IN_MEMCPY];
11312 break;
11313 case BUILT_IN_MEMPCPY_CHK:
11314 fn = built_in_decls[BUILT_IN_MEMPCPY];
11315 break;
11316 case BUILT_IN_MEMMOVE_CHK:
11317 fn = built_in_decls[BUILT_IN_MEMMOVE];
11318 break;
11319 case BUILT_IN_MEMSET_CHK:
11320 fn = built_in_decls[BUILT_IN_MEMSET];
11321 break;
11322 default:
11323 break;
11324 }
11325
11326 if (! fn)
c2f47e15 11327 return NULL_RTX;
0a39fd54 11328
c2f47e15 11329 fn = build_call_expr (fn, 3, dest, src, len);
0a39fd54 11330 if (TREE_CODE (fn) == CALL_EXPR)
11331 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
11332 return expand_expr (fn, target, mode, EXPAND_NORMAL);
11333 }
11334 else if (fcode == BUILT_IN_MEMSET_CHK)
c2f47e15 11335 return NULL_RTX;
0a39fd54 11336 else
11337 {
11338 unsigned int dest_align
11339 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
11340
11341 /* If DEST is not a pointer type, call the normal function. */
11342 if (dest_align == 0)
c2f47e15 11343 return NULL_RTX;
0a39fd54 11344
11345 /* If SRC and DEST are the same (and not volatile), do nothing. */
11346 if (operand_equal_p (src, dest, 0))
11347 {
11348 tree expr;
11349
11350 if (fcode != BUILT_IN_MEMPCPY_CHK)
11351 {
11352 /* Evaluate and ignore LEN in case it has side-effects. */
11353 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
11354 return expand_expr (dest, target, mode, EXPAND_NORMAL);
11355 }
11356
11357 len = fold_convert (TREE_TYPE (dest), len);
11358 expr = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
11359 return expand_expr (expr, target, mode, EXPAND_NORMAL);
11360 }
11361
11362 /* __memmove_chk special case. */
11363 if (fcode == BUILT_IN_MEMMOVE_CHK)
11364 {
11365 unsigned int src_align
11366 = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
11367
11368 if (src_align == 0)
c2f47e15 11369 return NULL_RTX;
0a39fd54 11370
11371 /* If src is categorized for a readonly section we can use
11372 normal __memcpy_chk. */
11373 if (readonly_data_expr (src))
11374 {
11375 tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
11376 if (!fn)
c2f47e15 11377 return NULL_RTX;
11378 fn = build_call_expr (fn, 4, dest, src, len, size);
0a39fd54 11379 if (TREE_CODE (fn) == CALL_EXPR)
11380 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
11381 return expand_expr (fn, target, mode, EXPAND_NORMAL);
11382 }
11383 }
c2f47e15 11384 return NULL_RTX;
0a39fd54 11385 }
11386}
11387
11388/* Emit warning if a buffer overflow is detected at compile time. */
11389
11390static void
11391maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
11392{
c2f47e15 11393 int is_strlen = 0;
0a39fd54 11394 tree len, size;
11395 location_t locus;
11396
11397 switch (fcode)
11398 {
11399 case BUILT_IN_STRCPY_CHK:
11400 case BUILT_IN_STPCPY_CHK:
11401 /* For __strcat_chk the warning will be emitted only if overflowing
11402 by at least strlen (dest) + 1 bytes. */
11403 case BUILT_IN_STRCAT_CHK:
c2f47e15 11404 len = CALL_EXPR_ARG (exp, 1);
11405 size = CALL_EXPR_ARG (exp, 2);
0a39fd54 11406 is_strlen = 1;
11407 break;
b356dfef 11408 case BUILT_IN_STRNCAT_CHK:
0a39fd54 11409 case BUILT_IN_STRNCPY_CHK:
c2f47e15 11410 len = CALL_EXPR_ARG (exp, 2);
11411 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11412 break;
11413 case BUILT_IN_SNPRINTF_CHK:
11414 case BUILT_IN_VSNPRINTF_CHK:
c2f47e15 11415 len = CALL_EXPR_ARG (exp, 1);
11416 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11417 break;
11418 default:
11419 gcc_unreachable ();
11420 }
11421
0a39fd54 11422 if (!len || !size)
11423 return;
11424
0a39fd54 11425 if (! host_integerp (size, 1) || integer_all_onesp (size))
11426 return;
11427
11428 if (is_strlen)
11429 {
11430 len = c_strlen (len, 1);
11431 if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
11432 return;
11433 }
b356dfef 11434 else if (fcode == BUILT_IN_STRNCAT_CHK)
11435 {
c2f47e15 11436 tree src = CALL_EXPR_ARG (exp, 1);
b356dfef 11437 if (! src || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
11438 return;
11439 src = c_strlen (src, 1);
11440 if (! src || ! host_integerp (src, 1))
11441 {
11442 locus = EXPR_LOCATION (exp);
11443 warning (0, "%Hcall to %D might overflow destination buffer",
11444 &locus, get_callee_fndecl (exp));
11445 return;
11446 }
11447 else if (tree_int_cst_lt (src, size))
11448 return;
11449 }
0a39fd54 11450 else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
11451 return;
11452
11453 locus = EXPR_LOCATION (exp);
11454 warning (0, "%Hcall to %D will always overflow destination buffer",
11455 &locus, get_callee_fndecl (exp));
11456}
11457
11458/* Emit warning if a buffer overflow is detected at compile time
11459 in __sprintf_chk/__vsprintf_chk calls. */
11460
11461static void
11462maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
11463{
0a39fd54 11464 tree dest, size, len, fmt, flag;
11465 const char *fmt_str;
c2f47e15 11466 int nargs = call_expr_nargs (exp);
0a39fd54 11467
11468 /* Verify the required arguments in the original call. */
c2f47e15 11469
11470 if (nargs < 4)
0a39fd54 11471 return;
c2f47e15 11472 dest = CALL_EXPR_ARG (exp, 0);
11473 flag = CALL_EXPR_ARG (exp, 1);
11474 size = CALL_EXPR_ARG (exp, 2);
11475 fmt = CALL_EXPR_ARG (exp, 3);
0a39fd54 11476
11477 if (! host_integerp (size, 1) || integer_all_onesp (size))
11478 return;
11479
11480 /* Check whether the format is a literal string constant. */
11481 fmt_str = c_getstr (fmt);
11482 if (fmt_str == NULL)
11483 return;
11484
d4473c84 11485 if (!init_target_chars ())
99eabcc1 11486 return;
11487
0a39fd54 11488 /* If the format doesn't contain % args or %%, we know its size. */
99eabcc1 11489 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 11490 len = build_int_cstu (size_type_node, strlen (fmt_str));
11491 /* If the format is "%s" and first ... argument is a string literal,
11492 we know it too. */
c2f47e15 11493 else if (fcode == BUILT_IN_SPRINTF_CHK
11494 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 11495 {
11496 tree arg;
11497
c2f47e15 11498 if (nargs < 5)
0a39fd54 11499 return;
c2f47e15 11500 arg = CALL_EXPR_ARG (exp, 4);
0a39fd54 11501 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
11502 return;
11503
11504 len = c_strlen (arg, 1);
11505 if (!len || ! host_integerp (len, 1))
11506 return;
11507 }
11508 else
11509 return;
11510
11511 if (! tree_int_cst_lt (len, size))
11512 {
11513 location_t locus = EXPR_LOCATION (exp);
11514 warning (0, "%Hcall to %D will always overflow destination buffer",
11515 &locus, get_callee_fndecl (exp));
11516 }
11517}
11518
c2f47e15 11519/* Fold a call to __builtin_object_size with arguments PTR and OST,
11520 if possible. */
0a39fd54 11521
11522tree
c2f47e15 11523fold_builtin_object_size (tree ptr, tree ost)
0a39fd54 11524{
c2f47e15 11525 tree ret = NULL_TREE;
0a39fd54 11526 int object_size_type;
11527
c2f47e15 11528 if (!validate_arg (ptr, POINTER_TYPE)
11529 || !validate_arg (ost, INTEGER_TYPE))
11530 return NULL_TREE;
0a39fd54 11531
0a39fd54 11532 STRIP_NOPS (ost);
11533
11534 if (TREE_CODE (ost) != INTEGER_CST
11535 || tree_int_cst_sgn (ost) < 0
11536 || compare_tree_int (ost, 3) > 0)
c2f47e15 11537 return NULL_TREE;
0a39fd54 11538
11539 object_size_type = tree_low_cst (ost, 0);
11540
11541 /* __builtin_object_size doesn't evaluate side-effects in its arguments;
11542 if there are any side-effects, it returns (size_t) -1 for types 0 and 1
11543 and (size_t) 0 for types 2 and 3. */
11544 if (TREE_SIDE_EFFECTS (ptr))
697bbc3f 11545 return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
0a39fd54 11546
11547 if (TREE_CODE (ptr) == ADDR_EXPR)
11548 ret = build_int_cstu (size_type_node,
697bbc3f 11549 compute_builtin_object_size (ptr, object_size_type));
0a39fd54 11550
11551 else if (TREE_CODE (ptr) == SSA_NAME)
11552 {
11553 unsigned HOST_WIDE_INT bytes;
11554
11555 /* If object size is not known yet, delay folding until
11556 later. Maybe subsequent passes will help determining
11557 it. */
11558 bytes = compute_builtin_object_size (ptr, object_size_type);
11559 if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2
11560 ? -1 : 0))
11561 ret = build_int_cstu (size_type_node, bytes);
11562 }
11563
11564 if (ret)
11565 {
697bbc3f 11566 unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (ret);
11567 HOST_WIDE_INT high = TREE_INT_CST_HIGH (ret);
11568 if (fit_double_type (low, high, &low, &high, TREE_TYPE (ret)))
11569 ret = NULL_TREE;
0a39fd54 11570 }
11571
11572 return ret;
11573}
11574
11575/* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
c2f47e15 11576 DEST, SRC, LEN, and SIZE are the arguments to the call.
0a39fd54 11577 IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_*
11578 code of the builtin. If MAXLEN is not NULL, it is maximum length
11579 passed as third argument. */
11580
11581tree
c2f47e15 11582fold_builtin_memory_chk (tree fndecl,
11583 tree dest, tree src, tree len, tree size,
11584 tree maxlen, bool ignore,
0a39fd54 11585 enum built_in_function fcode)
11586{
c2f47e15 11587 tree fn;
0a39fd54 11588
c2f47e15 11589 if (!validate_arg (dest, POINTER_TYPE)
11590 || !validate_arg (src,
11591 (fcode == BUILT_IN_MEMSET_CHK
11592 ? INTEGER_TYPE : POINTER_TYPE))
11593 || !validate_arg (len, INTEGER_TYPE)
11594 || !validate_arg (size, INTEGER_TYPE))
11595 return NULL_TREE;
0a39fd54 11596
11597 /* If SRC and DEST are the same (and not volatile), return DEST
11598 (resp. DEST+LEN for __mempcpy_chk). */
11599 if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
11600 {
11601 if (fcode != BUILT_IN_MEMPCPY_CHK)
11602 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
11603 else
11604 {
11605 tree temp = fold_convert (TREE_TYPE (dest), len);
11606 temp = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, temp);
11607 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), temp);
11608 }
11609 }
11610
11611 if (! host_integerp (size, 1))
c2f47e15 11612 return NULL_TREE;
0a39fd54 11613
11614 if (! integer_all_onesp (size))
11615 {
11616 if (! host_integerp (len, 1))
11617 {
11618 /* If LEN is not constant, try MAXLEN too.
11619 For MAXLEN only allow optimizing into non-_ocs function
11620 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
11621 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
11622 {
11623 if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
11624 {
11625 /* (void) __mempcpy_chk () can be optimized into
11626 (void) __memcpy_chk (). */
11627 fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
11628 if (!fn)
c2f47e15 11629 return NULL_TREE;
0a39fd54 11630
c2f47e15 11631 return build_call_expr (fn, 4, dest, src, len, size);
0a39fd54 11632 }
c2f47e15 11633 return NULL_TREE;
0a39fd54 11634 }
0a39fd54 11635 }
ad89623c 11636 else
11637 maxlen = len;
0a39fd54 11638
ad89623c 11639 if (tree_int_cst_lt (size, maxlen))
c2f47e15 11640 return NULL_TREE;
0a39fd54 11641 }
11642
0a39fd54 11643 fn = NULL_TREE;
11644 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
11645 mem{cpy,pcpy,move,set} is available. */
11646 switch (fcode)
11647 {
11648 case BUILT_IN_MEMCPY_CHK:
11649 fn = built_in_decls[BUILT_IN_MEMCPY];
11650 break;
11651 case BUILT_IN_MEMPCPY_CHK:
11652 fn = built_in_decls[BUILT_IN_MEMPCPY];
11653 break;
11654 case BUILT_IN_MEMMOVE_CHK:
11655 fn = built_in_decls[BUILT_IN_MEMMOVE];
11656 break;
11657 case BUILT_IN_MEMSET_CHK:
11658 fn = built_in_decls[BUILT_IN_MEMSET];
11659 break;
11660 default:
11661 break;
11662 }
11663
11664 if (!fn)
c2f47e15 11665 return NULL_TREE;
0a39fd54 11666
c2f47e15 11667 return build_call_expr (fn, 3, dest, src, len);
0a39fd54 11668}
11669
11670/* Fold a call to the __st[rp]cpy_chk builtin.
c2f47e15 11671 DEST, SRC, and SIZE are the arguments to the call.
11672 IGNORE is true if return value can be ignored. FCODE is the BUILT_IN_*
0a39fd54 11673 code of the builtin. If MAXLEN is not NULL, it is maximum length of
11674 strings passed as second argument. */
11675
11676tree
c2f47e15 11677fold_builtin_stxcpy_chk (tree fndecl, tree dest, tree src, tree size,
11678 tree maxlen, bool ignore,
0a39fd54 11679 enum built_in_function fcode)
11680{
c2f47e15 11681 tree len, fn;
0a39fd54 11682
c2f47e15 11683 if (!validate_arg (dest, POINTER_TYPE)
11684 || !validate_arg (src, POINTER_TYPE)
11685 || !validate_arg (size, INTEGER_TYPE))
11686 return NULL_TREE;
0a39fd54 11687
11688 /* If SRC and DEST are the same (and not volatile), return DEST. */
11689 if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
11690 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
a0c938f0 11691
0a39fd54 11692 if (! host_integerp (size, 1))
c2f47e15 11693 return NULL_TREE;
0a39fd54 11694
11695 if (! integer_all_onesp (size))
11696 {
11697 len = c_strlen (src, 1);
11698 if (! len || ! host_integerp (len, 1))
11699 {
11700 /* If LEN is not constant, try MAXLEN too.
11701 For MAXLEN only allow optimizing into non-_ocs function
11702 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
11703 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
11704 {
11705 if (fcode == BUILT_IN_STPCPY_CHK)
11706 {
11707 if (! ignore)
c2f47e15 11708 return NULL_TREE;
0a39fd54 11709
11710 /* If return value of __stpcpy_chk is ignored,
11711 optimize into __strcpy_chk. */
11712 fn = built_in_decls[BUILT_IN_STRCPY_CHK];
11713 if (!fn)
c2f47e15 11714 return NULL_TREE;
0a39fd54 11715
c2f47e15 11716 return build_call_expr (fn, 3, dest, src, size);
0a39fd54 11717 }
11718
11719 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 11720 return NULL_TREE;
0a39fd54 11721
11722 /* If c_strlen returned something, but not a constant,
11723 transform __strcpy_chk into __memcpy_chk. */
11724 fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
11725 if (!fn)
c2f47e15 11726 return NULL_TREE;
0a39fd54 11727
11728 len = size_binop (PLUS_EXPR, len, ssize_int (1));
0a39fd54 11729 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
c2f47e15 11730 build_call_expr (fn, 4,
11731 dest, src, len, size));
0a39fd54 11732 }
0a39fd54 11733 }
ad89623c 11734 else
11735 maxlen = len;
11736
11737 if (! tree_int_cst_lt (maxlen, size))
c2f47e15 11738 return NULL_TREE;
0a39fd54 11739 }
11740
0a39fd54 11741 /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available. */
11742 fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK
11743 ? BUILT_IN_STPCPY : BUILT_IN_STRCPY];
11744 if (!fn)
c2f47e15 11745 return NULL_TREE;
0a39fd54 11746
c2f47e15 11747 return build_call_expr (fn, 2, dest, src);
0a39fd54 11748}
11749
c2f47e15 11750/* Fold a call to the __strncpy_chk builtin. DEST, SRC, LEN, and SIZE
11751 are the arguments to the call. If MAXLEN is not NULL, it is maximum
11752 length passed as third argument. */
0a39fd54 11753
11754tree
c2f47e15 11755fold_builtin_strncpy_chk (tree dest, tree src, tree len, tree size,
11756 tree maxlen)
0a39fd54 11757{
c2f47e15 11758 tree fn;
0a39fd54 11759
c2f47e15 11760 if (!validate_arg (dest, POINTER_TYPE)
11761 || !validate_arg (src, POINTER_TYPE)
11762 || !validate_arg (len, INTEGER_TYPE)
11763 || !validate_arg (size, INTEGER_TYPE))
11764 return NULL_TREE;
0a39fd54 11765
11766 if (! host_integerp (size, 1))
c2f47e15 11767 return NULL_TREE;
0a39fd54 11768
11769 if (! integer_all_onesp (size))
11770 {
11771 if (! host_integerp (len, 1))
11772 {
11773 /* If LEN is not constant, try MAXLEN too.
11774 For MAXLEN only allow optimizing into non-_ocs function
11775 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
11776 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 11777 return NULL_TREE;
0a39fd54 11778 }
ad89623c 11779 else
11780 maxlen = len;
0a39fd54 11781
ad89623c 11782 if (tree_int_cst_lt (size, maxlen))
c2f47e15 11783 return NULL_TREE;
0a39fd54 11784 }
11785
0a39fd54 11786 /* If __builtin_strncpy_chk is used, assume strncpy is available. */
11787 fn = built_in_decls[BUILT_IN_STRNCPY];
11788 if (!fn)
c2f47e15 11789 return NULL_TREE;
0a39fd54 11790
c2f47e15 11791 return build_call_expr (fn, 3, dest, src, len);
0a39fd54 11792}
11793
c2f47e15 11794/* Fold a call to the __strcat_chk builtin FNDECL. DEST, SRC, and SIZE
11795 are the arguments to the call. */
0a39fd54 11796
11797static tree
c2f47e15 11798fold_builtin_strcat_chk (tree fndecl, tree dest, tree src, tree size)
0a39fd54 11799{
c2f47e15 11800 tree fn;
0a39fd54 11801 const char *p;
11802
c2f47e15 11803 if (!validate_arg (dest, POINTER_TYPE)
11804 || !validate_arg (src, POINTER_TYPE)
11805 || !validate_arg (size, INTEGER_TYPE))
11806 return NULL_TREE;
0a39fd54 11807
11808 p = c_getstr (src);
11809 /* If the SRC parameter is "", return DEST. */
11810 if (p && *p == '\0')
11811 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
11812
11813 if (! host_integerp (size, 1) || ! integer_all_onesp (size))
c2f47e15 11814 return NULL_TREE;
0a39fd54 11815
11816 /* If __builtin_strcat_chk is used, assume strcat is available. */
11817 fn = built_in_decls[BUILT_IN_STRCAT];
11818 if (!fn)
c2f47e15 11819 return NULL_TREE;
0a39fd54 11820
c2f47e15 11821 return build_call_expr (fn, 2, dest, src);
0a39fd54 11822}
11823
c2f47e15 11824/* Fold a call to the __strncat_chk builtin with arguments DEST, SRC,
11825 LEN, and SIZE. */
0a39fd54 11826
11827static tree
c2f47e15 11828fold_builtin_strncat_chk (tree fndecl,
11829 tree dest, tree src, tree len, tree size)
0a39fd54 11830{
c2f47e15 11831 tree fn;
0a39fd54 11832 const char *p;
11833
c2f47e15 11834 if (!validate_arg (dest, POINTER_TYPE)
11835 || !validate_arg (src, POINTER_TYPE)
11836 || !validate_arg (size, INTEGER_TYPE)
11837 || !validate_arg (size, INTEGER_TYPE))
11838 return NULL_TREE;
0a39fd54 11839
11840 p = c_getstr (src);
11841 /* If the SRC parameter is "" or if LEN is 0, return DEST. */
11842 if (p && *p == '\0')
11843 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
11844 else if (integer_zerop (len))
11845 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
11846
11847 if (! host_integerp (size, 1))
c2f47e15 11848 return NULL_TREE;
0a39fd54 11849
11850 if (! integer_all_onesp (size))
11851 {
11852 tree src_len = c_strlen (src, 1);
11853 if (src_len
11854 && host_integerp (src_len, 1)
11855 && host_integerp (len, 1)
11856 && ! tree_int_cst_lt (len, src_len))
11857 {
11858 /* If LEN >= strlen (SRC), optimize into __strcat_chk. */
11859 fn = built_in_decls[BUILT_IN_STRCAT_CHK];
11860 if (!fn)
c2f47e15 11861 return NULL_TREE;
0a39fd54 11862
c2f47e15 11863 return build_call_expr (fn, 3, dest, src, size);
0a39fd54 11864 }
c2f47e15 11865 return NULL_TREE;
0a39fd54 11866 }
11867
0a39fd54 11868 /* If __builtin_strncat_chk is used, assume strncat is available. */
11869 fn = built_in_decls[BUILT_IN_STRNCAT];
11870 if (!fn)
c2f47e15 11871 return NULL_TREE;
0a39fd54 11872
c2f47e15 11873 return build_call_expr (fn, 3, dest, src, len);
0a39fd54 11874}
11875
c2f47e15 11876/* Fold a call EXP to __{,v}sprintf_chk. Return NULL_TREE if
0a39fd54 11877 a normal call should be emitted rather than expanding the function
11878 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
11879
11880static tree
c2f47e15 11881fold_builtin_sprintf_chk (tree exp, enum built_in_function fcode)
0a39fd54 11882{
11883 tree dest, size, len, fn, fmt, flag;
11884 const char *fmt_str;
c2f47e15 11885 int nargs = call_expr_nargs (exp);
0a39fd54 11886
11887 /* Verify the required arguments in the original call. */
c2f47e15 11888 if (nargs < 4)
11889 return NULL_TREE;
11890 dest = CALL_EXPR_ARG (exp, 0);
11891 if (!validate_arg (dest, POINTER_TYPE))
11892 return NULL_TREE;
11893 flag = CALL_EXPR_ARG (exp, 1);
11894 if (!validate_arg (flag, INTEGER_TYPE))
11895 return NULL_TREE;
11896 size = CALL_EXPR_ARG (exp, 2);
11897 if (!validate_arg (size, INTEGER_TYPE))
11898 return NULL_TREE;
11899 fmt = CALL_EXPR_ARG (exp, 3);
11900 if (!validate_arg (fmt, POINTER_TYPE))
11901 return NULL_TREE;
0a39fd54 11902
11903 if (! host_integerp (size, 1))
c2f47e15 11904 return NULL_TREE;
0a39fd54 11905
11906 len = NULL_TREE;
11907
d4473c84 11908 if (!init_target_chars ())
c2f47e15 11909 return NULL_TREE;
99eabcc1 11910
0a39fd54 11911 /* Check whether the format is a literal string constant. */
11912 fmt_str = c_getstr (fmt);
11913 if (fmt_str != NULL)
11914 {
11915 /* If the format doesn't contain % args or %%, we know the size. */
99eabcc1 11916 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 11917 {
c2f47e15 11918 if (fcode != BUILT_IN_SPRINTF_CHK || nargs == 4)
0a39fd54 11919 len = build_int_cstu (size_type_node, strlen (fmt_str));
11920 }
11921 /* If the format is "%s" and first ... argument is a string literal,
11922 we know the size too. */
c2f47e15 11923 else if (fcode == BUILT_IN_SPRINTF_CHK
11924 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 11925 {
11926 tree arg;
11927
c2f47e15 11928 if (nargs == 5)
0a39fd54 11929 {
c2f47e15 11930 arg = CALL_EXPR_ARG (exp, 4);
11931 if (validate_arg (arg, POINTER_TYPE))
0a39fd54 11932 {
11933 len = c_strlen (arg, 1);
11934 if (! len || ! host_integerp (len, 1))
11935 len = NULL_TREE;
11936 }
11937 }
11938 }
11939 }
11940
11941 if (! integer_all_onesp (size))
11942 {
11943 if (! len || ! tree_int_cst_lt (len, size))
c2f47e15 11944 return NULL_TREE;
0a39fd54 11945 }
11946
11947 /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
11948 or if format doesn't contain % chars or is "%s". */
11949 if (! integer_zerop (flag))
11950 {
11951 if (fmt_str == NULL)
c2f47e15 11952 return NULL_TREE;
11953 if (strchr (fmt_str, target_percent) != NULL
11954 && strcmp (fmt_str, target_percent_s))
11955 return NULL_TREE;
0a39fd54 11956 }
11957
0a39fd54 11958 /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
11959 fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
11960 ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
11961 if (!fn)
c2f47e15 11962 return NULL_TREE;
0a39fd54 11963
c2f47e15 11964 return rewrite_call_expr (exp, 4, fn, 2, dest, fmt);
0a39fd54 11965}
11966
c2f47e15 11967/* Fold a call EXP to {,v}snprintf. Return NULL_TREE if
0a39fd54 11968 a normal call should be emitted rather than expanding the function
11969 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
11970 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
11971 passed as second argument. */
11972
11973tree
c2f47e15 11974fold_builtin_snprintf_chk (tree exp, tree maxlen,
0a39fd54 11975 enum built_in_function fcode)
11976{
11977 tree dest, size, len, fn, fmt, flag;
11978 const char *fmt_str;
11979
11980 /* Verify the required arguments in the original call. */
c2f47e15 11981 if (call_expr_nargs (exp) < 5)
11982 return NULL_TREE;
11983 dest = CALL_EXPR_ARG (exp, 0);
11984 if (!validate_arg (dest, POINTER_TYPE))
11985 return NULL_TREE;
11986 len = CALL_EXPR_ARG (exp, 1);
11987 if (!validate_arg (len, INTEGER_TYPE))
11988 return NULL_TREE;
11989 flag = CALL_EXPR_ARG (exp, 2);
11990 if (!validate_arg (flag, INTEGER_TYPE))
11991 return NULL_TREE;
11992 size = CALL_EXPR_ARG (exp, 3);
11993 if (!validate_arg (size, INTEGER_TYPE))
11994 return NULL_TREE;
11995 fmt = CALL_EXPR_ARG (exp, 4);
11996 if (!validate_arg (fmt, POINTER_TYPE))
11997 return NULL_TREE;
0a39fd54 11998
11999 if (! host_integerp (size, 1))
c2f47e15 12000 return NULL_TREE;
0a39fd54 12001
12002 if (! integer_all_onesp (size))
12003 {
12004 if (! host_integerp (len, 1))
12005 {
12006 /* If LEN is not constant, try MAXLEN too.
12007 For MAXLEN only allow optimizing into non-_ocs function
12008 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12009 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 12010 return NULL_TREE;
0a39fd54 12011 }
ad89623c 12012 else
12013 maxlen = len;
0a39fd54 12014
ad89623c 12015 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12016 return NULL_TREE;
0a39fd54 12017 }
12018
d4473c84 12019 if (!init_target_chars ())
c2f47e15 12020 return NULL_TREE;
99eabcc1 12021
0a39fd54 12022 /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
12023 or if format doesn't contain % chars or is "%s". */
12024 if (! integer_zerop (flag))
12025 {
12026 fmt_str = c_getstr (fmt);
12027 if (fmt_str == NULL)
c2f47e15 12028 return NULL_TREE;
12029 if (strchr (fmt_str, target_percent) != NULL
12030 && strcmp (fmt_str, target_percent_s))
12031 return NULL_TREE;
0a39fd54 12032 }
12033
0a39fd54 12034 /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
12035 available. */
12036 fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
12037 ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
12038 if (!fn)
c2f47e15 12039 return NULL_TREE;
0a39fd54 12040
c2f47e15 12041 return rewrite_call_expr (exp, 5, fn, 3, dest, len, fmt);
0a39fd54 12042}
12043
12044/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 12045 FMT and ARG are the arguments to the call; we don't fold cases with
12046 more than 2 arguments, and ARG may be null if this is a 1-argument case.
0a39fd54 12047
c2f47e15 12048 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 12049 simplified form of the call as a tree. FCODE is the BUILT_IN_*
12050 code of the function to be simplified. */
12051
12052static tree
c2f47e15 12053fold_builtin_printf (tree fndecl, tree fmt, tree arg, bool ignore,
0a39fd54 12054 enum built_in_function fcode)
12055{
c2f47e15 12056 tree fn_putchar, fn_puts, newarg, call = NULL_TREE;
0a39fd54 12057 const char *fmt_str = NULL;
12058
12059 /* If the return value is used, don't do the transformation. */
12060 if (! ignore)
c2f47e15 12061 return NULL_TREE;
0a39fd54 12062
12063 /* Verify the required arguments in the original call. */
c2f47e15 12064 if (!validate_arg (fmt, POINTER_TYPE))
12065 return NULL_TREE;
0a39fd54 12066
12067 /* Check whether the format is a literal string constant. */
12068 fmt_str = c_getstr (fmt);
12069 if (fmt_str == NULL)
12070 return NULL_TREE;
12071
12072 if (fcode == BUILT_IN_PRINTF_UNLOCKED)
12073 {
6d77ed92 12074 /* If we're using an unlocked function, assume the other
12075 unlocked functions exist explicitly. */
12076 fn_putchar = built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED];
12077 fn_puts = built_in_decls[BUILT_IN_PUTS_UNLOCKED];
0a39fd54 12078 }
12079 else
12080 {
12081 fn_putchar = implicit_built_in_decls[BUILT_IN_PUTCHAR];
12082 fn_puts = implicit_built_in_decls[BUILT_IN_PUTS];
12083 }
12084
d4473c84 12085 if (!init_target_chars ())
c2f47e15 12086 return NULL_TREE;
a0c938f0 12087
c2f47e15 12088 if (strcmp (fmt_str, target_percent_s) == 0
12089 || strchr (fmt_str, target_percent) == NULL)
0a39fd54 12090 {
12091 const char *str;
12092
99eabcc1 12093 if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12094 {
12095 if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 12096 return NULL_TREE;
0a39fd54 12097
c2f47e15 12098 if (!arg || !validate_arg (arg, POINTER_TYPE))
12099 return NULL_TREE;
0a39fd54 12100
c2f47e15 12101 str = c_getstr (arg);
0a39fd54 12102 if (str == NULL)
c2f47e15 12103 return NULL_TREE;
0a39fd54 12104 }
12105 else
12106 {
12107 /* The format specifier doesn't contain any '%' characters. */
12108 if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
c2f47e15 12109 && arg)
12110 return NULL_TREE;
0a39fd54 12111 str = fmt_str;
12112 }
12113
12114 /* If the string was "", printf does nothing. */
12115 if (str[0] == '\0')
12116 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
12117
12118 /* If the string has length of 1, call putchar. */
12119 if (str[1] == '\0')
12120 {
12121 /* Given printf("c"), (where c is any one character,)
12122 convert "c"[0] to an int and pass that to the replacement
12123 function. */
c2f47e15 12124 newarg = build_int_cst (NULL_TREE, str[0]);
12125 if (fn_putchar)
12126 call = build_call_expr (fn_putchar, 1, newarg);
0a39fd54 12127 }
12128 else
12129 {
12130 /* If the string was "string\n", call puts("string"). */
12131 size_t len = strlen (str);
99eabcc1 12132 if ((unsigned char)str[len - 1] == target_newline)
0a39fd54 12133 {
12134 /* Create a NUL-terminated string that's one char shorter
12135 than the original, stripping off the trailing '\n'. */
12136 char *newstr = alloca (len);
12137 memcpy (newstr, str, len - 1);
12138 newstr[len - 1] = 0;
12139
c2f47e15 12140 newarg = build_string_literal (len, newstr);
12141 if (fn_puts)
12142 call = build_call_expr (fn_puts, 1, newarg);
0a39fd54 12143 }
12144 else
12145 /* We'd like to arrange to call fputs(string,stdout) here,
12146 but we need stdout and don't have a way to get it yet. */
c2f47e15 12147 return NULL_TREE;
0a39fd54 12148 }
12149 }
12150
12151 /* The other optimizations can be done only on the non-va_list variants. */
12152 else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 12153 return NULL_TREE;
0a39fd54 12154
12155 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
99eabcc1 12156 else if (strcmp (fmt_str, target_percent_s_newline) == 0)
0a39fd54 12157 {
c2f47e15 12158 if (!arg || !validate_arg (arg, POINTER_TYPE))
12159 return NULL_TREE;
12160 if (fn_puts)
12161 call = build_call_expr (fn_puts, 1, arg);
0a39fd54 12162 }
12163
12164 /* If the format specifier was "%c", call __builtin_putchar(arg). */
99eabcc1 12165 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 12166 {
c2f47e15 12167 if (!arg || !validate_arg (arg, INTEGER_TYPE))
12168 return NULL_TREE;
12169 if (fn_putchar)
12170 call = build_call_expr (fn_putchar, 1, arg);
0a39fd54 12171 }
12172
c2f47e15 12173 if (!call)
12174 return NULL_TREE;
0a39fd54 12175
0a39fd54 12176 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
12177}
12178
12179/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 12180 FP, FMT, and ARG are the arguments to the call. We don't fold calls with
12181 more than 3 arguments, and ARG may be null in the 2-argument case.
0a39fd54 12182
c2f47e15 12183 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 12184 simplified form of the call as a tree. FCODE is the BUILT_IN_*
12185 code of the function to be simplified. */
12186
12187static tree
c2f47e15 12188fold_builtin_fprintf (tree fndecl, tree fp, tree fmt, tree arg, bool ignore,
0a39fd54 12189 enum built_in_function fcode)
12190{
c2f47e15 12191 tree fn_fputc, fn_fputs, call = NULL_TREE;
0a39fd54 12192 const char *fmt_str = NULL;
12193
12194 /* If the return value is used, don't do the transformation. */
12195 if (! ignore)
c2f47e15 12196 return NULL_TREE;
0a39fd54 12197
12198 /* Verify the required arguments in the original call. */
c2f47e15 12199 if (!validate_arg (fp, POINTER_TYPE))
12200 return NULL_TREE;
12201 if (!validate_arg (fmt, POINTER_TYPE))
12202 return NULL_TREE;
0a39fd54 12203
12204 /* Check whether the format is a literal string constant. */
12205 fmt_str = c_getstr (fmt);
12206 if (fmt_str == NULL)
12207 return NULL_TREE;
12208
12209 if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
12210 {
6d77ed92 12211 /* If we're using an unlocked function, assume the other
12212 unlocked functions exist explicitly. */
12213 fn_fputc = built_in_decls[BUILT_IN_FPUTC_UNLOCKED];
12214 fn_fputs = built_in_decls[BUILT_IN_FPUTS_UNLOCKED];
0a39fd54 12215 }
12216 else
12217 {
12218 fn_fputc = implicit_built_in_decls[BUILT_IN_FPUTC];
12219 fn_fputs = implicit_built_in_decls[BUILT_IN_FPUTS];
12220 }
12221
d4473c84 12222 if (!init_target_chars ())
c2f47e15 12223 return NULL_TREE;
a0c938f0 12224
0a39fd54 12225 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 12226 if (strchr (fmt_str, target_percent) == NULL)
0a39fd54 12227 {
12228 if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
c2f47e15 12229 && arg)
12230 return NULL_TREE;
0a39fd54 12231
12232 /* If the format specifier was "", fprintf does nothing. */
12233 if (fmt_str[0] == '\0')
12234 {
12235 /* If FP has side-effects, just wait until gimplification is
12236 done. */
12237 if (TREE_SIDE_EFFECTS (fp))
c2f47e15 12238 return NULL_TREE;
0a39fd54 12239
12240 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
12241 }
12242
12243 /* When "string" doesn't contain %, replace all cases of
12244 fprintf (fp, string) with fputs (string, fp). The fputs
12245 builtin will take care of special cases like length == 1. */
c2f47e15 12246 if (fn_fputs)
12247 call = build_call_expr (fn_fputs, 2, fmt, fp);
0a39fd54 12248 }
12249
12250 /* The other optimizations can be done only on the non-va_list variants. */
12251 else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
c2f47e15 12252 return NULL_TREE;
0a39fd54 12253
12254 /* If the format specifier was "%s", call __builtin_fputs (arg, fp). */
99eabcc1 12255 else if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12256 {
c2f47e15 12257 if (!arg || !validate_arg (arg, POINTER_TYPE))
12258 return NULL_TREE;
12259 if (fn_fputs)
12260 call = build_call_expr (fn_fputs, 2, arg, fp);
0a39fd54 12261 }
12262
12263 /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */
99eabcc1 12264 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 12265 {
c2f47e15 12266 if (!arg || !validate_arg (arg, INTEGER_TYPE))
12267 return NULL_TREE;
12268 if (fn_fputc)
12269 call = build_call_expr (fn_fputc, 2, arg, fp);
0a39fd54 12270 }
12271
c2f47e15 12272 if (!call)
12273 return NULL_TREE;
0a39fd54 12274 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
12275}
99eabcc1 12276
12277/* Initialize format string characters in the target charset. */
12278
12279static bool
12280init_target_chars (void)
12281{
12282 static bool init;
12283 if (!init)
12284 {
12285 target_newline = lang_hooks.to_target_charset ('\n');
12286 target_percent = lang_hooks.to_target_charset ('%');
12287 target_c = lang_hooks.to_target_charset ('c');
12288 target_s = lang_hooks.to_target_charset ('s');
12289 if (target_newline == 0 || target_percent == 0 || target_c == 0
12290 || target_s == 0)
12291 return false;
12292
12293 target_percent_c[0] = target_percent;
12294 target_percent_c[1] = target_c;
12295 target_percent_c[2] = '\0';
12296
12297 target_percent_s[0] = target_percent;
12298 target_percent_s[1] = target_s;
12299 target_percent_s[2] = '\0';
12300
12301 target_percent_s_newline[0] = target_percent;
12302 target_percent_s_newline[1] = target_s;
12303 target_percent_s_newline[2] = target_newline;
12304 target_percent_s_newline[3] = '\0';
a0c938f0 12305
99eabcc1 12306 init = true;
12307 }
12308 return true;
12309}
bffb7645 12310
f0c477f2 12311/* Helper function for do_mpfr_arg*(). Ensure M is a normal number
12312 and no overflow/underflow occurred. INEXACT is true if M was not
fa7637bd 12313 exactly calculated. TYPE is the tree type for the result. This
f0c477f2 12314 function assumes that you cleared the MPFR flags and then
12315 calculated M to see if anything subsequently set a flag prior to
12316 entering this function. Return NULL_TREE if any checks fail. */
12317
12318static tree
d4473c84 12319do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
f0c477f2 12320{
12321 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
12322 overflow/underflow occurred. If -frounding-math, proceed iff the
12323 result of calling FUNC was exact. */
d4473c84 12324 if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
f0c477f2 12325 && (!flag_rounding_math || !inexact))
12326 {
12327 REAL_VALUE_TYPE rr;
12328
66fa16e6 12329 real_from_mpfr (&rr, m, type, GMP_RNDN);
f0c477f2 12330 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
12331 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
12332 but the mpft_t is not, then we underflowed in the
12333 conversion. */
12334 if (!real_isnan (&rr) && !real_isinf (&rr)
12335 && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
12336 {
12337 REAL_VALUE_TYPE rmode;
12338
12339 real_convert (&rmode, TYPE_MODE (type), &rr);
12340 /* Proceed iff the specified mode can hold the value. */
12341 if (real_identical (&rmode, &rr))
12342 return build_real (type, rmode);
12343 }
12344 }
12345 return NULL_TREE;
12346}
12347
bffb7645 12348/* If argument ARG is a REAL_CST, call the one-argument mpfr function
12349 FUNC on it and return the resulting value as a tree with type TYPE.
728bac60 12350 If MIN and/or MAX are not NULL, then the supplied ARG must be
12351 within those bounds. If INCLUSIVE is true, then MIN/MAX are
12352 acceptable values, otherwise they are not. The mpfr precision is
12353 set to the precision of TYPE. We assume that function FUNC returns
12354 zero if the result could be calculated exactly within the requested
12355 precision. */
bffb7645 12356
12357static tree
728bac60 12358do_mpfr_arg1 (tree arg, tree type, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
12359 const REAL_VALUE_TYPE *min, const REAL_VALUE_TYPE *max,
12360 bool inclusive)
bffb7645 12361{
12362 tree result = NULL_TREE;
12363
12364 STRIP_NOPS (arg);
12365
bd7d6fa4 12366 /* To proceed, MPFR must exactly represent the target floating point
12367 format, which only happens when the target base equals two. */
12368 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12369 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
bffb7645 12370 {
f0c477f2 12371 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
bffb7645 12372
f0c477f2 12373 if (!real_isnan (ra) && !real_isinf (ra)
12374 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min))
12375 && (!max || real_compare (inclusive ? LE_EXPR: LT_EXPR , ra, max)))
bffb7645 12376 {
f0c477f2 12377 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
debf9994 12378 int inexact;
bffb7645 12379 mpfr_t m;
12380
12381 mpfr_init2 (m, prec);
66fa16e6 12382 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 12383 mpfr_clear_flags ();
debf9994 12384 inexact = func (m, m, GMP_RNDN);
f0c477f2 12385 result = do_mpfr_ckconv (m, type, inexact);
bffb7645 12386 mpfr_clear (m);
12387 }
12388 }
12389
12390 return result;
12391}
f0c477f2 12392
12393/* If argument ARG is a REAL_CST, call the two-argument mpfr function
12394 FUNC on it and return the resulting value as a tree with type TYPE.
12395 The mpfr precision is set to the precision of TYPE. We assume that
12396 function FUNC returns zero if the result could be calculated
12397 exactly within the requested precision. */
12398
12399static tree
12400do_mpfr_arg2 (tree arg1, tree arg2, tree type,
12401 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
12402{
12403 tree result = NULL_TREE;
12404
12405 STRIP_NOPS (arg1);
12406 STRIP_NOPS (arg2);
12407
bd7d6fa4 12408 /* To proceed, MPFR must exactly represent the target floating point
12409 format, which only happens when the target base equals two. */
12410 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12411 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
12412 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
f0c477f2 12413 {
12414 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
12415 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
12416
12417 if (!real_isnan (ra1) && !real_isinf (ra1)
12418 && !real_isnan (ra2) && !real_isinf (ra2))
12419 {
12420 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12421 int inexact;
12422 mpfr_t m1, m2;
12423
12424 mpfr_inits2 (prec, m1, m2, NULL);
66fa16e6 12425 mpfr_from_real (m1, ra1, GMP_RNDN);
12426 mpfr_from_real (m2, ra2, GMP_RNDN);
d4473c84 12427 mpfr_clear_flags ();
f0c477f2 12428 inexact = func (m1, m1, m2, GMP_RNDN);
12429 result = do_mpfr_ckconv (m1, type, inexact);
12430 mpfr_clears (m1, m2, NULL);
12431 }
12432 }
12433
12434 return result;
12435}
d92f994c 12436
9917422b 12437/* If argument ARG is a REAL_CST, call the three-argument mpfr function
12438 FUNC on it and return the resulting value as a tree with type TYPE.
12439 The mpfr precision is set to the precision of TYPE. We assume that
12440 function FUNC returns zero if the result could be calculated
12441 exactly within the requested precision. */
12442
12443static tree
12444do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type,
12445 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
12446{
12447 tree result = NULL_TREE;
12448
12449 STRIP_NOPS (arg1);
12450 STRIP_NOPS (arg2);
12451 STRIP_NOPS (arg3);
12452
bd7d6fa4 12453 /* To proceed, MPFR must exactly represent the target floating point
12454 format, which only happens when the target base equals two. */
12455 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12456 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
12457 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2)
12458 && TREE_CODE (arg3) == REAL_CST && !TREE_OVERFLOW (arg3))
9917422b 12459 {
12460 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
12461 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
12462 const REAL_VALUE_TYPE *const ra3 = &TREE_REAL_CST (arg3);
12463
12464 if (!real_isnan (ra1) && !real_isinf (ra1)
12465 && !real_isnan (ra2) && !real_isinf (ra2)
12466 && !real_isnan (ra3) && !real_isinf (ra3))
12467 {
12468 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12469 int inexact;
12470 mpfr_t m1, m2, m3;
12471
12472 mpfr_inits2 (prec, m1, m2, m3, NULL);
66fa16e6 12473 mpfr_from_real (m1, ra1, GMP_RNDN);
12474 mpfr_from_real (m2, ra2, GMP_RNDN);
12475 mpfr_from_real (m3, ra3, GMP_RNDN);
d4473c84 12476 mpfr_clear_flags ();
9917422b 12477 inexact = func (m1, m1, m2, m3, GMP_RNDN);
12478 result = do_mpfr_ckconv (m1, type, inexact);
12479 mpfr_clears (m1, m2, m3, NULL);
12480 }
12481 }
12482
12483 return result;
12484}
12485
d92f994c 12486/* If argument ARG is a REAL_CST, call mpfr_sin_cos() on it and set
12487 the pointers *(ARG_SINP) and *(ARG_COSP) to the resulting values.
d735c391 12488 If ARG_SINP and ARG_COSP are NULL then the result is returned
12489 as a complex value.
d92f994c 12490 The type is taken from the type of ARG and is used for setting the
12491 precision of the calculation and results. */
12492
12493static tree
12494do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp)
12495{
bd7d6fa4 12496 tree const type = TREE_TYPE (arg);
d92f994c 12497 tree result = NULL_TREE;
12498
12499 STRIP_NOPS (arg);
12500
bd7d6fa4 12501 /* To proceed, MPFR must exactly represent the target floating point
12502 format, which only happens when the target base equals two. */
12503 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12504 && TREE_CODE (arg) == REAL_CST
12505 && !TREE_OVERFLOW (arg))
d92f994c 12506 {
12507 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
12508
12509 if (!real_isnan (ra) && !real_isinf (ra))
12510 {
d92f994c 12511 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12512 tree result_s, result_c;
12513 int inexact;
12514 mpfr_t m, ms, mc;
12515
12516 mpfr_inits2 (prec, m, ms, mc, NULL);
66fa16e6 12517 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 12518 mpfr_clear_flags ();
d92f994c 12519 inexact = mpfr_sin_cos (ms, mc, m, GMP_RNDN);
12520 result_s = do_mpfr_ckconv (ms, type, inexact);
12521 result_c = do_mpfr_ckconv (mc, type, inexact);
12522 mpfr_clears (m, ms, mc, NULL);
12523 if (result_s && result_c)
12524 {
d735c391 12525 /* If we are to return in a complex value do so. */
12526 if (!arg_sinp && !arg_cosp)
12527 return build_complex (build_complex_type (type),
12528 result_c, result_s);
12529
d92f994c 12530 /* Dereference the sin/cos pointer arguments. */
12531 arg_sinp = build_fold_indirect_ref (arg_sinp);
12532 arg_cosp = build_fold_indirect_ref (arg_cosp);
12533 /* Proceed if valid pointer type were passed in. */
12534 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_sinp)) == TYPE_MAIN_VARIANT (type)
12535 && TYPE_MAIN_VARIANT (TREE_TYPE (arg_cosp)) == TYPE_MAIN_VARIANT (type))
12536 {
12537 /* Set the values. */
41076ef6 12538 result_s = fold_build2 (MODIFY_EXPR, type, arg_sinp,
35cc02b5 12539 result_s);
d92f994c 12540 TREE_SIDE_EFFECTS (result_s) = 1;
41076ef6 12541 result_c = fold_build2 (MODIFY_EXPR, type, arg_cosp,
35cc02b5 12542 result_c);
d92f994c 12543 TREE_SIDE_EFFECTS (result_c) = 1;
12544 /* Combine the assignments into a compound expr. */
12545 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
12546 result_s, result_c));
12547 }
12548 }
12549 }
12550 }
12551 return result;
12552}
65dd1378 12553
12554#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
12555/* If argument ARG1 is an INTEGER_CST and ARG2 is a REAL_CST, call the
12556 two-argument mpfr order N Bessel function FUNC on them and return
12557 the resulting value as a tree with type TYPE. The mpfr precision
12558 is set to the precision of TYPE. We assume that function FUNC
12559 returns zero if the result could be calculated exactly within the
12560 requested precision. */
12561static tree
12562do_mpfr_bessel_n (tree arg1, tree arg2, tree type,
12563 int (*func)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
12564 const REAL_VALUE_TYPE *min, bool inclusive)
12565{
12566 tree result = NULL_TREE;
12567
12568 STRIP_NOPS (arg1);
12569 STRIP_NOPS (arg2);
12570
12571 /* To proceed, MPFR must exactly represent the target floating point
12572 format, which only happens when the target base equals two. */
12573 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
12574 && host_integerp (arg1, 0)
12575 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
12576 {
12577 const HOST_WIDE_INT n = tree_low_cst(arg1, 0);
12578 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg2);
12579
12580 if (n == (long)n
12581 && !real_isnan (ra) && !real_isinf (ra)
12582 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min)))
12583 {
12584 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12585 int inexact;
12586 mpfr_t m;
12587
12588 mpfr_init2 (m, prec);
12589 mpfr_from_real (m, ra, GMP_RNDN);
12590 mpfr_clear_flags ();
12591 inexact = func (m, n, m, GMP_RNDN);
12592 result = do_mpfr_ckconv (m, type, inexact);
12593 mpfr_clear (m);
12594 }
12595 }
12596
12597 return result;
12598}
12599#endif