]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/builtins.c
2008-07-20 Daniel Berlin <dberlin@dberlin.org>
[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,
f0b5f617 3 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
f96bd2bf 4 Free Software Foundation, Inc.
53800dbe 5
f12b58b3 6This file is part of GCC.
53800dbe 7
f12b58b3 8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
8c4c00c1 10Software Foundation; either version 3, or (at your option) any later
f12b58b3 11version.
53800dbe 12
f12b58b3 13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
53800dbe 17
18You should have received a copy of the GNU General Public License
8c4c00c1 19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
53800dbe 21
22#include "config.h"
23#include "system.h"
805e22b2 24#include "coretypes.h"
25#include "tm.h"
53800dbe 26#include "machmode.h"
ef258422 27#include "real.h"
53800dbe 28#include "rtl.h"
29#include "tree.h"
9ff0637e 30#include "tree-gimple.h"
53800dbe 31#include "flags.h"
32#include "regs.h"
33#include "hard-reg-set.h"
34#include "except.h"
35#include "function.h"
53800dbe 36#include "insn-config.h"
37#include "expr.h"
d8fc4d0b 38#include "optabs.h"
39#include "libfuncs.h"
53800dbe 40#include "recog.h"
41#include "output.h"
42#include "typeclass.h"
53800dbe 43#include "toplev.h"
689df48e 44#include "predict.h"
1dd6c958 45#include "tm_p.h"
fc2a2dcb 46#include "target.h"
63c62881 47#include "langhooks.h"
0ec80471 48#include "basic-block.h"
fd62c19a 49#include "tree-mudflap.h"
5a84fdd6 50#include "tree-flow.h"
162719b3 51#include "value-prof.h"
07311427 52#include "diagnostic.h"
53800dbe 53
726e2588 54#ifndef PAD_VARARGS_DOWN
55#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
56#endif
57
ab7943b9 58/* Define the names of the builtin function types and codes. */
8934cb0c 59const char *const built_in_class_names[4]
ab7943b9 60 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
61
9cfddb70 62#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
0dfc45b5 63const char * built_in_names[(int) END_BUILTINS] =
4e9d90c7 64{
65#include "builtins.def"
66};
67#undef DEF_BUILTIN
ab7943b9 68
df94cd3b 69/* Setup an array of _DECL trees, make sure each element is
70 initialized to NULL_TREE. */
d2d4bdde 71tree built_in_decls[(int) END_BUILTINS];
0a68165a 72/* Declarations used when constructing the builtin implicitly in the compiler.
73 It may be NULL_TREE when this is invalid (for instance runtime is not
4ee9c684 74 required to implement the function call in all cases). */
0a68165a 75tree implicit_built_in_decls[(int) END_BUILTINS];
df94cd3b 76
aecda0d6 77static const char *c_getstr (tree);
78static rtx c_readstr (const char *, enum machine_mode);
79static int target_char_cast (tree, char *);
d8ae1baa 80static rtx get_memory_rtx (tree, tree);
aecda0d6 81static int apply_args_size (void);
82static int apply_result_size (void);
d8c9779c 83#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
aecda0d6 84static rtx result_vector (int, rtx);
d8c9779c 85#endif
843d08a9 86static void expand_builtin_update_setjmp_buf (rtx);
aecda0d6 87static void expand_builtin_prefetch (tree);
88static rtx expand_builtin_apply_args (void);
89static rtx expand_builtin_apply_args_1 (void);
90static rtx expand_builtin_apply (rtx, rtx, rtx);
91static void expand_builtin_return (rtx);
92static enum type_class type_to_class (tree);
93static rtx expand_builtin_classify_type (tree);
94static void expand_errno_check (tree, rtx);
95static rtx expand_builtin_mathfn (tree, rtx, rtx);
96static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
6b43bae4 97static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
a67a90e5 98static rtx expand_builtin_interclass_mathfn (tree, rtx, rtx);
c3147c1a 99static rtx expand_builtin_sincos (tree);
d735c391 100static rtx expand_builtin_cexpi (tree, rtx, rtx);
ad52b9b7 101static rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
7d3afc77 102static rtx expand_builtin_int_roundingfn_2 (tree, rtx, rtx);
aecda0d6 103static rtx expand_builtin_args_info (tree);
79012a9d 104static rtx expand_builtin_next_arg (void);
aecda0d6 105static rtx expand_builtin_va_start (tree);
106static rtx expand_builtin_va_end (tree);
107static rtx expand_builtin_va_copy (tree);
7959b13b 108static rtx expand_builtin_memchr (tree, rtx, enum machine_mode);
c2f47e15 109static rtx expand_builtin_memcmp (tree, rtx, enum machine_mode);
aecda0d6 110static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
111static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
112static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
7da1412b 113static rtx expand_builtin_strcat (tree, tree, rtx, enum machine_mode);
aecda0d6 114static rtx expand_builtin_strncat (tree, rtx, enum machine_mode);
115static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
116static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
117static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
c2f47e15 118static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode);
119static rtx expand_builtin_mempcpy_args (tree, tree, tree, tree, rtx,
120 enum machine_mode, int);
121static rtx expand_builtin_memmove (tree, rtx, enum machine_mode, int);
122static rtx expand_builtin_memmove_args (tree, tree, tree, tree, rtx,
123 enum machine_mode, int);
124static rtx expand_builtin_bcopy (tree, int);
1d89860b 125static rtx expand_builtin_strcpy (tree, tree, rtx, enum machine_mode);
c2f47e15 126static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx, enum machine_mode);
aecda0d6 127static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
aecda0d6 128static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
aecda0d6 129static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
c2f47e15 130static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
131static rtx expand_builtin_memset_args (tree, tree, tree, rtx, enum machine_mode, tree);
aecda0d6 132static rtx expand_builtin_bzero (tree);
133static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
c2f47e15 134static rtx expand_builtin_strstr (tree, rtx, enum machine_mode);
135static rtx expand_builtin_strpbrk (tree, rtx, enum machine_mode);
136static rtx expand_builtin_strchr (tree, rtx, enum machine_mode);
137static rtx expand_builtin_strrchr (tree, rtx, enum machine_mode);
aecda0d6 138static rtx expand_builtin_alloca (tree, rtx);
139static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
140static rtx expand_builtin_frame_address (tree, tree);
19bf118a 141static rtx expand_builtin_fputs (tree, rtx, bool);
142static rtx expand_builtin_printf (tree, rtx, enum machine_mode, bool);
143static rtx expand_builtin_fprintf (tree, rtx, enum machine_mode, bool);
6411575e 144static rtx expand_builtin_sprintf (tree, rtx, enum machine_mode);
aecda0d6 145static tree stabilize_va_list (tree, int);
146static rtx expand_builtin_expect (tree, rtx);
147static tree fold_builtin_constant_p (tree);
76f5a783 148static tree fold_builtin_expect (tree, tree);
aecda0d6 149static tree fold_builtin_classify_type (tree);
e6e27594 150static tree fold_builtin_strlen (tree);
aecda0d6 151static tree fold_builtin_inf (tree, int);
152static tree fold_builtin_nan (tree, tree, int);
c2f47e15 153static tree rewrite_call_expr (tree, int, tree, int, ...);
b7bf20db 154static bool validate_arg (const_tree, enum tree_code code);
277f8dd2 155static bool integer_valued_real_p (tree);
76b9b24b 156static tree fold_trunc_transparent_mathfn (tree, tree);
aecda0d6 157static bool readonly_data_expr (tree);
158static rtx expand_builtin_fabs (tree, rtx, rtx);
27f261ef 159static rtx expand_builtin_signbit (tree, rtx);
e6e27594 160static tree fold_builtin_sqrt (tree, tree);
161static tree fold_builtin_cbrt (tree, tree);
c2f47e15 162static tree fold_builtin_pow (tree, tree, tree, tree);
163static tree fold_builtin_powi (tree, tree, tree, tree);
e6e27594 164static tree fold_builtin_cos (tree, tree, tree);
cacdc1af 165static tree fold_builtin_cosh (tree, tree, tree);
bffb7645 166static tree fold_builtin_tan (tree, tree);
7169af54 167static tree fold_builtin_trunc (tree, tree);
168static tree fold_builtin_floor (tree, tree);
169static tree fold_builtin_ceil (tree, tree);
170static tree fold_builtin_round (tree, tree);
ad52b9b7 171static tree fold_builtin_int_roundingfn (tree, tree);
10b9666f 172static tree fold_builtin_bitop (tree, tree);
c2f47e15 173static tree fold_builtin_memory_op (tree, tree, tree, tree, bool, int);
174static tree fold_builtin_strchr (tree, tree, tree);
7959b13b 175static tree fold_builtin_memchr (tree, tree, tree, tree);
c2f47e15 176static tree fold_builtin_memcmp (tree, tree, tree);
177static tree fold_builtin_strcmp (tree, tree);
178static tree fold_builtin_strncmp (tree, tree, tree);
64c18e8d 179static tree fold_builtin_signbit (tree, tree);
c2f47e15 180static tree fold_builtin_copysign (tree, tree, tree, tree);
467214fd 181static tree fold_builtin_isascii (tree);
182static tree fold_builtin_toascii (tree);
183static tree fold_builtin_isdigit (tree);
d1aade50 184static tree fold_builtin_fabs (tree, tree);
185static tree fold_builtin_abs (tree, tree);
c2f47e15 186static tree fold_builtin_unordered_cmp (tree, tree, tree, enum tree_code,
d5019fe8 187 enum tree_code);
c2f47e15 188static tree fold_builtin_n (tree, tree *, int, bool);
189static tree fold_builtin_0 (tree, bool);
3d3d84b8 190static tree fold_builtin_1 (tree, tree, bool);
c2f47e15 191static tree fold_builtin_2 (tree, tree, tree, bool);
192static tree fold_builtin_3 (tree, tree, tree, tree, bool);
193static tree fold_builtin_4 (tree, tree, tree, tree, tree, bool);
194static tree fold_builtin_varargs (tree, tree, bool);
195
196static tree fold_builtin_strpbrk (tree, tree, tree);
197static tree fold_builtin_strstr (tree, tree, tree);
198static tree fold_builtin_strrchr (tree, tree, tree);
199static tree fold_builtin_strcat (tree, tree);
200static tree fold_builtin_strncat (tree, tree, tree);
201static tree fold_builtin_strspn (tree, tree);
202static tree fold_builtin_strcspn (tree, tree);
203static tree fold_builtin_sprintf (tree, tree, tree, int);
4ee9c684 204
0a39fd54 205static rtx expand_builtin_object_size (tree);
206static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
207 enum built_in_function);
208static void maybe_emit_chk_warning (tree, enum built_in_function);
209static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
c2f47e15 210static tree fold_builtin_object_size (tree, tree);
211static tree fold_builtin_strcat_chk (tree, tree, tree, tree);
212static tree fold_builtin_strncat_chk (tree, tree, tree, tree, tree);
0a39fd54 213static tree fold_builtin_sprintf_chk (tree, enum built_in_function);
c2f47e15 214static tree fold_builtin_printf (tree, tree, tree, bool, enum built_in_function);
215static tree fold_builtin_fprintf (tree, tree, tree, tree, bool,
216 enum built_in_function);
99eabcc1 217static bool init_target_chars (void);
218
219static unsigned HOST_WIDE_INT target_newline;
220static unsigned HOST_WIDE_INT target_percent;
221static unsigned HOST_WIDE_INT target_c;
222static unsigned HOST_WIDE_INT target_s;
223static char target_percent_c[3];
224static char target_percent_s[3];
225static char target_percent_s_newline[4];
728bac60 226static tree do_mpfr_arg1 (tree, tree, int (*)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
227 const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, bool);
f0c477f2 228static tree do_mpfr_arg2 (tree, tree, tree,
229 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
9917422b 230static tree do_mpfr_arg3 (tree, tree, tree, tree,
231 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
d92f994c 232static tree do_mpfr_sincos (tree, tree, tree);
65dd1378 233#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
234static tree do_mpfr_bessel_n (tree, tree, tree,
235 int (*)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
236 const REAL_VALUE_TYPE *, bool);
e5407ca6 237static tree do_mpfr_remquo (tree, tree, tree);
e84da7c1 238static tree do_mpfr_lgamma_r (tree, tree, tree);
65dd1378 239#endif
0a39fd54 240
b6a5fc45 241/* Return true if NODE should be considered for inline expansion regardless
242 of the optimization level. This means whenever a function is invoked with
243 its "internal" name, which normally contains the prefix "__builtin". */
244
245static bool called_as_built_in (tree node)
246{
247 const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
248 if (strncmp (name, "__builtin_", 10) == 0)
249 return true;
250 if (strncmp (name, "__sync_", 7) == 0)
251 return true;
252 return false;
253}
4ee9c684 254
53800dbe 255/* Return the alignment in bits of EXP, a pointer valued expression.
256 But don't return more than MAX_ALIGN no matter what.
257 The alignment returned is, by default, the alignment of the thing that
27d0c333 258 EXP points to. If it is not a POINTER_TYPE, 0 is returned.
53800dbe 259
260 Otherwise, look at the expression to see if we can do better, i.e., if the
261 expression is actually pointing at an object whose alignment is tighter. */
262
f656b751 263int
aecda0d6 264get_pointer_alignment (tree exp, unsigned int max_align)
53800dbe 265{
27d0c333 266 unsigned int align, inner;
53800dbe 267
189575ff 268 /* We rely on TER to compute accurate alignment information. */
269 if (!(optimize && flag_tree_ter))
270 return 0;
271
535e2026 272 if (!POINTER_TYPE_P (TREE_TYPE (exp)))
273 return 0;
274
53800dbe 275 align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
276 align = MIN (align, max_align);
277
278 while (1)
279 {
280 switch (TREE_CODE (exp))
281 {
72dd6141 282 CASE_CONVERT:
53800dbe 283 exp = TREE_OPERAND (exp, 0);
552752f7 284 if (! POINTER_TYPE_P (TREE_TYPE (exp)))
53800dbe 285 return align;
325d1c45 286
53800dbe 287 inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
288 align = MIN (inner, max_align);
289 break;
290
0de36bdb 291 case POINTER_PLUS_EXPR:
53800dbe 292 /* If sum of pointer + int, restrict our maximum alignment to that
293 imposed by the integer. If not, we can't do any better than
294 ALIGN. */
325d1c45 295 if (! host_integerp (TREE_OPERAND (exp, 1), 1))
53800dbe 296 return align;
297
0994d2ed 298 while (((tree_low_cst (TREE_OPERAND (exp, 1), 1))
299 & (max_align / BITS_PER_UNIT - 1))
53800dbe 300 != 0)
301 max_align >>= 1;
302
303 exp = TREE_OPERAND (exp, 0);
304 break;
305
306 case ADDR_EXPR:
307 /* See what we are pointing at and look at its alignment. */
308 exp = TREE_OPERAND (exp, 0);
3c15318e 309 inner = max_align;
d2df7679 310 if (handled_component_p (exp))
1eee24cf 311 {
d2df7679 312 HOST_WIDE_INT bitsize, bitpos;
313 tree offset;
314 enum machine_mode mode;
315 int unsignedp, volatilep;
316
317 exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
318 &mode, &unsignedp, &volatilep, true);
319 if (bitpos)
320 inner = MIN (inner, (unsigned) (bitpos & -bitpos));
321 if (offset && TREE_CODE (offset) == PLUS_EXPR
322 && host_integerp (TREE_OPERAND (offset, 1), 1))
323 {
324 /* Any overflow in calculating offset_bits won't change
325 the alignment. */
326 unsigned offset_bits
327 = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
328 * BITS_PER_UNIT);
329
330 if (offset_bits)
331 inner = MIN (inner, (offset_bits & -offset_bits));
332 offset = TREE_OPERAND (offset, 0);
333 }
334 if (offset && TREE_CODE (offset) == MULT_EXPR
335 && host_integerp (TREE_OPERAND (offset, 1), 1))
336 {
337 /* Any overflow in calculating offset_factor won't change
338 the alignment. */
339 unsigned offset_factor
340 = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
341 * BITS_PER_UNIT);
342
343 if (offset_factor)
344 inner = MIN (inner, (offset_factor & -offset_factor));
345 }
346 else if (offset)
347 inner = MIN (inner, BITS_PER_UNIT);
1eee24cf 348 }
6c96b31e 349 if (DECL_P (exp))
3c15318e 350 align = MIN (inner, DECL_ALIGN (exp));
53800dbe 351#ifdef CONSTANT_ALIGNMENT
ce45a448 352 else if (CONSTANT_CLASS_P (exp))
e068b646 353 align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align));
53800dbe 354#endif
d2df7679 355 else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR
356 || TREE_CODE (exp) == INDIRECT_REF)
357 align = MIN (TYPE_ALIGN (TREE_TYPE (exp)), inner);
3c15318e 358 else
359 align = MIN (align, inner);
360 return MIN (align, max_align);
53800dbe 361
362 default:
363 return align;
364 }
365 }
366}
367
368/* Compute the length of a C string. TREE_STRING_LENGTH is not the right
369 way, because it could contain a zero byte in the middle.
370 TREE_STRING_LENGTH is the size of the character array, not the string.
371
4172d65e 372 ONLY_VALUE should be nonzero if the result is not going to be emitted
c09841f6 373 into the instruction stream and zero if it is going to be expanded.
4172d65e 374 E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
681fab1e 375 is returned, otherwise NULL, since
376 len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
377 evaluate the side-effects.
378
902de8ed 379 The value returned is of type `ssizetype'.
380
53800dbe 381 Unfortunately, string_constant can't access the values of const char
382 arrays with initializers, so neither can we do so here. */
383
4ee9c684 384tree
681fab1e 385c_strlen (tree src, int only_value)
53800dbe 386{
387 tree offset_node;
27d0c333 388 HOST_WIDE_INT offset;
389 int max;
44acf429 390 const char *ptr;
53800dbe 391
681fab1e 392 STRIP_NOPS (src);
393 if (TREE_CODE (src) == COND_EXPR
394 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
395 {
396 tree len1, len2;
397
398 len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
399 len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
0862b7e9 400 if (tree_int_cst_equal (len1, len2))
681fab1e 401 return len1;
402 }
403
404 if (TREE_CODE (src) == COMPOUND_EXPR
405 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
406 return c_strlen (TREE_OPERAND (src, 1), only_value);
407
53800dbe 408 src = string_constant (src, &offset_node);
409 if (src == 0)
c2f47e15 410 return NULL_TREE;
902de8ed 411
83d79705 412 max = TREE_STRING_LENGTH (src) - 1;
53800dbe 413 ptr = TREE_STRING_POINTER (src);
902de8ed 414
53800dbe 415 if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
416 {
417 /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
418 compute the offset to the following null if we don't know where to
419 start searching for it. */
420 int i;
902de8ed 421
53800dbe 422 for (i = 0; i < max; i++)
423 if (ptr[i] == 0)
c2f47e15 424 return NULL_TREE;
902de8ed 425
53800dbe 426 /* We don't know the starting offset, but we do know that the string
427 has no internal zero bytes. We can assume that the offset falls
428 within the bounds of the string; otherwise, the programmer deserves
429 what he gets. Subtract the offset from the length of the string,
902de8ed 430 and return that. This would perhaps not be valid if we were dealing
431 with named arrays in addition to literal string constants. */
432
433 return size_diffop (size_int (max), offset_node);
53800dbe 434 }
435
436 /* We have a known offset into the string. Start searching there for
27d0c333 437 a null character if we can represent it as a single HOST_WIDE_INT. */
dabc4084 438 if (offset_node == 0)
53800dbe 439 offset = 0;
dabc4084 440 else if (! host_integerp (offset_node, 0))
441 offset = -1;
53800dbe 442 else
27d0c333 443 offset = tree_low_cst (offset_node, 0);
902de8ed 444
53800dbe 445 /* If the offset is known to be out of bounds, warn, and call strlen at
446 runtime. */
447 if (offset < 0 || offset > max)
448 {
7e3b64b4 449 /* Suppress multiple warnings for propagated constant strings. */
450 if (! TREE_NO_WARNING (src))
451 {
452 warning (0, "offset outside bounds of constant string");
453 TREE_NO_WARNING (src) = 1;
454 }
c2f47e15 455 return NULL_TREE;
53800dbe 456 }
902de8ed 457
53800dbe 458 /* Use strlen to search for the first zero byte. Since any strings
459 constructed with build_string will have nulls appended, we win even
460 if we get handed something like (char[4])"abcd".
461
462 Since OFFSET is our starting index into the string, no further
463 calculation is needed. */
902de8ed 464 return ssize_int (strlen (ptr + offset));
53800dbe 465}
466
83d79705 467/* Return a char pointer for a C string if it is a string constant
468 or sum of string constant and integer constant. */
469
470static const char *
aecda0d6 471c_getstr (tree src)
83d79705 472{
473 tree offset_node;
83d79705 474
475 src = string_constant (src, &offset_node);
476 if (src == 0)
477 return 0;
478
8c85fcb7 479 if (offset_node == 0)
480 return TREE_STRING_POINTER (src);
481 else if (!host_integerp (offset_node, 1)
482 || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
83d79705 483 return 0;
83d79705 484
8c85fcb7 485 return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
83d79705 486}
487
8c85fcb7 488/* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
489 GET_MODE_BITSIZE (MODE) bits from string constant STR. */
ecc318ff 490
6840589f 491static rtx
aecda0d6 492c_readstr (const char *str, enum machine_mode mode)
6840589f 493{
494 HOST_WIDE_INT c[2];
495 HOST_WIDE_INT ch;
496 unsigned int i, j;
497
64db345d 498 gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
7d3f6cc7 499
6840589f 500 c[0] = 0;
501 c[1] = 0;
502 ch = 1;
503 for (i = 0; i < GET_MODE_SIZE (mode); i++)
504 {
505 j = i;
506 if (WORDS_BIG_ENDIAN)
507 j = GET_MODE_SIZE (mode) - i - 1;
508 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
509 && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
510 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
511 j *= BITS_PER_UNIT;
64db345d 512 gcc_assert (j <= 2 * HOST_BITS_PER_WIDE_INT);
7d3f6cc7 513
6840589f 514 if (ch)
515 ch = (unsigned char) str[i];
516 c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
517 }
518 return immed_double_const (c[0], c[1], mode);
519}
520
ecc318ff 521/* Cast a target constant CST to target CHAR and if that value fits into
5206b159 522 host char type, return zero and put that value into variable pointed to by
ecc318ff 523 P. */
524
525static int
aecda0d6 526target_char_cast (tree cst, char *p)
ecc318ff 527{
528 unsigned HOST_WIDE_INT val, hostval;
529
27d0c333 530 if (!host_integerp (cst, 1)
ecc318ff 531 || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
532 return 1;
533
27d0c333 534 val = tree_low_cst (cst, 1);
ecc318ff 535 if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
536 val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
537
538 hostval = val;
539 if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
540 hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
541
542 if (val != hostval)
543 return 1;
544
545 *p = hostval;
546 return 0;
547}
548
4ee9c684 549/* Similar to save_expr, but assumes that arbitrary code is not executed
550 in between the multiple evaluations. In particular, we assume that a
551 non-addressable local variable will not be modified. */
552
553static tree
554builtin_save_expr (tree exp)
555{
556 if (TREE_ADDRESSABLE (exp) == 0
557 && (TREE_CODE (exp) == PARM_DECL
558 || (TREE_CODE (exp) == VAR_DECL && !TREE_STATIC (exp))))
559 return exp;
560
561 return save_expr (exp);
562}
563
53800dbe 564/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
565 times to get the address of either a higher stack frame, or a return
566 address located within it (depending on FNDECL_CODE). */
902de8ed 567
c626df3d 568static rtx
869d0ef0 569expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
53800dbe 570{
571 int i;
572
869d0ef0 573#ifdef INITIAL_FRAME_ADDRESS_RTX
574 rtx tem = INITIAL_FRAME_ADDRESS_RTX;
575#else
e3e15c50 576 rtx tem;
577
1b74fde7 578 /* For a zero count with __builtin_return_address, we don't care what
579 frame address we return, because target-specific definitions will
580 override us. Therefore frame pointer elimination is OK, and using
581 the soft frame pointer is OK.
582
fa7637bd 583 For a nonzero count, or a zero count with __builtin_frame_address,
1b74fde7 584 we require a stable offset from the current frame pointer to the
585 previous one, so we must use the hard frame pointer, and
e3e15c50 586 we must disable frame pointer elimination. */
1b74fde7 587 if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
e3e15c50 588 tem = frame_pointer_rtx;
a0c938f0 589 else
e3e15c50 590 {
591 tem = hard_frame_pointer_rtx;
592
593 /* Tell reload not to eliminate the frame pointer. */
18d50ae6 594 crtl->accesses_prior_frames = 1;
e3e15c50 595 }
869d0ef0 596#endif
597
53800dbe 598 /* Some machines need special handling before we can access
3a69c60c 599 arbitrary frames. For example, on the SPARC, we must first flush
53800dbe 600 all register windows to the stack. */
601#ifdef SETUP_FRAME_ADDRESSES
602 if (count > 0)
603 SETUP_FRAME_ADDRESSES ();
604#endif
605
3a69c60c 606 /* On the SPARC, the return address is not in the frame, it is in a
53800dbe 607 register. There is no way to access it off of the current frame
608 pointer, but it can be accessed off the previous frame pointer by
609 reading the value from the register window save area. */
610#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
611 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
612 count--;
613#endif
614
615 /* Scan back COUNT frames to the specified frame. */
616 for (i = 0; i < count; i++)
617 {
618 /* Assume the dynamic chain pointer is in the word that the
619 frame address points to, unless otherwise specified. */
620#ifdef DYNAMIC_CHAIN_ADDRESS
621 tem = DYNAMIC_CHAIN_ADDRESS (tem);
622#endif
623 tem = memory_address (Pmode, tem);
00060fc2 624 tem = gen_frame_mem (Pmode, tem);
83fc1478 625 tem = copy_to_reg (tem);
53800dbe 626 }
627
3a69c60c 628 /* For __builtin_frame_address, return what we've got. But, on
629 the SPARC for example, we may have to add a bias. */
53800dbe 630 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
3a69c60c 631#ifdef FRAME_ADDR_RTX
632 return FRAME_ADDR_RTX (tem);
633#else
53800dbe 634 return tem;
3a69c60c 635#endif
53800dbe 636
3a69c60c 637 /* For __builtin_return_address, get the return address from that frame. */
53800dbe 638#ifdef RETURN_ADDR_RTX
639 tem = RETURN_ADDR_RTX (count, tem);
640#else
641 tem = memory_address (Pmode,
642 plus_constant (tem, GET_MODE_SIZE (Pmode)));
00060fc2 643 tem = gen_frame_mem (Pmode, tem);
53800dbe 644#endif
645 return tem;
646}
647
f7c44134 648/* Alias set used for setjmp buffer. */
32c2fdea 649static alias_set_type setjmp_alias_set = -1;
f7c44134 650
6b7f6858 651/* Construct the leading half of a __builtin_setjmp call. Control will
2c8a1497 652 return to RECEIVER_LABEL. This is also called directly by the SJLJ
653 exception handling code. */
53800dbe 654
6b7f6858 655void
aecda0d6 656expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
53800dbe 657{
53800dbe 658 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
53800dbe 659 rtx stack_save;
f7c44134 660 rtx mem;
53800dbe 661
f7c44134 662 if (setjmp_alias_set == -1)
663 setjmp_alias_set = new_alias_set ();
664
85d654dd 665 buf_addr = convert_memory_address (Pmode, buf_addr);
53800dbe 666
37ae8504 667 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
53800dbe 668
6b7f6858 669 /* We store the frame pointer and the address of receiver_label in
670 the buffer and use the rest of it for the stack save area, which
671 is machine-dependent. */
53800dbe 672
f7c44134 673 mem = gen_rtx_MEM (Pmode, buf_addr);
ab6ab77e 674 set_mem_alias_set (mem, setjmp_alias_set);
e3e026e8 675 emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
f7c44134 676
677 mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
ab6ab77e 678 set_mem_alias_set (mem, setjmp_alias_set);
f7c44134 679
680 emit_move_insn (validize_mem (mem),
6b7f6858 681 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
53800dbe 682
683 stack_save = gen_rtx_MEM (sa_mode,
684 plus_constant (buf_addr,
685 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 686 set_mem_alias_set (stack_save, setjmp_alias_set);
53800dbe 687 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
688
689 /* If there is further processing to do, do it. */
690#ifdef HAVE_builtin_setjmp_setup
691 if (HAVE_builtin_setjmp_setup)
692 emit_insn (gen_builtin_setjmp_setup (buf_addr));
693#endif
694
6b7f6858 695 /* Tell optimize_save_area_alloca that extra work is going to
696 need to go on during alloca. */
18d50ae6 697 cfun->calls_setjmp = 1;
80ab81b9 698
29f09705 699 /* We have a nonlocal label. */
18d50ae6 700 cfun->has_nonlocal_label = 1;
6b7f6858 701}
53800dbe 702
2c8a1497 703/* Construct the trailing part of a __builtin_setjmp call. This is
704 also called directly by the SJLJ exception handling code. */
6b7f6858 705
706void
aecda0d6 707expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
6b7f6858 708{
53800dbe 709 /* Clobber the FP when we get here, so we have to make sure it's
710 marked as used by this function. */
18b42941 711 emit_use (hard_frame_pointer_rtx);
53800dbe 712
713 /* Mark the static chain as clobbered here so life information
714 doesn't get messed up for it. */
18b42941 715 emit_clobber (static_chain_rtx);
53800dbe 716
717 /* Now put in the code to restore the frame pointer, and argument
491e04ef 718 pointer, if needed. */
53800dbe 719#ifdef HAVE_nonlocal_goto
720 if (! HAVE_nonlocal_goto)
721#endif
5a1c3f40 722 {
723 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
724 /* This might change the hard frame pointer in ways that aren't
725 apparent to early optimization passes, so force a clobber. */
18b42941 726 emit_clobber (hard_frame_pointer_rtx);
5a1c3f40 727 }
53800dbe 728
729#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
730 if (fixed_regs[ARG_POINTER_REGNUM])
731 {
732#ifdef ELIMINABLE_REGS
733 size_t i;
e99c3a1d 734 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
53800dbe 735
3098b2d3 736 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
53800dbe 737 if (elim_regs[i].from == ARG_POINTER_REGNUM
738 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
739 break;
740
3098b2d3 741 if (i == ARRAY_SIZE (elim_regs))
53800dbe 742#endif
743 {
744 /* Now restore our arg pointer from the address at which it
05927e40 745 was saved in our stack frame. */
53800dbe 746 emit_move_insn (virtual_incoming_args_rtx,
b079a207 747 copy_to_reg (get_arg_pointer_save_area ()));
53800dbe 748 }
749 }
750#endif
751
752#ifdef HAVE_builtin_setjmp_receiver
753 if (HAVE_builtin_setjmp_receiver)
6b7f6858 754 emit_insn (gen_builtin_setjmp_receiver (receiver_label));
53800dbe 755 else
756#endif
757#ifdef HAVE_nonlocal_goto_receiver
758 if (HAVE_nonlocal_goto_receiver)
759 emit_insn (gen_nonlocal_goto_receiver ());
760 else
761#endif
6b7f6858 762 { /* Nothing */ }
57f6bb94 763
3072d30e 764 /* We must not allow the code we just generated to be reordered by
765 scheduling. Specifically, the update of the frame pointer must
766 happen immediately, not later. */
767 emit_insn (gen_blockage ());
6b7f6858 768}
53800dbe 769
53800dbe 770/* __builtin_longjmp is passed a pointer to an array of five words (not
771 all will be used on all machines). It operates similarly to the C
772 library function of the same name, but is more efficient. Much of
2c8a1497 773 the code below is copied from the handling of non-local gotos. */
53800dbe 774
c626df3d 775static void
aecda0d6 776expand_builtin_longjmp (rtx buf_addr, rtx value)
53800dbe 777{
4712c7d6 778 rtx fp, lab, stack, insn, last;
53800dbe 779 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
780
f7c44134 781 if (setjmp_alias_set == -1)
782 setjmp_alias_set = new_alias_set ();
783
85d654dd 784 buf_addr = convert_memory_address (Pmode, buf_addr);
479e4d5e 785
53800dbe 786 buf_addr = force_reg (Pmode, buf_addr);
787
788 /* We used to store value in static_chain_rtx, but that fails if pointers
789 are smaller than integers. We instead require that the user must pass
790 a second argument of 1, because that is what builtin_setjmp will
791 return. This also makes EH slightly more efficient, since we are no
792 longer copying around a value that we don't care about. */
64db345d 793 gcc_assert (value == const1_rtx);
53800dbe 794
4712c7d6 795 last = get_last_insn ();
53800dbe 796#ifdef HAVE_builtin_longjmp
797 if (HAVE_builtin_longjmp)
798 emit_insn (gen_builtin_longjmp (buf_addr));
799 else
800#endif
801 {
802 fp = gen_rtx_MEM (Pmode, buf_addr);
803 lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
804 GET_MODE_SIZE (Pmode)));
805
806 stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
807 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 808 set_mem_alias_set (fp, setjmp_alias_set);
809 set_mem_alias_set (lab, setjmp_alias_set);
810 set_mem_alias_set (stack, setjmp_alias_set);
53800dbe 811
812 /* Pick up FP, label, and SP from the block and jump. This code is
813 from expand_goto in stmt.c; see there for detailed comments. */
03fd9d2c 814#ifdef HAVE_nonlocal_goto
53800dbe 815 if (HAVE_nonlocal_goto)
816 /* We have to pass a value to the nonlocal_goto pattern that will
817 get copied into the static_chain pointer, but it does not matter
818 what that value is, because builtin_setjmp does not use it. */
28d202a8 819 emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
53800dbe 820 else
821#endif
822 {
823 lab = copy_to_reg (lab);
824
18b42941 825 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
826 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
2a871ad1 827
53800dbe 828 emit_move_insn (hard_frame_pointer_rtx, fp);
829 emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
830
18b42941 831 emit_use (hard_frame_pointer_rtx);
832 emit_use (stack_pointer_rtx);
53800dbe 833 emit_indirect_jump (lab);
834 }
835 }
615166bb 836
837 /* Search backwards and mark the jump insn as a non-local goto.
838 Note that this precludes the use of __builtin_longjmp to a
839 __builtin_setjmp target in the same function. However, we've
840 already cautioned the user that these functions are for
841 internal exception handling use only. */
449c0509 842 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
843 {
64db345d 844 gcc_assert (insn != last);
7d3f6cc7 845
6d7dc5b9 846 if (JUMP_P (insn))
449c0509 847 {
a1ddb869 848 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
449c0509 849 break;
850 }
6d7dc5b9 851 else if (CALL_P (insn))
9342ee68 852 break;
449c0509 853 }
53800dbe 854}
855
4ee9c684 856/* Expand a call to __builtin_nonlocal_goto. We're passed the target label
857 and the address of the save area. */
858
859static rtx
c2f47e15 860expand_builtin_nonlocal_goto (tree exp)
4ee9c684 861{
862 tree t_label, t_save_area;
863 rtx r_label, r_save_area, r_fp, r_sp, insn;
864
c2f47e15 865 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4ee9c684 866 return NULL_RTX;
867
c2f47e15 868 t_label = CALL_EXPR_ARG (exp, 0);
869 t_save_area = CALL_EXPR_ARG (exp, 1);
4ee9c684 870
8ec3c5c2 871 r_label = expand_normal (t_label);
3dce56cc 872 r_label = convert_memory_address (Pmode, r_label);
8ec3c5c2 873 r_save_area = expand_normal (t_save_area);
3dce56cc 874 r_save_area = convert_memory_address (Pmode, r_save_area);
51adbc8a 875 /* Copy the address of the save location to a register just in case it was based
876 on the frame pointer. */
877 r_save_area = copy_to_reg (r_save_area);
4ee9c684 878 r_fp = gen_rtx_MEM (Pmode, r_save_area);
879 r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
880 plus_constant (r_save_area, GET_MODE_SIZE (Pmode)));
881
18d50ae6 882 crtl->has_nonlocal_goto = 1;
4ee9c684 883
03fd9d2c 884#ifdef HAVE_nonlocal_goto
4ee9c684 885 /* ??? We no longer need to pass the static chain value, afaik. */
886 if (HAVE_nonlocal_goto)
887 emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
888 else
889#endif
890 {
891 r_label = copy_to_reg (r_label);
892
18b42941 893 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
894 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
491e04ef 895
4ee9c684 896 /* Restore frame pointer for containing function.
897 This sets the actual hard register used for the frame pointer
898 to the location of the function's incoming static chain info.
899 The non-local goto handler will then adjust it to contain the
900 proper value and reload the argument pointer, if needed. */
901 emit_move_insn (hard_frame_pointer_rtx, r_fp);
902 emit_stack_restore (SAVE_NONLOCAL, r_sp, NULL_RTX);
491e04ef 903
4ee9c684 904 /* USE of hard_frame_pointer_rtx added for consistency;
905 not clear if really needed. */
18b42941 906 emit_use (hard_frame_pointer_rtx);
907 emit_use (stack_pointer_rtx);
ad0d0af8 908
909 /* If the architecture is using a GP register, we must
910 conservatively assume that the target function makes use of it.
911 The prologue of functions with nonlocal gotos must therefore
912 initialize the GP register to the appropriate value, and we
913 must then make sure that this value is live at the point
914 of the jump. (Note that this doesn't necessarily apply
915 to targets with a nonlocal_goto pattern; they are free
916 to implement it in their own way. Note also that this is
917 a no-op if the GP register is a global invariant.) */
918 if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
919 && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
18b42941 920 emit_use (pic_offset_table_rtx);
ad0d0af8 921
4ee9c684 922 emit_indirect_jump (r_label);
923 }
491e04ef 924
4ee9c684 925 /* Search backwards to the jump insn and mark it as a
926 non-local goto. */
927 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
928 {
6d7dc5b9 929 if (JUMP_P (insn))
4ee9c684 930 {
a1ddb869 931 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
4ee9c684 932 break;
933 }
6d7dc5b9 934 else if (CALL_P (insn))
4ee9c684 935 break;
936 }
937
938 return const0_rtx;
939}
940
843d08a9 941/* __builtin_update_setjmp_buf is passed a pointer to an array of five words
942 (not all will be used on all machines) that was passed to __builtin_setjmp.
943 It updates the stack pointer in that block to correspond to the current
944 stack pointer. */
945
946static void
947expand_builtin_update_setjmp_buf (rtx buf_addr)
948{
949 enum machine_mode sa_mode = Pmode;
950 rtx stack_save;
951
952
953#ifdef HAVE_save_stack_nonlocal
954 if (HAVE_save_stack_nonlocal)
955 sa_mode = insn_data[(int) CODE_FOR_save_stack_nonlocal].operand[0].mode;
956#endif
957#ifdef STACK_SAVEAREA_MODE
958 sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
959#endif
960
961 stack_save
962 = gen_rtx_MEM (sa_mode,
963 memory_address
964 (sa_mode,
965 plus_constant (buf_addr, 2 * GET_MODE_SIZE (Pmode))));
966
967#ifdef HAVE_setjmp
968 if (HAVE_setjmp)
969 emit_insn (gen_setjmp ());
970#endif
971
972 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
973}
974
5e3608d8 975/* Expand a call to __builtin_prefetch. For a target that does not support
976 data prefetch, evaluate the memory address argument in case it has side
977 effects. */
978
979static void
c2f47e15 980expand_builtin_prefetch (tree exp)
5e3608d8 981{
982 tree arg0, arg1, arg2;
c2f47e15 983 int nargs;
5e3608d8 984 rtx op0, op1, op2;
985
c2f47e15 986 if (!validate_arglist (exp, POINTER_TYPE, 0))
26a5cadb 987 return;
988
c2f47e15 989 arg0 = CALL_EXPR_ARG (exp, 0);
990
26a5cadb 991 /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
992 zero (read) and argument 2 (locality) defaults to 3 (high degree of
993 locality). */
c2f47e15 994 nargs = call_expr_nargs (exp);
995 if (nargs > 1)
996 arg1 = CALL_EXPR_ARG (exp, 1);
26a5cadb 997 else
c2f47e15 998 arg1 = integer_zero_node;
999 if (nargs > 2)
1000 arg2 = CALL_EXPR_ARG (exp, 2);
1001 else
1002 arg2 = build_int_cst (NULL_TREE, 3);
5e3608d8 1003
1004 /* Argument 0 is an address. */
1005 op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
1006
1007 /* Argument 1 (read/write flag) must be a compile-time constant int. */
1008 if (TREE_CODE (arg1) != INTEGER_CST)
1009 {
07e3a3d2 1010 error ("second argument to %<__builtin_prefetch%> must be a constant");
9342ee68 1011 arg1 = integer_zero_node;
5e3608d8 1012 }
8ec3c5c2 1013 op1 = expand_normal (arg1);
5e3608d8 1014 /* Argument 1 must be either zero or one. */
1015 if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
1016 {
c3ceba8e 1017 warning (0, "invalid second argument to %<__builtin_prefetch%>;"
07e3a3d2 1018 " using zero");
5e3608d8 1019 op1 = const0_rtx;
1020 }
1021
1022 /* Argument 2 (locality) must be a compile-time constant int. */
1023 if (TREE_CODE (arg2) != INTEGER_CST)
1024 {
07e3a3d2 1025 error ("third argument to %<__builtin_prefetch%> must be a constant");
5e3608d8 1026 arg2 = integer_zero_node;
1027 }
8ec3c5c2 1028 op2 = expand_normal (arg2);
5e3608d8 1029 /* Argument 2 must be 0, 1, 2, or 3. */
1030 if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
1031 {
c3ceba8e 1032 warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
5e3608d8 1033 op2 = const0_rtx;
1034 }
1035
1036#ifdef HAVE_prefetch
1037 if (HAVE_prefetch)
1038 {
f0ce3b1f 1039 if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate)
4cd21437 1040 (op0,
f0ce3b1f 1041 insn_data[(int) CODE_FOR_prefetch].operand[0].mode))
19bf118a 1042 || (GET_MODE (op0) != Pmode))
9342ee68 1043 {
85d654dd 1044 op0 = convert_memory_address (Pmode, op0);
9342ee68 1045 op0 = force_reg (Pmode, op0);
1046 }
5e3608d8 1047 emit_insn (gen_prefetch (op0, op1, op2));
1048 }
5e3608d8 1049#endif
0a534ba7 1050
f0ce3b1f 1051 /* Don't do anything with direct references to volatile memory, but
1052 generate code to handle other side effects. */
e16ceb8e 1053 if (!MEM_P (op0) && side_effects_p (op0))
f0ce3b1f 1054 emit_insn (op0);
5e3608d8 1055}
1056
f7c44134 1057/* Get a MEM rtx for expression EXP which is the address of an operand
d8ae1baa 1058 to be used in a string instruction (cmpstrsi, movmemsi, ..). LEN is
1059 the maximum length of the block of memory that might be accessed or
1060 NULL if unknown. */
f7c44134 1061
53800dbe 1062static rtx
d8ae1baa 1063get_memory_rtx (tree exp, tree len)
53800dbe 1064{
bb2327a8 1065 rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
1066 rtx mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
2a631e19 1067
f7c44134 1068 /* Get an expression we can use to find the attributes to assign to MEM.
1069 If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
1070 we can. First remove any nops. */
72dd6141 1071 while (CONVERT_EXPR_P (exp)
f7c44134 1072 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
1073 exp = TREE_OPERAND (exp, 0);
1074
1075 if (TREE_CODE (exp) == ADDR_EXPR)
a1a25d19 1076 exp = TREE_OPERAND (exp, 0);
f7c44134 1077 else if (POINTER_TYPE_P (TREE_TYPE (exp)))
a1a25d19 1078 exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
1079 else
1080 exp = NULL;
1081
1082 /* Honor attributes derived from exp, except for the alias set
1083 (as builtin stringops may alias with anything) and the size
1084 (as stringops may access multiple array elements). */
1085 if (exp)
eec8e941 1086 {
a1a25d19 1087 set_mem_attributes (mem, exp, 0);
d8ae1baa 1088
1089 /* Allow the string and memory builtins to overflow from one
1090 field into another, see http://gcc.gnu.org/PR23561.
1091 Thus avoid COMPONENT_REFs in MEM_EXPR unless we know the whole
1092 memory accessed by the string or memory builtin will fit
1093 within the field. */
1094 if (MEM_EXPR (mem) && TREE_CODE (MEM_EXPR (mem)) == COMPONENT_REF)
1095 {
1096 tree mem_expr = MEM_EXPR (mem);
1097 HOST_WIDE_INT offset = -1, length = -1;
1098 tree inner = exp;
1099
1100 while (TREE_CODE (inner) == ARRAY_REF
72dd6141 1101 || CONVERT_EXPR_P (inner)
d8ae1baa 1102 || TREE_CODE (inner) == VIEW_CONVERT_EXPR
1103 || TREE_CODE (inner) == SAVE_EXPR)
1104 inner = TREE_OPERAND (inner, 0);
1105
1106 gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
1107
1108 if (MEM_OFFSET (mem)
1109 && GET_CODE (MEM_OFFSET (mem)) == CONST_INT)
1110 offset = INTVAL (MEM_OFFSET (mem));
1111
1112 if (offset >= 0 && len && host_integerp (len, 0))
1113 length = tree_low_cst (len, 0);
1114
1115 while (TREE_CODE (inner) == COMPONENT_REF)
1116 {
1117 tree field = TREE_OPERAND (inner, 1);
d8ae1baa 1118 gcc_assert (TREE_CODE (mem_expr) == COMPONENT_REF);
1119 gcc_assert (field == TREE_OPERAND (mem_expr, 1));
1120
6933ebec 1121 /* Bitfields are generally not byte-addressable. */
1122 gcc_assert (!DECL_BIT_FIELD (field)
1123 || ((tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
1124 % BITS_PER_UNIT) == 0
1125 && host_integerp (DECL_SIZE (field), 0)
1126 && (TREE_INT_CST_LOW (DECL_SIZE (field))
1127 % BITS_PER_UNIT) == 0));
1128
b2f0b2a3 1129 /* If we can prove that the memory starting at XEXP (mem, 0) and
1130 ending at XEXP (mem, 0) + LENGTH will fit into this field, we
1131 can keep the COMPONENT_REF in MEM_EXPR. But be careful with
1132 fields without DECL_SIZE_UNIT like flexible array members. */
d8ae1baa 1133 if (length >= 0
b2f0b2a3 1134 && DECL_SIZE_UNIT (field)
6933ebec 1135 && host_integerp (DECL_SIZE_UNIT (field), 0))
d8ae1baa 1136 {
1137 HOST_WIDE_INT size
6933ebec 1138 = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
d8ae1baa 1139 if (offset <= size
1140 && length <= size
1141 && offset + length <= size)
1142 break;
1143 }
1144
1145 if (offset >= 0
1146 && host_integerp (DECL_FIELD_OFFSET (field), 0))
6933ebec 1147 offset += TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
d8ae1baa 1148 + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
1149 / BITS_PER_UNIT;
1150 else
1151 {
1152 offset = -1;
1153 length = -1;
1154 }
1155
1156 mem_expr = TREE_OPERAND (mem_expr, 0);
1157 inner = TREE_OPERAND (inner, 0);
d8ae1baa 1158 }
1159
1160 if (mem_expr == NULL)
1161 offset = -1;
1162 if (mem_expr != MEM_EXPR (mem))
1163 {
1164 set_mem_expr (mem, mem_expr);
1165 set_mem_offset (mem, offset >= 0 ? GEN_INT (offset) : NULL_RTX);
1166 }
1167 }
eec8e941 1168 set_mem_alias_set (mem, 0);
a1a25d19 1169 set_mem_size (mem, NULL_RTX);
eec8e941 1170 }
53800dbe 1171
53800dbe 1172 return mem;
1173}
1174\f
1175/* Built-in functions to perform an untyped call and return. */
1176
1177/* For each register that may be used for calling a function, this
1178 gives a mode used to copy the register's value. VOIDmode indicates
1179 the register is not used for calling a function. If the machine
1180 has register windows, this gives only the outbound registers.
1181 INCOMING_REGNO gives the corresponding inbound register. */
1182static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
1183
1184/* For each register that may be used for returning values, this gives
1185 a mode used to copy the register's value. VOIDmode indicates the
1186 register is not used for returning values. If the machine has
1187 register windows, this gives only the outbound registers.
1188 INCOMING_REGNO gives the corresponding inbound register. */
1189static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
1190
1191/* For each register that may be used for calling a function, this
1192 gives the offset of that register into the block returned by
1193 __builtin_apply_args. 0 indicates that the register is not
1194 used for calling a function. */
1195static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
1196
53800dbe 1197/* Return the size required for the block returned by __builtin_apply_args,
1198 and initialize apply_args_mode. */
1199
1200static int
aecda0d6 1201apply_args_size (void)
53800dbe 1202{
1203 static int size = -1;
58e9ce8f 1204 int align;
1205 unsigned int regno;
53800dbe 1206 enum machine_mode mode;
1207
1208 /* The values computed by this function never change. */
1209 if (size < 0)
1210 {
1211 /* The first value is the incoming arg-pointer. */
1212 size = GET_MODE_SIZE (Pmode);
1213
1214 /* The second value is the structure value address unless this is
1215 passed as an "invisible" first argument. */
6812c89e 1216 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1217 size += GET_MODE_SIZE (Pmode);
1218
1219 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1220 if (FUNCTION_ARG_REGNO_P (regno))
1221 {
0862b7e9 1222 mode = reg_raw_mode[regno];
1223
64db345d 1224 gcc_assert (mode != VOIDmode);
53800dbe 1225
1226 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1227 if (size % align != 0)
1228 size = CEIL (size, align) * align;
1229 apply_args_reg_offset[regno] = size;
1230 size += GET_MODE_SIZE (mode);
1231 apply_args_mode[regno] = mode;
1232 }
1233 else
1234 {
1235 apply_args_mode[regno] = VOIDmode;
1236 apply_args_reg_offset[regno] = 0;
1237 }
1238 }
1239 return size;
1240}
1241
1242/* Return the size required for the block returned by __builtin_apply,
1243 and initialize apply_result_mode. */
1244
1245static int
aecda0d6 1246apply_result_size (void)
53800dbe 1247{
1248 static int size = -1;
1249 int align, regno;
1250 enum machine_mode mode;
1251
1252 /* The values computed by this function never change. */
1253 if (size < 0)
1254 {
1255 size = 0;
1256
1257 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1258 if (FUNCTION_VALUE_REGNO_P (regno))
1259 {
0862b7e9 1260 mode = reg_raw_mode[regno];
1261
64db345d 1262 gcc_assert (mode != VOIDmode);
53800dbe 1263
1264 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1265 if (size % align != 0)
1266 size = CEIL (size, align) * align;
1267 size += GET_MODE_SIZE (mode);
1268 apply_result_mode[regno] = mode;
1269 }
1270 else
1271 apply_result_mode[regno] = VOIDmode;
1272
1273 /* Allow targets that use untyped_call and untyped_return to override
1274 the size so that machine-specific information can be stored here. */
1275#ifdef APPLY_RESULT_SIZE
1276 size = APPLY_RESULT_SIZE;
1277#endif
1278 }
1279 return size;
1280}
1281
1282#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1283/* Create a vector describing the result block RESULT. If SAVEP is true,
1284 the result block is used to save the values; otherwise it is used to
1285 restore the values. */
1286
1287static rtx
aecda0d6 1288result_vector (int savep, rtx result)
53800dbe 1289{
1290 int regno, size, align, nelts;
1291 enum machine_mode mode;
1292 rtx reg, mem;
364c0c59 1293 rtx *savevec = XALLOCAVEC (rtx, FIRST_PSEUDO_REGISTER);
bf8e3599 1294
53800dbe 1295 size = nelts = 0;
1296 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1297 if ((mode = apply_result_mode[regno]) != VOIDmode)
1298 {
1299 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1300 if (size % align != 0)
1301 size = CEIL (size, align) * align;
1302 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
e513d163 1303 mem = adjust_address (result, mode, size);
53800dbe 1304 savevec[nelts++] = (savep
1305 ? gen_rtx_SET (VOIDmode, mem, reg)
1306 : gen_rtx_SET (VOIDmode, reg, mem));
1307 size += GET_MODE_SIZE (mode);
1308 }
1309 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1310}
1311#endif /* HAVE_untyped_call or HAVE_untyped_return */
1312
1313/* Save the state required to perform an untyped call with the same
1314 arguments as were passed to the current function. */
1315
1316static rtx
aecda0d6 1317expand_builtin_apply_args_1 (void)
53800dbe 1318{
1c7e61a7 1319 rtx registers, tem;
53800dbe 1320 int size, align, regno;
1321 enum machine_mode mode;
6812c89e 1322 rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
53800dbe 1323
1324 /* Create a block where the arg-pointer, structure value address,
1325 and argument registers can be saved. */
1326 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1327
1328 /* Walk past the arg-pointer and structure value address. */
1329 size = GET_MODE_SIZE (Pmode);
6812c89e 1330 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1331 size += GET_MODE_SIZE (Pmode);
1332
1333 /* Save each register used in calling a function to the block. */
1334 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1335 if ((mode = apply_args_mode[regno]) != VOIDmode)
1336 {
53800dbe 1337 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1338 if (size % align != 0)
1339 size = CEIL (size, align) * align;
1340
1341 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1342
e513d163 1343 emit_move_insn (adjust_address (registers, mode, size), tem);
53800dbe 1344 size += GET_MODE_SIZE (mode);
1345 }
1346
1347 /* Save the arg pointer to the block. */
1c7e61a7 1348 tem = copy_to_reg (virtual_incoming_args_rtx);
f083a92b 1349#ifdef STACK_GROWS_DOWNWARD
1c7e61a7 1350 /* We need the pointer as the caller actually passed them to us, not
9d4b544c 1351 as we might have pretended they were passed. Make sure it's a valid
1352 operand, as emit_move_insn isn't expected to handle a PLUS. */
1353 tem
abe32cce 1354 = force_operand (plus_constant (tem, crtl->args.pretend_args_size),
9d4b544c 1355 NULL_RTX);
1c7e61a7 1356#endif
1357 emit_move_insn (adjust_address (registers, Pmode, 0), tem);
0862b7e9 1358
53800dbe 1359 size = GET_MODE_SIZE (Pmode);
1360
1361 /* Save the structure value address unless this is passed as an
1362 "invisible" first argument. */
45550790 1363 if (struct_incoming_value)
53800dbe 1364 {
e513d163 1365 emit_move_insn (adjust_address (registers, Pmode, size),
45550790 1366 copy_to_reg (struct_incoming_value));
53800dbe 1367 size += GET_MODE_SIZE (Pmode);
1368 }
1369
1370 /* Return the address of the block. */
1371 return copy_addr_to_reg (XEXP (registers, 0));
1372}
1373
1374/* __builtin_apply_args returns block of memory allocated on
1375 the stack into which is stored the arg pointer, structure
1376 value address, static chain, and all the registers that might
1377 possibly be used in performing a function call. The code is
1378 moved to the start of the function so the incoming values are
1379 saved. */
27d0c333 1380
53800dbe 1381static rtx
aecda0d6 1382expand_builtin_apply_args (void)
53800dbe 1383{
1384 /* Don't do __builtin_apply_args more than once in a function.
1385 Save the result of the first call and reuse it. */
1386 if (apply_args_value != 0)
1387 return apply_args_value;
1388 {
1389 /* When this function is called, it means that registers must be
1390 saved on entry to this function. So we migrate the
1391 call to the first insn of this function. */
1392 rtx temp;
1393 rtx seq;
1394
1395 start_sequence ();
1396 temp = expand_builtin_apply_args_1 ();
1397 seq = get_insns ();
1398 end_sequence ();
1399
1400 apply_args_value = temp;
1401
31d3e01c 1402 /* Put the insns after the NOTE that starts the function.
1403 If this is inside a start_sequence, make the outer-level insn
53800dbe 1404 chain current, so the code is placed at the start of the
1405 function. */
1406 push_topmost_sequence ();
0ec80471 1407 emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
53800dbe 1408 pop_topmost_sequence ();
1409 return temp;
1410 }
1411}
1412
1413/* Perform an untyped call and save the state required to perform an
1414 untyped return of whatever value was returned by the given function. */
1415
1416static rtx
aecda0d6 1417expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
53800dbe 1418{
1419 int size, align, regno;
1420 enum machine_mode mode;
2a631e19 1421 rtx incoming_args, result, reg, dest, src, call_insn;
53800dbe 1422 rtx old_stack_level = 0;
1423 rtx call_fusage = 0;
6812c89e 1424 rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
53800dbe 1425
85d654dd 1426 arguments = convert_memory_address (Pmode, arguments);
726ec87c 1427
53800dbe 1428 /* Create a block where the return registers can be saved. */
1429 result = assign_stack_local (BLKmode, apply_result_size (), -1);
1430
53800dbe 1431 /* Fetch the arg pointer from the ARGUMENTS block. */
1432 incoming_args = gen_reg_rtx (Pmode);
726ec87c 1433 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
53800dbe 1434#ifndef STACK_GROWS_DOWNWARD
ad99e708 1435 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1436 incoming_args, 0, OPTAB_LIB_WIDEN);
53800dbe 1437#endif
1438
04a46d40 1439 /* Push a new argument block and copy the arguments. Do not allow
1440 the (potential) memcpy call below to interfere with our stack
1441 manipulations. */
53800dbe 1442 do_pending_stack_adjust ();
04a46d40 1443 NO_DEFER_POP;
53800dbe 1444
2358393e 1445 /* Save the stack with nonlocal if available. */
53800dbe 1446#ifdef HAVE_save_stack_nonlocal
1447 if (HAVE_save_stack_nonlocal)
1448 emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
1449 else
1450#endif
1451 emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
1452
59647703 1453 /* Allocate a block of memory onto the stack and copy the memory
1454 arguments to the outgoing arguments address. */
1455 allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
1456 dest = virtual_outgoing_args_rtx;
1457#ifndef STACK_GROWS_DOWNWARD
1458 if (GET_CODE (argsize) == CONST_INT)
1459 dest = plus_constant (dest, -INTVAL (argsize));
1460 else
1461 dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1462#endif
2a631e19 1463 dest = gen_rtx_MEM (BLKmode, dest);
1464 set_mem_align (dest, PARM_BOUNDARY);
1465 src = gen_rtx_MEM (BLKmode, incoming_args);
1466 set_mem_align (src, PARM_BOUNDARY);
0378dbdc 1467 emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
53800dbe 1468
1469 /* Refer to the argument block. */
1470 apply_args_size ();
1471 arguments = gen_rtx_MEM (BLKmode, arguments);
2a631e19 1472 set_mem_align (arguments, PARM_BOUNDARY);
53800dbe 1473
1474 /* Walk past the arg-pointer and structure value address. */
1475 size = GET_MODE_SIZE (Pmode);
45550790 1476 if (struct_value)
53800dbe 1477 size += GET_MODE_SIZE (Pmode);
1478
1479 /* Restore each of the registers previously saved. Make USE insns
1480 for each of these registers for use in making the call. */
1481 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1482 if ((mode = apply_args_mode[regno]) != VOIDmode)
1483 {
1484 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1485 if (size % align != 0)
1486 size = CEIL (size, align) * align;
1487 reg = gen_rtx_REG (mode, regno);
e513d163 1488 emit_move_insn (reg, adjust_address (arguments, mode, size));
53800dbe 1489 use_reg (&call_fusage, reg);
1490 size += GET_MODE_SIZE (mode);
1491 }
1492
1493 /* Restore the structure value address unless this is passed as an
1494 "invisible" first argument. */
1495 size = GET_MODE_SIZE (Pmode);
45550790 1496 if (struct_value)
53800dbe 1497 {
1498 rtx value = gen_reg_rtx (Pmode);
e513d163 1499 emit_move_insn (value, adjust_address (arguments, Pmode, size));
45550790 1500 emit_move_insn (struct_value, value);
8ad4c111 1501 if (REG_P (struct_value))
45550790 1502 use_reg (&call_fusage, struct_value);
53800dbe 1503 size += GET_MODE_SIZE (Pmode);
1504 }
1505
1506 /* All arguments and registers used for the call are set up by now! */
4ee9c684 1507 function = prepare_call_address (function, NULL, &call_fusage, 0, 0);
53800dbe 1508
1509 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1510 and we don't want to load it into a register as an optimization,
1511 because prepare_call_address already did it if it should be done. */
1512 if (GET_CODE (function) != SYMBOL_REF)
1513 function = memory_address (FUNCTION_MODE, function);
1514
1515 /* Generate the actual call instruction and save the return value. */
1516#ifdef HAVE_untyped_call
1517 if (HAVE_untyped_call)
1518 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1519 result, result_vector (1, result)));
1520 else
1521#endif
1522#ifdef HAVE_call_value
1523 if (HAVE_call_value)
1524 {
1525 rtx valreg = 0;
1526
1527 /* Locate the unique return register. It is not possible to
1528 express a call that sets more than one return register using
1529 call_value; use untyped_call for that. In fact, untyped_call
1530 only needs to save the return registers in the given block. */
1531 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1532 if ((mode = apply_result_mode[regno]) != VOIDmode)
1533 {
64db345d 1534 gcc_assert (!valreg); /* HAVE_untyped_call required. */
7d3f6cc7 1535
53800dbe 1536 valreg = gen_rtx_REG (mode, regno);
1537 }
1538
2ed6c343 1539 emit_call_insn (GEN_CALL_VALUE (valreg,
53800dbe 1540 gen_rtx_MEM (FUNCTION_MODE, function),
1541 const0_rtx, NULL_RTX, const0_rtx));
1542
e513d163 1543 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
53800dbe 1544 }
1545 else
1546#endif
64db345d 1547 gcc_unreachable ();
53800dbe 1548
d5f9786f 1549 /* Find the CALL insn we just emitted, and attach the register usage
1550 information. */
1551 call_insn = last_call_insn ();
1552 add_function_usage_to (call_insn, call_fusage);
53800dbe 1553
1554 /* Restore the stack. */
1555#ifdef HAVE_save_stack_nonlocal
1556 if (HAVE_save_stack_nonlocal)
1557 emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1558 else
1559#endif
1560 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1561
04a46d40 1562 OK_DEFER_POP;
1563
53800dbe 1564 /* Return the address of the result block. */
85d654dd 1565 result = copy_addr_to_reg (XEXP (result, 0));
1566 return convert_memory_address (ptr_mode, result);
53800dbe 1567}
1568
1569/* Perform an untyped return. */
1570
1571static void
aecda0d6 1572expand_builtin_return (rtx result)
53800dbe 1573{
1574 int size, align, regno;
1575 enum machine_mode mode;
1576 rtx reg;
1577 rtx call_fusage = 0;
1578
85d654dd 1579 result = convert_memory_address (Pmode, result);
726ec87c 1580
53800dbe 1581 apply_result_size ();
1582 result = gen_rtx_MEM (BLKmode, result);
1583
1584#ifdef HAVE_untyped_return
1585 if (HAVE_untyped_return)
1586 {
1587 emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1588 emit_barrier ();
1589 return;
1590 }
1591#endif
1592
1593 /* Restore the return value and note that each value is used. */
1594 size = 0;
1595 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1596 if ((mode = apply_result_mode[regno]) != VOIDmode)
1597 {
1598 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1599 if (size % align != 0)
1600 size = CEIL (size, align) * align;
1601 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
e513d163 1602 emit_move_insn (reg, adjust_address (result, mode, size));
53800dbe 1603
1604 push_to_sequence (call_fusage);
18b42941 1605 emit_use (reg);
53800dbe 1606 call_fusage = get_insns ();
1607 end_sequence ();
1608 size += GET_MODE_SIZE (mode);
1609 }
1610
1611 /* Put the USE insns before the return. */
31d3e01c 1612 emit_insn (call_fusage);
53800dbe 1613
1614 /* Return whatever values was restored by jumping directly to the end
1615 of the function. */
62380d2d 1616 expand_naked_return ();
53800dbe 1617}
1618
539a3a92 1619/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
27d0c333 1620
539a3a92 1621static enum type_class
aecda0d6 1622type_to_class (tree type)
539a3a92 1623{
1624 switch (TREE_CODE (type))
1625 {
1626 case VOID_TYPE: return void_type_class;
1627 case INTEGER_TYPE: return integer_type_class;
539a3a92 1628 case ENUMERAL_TYPE: return enumeral_type_class;
1629 case BOOLEAN_TYPE: return boolean_type_class;
1630 case POINTER_TYPE: return pointer_type_class;
1631 case REFERENCE_TYPE: return reference_type_class;
1632 case OFFSET_TYPE: return offset_type_class;
1633 case REAL_TYPE: return real_type_class;
1634 case COMPLEX_TYPE: return complex_type_class;
1635 case FUNCTION_TYPE: return function_type_class;
1636 case METHOD_TYPE: return method_type_class;
1637 case RECORD_TYPE: return record_type_class;
1638 case UNION_TYPE:
1639 case QUAL_UNION_TYPE: return union_type_class;
1640 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1641 ? string_type_class : array_type_class);
539a3a92 1642 case LANG_TYPE: return lang_type_class;
1643 default: return no_type_class;
1644 }
1645}
bf8e3599 1646
c2f47e15 1647/* Expand a call EXP to __builtin_classify_type. */
27d0c333 1648
53800dbe 1649static rtx
c2f47e15 1650expand_builtin_classify_type (tree exp)
53800dbe 1651{
c2f47e15 1652 if (call_expr_nargs (exp))
1653 return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0))));
53800dbe 1654 return GEN_INT (no_type_class);
1655}
1656
07976da7 1657/* This helper macro, meant to be used in mathfn_built_in below,
1658 determines which among a set of three builtin math functions is
1659 appropriate for a given type mode. The `F' and `L' cases are
1660 automatically generated from the `double' case. */
1661#define CASE_MATHFN(BUILT_IN_MATHFN) \
1662 case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1663 fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1664 fcodel = BUILT_IN_MATHFN##L ; break;
cd2656b0 1665/* Similar to above, but appends _R after any F/L suffix. */
1666#define CASE_MATHFN_REENT(BUILT_IN_MATHFN) \
1667 case BUILT_IN_MATHFN##_R: case BUILT_IN_MATHFN##F_R: case BUILT_IN_MATHFN##L_R: \
1668 fcode = BUILT_IN_MATHFN##_R; fcodef = BUILT_IN_MATHFN##F_R ; \
1669 fcodel = BUILT_IN_MATHFN##L_R ; break;
07976da7 1670
1671/* Return mathematic function equivalent to FN but operating directly
c319d56a 1672 on TYPE, if available. If IMPLICIT is true find the function in
1673 implicit_built_in_decls[], otherwise use built_in_decls[]. If we
1674 can't do the conversion, return zero. */
1675
1676static tree
1677mathfn_built_in_1 (tree type, enum built_in_function fn, bool implicit)
0a68165a 1678{
c319d56a 1679 tree const *const fn_arr
1680 = implicit ? implicit_built_in_decls : built_in_decls;
07976da7 1681 enum built_in_function fcode, fcodef, fcodel;
1682
1683 switch (fn)
1684 {
746114e8 1685 CASE_MATHFN (BUILT_IN_ACOS)
1686 CASE_MATHFN (BUILT_IN_ACOSH)
1687 CASE_MATHFN (BUILT_IN_ASIN)
1688 CASE_MATHFN (BUILT_IN_ASINH)
07976da7 1689 CASE_MATHFN (BUILT_IN_ATAN)
746114e8 1690 CASE_MATHFN (BUILT_IN_ATAN2)
1691 CASE_MATHFN (BUILT_IN_ATANH)
1692 CASE_MATHFN (BUILT_IN_CBRT)
07976da7 1693 CASE_MATHFN (BUILT_IN_CEIL)
d735c391 1694 CASE_MATHFN (BUILT_IN_CEXPI)
746114e8 1695 CASE_MATHFN (BUILT_IN_COPYSIGN)
07976da7 1696 CASE_MATHFN (BUILT_IN_COS)
746114e8 1697 CASE_MATHFN (BUILT_IN_COSH)
1698 CASE_MATHFN (BUILT_IN_DREM)
1699 CASE_MATHFN (BUILT_IN_ERF)
1700 CASE_MATHFN (BUILT_IN_ERFC)
07976da7 1701 CASE_MATHFN (BUILT_IN_EXP)
746114e8 1702 CASE_MATHFN (BUILT_IN_EXP10)
1703 CASE_MATHFN (BUILT_IN_EXP2)
1704 CASE_MATHFN (BUILT_IN_EXPM1)
1705 CASE_MATHFN (BUILT_IN_FABS)
1706 CASE_MATHFN (BUILT_IN_FDIM)
07976da7 1707 CASE_MATHFN (BUILT_IN_FLOOR)
746114e8 1708 CASE_MATHFN (BUILT_IN_FMA)
1709 CASE_MATHFN (BUILT_IN_FMAX)
1710 CASE_MATHFN (BUILT_IN_FMIN)
1711 CASE_MATHFN (BUILT_IN_FMOD)
1712 CASE_MATHFN (BUILT_IN_FREXP)
1713 CASE_MATHFN (BUILT_IN_GAMMA)
cd2656b0 1714 CASE_MATHFN_REENT (BUILT_IN_GAMMA) /* GAMMA_R */
746114e8 1715 CASE_MATHFN (BUILT_IN_HUGE_VAL)
1716 CASE_MATHFN (BUILT_IN_HYPOT)
1717 CASE_MATHFN (BUILT_IN_ILOGB)
1718 CASE_MATHFN (BUILT_IN_INF)
69b779ea 1719 CASE_MATHFN (BUILT_IN_ISINF)
746114e8 1720 CASE_MATHFN (BUILT_IN_J0)
1721 CASE_MATHFN (BUILT_IN_J1)
1722 CASE_MATHFN (BUILT_IN_JN)
ac148751 1723 CASE_MATHFN (BUILT_IN_LCEIL)
746114e8 1724 CASE_MATHFN (BUILT_IN_LDEXP)
ad52b9b7 1725 CASE_MATHFN (BUILT_IN_LFLOOR)
746114e8 1726 CASE_MATHFN (BUILT_IN_LGAMMA)
cd2656b0 1727 CASE_MATHFN_REENT (BUILT_IN_LGAMMA) /* LGAMMA_R */
ac148751 1728 CASE_MATHFN (BUILT_IN_LLCEIL)
ad52b9b7 1729 CASE_MATHFN (BUILT_IN_LLFLOOR)
746114e8 1730 CASE_MATHFN (BUILT_IN_LLRINT)
1731 CASE_MATHFN (BUILT_IN_LLROUND)
07976da7 1732 CASE_MATHFN (BUILT_IN_LOG)
746114e8 1733 CASE_MATHFN (BUILT_IN_LOG10)
1734 CASE_MATHFN (BUILT_IN_LOG1P)
1735 CASE_MATHFN (BUILT_IN_LOG2)
1736 CASE_MATHFN (BUILT_IN_LOGB)
1737 CASE_MATHFN (BUILT_IN_LRINT)
1738 CASE_MATHFN (BUILT_IN_LROUND)
1739 CASE_MATHFN (BUILT_IN_MODF)
1740 CASE_MATHFN (BUILT_IN_NAN)
1741 CASE_MATHFN (BUILT_IN_NANS)
07976da7 1742 CASE_MATHFN (BUILT_IN_NEARBYINT)
746114e8 1743 CASE_MATHFN (BUILT_IN_NEXTAFTER)
1744 CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1745 CASE_MATHFN (BUILT_IN_POW)
757c219d 1746 CASE_MATHFN (BUILT_IN_POWI)
746114e8 1747 CASE_MATHFN (BUILT_IN_POW10)
1748 CASE_MATHFN (BUILT_IN_REMAINDER)
1749 CASE_MATHFN (BUILT_IN_REMQUO)
1750 CASE_MATHFN (BUILT_IN_RINT)
07976da7 1751 CASE_MATHFN (BUILT_IN_ROUND)
746114e8 1752 CASE_MATHFN (BUILT_IN_SCALB)
1753 CASE_MATHFN (BUILT_IN_SCALBLN)
1754 CASE_MATHFN (BUILT_IN_SCALBN)
c319d56a 1755 CASE_MATHFN (BUILT_IN_SIGNBIT)
746114e8 1756 CASE_MATHFN (BUILT_IN_SIGNIFICAND)
07976da7 1757 CASE_MATHFN (BUILT_IN_SIN)
746114e8 1758 CASE_MATHFN (BUILT_IN_SINCOS)
1759 CASE_MATHFN (BUILT_IN_SINH)
07976da7 1760 CASE_MATHFN (BUILT_IN_SQRT)
1761 CASE_MATHFN (BUILT_IN_TAN)
746114e8 1762 CASE_MATHFN (BUILT_IN_TANH)
1763 CASE_MATHFN (BUILT_IN_TGAMMA)
07976da7 1764 CASE_MATHFN (BUILT_IN_TRUNC)
746114e8 1765 CASE_MATHFN (BUILT_IN_Y0)
1766 CASE_MATHFN (BUILT_IN_Y1)
1767 CASE_MATHFN (BUILT_IN_YN)
07976da7 1768
0a68165a 1769 default:
c2f47e15 1770 return NULL_TREE;
0a68165a 1771 }
07976da7 1772
96b9f485 1773 if (TYPE_MAIN_VARIANT (type) == double_type_node)
c319d56a 1774 return fn_arr[fcode];
96b9f485 1775 else if (TYPE_MAIN_VARIANT (type) == float_type_node)
c319d56a 1776 return fn_arr[fcodef];
96b9f485 1777 else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
c319d56a 1778 return fn_arr[fcodel];
07976da7 1779 else
c2f47e15 1780 return NULL_TREE;
0a68165a 1781}
1782
c319d56a 1783/* Like mathfn_built_in_1(), but always use the implicit array. */
1784
1785tree
1786mathfn_built_in (tree type, enum built_in_function fn)
1787{
1788 return mathfn_built_in_1 (type, fn, /*implicit=*/ 1);
1789}
1790
0fd605a5 1791/* If errno must be maintained, expand the RTL to check if the result,
1792 TARGET, of a built-in function call, EXP, is NaN, and if so set
1793 errno to EDOM. */
1794
1795static void
aecda0d6 1796expand_errno_check (tree exp, rtx target)
0fd605a5 1797{
7f05340e 1798 rtx lab = gen_label_rtx ();
0fd605a5 1799
7f05340e 1800 /* Test the result; if it is NaN, set errno=EDOM because
1801 the argument was not in the domain. */
1802 emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
1803 0, lab);
0fd605a5 1804
1805#ifdef TARGET_EDOM
7f05340e 1806 /* If this built-in doesn't throw an exception, set errno directly. */
c2f47e15 1807 if (TREE_NOTHROW (TREE_OPERAND (CALL_EXPR_FN (exp), 0)))
7f05340e 1808 {
0fd605a5 1809#ifdef GEN_ERRNO_RTX
7f05340e 1810 rtx errno_rtx = GEN_ERRNO_RTX;
0fd605a5 1811#else
7f05340e 1812 rtx errno_rtx
0fd605a5 1813 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1814#endif
7f05340e 1815 emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
0fd605a5 1816 emit_label (lab);
7f05340e 1817 return;
0fd605a5 1818 }
7f05340e 1819#endif
1820
08491912 1821 /* Make sure the library call isn't expanded as a tail call. */
1822 CALL_EXPR_TAILCALL (exp) = 0;
1823
7f05340e 1824 /* We can't set errno=EDOM directly; let the library call do it.
1825 Pop the arguments right away in case the call gets deleted. */
1826 NO_DEFER_POP;
1827 expand_call (exp, target, 0);
1828 OK_DEFER_POP;
1829 emit_label (lab);
0fd605a5 1830}
1831
6b43bae4 1832/* Expand a call to one of the builtin math functions (sqrt, exp, or log).
c2f47e15 1833 Return NULL_RTX if a normal call should be emitted rather than expanding
1834 the function in-line. EXP is the expression that is a call to the builtin
53800dbe 1835 function; if convenient, the result should be placed in TARGET.
1836 SUBTARGET may be used as the target for computing one of EXP's operands. */
27d0c333 1837
53800dbe 1838static rtx
aecda0d6 1839expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
53800dbe 1840{
bf8e3599 1841 optab builtin_optab;
bd421108 1842 rtx op0, insns, before_call;
c6e6ecb1 1843 tree fndecl = get_callee_fndecl (exp);
7f05340e 1844 enum machine_mode mode;
528ee710 1845 bool errno_set = false;
abfea505 1846 tree arg;
53800dbe 1847
c2f47e15 1848 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
1849 return NULL_RTX;
53800dbe 1850
c2f47e15 1851 arg = CALL_EXPR_ARG (exp, 0);
53800dbe 1852
1853 switch (DECL_FUNCTION_CODE (fndecl))
1854 {
4f35b1fc 1855 CASE_FLT_FN (BUILT_IN_SQRT):
7f05340e 1856 errno_set = ! tree_expr_nonnegative_p (arg);
1857 builtin_optab = sqrt_optab;
1858 break;
4f35b1fc 1859 CASE_FLT_FN (BUILT_IN_EXP):
528ee710 1860 errno_set = true; builtin_optab = exp_optab; break;
4f35b1fc 1861 CASE_FLT_FN (BUILT_IN_EXP10):
1862 CASE_FLT_FN (BUILT_IN_POW10):
750ef9f5 1863 errno_set = true; builtin_optab = exp10_optab; break;
4f35b1fc 1864 CASE_FLT_FN (BUILT_IN_EXP2):
750ef9f5 1865 errno_set = true; builtin_optab = exp2_optab; break;
4f35b1fc 1866 CASE_FLT_FN (BUILT_IN_EXPM1):
a6b4eed2 1867 errno_set = true; builtin_optab = expm1_optab; break;
4f35b1fc 1868 CASE_FLT_FN (BUILT_IN_LOGB):
4efbc641 1869 errno_set = true; builtin_optab = logb_optab; break;
4f35b1fc 1870 CASE_FLT_FN (BUILT_IN_LOG):
528ee710 1871 errno_set = true; builtin_optab = log_optab; break;
4f35b1fc 1872 CASE_FLT_FN (BUILT_IN_LOG10):
d3cd9bde 1873 errno_set = true; builtin_optab = log10_optab; break;
4f35b1fc 1874 CASE_FLT_FN (BUILT_IN_LOG2):
d3cd9bde 1875 errno_set = true; builtin_optab = log2_optab; break;
4f35b1fc 1876 CASE_FLT_FN (BUILT_IN_LOG1P):
f474cd93 1877 errno_set = true; builtin_optab = log1p_optab; break;
4f35b1fc 1878 CASE_FLT_FN (BUILT_IN_ASIN):
8de2f465 1879 builtin_optab = asin_optab; break;
4f35b1fc 1880 CASE_FLT_FN (BUILT_IN_ACOS):
8de2f465 1881 builtin_optab = acos_optab; break;
4f35b1fc 1882 CASE_FLT_FN (BUILT_IN_TAN):
528ee710 1883 builtin_optab = tan_optab; break;
4f35b1fc 1884 CASE_FLT_FN (BUILT_IN_ATAN):
528ee710 1885 builtin_optab = atan_optab; break;
4f35b1fc 1886 CASE_FLT_FN (BUILT_IN_FLOOR):
528ee710 1887 builtin_optab = floor_optab; break;
4f35b1fc 1888 CASE_FLT_FN (BUILT_IN_CEIL):
528ee710 1889 builtin_optab = ceil_optab; break;
4f35b1fc 1890 CASE_FLT_FN (BUILT_IN_TRUNC):
a7cc195f 1891 builtin_optab = btrunc_optab; break;
4f35b1fc 1892 CASE_FLT_FN (BUILT_IN_ROUND):
528ee710 1893 builtin_optab = round_optab; break;
4f35b1fc 1894 CASE_FLT_FN (BUILT_IN_NEARBYINT):
0ddf4ad9 1895 builtin_optab = nearbyint_optab;
1896 if (flag_trapping_math)
1897 break;
1898 /* Else fallthrough and expand as rint. */
4f35b1fc 1899 CASE_FLT_FN (BUILT_IN_RINT):
aef94a0f 1900 builtin_optab = rint_optab; break;
42721db0 1901 default:
64db345d 1902 gcc_unreachable ();
53800dbe 1903 }
1904
7f05340e 1905 /* Make a suitable register to place result in. */
1906 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 1907
7f05340e 1908 if (! flag_errno_math || ! HONOR_NANS (mode))
1909 errno_set = false;
1910
bd421108 1911 /* Before working hard, check whether the instruction is available. */
99bdde56 1912 if (optab_handler (builtin_optab, mode)->insn_code != CODE_FOR_nothing)
68e6cb9d 1913 {
bd421108 1914 target = gen_reg_rtx (mode);
7f05340e 1915
bd421108 1916 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
1917 need to expand the argument again. This way, we will not perform
1918 side-effects more the once. */
abfea505 1919 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7f05340e 1920
1db6d067 1921 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
7f05340e 1922
bd421108 1923 start_sequence ();
53800dbe 1924
bd421108 1925 /* Compute into TARGET.
1926 Set TARGET to wherever the result comes back. */
1927 target = expand_unop (mode, builtin_optab, op0, target, 0);
1928
1929 if (target != 0)
1930 {
1931 if (errno_set)
1932 expand_errno_check (exp, target);
1933
1934 /* Output the entire sequence. */
1935 insns = get_insns ();
1936 end_sequence ();
1937 emit_insn (insns);
1938 return target;
1939 }
1940
1941 /* If we were unable to expand via the builtin, stop the sequence
1942 (without outputting the insns) and call to the library function
1943 with the stabilized argument list. */
53800dbe 1944 end_sequence ();
53800dbe 1945 }
1946
bd421108 1947 before_call = get_last_insn ();
1948
1e5b92fa 1949 return expand_call (exp, target, target == const0_rtx);
0fd605a5 1950}
1951
1952/* Expand a call to the builtin binary math functions (pow and atan2).
c2f47e15 1953 Return NULL_RTX if a normal call should be emitted rather than expanding the
0fd605a5 1954 function in-line. EXP is the expression that is a call to the builtin
1955 function; if convenient, the result should be placed in TARGET.
1956 SUBTARGET may be used as the target for computing one of EXP's
1957 operands. */
1958
1959static rtx
aecda0d6 1960expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
0fd605a5 1961{
1962 optab builtin_optab;
1963 rtx op0, op1, insns;
4737caf2 1964 int op1_type = REAL_TYPE;
c6e6ecb1 1965 tree fndecl = get_callee_fndecl (exp);
abfea505 1966 tree arg0, arg1;
7f05340e 1967 enum machine_mode mode;
0fd605a5 1968 bool errno_set = true;
0fd605a5 1969
73a954a1 1970 switch (DECL_FUNCTION_CODE (fndecl))
1971 {
1972 CASE_FLT_FN (BUILT_IN_SCALBN):
1973 CASE_FLT_FN (BUILT_IN_SCALBLN):
1974 CASE_FLT_FN (BUILT_IN_LDEXP):
1975 op1_type = INTEGER_TYPE;
1976 default:
1977 break;
1978 }
4737caf2 1979
c2f47e15 1980 if (!validate_arglist (exp, REAL_TYPE, op1_type, VOID_TYPE))
1981 return NULL_RTX;
0fd605a5 1982
c2f47e15 1983 arg0 = CALL_EXPR_ARG (exp, 0);
1984 arg1 = CALL_EXPR_ARG (exp, 1);
0fd605a5 1985
0fd605a5 1986 switch (DECL_FUNCTION_CODE (fndecl))
1987 {
4f35b1fc 1988 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 1989 builtin_optab = pow_optab; break;
4f35b1fc 1990 CASE_FLT_FN (BUILT_IN_ATAN2):
0fd605a5 1991 builtin_optab = atan2_optab; break;
73a954a1 1992 CASE_FLT_FN (BUILT_IN_SCALB):
1993 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
1994 return 0;
1995 builtin_optab = scalb_optab; break;
1996 CASE_FLT_FN (BUILT_IN_SCALBN):
1997 CASE_FLT_FN (BUILT_IN_SCALBLN):
1998 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
1999 return 0;
2000 /* Fall through... */
4f35b1fc 2001 CASE_FLT_FN (BUILT_IN_LDEXP):
4737caf2 2002 builtin_optab = ldexp_optab; break;
4f35b1fc 2003 CASE_FLT_FN (BUILT_IN_FMOD):
80ed5c06 2004 builtin_optab = fmod_optab; break;
ef722005 2005 CASE_FLT_FN (BUILT_IN_REMAINDER):
4f35b1fc 2006 CASE_FLT_FN (BUILT_IN_DREM):
ef722005 2007 builtin_optab = remainder_optab; break;
0fd605a5 2008 default:
64db345d 2009 gcc_unreachable ();
0fd605a5 2010 }
2011
7f05340e 2012 /* Make a suitable register to place result in. */
2013 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2014
2015 /* Before working hard, check whether the instruction is available. */
99bdde56 2016 if (optab_handler (builtin_optab, mode)->insn_code == CODE_FOR_nothing)
c2f47e15 2017 return NULL_RTX;
fc4eef90 2018
7f05340e 2019 target = gen_reg_rtx (mode);
2020
2021 if (! flag_errno_math || ! HONOR_NANS (mode))
2022 errno_set = false;
2023
4ee9c684 2024 /* Always stabilize the argument list. */
abfea505 2025 CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
2026 CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
7f05340e 2027
8ec3c5c2 2028 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2029 op1 = expand_normal (arg1);
7f05340e 2030
7f05340e 2031 start_sequence ();
2032
0fd605a5 2033 /* Compute into TARGET.
2034 Set TARGET to wherever the result comes back. */
7f05340e 2035 target = expand_binop (mode, builtin_optab, op0, op1,
0fd605a5 2036 target, 0, OPTAB_DIRECT);
53800dbe 2037
68e6cb9d 2038 /* If we were unable to expand via the builtin, stop the sequence
2039 (without outputting the insns) and call to the library function
2040 with the stabilized argument list. */
0fd605a5 2041 if (target == 0)
2042 {
2043 end_sequence ();
68e6cb9d 2044 return expand_call (exp, target, target == const0_rtx);
53800dbe 2045 }
2046
a4356fb9 2047 if (errno_set)
2048 expand_errno_check (exp, target);
0fd605a5 2049
53800dbe 2050 /* Output the entire sequence. */
2051 insns = get_insns ();
2052 end_sequence ();
31d3e01c 2053 emit_insn (insns);
bf8e3599 2054
53800dbe 2055 return target;
2056}
2057
6b43bae4 2058/* Expand a call to the builtin sin and cos math functions.
c2f47e15 2059 Return NULL_RTX if a normal call should be emitted rather than expanding the
6b43bae4 2060 function in-line. EXP is the expression that is a call to the builtin
2061 function; if convenient, the result should be placed in TARGET.
2062 SUBTARGET may be used as the target for computing one of EXP's
2063 operands. */
2064
2065static rtx
2066expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
2067{
2068 optab builtin_optab;
7511b819 2069 rtx op0, insns;
6b43bae4 2070 tree fndecl = get_callee_fndecl (exp);
6b43bae4 2071 enum machine_mode mode;
abfea505 2072 tree arg;
6b43bae4 2073
c2f47e15 2074 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2075 return NULL_RTX;
6b43bae4 2076
c2f47e15 2077 arg = CALL_EXPR_ARG (exp, 0);
6b43bae4 2078
2079 switch (DECL_FUNCTION_CODE (fndecl))
2080 {
4f35b1fc 2081 CASE_FLT_FN (BUILT_IN_SIN):
2082 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2083 builtin_optab = sincos_optab; break;
2084 default:
64db345d 2085 gcc_unreachable ();
6b43bae4 2086 }
2087
2088 /* Make a suitable register to place result in. */
2089 mode = TYPE_MODE (TREE_TYPE (exp));
2090
6b43bae4 2091 /* Check if sincos insn is available, otherwise fallback
0bed3869 2092 to sin or cos insn. */
99bdde56 2093 if (optab_handler (builtin_optab, mode)->insn_code == CODE_FOR_nothing)
6b43bae4 2094 switch (DECL_FUNCTION_CODE (fndecl))
2095 {
4f35b1fc 2096 CASE_FLT_FN (BUILT_IN_SIN):
6b43bae4 2097 builtin_optab = sin_optab; break;
4f35b1fc 2098 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2099 builtin_optab = cos_optab; break;
2100 default:
64db345d 2101 gcc_unreachable ();
6b43bae4 2102 }
6b43bae4 2103
2104 /* Before working hard, check whether the instruction is available. */
99bdde56 2105 if (optab_handler (builtin_optab, mode)->insn_code != CODE_FOR_nothing)
6b43bae4 2106 {
2107 target = gen_reg_rtx (mode);
2108
2109 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2110 need to expand the argument again. This way, we will not perform
2111 side-effects more the once. */
abfea505 2112 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
6b43bae4 2113
1db6d067 2114 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
6b43bae4 2115
6b43bae4 2116 start_sequence ();
2117
2118 /* Compute into TARGET.
2119 Set TARGET to wherever the result comes back. */
2120 if (builtin_optab == sincos_optab)
2121 {
64db345d 2122 int result;
7d3f6cc7 2123
6b43bae4 2124 switch (DECL_FUNCTION_CODE (fndecl))
2125 {
4f35b1fc 2126 CASE_FLT_FN (BUILT_IN_SIN):
64db345d 2127 result = expand_twoval_unop (builtin_optab, op0, 0, target, 0);
6b43bae4 2128 break;
4f35b1fc 2129 CASE_FLT_FN (BUILT_IN_COS):
64db345d 2130 result = expand_twoval_unop (builtin_optab, op0, target, 0, 0);
6b43bae4 2131 break;
2132 default:
64db345d 2133 gcc_unreachable ();
6b43bae4 2134 }
64db345d 2135 gcc_assert (result);
6b43bae4 2136 }
2137 else
2138 {
2139 target = expand_unop (mode, builtin_optab, op0, target, 0);
2140 }
2141
2142 if (target != 0)
2143 {
6b43bae4 2144 /* Output the entire sequence. */
2145 insns = get_insns ();
2146 end_sequence ();
2147 emit_insn (insns);
2148 return target;
2149 }
2150
2151 /* If we were unable to expand via the builtin, stop the sequence
2152 (without outputting the insns) and call to the library function
2153 with the stabilized argument list. */
2154 end_sequence ();
2155 }
2156
6b43bae4 2157 target = expand_call (exp, target, target == const0_rtx);
2158
2159 return target;
2160}
2161
a67a90e5 2162/* Expand a call to one of the builtin math functions that operate on
2163 floating point argument and output an integer result (ilogb, isinf,
2164 isnan, etc).
2165 Return 0 if a normal call should be emitted rather than expanding the
2166 function in-line. EXP is the expression that is a call to the builtin
2167 function; if convenient, the result should be placed in TARGET.
2168 SUBTARGET may be used as the target for computing one of EXP's operands. */
2169
2170static rtx
2171expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
2172{
cde061c1 2173 optab builtin_optab = 0;
2174 enum insn_code icode = CODE_FOR_nothing;
a67a90e5 2175 rtx op0;
2176 tree fndecl = get_callee_fndecl (exp);
a67a90e5 2177 enum machine_mode mode;
2178 bool errno_set = false;
abfea505 2179 tree arg;
a67a90e5 2180
c2f47e15 2181 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2182 return NULL_RTX;
a67a90e5 2183
c2f47e15 2184 arg = CALL_EXPR_ARG (exp, 0);
a67a90e5 2185
2186 switch (DECL_FUNCTION_CODE (fndecl))
2187 {
2188 CASE_FLT_FN (BUILT_IN_ILOGB):
2189 errno_set = true; builtin_optab = ilogb_optab; break;
69b779ea 2190 CASE_FLT_FN (BUILT_IN_ISINF):
2191 builtin_optab = isinf_optab; break;
8a1a9cb7 2192 case BUILT_IN_ISNORMAL:
cde061c1 2193 case BUILT_IN_ISFINITE:
2194 CASE_FLT_FN (BUILT_IN_FINITE):
2195 /* These builtins have no optabs (yet). */
2196 break;
a67a90e5 2197 default:
2198 gcc_unreachable ();
2199 }
2200
2201 /* There's no easy way to detect the case we need to set EDOM. */
2202 if (flag_errno_math && errno_set)
2203 return NULL_RTX;
2204
2205 /* Optab mode depends on the mode of the input argument. */
2206 mode = TYPE_MODE (TREE_TYPE (arg));
2207
cde061c1 2208 if (builtin_optab)
99bdde56 2209 icode = optab_handler (builtin_optab, mode)->insn_code;
a67a90e5 2210
2211 /* Before working hard, check whether the instruction is available. */
2212 if (icode != CODE_FOR_nothing)
2213 {
2214 /* Make a suitable register to place result in. */
2215 if (!target
2216 || GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
2217 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
2218
2219 gcc_assert (insn_data[icode].operand[0].predicate
2220 (target, GET_MODE (target)));
2221
2222 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2223 need to expand the argument again. This way, we will not perform
2224 side-effects more the once. */
abfea505 2225 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
a67a90e5 2226
1db6d067 2227 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
a67a90e5 2228
2229 if (mode != GET_MODE (op0))
2230 op0 = convert_to_mode (mode, op0, 0);
2231
2232 /* Compute into TARGET.
2233 Set TARGET to wherever the result comes back. */
2234 emit_unop_insn (icode, target, op0, UNKNOWN);
2235 return target;
2236 }
2237
06f7a99d 2238 /* If there is no optab, try generic code. */
2239 switch (DECL_FUNCTION_CODE (fndecl))
2240 {
2241 tree result;
2242
2243 CASE_FLT_FN (BUILT_IN_ISINF):
2244 {
2245 /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
2246 tree const isgr_fn = built_in_decls[BUILT_IN_ISGREATER];
2247 tree const type = TREE_TYPE (arg);
2248 REAL_VALUE_TYPE r;
2249 char buf[128];
2250
2251 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
2252 real_from_string (&r, buf);
2253 result = build_call_expr (isgr_fn, 2,
2254 fold_build1 (ABS_EXPR, type, arg),
2255 build_real (type, r));
2256 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
2257 }
cde061c1 2258 CASE_FLT_FN (BUILT_IN_FINITE):
2259 case BUILT_IN_ISFINITE:
2260 {
2261 /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
2262 tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
2263 tree const type = TREE_TYPE (arg);
2264 REAL_VALUE_TYPE r;
2265 char buf[128];
2266
2267 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
2268 real_from_string (&r, buf);
2269 result = build_call_expr (isle_fn, 2,
2270 fold_build1 (ABS_EXPR, type, arg),
2271 build_real (type, r));
2272 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
2273 }
8a1a9cb7 2274 case BUILT_IN_ISNORMAL:
2275 {
2276 /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
2277 islessequal(fabs(x),DBL_MAX). */
2278 tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
2279 tree const isge_fn = built_in_decls[BUILT_IN_ISGREATEREQUAL];
2280 tree const type = TREE_TYPE (arg);
2281 REAL_VALUE_TYPE rmax, rmin;
2282 char buf[128];
2283
2284 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
2285 real_from_string (&rmax, buf);
2286 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
2287 real_from_string (&rmin, buf);
2288 arg = builtin_save_expr (fold_build1 (ABS_EXPR, type, arg));
2289 result = build_call_expr (isle_fn, 2, arg,
2290 build_real (type, rmax));
2291 result = fold_build2 (BIT_AND_EXPR, integer_type_node, result,
2292 build_call_expr (isge_fn, 2, arg,
2293 build_real (type, rmin)));
2294 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
2295 }
06f7a99d 2296 default:
2297 break;
2298 }
2299
a67a90e5 2300 target = expand_call (exp, target, target == const0_rtx);
2301
2302 return target;
2303}
2304
c3147c1a 2305/* Expand a call to the builtin sincos math function.
c2f47e15 2306 Return NULL_RTX if a normal call should be emitted rather than expanding the
c3147c1a 2307 function in-line. EXP is the expression that is a call to the builtin
2308 function. */
2309
2310static rtx
2311expand_builtin_sincos (tree exp)
2312{
2313 rtx op0, op1, op2, target1, target2;
c3147c1a 2314 enum machine_mode mode;
2315 tree arg, sinp, cosp;
2316 int result;
2317
c2f47e15 2318 if (!validate_arglist (exp, REAL_TYPE,
2319 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2320 return NULL_RTX;
c3147c1a 2321
c2f47e15 2322 arg = CALL_EXPR_ARG (exp, 0);
2323 sinp = CALL_EXPR_ARG (exp, 1);
2324 cosp = CALL_EXPR_ARG (exp, 2);
c3147c1a 2325
2326 /* Make a suitable register to place result in. */
2327 mode = TYPE_MODE (TREE_TYPE (arg));
2328
2329 /* Check if sincos insn is available, otherwise emit the call. */
99bdde56 2330 if (optab_handler (sincos_optab, mode)->insn_code == CODE_FOR_nothing)
c3147c1a 2331 return NULL_RTX;
2332
2333 target1 = gen_reg_rtx (mode);
2334 target2 = gen_reg_rtx (mode);
2335
8ec3c5c2 2336 op0 = expand_normal (arg);
2337 op1 = expand_normal (build_fold_indirect_ref (sinp));
2338 op2 = expand_normal (build_fold_indirect_ref (cosp));
c3147c1a 2339
2340 /* Compute into target1 and target2.
2341 Set TARGET to wherever the result comes back. */
2342 result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
2343 gcc_assert (result);
2344
2345 /* Move target1 and target2 to the memory locations indicated
2346 by op1 and op2. */
2347 emit_move_insn (op1, target1);
2348 emit_move_insn (op2, target2);
2349
2350 return const0_rtx;
2351}
2352
d735c391 2353/* Expand a call to the internal cexpi builtin to the sincos math function.
2354 EXP is the expression that is a call to the builtin function; if convenient,
2355 the result should be placed in TARGET. SUBTARGET may be used as the target
2356 for computing one of EXP's operands. */
2357
2358static rtx
2359expand_builtin_cexpi (tree exp, rtx target, rtx subtarget)
2360{
2361 tree fndecl = get_callee_fndecl (exp);
d735c391 2362 tree arg, type;
c2f47e15 2363 enum machine_mode mode;
d735c391 2364 rtx op0, op1, op2;
2365
c2f47e15 2366 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2367 return NULL_RTX;
d735c391 2368
c2f47e15 2369 arg = CALL_EXPR_ARG (exp, 0);
d735c391 2370 type = TREE_TYPE (arg);
2371 mode = TYPE_MODE (TREE_TYPE (arg));
2372
2373 /* Try expanding via a sincos optab, fall back to emitting a libcall
18b8d8ae 2374 to sincos or cexp. We are sure we have sincos or cexp because cexpi
2375 is only generated from sincos, cexp or if we have either of them. */
99bdde56 2376 if (optab_handler (sincos_optab, mode)->insn_code != CODE_FOR_nothing)
d735c391 2377 {
2378 op1 = gen_reg_rtx (mode);
2379 op2 = gen_reg_rtx (mode);
2380
1db6d067 2381 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
d735c391 2382
2383 /* Compute into op1 and op2. */
2384 expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
2385 }
18b8d8ae 2386 else if (TARGET_HAS_SINCOS)
d735c391 2387 {
c2f47e15 2388 tree call, fn = NULL_TREE;
d735c391 2389 tree top1, top2;
2390 rtx op1a, op2a;
2391
2392 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2393 fn = built_in_decls[BUILT_IN_SINCOSF];
2394 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2395 fn = built_in_decls[BUILT_IN_SINCOS];
2396 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2397 fn = built_in_decls[BUILT_IN_SINCOSL];
c2f47e15 2398 else
2399 gcc_unreachable ();
d735c391 2400
2401 op1 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
2402 op2 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
2403 op1a = copy_to_mode_reg (Pmode, XEXP (op1, 0));
2404 op2a = copy_to_mode_reg (Pmode, XEXP (op2, 0));
2405 top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
2406 top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
2407
d735c391 2408 /* Make sure not to fold the sincos call again. */
2409 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
c2f47e15 2410 expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
2411 call, 3, arg, top1, top2));
d735c391 2412 }
18b8d8ae 2413 else
2414 {
0ecbc158 2415 tree call, fn = NULL_TREE, narg;
18b8d8ae 2416 tree ctype = build_complex_type (type);
2417
0ecbc158 2418 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2419 fn = built_in_decls[BUILT_IN_CEXPF];
2420 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2421 fn = built_in_decls[BUILT_IN_CEXP];
2422 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2423 fn = built_in_decls[BUILT_IN_CEXPL];
c2f47e15 2424 else
2425 gcc_unreachable ();
fc0dfa6e 2426
2427 /* If we don't have a decl for cexp create one. This is the
2428 friendliest fallback if the user calls __builtin_cexpi
2429 without full target C99 function support. */
2430 if (fn == NULL_TREE)
2431 {
2432 tree fntype;
2433 const char *name = NULL;
2434
2435 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2436 name = "cexpf";
2437 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2438 name = "cexp";
2439 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2440 name = "cexpl";
2441
2442 fntype = build_function_type_list (ctype, ctype, NULL_TREE);
2443 fn = build_fn_decl (name, fntype);
2444 }
2445
18b8d8ae 2446 narg = fold_build2 (COMPLEX_EXPR, ctype,
2447 build_real (type, dconst0), arg);
2448
2449 /* Make sure not to fold the cexp call again. */
2450 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
3737e769 2451 return expand_expr (build_call_nary (ctype, call, 1, narg),
1db6d067 2452 target, VOIDmode, EXPAND_NORMAL);
18b8d8ae 2453 }
d735c391 2454
2455 /* Now build the proper return type. */
2456 return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
2457 make_tree (TREE_TYPE (arg), op2),
2458 make_tree (TREE_TYPE (arg), op1)),
1db6d067 2459 target, VOIDmode, EXPAND_NORMAL);
d735c391 2460}
2461
7d3afc77 2462/* Expand a call to one of the builtin rounding functions gcc defines
2463 as an extension (lfloor and lceil). As these are gcc extensions we
2464 do not need to worry about setting errno to EDOM.
ad52b9b7 2465 If expanding via optab fails, lower expression to (int)(floor(x)).
2466 EXP is the expression that is a call to the builtin function;
2467 if convenient, the result should be placed in TARGET. SUBTARGET may
2468 be used as the target for computing one of EXP's operands. */
2469
2470static rtx
2471expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget)
2472{
9c42dd28 2473 convert_optab builtin_optab;
ad52b9b7 2474 rtx op0, insns, tmp;
2475 tree fndecl = get_callee_fndecl (exp);
ad52b9b7 2476 enum built_in_function fallback_fn;
2477 tree fallback_fndecl;
2478 enum machine_mode mode;
4de0924f 2479 tree arg;
ad52b9b7 2480
c2f47e15 2481 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
ad52b9b7 2482 gcc_unreachable ();
2483
c2f47e15 2484 arg = CALL_EXPR_ARG (exp, 0);
ad52b9b7 2485
2486 switch (DECL_FUNCTION_CODE (fndecl))
2487 {
4f35b1fc 2488 CASE_FLT_FN (BUILT_IN_LCEIL):
2489 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 2490 builtin_optab = lceil_optab;
2491 fallback_fn = BUILT_IN_CEIL;
2492 break;
2493
4f35b1fc 2494 CASE_FLT_FN (BUILT_IN_LFLOOR):
2495 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 2496 builtin_optab = lfloor_optab;
2497 fallback_fn = BUILT_IN_FLOOR;
2498 break;
2499
2500 default:
2501 gcc_unreachable ();
2502 }
2503
2504 /* Make a suitable register to place result in. */
2505 mode = TYPE_MODE (TREE_TYPE (exp));
2506
9c42dd28 2507 target = gen_reg_rtx (mode);
ad52b9b7 2508
9c42dd28 2509 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2510 need to expand the argument again. This way, we will not perform
2511 side-effects more the once. */
abfea505 2512 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
ad52b9b7 2513
1db6d067 2514 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
ad52b9b7 2515
9c42dd28 2516 start_sequence ();
ad52b9b7 2517
9c42dd28 2518 /* Compute into TARGET. */
2519 if (expand_sfix_optab (target, op0, builtin_optab))
2520 {
2521 /* Output the entire sequence. */
2522 insns = get_insns ();
ad52b9b7 2523 end_sequence ();
9c42dd28 2524 emit_insn (insns);
2525 return target;
ad52b9b7 2526 }
2527
9c42dd28 2528 /* If we were unable to expand via the builtin, stop the sequence
2529 (without outputting the insns). */
2530 end_sequence ();
2531
ad52b9b7 2532 /* Fall back to floating point rounding optab. */
2533 fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
fc0dfa6e 2534
2535 /* For non-C99 targets we may end up without a fallback fndecl here
2536 if the user called __builtin_lfloor directly. In this case emit
2537 a call to the floor/ceil variants nevertheless. This should result
2538 in the best user experience for not full C99 targets. */
2539 if (fallback_fndecl == NULL_TREE)
2540 {
2541 tree fntype;
2542 const char *name = NULL;
2543
2544 switch (DECL_FUNCTION_CODE (fndecl))
2545 {
2546 case BUILT_IN_LCEIL:
2547 case BUILT_IN_LLCEIL:
2548 name = "ceil";
2549 break;
2550 case BUILT_IN_LCEILF:
2551 case BUILT_IN_LLCEILF:
2552 name = "ceilf";
2553 break;
2554 case BUILT_IN_LCEILL:
2555 case BUILT_IN_LLCEILL:
2556 name = "ceill";
2557 break;
2558 case BUILT_IN_LFLOOR:
2559 case BUILT_IN_LLFLOOR:
2560 name = "floor";
2561 break;
2562 case BUILT_IN_LFLOORF:
2563 case BUILT_IN_LLFLOORF:
2564 name = "floorf";
2565 break;
2566 case BUILT_IN_LFLOORL:
2567 case BUILT_IN_LLFLOORL:
2568 name = "floorl";
2569 break;
2570 default:
2571 gcc_unreachable ();
2572 }
2573
2574 fntype = build_function_type_list (TREE_TYPE (arg),
2575 TREE_TYPE (arg), NULL_TREE);
2576 fallback_fndecl = build_fn_decl (name, fntype);
2577 }
2578
c2f47e15 2579 exp = build_call_expr (fallback_fndecl, 1, arg);
ad52b9b7 2580
d4c690af 2581 tmp = expand_normal (exp);
ad52b9b7 2582
2583 /* Truncate the result of floating point optab to integer
2584 via expand_fix (). */
2585 target = gen_reg_rtx (mode);
2586 expand_fix (target, tmp, 0);
2587
2588 return target;
2589}
2590
7d3afc77 2591/* Expand a call to one of the builtin math functions doing integer
2592 conversion (lrint).
2593 Return 0 if a normal call should be emitted rather than expanding the
2594 function in-line. EXP is the expression that is a call to the builtin
2595 function; if convenient, the result should be placed in TARGET.
2596 SUBTARGET may be used as the target for computing one of EXP's operands. */
2597
2598static rtx
2599expand_builtin_int_roundingfn_2 (tree exp, rtx target, rtx subtarget)
2600{
5f51ee59 2601 convert_optab builtin_optab;
7d3afc77 2602 rtx op0, insns;
2603 tree fndecl = get_callee_fndecl (exp);
4de0924f 2604 tree arg;
c2f47e15 2605 enum machine_mode mode;
7d3afc77 2606
2607 /* There's no easy way to detect the case we need to set EDOM. */
2608 if (flag_errno_math)
2609 return NULL_RTX;
2610
c2f47e15 2611 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2612 gcc_unreachable ();
2613
2614 arg = CALL_EXPR_ARG (exp, 0);
7d3afc77 2615
2616 switch (DECL_FUNCTION_CODE (fndecl))
2617 {
2618 CASE_FLT_FN (BUILT_IN_LRINT):
2619 CASE_FLT_FN (BUILT_IN_LLRINT):
2620 builtin_optab = lrint_optab; break;
ef2f1a10 2621 CASE_FLT_FN (BUILT_IN_LROUND):
2622 CASE_FLT_FN (BUILT_IN_LLROUND):
2623 builtin_optab = lround_optab; break;
7d3afc77 2624 default:
2625 gcc_unreachable ();
2626 }
2627
2628 /* Make a suitable register to place result in. */
2629 mode = TYPE_MODE (TREE_TYPE (exp));
2630
5f51ee59 2631 target = gen_reg_rtx (mode);
7d3afc77 2632
5f51ee59 2633 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2634 need to expand the argument again. This way, we will not perform
2635 side-effects more the once. */
abfea505 2636 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7d3afc77 2637
1db6d067 2638 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
7d3afc77 2639
5f51ee59 2640 start_sequence ();
7d3afc77 2641
5f51ee59 2642 if (expand_sfix_optab (target, op0, builtin_optab))
2643 {
2644 /* Output the entire sequence. */
2645 insns = get_insns ();
7d3afc77 2646 end_sequence ();
5f51ee59 2647 emit_insn (insns);
2648 return target;
7d3afc77 2649 }
2650
5f51ee59 2651 /* If we were unable to expand via the builtin, stop the sequence
2652 (without outputting the insns) and call to the library function
2653 with the stabilized argument list. */
2654 end_sequence ();
2655
7d3afc77 2656 target = expand_call (exp, target, target == const0_rtx);
2657
2658 return target;
2659}
2660
f1b844c6 2661/* To evaluate powi(x,n), the floating point value x raised to the
2662 constant integer exponent n, we use a hybrid algorithm that
2663 combines the "window method" with look-up tables. For an
2664 introduction to exponentiation algorithms and "addition chains",
2665 see section 4.6.3, "Evaluation of Powers" of Donald E. Knuth,
2666 "Seminumerical Algorithms", Vol. 2, "The Art of Computer Programming",
2667 3rd Edition, 1998, and Daniel M. Gordon, "A Survey of Fast Exponentiation
2668 Methods", Journal of Algorithms, Vol. 27, pp. 129-146, 1998. */
2669
2670/* Provide a default value for POWI_MAX_MULTS, the maximum number of
2671 multiplications to inline before calling the system library's pow
2672 function. powi(x,n) requires at worst 2*bits(n)-2 multiplications,
2673 so this default never requires calling pow, powf or powl. */
0862b7e9 2674
f1b844c6 2675#ifndef POWI_MAX_MULTS
2676#define POWI_MAX_MULTS (2*HOST_BITS_PER_WIDE_INT-2)
2677#endif
2678
2679/* The size of the "optimal power tree" lookup table. All
2680 exponents less than this value are simply looked up in the
2681 powi_table below. This threshold is also used to size the
2682 cache of pseudo registers that hold intermediate results. */
2683#define POWI_TABLE_SIZE 256
2684
2685/* The size, in bits of the window, used in the "window method"
2686 exponentiation algorithm. This is equivalent to a radix of
2687 (1<<POWI_WINDOW_SIZE) in the corresponding "m-ary method". */
2688#define POWI_WINDOW_SIZE 3
2689
2690/* The following table is an efficient representation of an
2691 "optimal power tree". For each value, i, the corresponding
2692 value, j, in the table states than an optimal evaluation
2693 sequence for calculating pow(x,i) can be found by evaluating
2694 pow(x,j)*pow(x,i-j). An optimal power tree for the first
2695 100 integers is given in Knuth's "Seminumerical algorithms". */
2696
2697static const unsigned char powi_table[POWI_TABLE_SIZE] =
2698 {
2699 0, 1, 1, 2, 2, 3, 3, 4, /* 0 - 7 */
2700 4, 6, 5, 6, 6, 10, 7, 9, /* 8 - 15 */
2701 8, 16, 9, 16, 10, 12, 11, 13, /* 16 - 23 */
2702 12, 17, 13, 18, 14, 24, 15, 26, /* 24 - 31 */
2703 16, 17, 17, 19, 18, 33, 19, 26, /* 32 - 39 */
2704 20, 25, 21, 40, 22, 27, 23, 44, /* 40 - 47 */
2705 24, 32, 25, 34, 26, 29, 27, 44, /* 48 - 55 */
2706 28, 31, 29, 34, 30, 60, 31, 36, /* 56 - 63 */
2707 32, 64, 33, 34, 34, 46, 35, 37, /* 64 - 71 */
2708 36, 65, 37, 50, 38, 48, 39, 69, /* 72 - 79 */
2709 40, 49, 41, 43, 42, 51, 43, 58, /* 80 - 87 */
2710 44, 64, 45, 47, 46, 59, 47, 76, /* 88 - 95 */
2711 48, 65, 49, 66, 50, 67, 51, 66, /* 96 - 103 */
2712 52, 70, 53, 74, 54, 104, 55, 74, /* 104 - 111 */
2713 56, 64, 57, 69, 58, 78, 59, 68, /* 112 - 119 */
2714 60, 61, 61, 80, 62, 75, 63, 68, /* 120 - 127 */
2715 64, 65, 65, 128, 66, 129, 67, 90, /* 128 - 135 */
2716 68, 73, 69, 131, 70, 94, 71, 88, /* 136 - 143 */
2717 72, 128, 73, 98, 74, 132, 75, 121, /* 144 - 151 */
2718 76, 102, 77, 124, 78, 132, 79, 106, /* 152 - 159 */
2719 80, 97, 81, 160, 82, 99, 83, 134, /* 160 - 167 */
2720 84, 86, 85, 95, 86, 160, 87, 100, /* 168 - 175 */
2721 88, 113, 89, 98, 90, 107, 91, 122, /* 176 - 183 */
2722 92, 111, 93, 102, 94, 126, 95, 150, /* 184 - 191 */
2723 96, 128, 97, 130, 98, 133, 99, 195, /* 192 - 199 */
2724 100, 128, 101, 123, 102, 164, 103, 138, /* 200 - 207 */
2725 104, 145, 105, 146, 106, 109, 107, 149, /* 208 - 215 */
2726 108, 200, 109, 146, 110, 170, 111, 157, /* 216 - 223 */
2727 112, 128, 113, 130, 114, 182, 115, 132, /* 224 - 231 */
2728 116, 200, 117, 132, 118, 158, 119, 206, /* 232 - 239 */
2729 120, 240, 121, 162, 122, 147, 123, 152, /* 240 - 247 */
2730 124, 166, 125, 214, 126, 138, 127, 153, /* 248 - 255 */
2731 };
2732
2733
2734/* Return the number of multiplications required to calculate
2735 powi(x,n) where n is less than POWI_TABLE_SIZE. This is a
2736 subroutine of powi_cost. CACHE is an array indicating
2737 which exponents have already been calculated. */
2738
2739static int
2740powi_lookup_cost (unsigned HOST_WIDE_INT n, bool *cache)
2741{
2742 /* If we've already calculated this exponent, then this evaluation
2743 doesn't require any additional multiplications. */
2744 if (cache[n])
2745 return 0;
2746
2747 cache[n] = true;
2748 return powi_lookup_cost (n - powi_table[n], cache)
2749 + powi_lookup_cost (powi_table[n], cache) + 1;
2750}
2751
2752/* Return the number of multiplications required to calculate
2753 powi(x,n) for an arbitrary x, given the exponent N. This
2754 function needs to be kept in sync with expand_powi below. */
2755
2756static int
2757powi_cost (HOST_WIDE_INT n)
2758{
2759 bool cache[POWI_TABLE_SIZE];
2760 unsigned HOST_WIDE_INT digit;
2761 unsigned HOST_WIDE_INT val;
2762 int result;
2763
2764 if (n == 0)
2765 return 0;
2766
2767 /* Ignore the reciprocal when calculating the cost. */
2768 val = (n < 0) ? -n : n;
2769
2770 /* Initialize the exponent cache. */
2771 memset (cache, 0, POWI_TABLE_SIZE * sizeof (bool));
2772 cache[1] = true;
2773
2774 result = 0;
2775
2776 while (val >= POWI_TABLE_SIZE)
2777 {
2778 if (val & 1)
2779 {
2780 digit = val & ((1 << POWI_WINDOW_SIZE) - 1);
2781 result += powi_lookup_cost (digit, cache)
2782 + POWI_WINDOW_SIZE + 1;
2783 val >>= POWI_WINDOW_SIZE;
2784 }
2785 else
2786 {
2787 val >>= 1;
2788 result++;
2789 }
2790 }
0862b7e9 2791
6881dbab 2792 return result + powi_lookup_cost (val, cache);
f1b844c6 2793}
2794
2795/* Recursive subroutine of expand_powi. This function takes the array,
2796 CACHE, of already calculated exponents and an exponent N and returns
2797 an RTX that corresponds to CACHE[1]**N, as calculated in mode MODE. */
2798
2799static rtx
2800expand_powi_1 (enum machine_mode mode, unsigned HOST_WIDE_INT n, rtx *cache)
2801{
2802 unsigned HOST_WIDE_INT digit;
2803 rtx target, result;
2804 rtx op0, op1;
2805
2806 if (n < POWI_TABLE_SIZE)
2807 {
2808 if (cache[n])
a0c938f0 2809 return cache[n];
f1b844c6 2810
2811 target = gen_reg_rtx (mode);
2812 cache[n] = target;
2813
2814 op0 = expand_powi_1 (mode, n - powi_table[n], cache);
2815 op1 = expand_powi_1 (mode, powi_table[n], cache);
2816 }
2817 else if (n & 1)
2818 {
2819 target = gen_reg_rtx (mode);
2820 digit = n & ((1 << POWI_WINDOW_SIZE) - 1);
2821 op0 = expand_powi_1 (mode, n - digit, cache);
2822 op1 = expand_powi_1 (mode, digit, cache);
2823 }
2824 else
2825 {
2826 target = gen_reg_rtx (mode);
2827 op0 = expand_powi_1 (mode, n >> 1, cache);
2828 op1 = op0;
2829 }
2830
2831 result = expand_mult (mode, op0, op1, target, 0);
2832 if (result != target)
2833 emit_move_insn (target, result);
2834 return target;
2835}
2836
2837/* Expand the RTL to evaluate powi(x,n) in mode MODE. X is the
2838 floating point operand in mode MODE, and N is the exponent. This
2839 function needs to be kept in sync with powi_cost above. */
0862b7e9 2840
f1b844c6 2841static rtx
2842expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n)
2843{
2844 unsigned HOST_WIDE_INT val;
2845 rtx cache[POWI_TABLE_SIZE];
2846 rtx result;
2847
2848 if (n == 0)
2849 return CONST1_RTX (mode);
2850
2851 val = (n < 0) ? -n : n;
2852
19bf118a 2853 memset (cache, 0, sizeof (cache));
f1b844c6 2854 cache[1] = x;
2855
2856 result = expand_powi_1 (mode, (n < 0) ? -n : n, cache);
2857
2858 /* If the original exponent was negative, reciprocate the result. */
2859 if (n < 0)
2860 result = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2861 result, NULL_RTX, 0, OPTAB_LIB_WIDEN);
2862
2863 return result;
2864}
2865
c2f47e15 2866/* Expand a call to the pow built-in mathematical function. Return NULL_RTX if
f1b844c6 2867 a normal call should be emitted rather than expanding the function
2868 in-line. EXP is the expression that is a call to the builtin
2869 function; if convenient, the result should be placed in TARGET. */
2870
2871static rtx
2872expand_builtin_pow (tree exp, rtx target, rtx subtarget)
2873{
c2f47e15 2874 tree arg0, arg1;
2875 tree fn, narg0;
1c4709b4 2876 tree type = TREE_TYPE (exp);
2877 REAL_VALUE_TYPE cint, c, c2;
2878 HOST_WIDE_INT n;
2879 rtx op, op2;
2880 enum machine_mode mode = TYPE_MODE (type);
f1b844c6 2881
c2f47e15 2882 if (! validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2883 return NULL_RTX;
f1b844c6 2884
c2f47e15 2885 arg0 = CALL_EXPR_ARG (exp, 0);
2886 arg1 = CALL_EXPR_ARG (exp, 1);
f1b844c6 2887
1c4709b4 2888 if (TREE_CODE (arg1) != REAL_CST
f96bd2bf 2889 || TREE_OVERFLOW (arg1))
1c4709b4 2890 return expand_builtin_mathfn_2 (exp, target, subtarget);
2891
2892 /* Handle constant exponents. */
2893
2894 /* For integer valued exponents we can expand to an optimal multiplication
2895 sequence using expand_powi. */
2896 c = TREE_REAL_CST (arg1);
2897 n = real_to_integer (&c);
2898 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
2899 if (real_identical (&c, &cint)
2900 && ((n >= -1 && n <= 2)
2901 || (flag_unsafe_math_optimizations
2902 && !optimize_size
2903 && powi_cost (n) <= POWI_MAX_MULTS)))
f1b844c6 2904 {
1db6d067 2905 op = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 2906 if (n != 1)
2907 {
2908 op = force_reg (mode, op);
2909 op = expand_powi (op, mode, n);
2910 }
2911 return op;
2912 }
2913
2914 narg0 = builtin_save_expr (arg0);
f1b844c6 2915
1c4709b4 2916 /* If the exponent is not integer valued, check if it is half of an integer.
2917 In this case we can expand to sqrt (x) * x**(n/2). */
2918 fn = mathfn_built_in (type, BUILT_IN_SQRT);
2919 if (fn != NULL_TREE)
2920 {
2921 real_arithmetic (&c2, MULT_EXPR, &c, &dconst2);
2922 n = real_to_integer (&c2);
f1b844c6 2923 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
1c4709b4 2924 if (real_identical (&c2, &cint)
2925 && ((flag_unsafe_math_optimizations
2926 && !optimize_size
2927 && powi_cost (n/2) <= POWI_MAX_MULTS)
2928 || n == 1))
f1b844c6 2929 {
c2f47e15 2930 tree call_expr = build_call_expr (fn, 1, narg0);
8697cf4d 2931 /* Use expand_expr in case the newly built call expression
2932 was folded to a non-call. */
2933 op = expand_expr (call_expr, subtarget, mode, EXPAND_NORMAL);
1c4709b4 2934 if (n != 1)
8c5cac78 2935 {
1db6d067 2936 op2 = expand_expr (narg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 2937 op2 = force_reg (mode, op2);
2938 op2 = expand_powi (op2, mode, abs (n / 2));
2939 op = expand_simple_binop (mode, MULT, op, op2, NULL_RTX,
2940 0, OPTAB_LIB_WIDEN);
2941 /* If the original exponent was negative, reciprocate the
2942 result. */
2943 if (n < 0)
2944 op = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2945 op, NULL_RTX, 0, OPTAB_LIB_WIDEN);
8c5cac78 2946 }
1c4709b4 2947 return op;
f1b844c6 2948 }
2949 }
b613c2a6 2950
1c4709b4 2951 /* Try if the exponent is a third of an integer. In this case
5a84ba55 2952 we can expand to x**(n/3) * cbrt(x)**(n%3). As cbrt (x) is
2953 different from pow (x, 1./3.) due to rounding and behavior
2954 with negative x we need to constrain this transformation to
2955 unsafe math and positive x or finite math. */
1c4709b4 2956 fn = mathfn_built_in (type, BUILT_IN_CBRT);
5a84ba55 2957 if (fn != NULL_TREE
2958 && flag_unsafe_math_optimizations
2959 && (tree_expr_nonnegative_p (arg0)
2960 || !HONOR_NANS (mode)))
1c4709b4 2961 {
3fa759a9 2962 REAL_VALUE_TYPE dconst3;
2963 real_from_integer (&dconst3, VOIDmode, 3, 0, 0);
1c4709b4 2964 real_arithmetic (&c2, MULT_EXPR, &c, &dconst3);
2965 real_round (&c2, mode, &c2);
2966 n = real_to_integer (&c2);
2967 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
2968 real_arithmetic (&c2, RDIV_EXPR, &cint, &dconst3);
2969 real_convert (&c2, mode, &c2);
2970 if (real_identical (&c2, &c)
2971 && ((!optimize_size
1c4709b4 2972 && powi_cost (n/3) <= POWI_MAX_MULTS)
2973 || n == 1))
2974 {
c2f47e15 2975 tree call_expr = build_call_expr (fn, 1,narg0);
1c4709b4 2976 op = expand_builtin (call_expr, NULL_RTX, subtarget, mode, 0);
2977 if (abs (n) % 3 == 2)
2978 op = expand_simple_binop (mode, MULT, op, op, op,
2979 0, OPTAB_LIB_WIDEN);
2980 if (n != 1)
2981 {
1db6d067 2982 op2 = expand_expr (narg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 2983 op2 = force_reg (mode, op2);
2984 op2 = expand_powi (op2, mode, abs (n / 3));
2985 op = expand_simple_binop (mode, MULT, op, op2, NULL_RTX,
2986 0, OPTAB_LIB_WIDEN);
2987 /* If the original exponent was negative, reciprocate the
2988 result. */
2989 if (n < 0)
2990 op = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2991 op, NULL_RTX, 0, OPTAB_LIB_WIDEN);
2992 }
2993 return op;
2994 }
2995 }
2996
2997 /* Fall back to optab expansion. */
b613c2a6 2998 return expand_builtin_mathfn_2 (exp, target, subtarget);
f1b844c6 2999}
3000
c2f47e15 3001/* Expand a call to the powi built-in mathematical function. Return NULL_RTX if
757c219d 3002 a normal call should be emitted rather than expanding the function
3003 in-line. EXP is the expression that is a call to the builtin
3004 function; if convenient, the result should be placed in TARGET. */
3005
3006static rtx
3007expand_builtin_powi (tree exp, rtx target, rtx subtarget)
3008{
757c219d 3009 tree arg0, arg1;
3010 rtx op0, op1;
3011 enum machine_mode mode;
d0405f40 3012 enum machine_mode mode2;
757c219d 3013
c2f47e15 3014 if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
3015 return NULL_RTX;
757c219d 3016
c2f47e15 3017 arg0 = CALL_EXPR_ARG (exp, 0);
3018 arg1 = CALL_EXPR_ARG (exp, 1);
757c219d 3019 mode = TYPE_MODE (TREE_TYPE (exp));
3020
3021 /* Handle constant power. */
3022
3023 if (TREE_CODE (arg1) == INTEGER_CST
f96bd2bf 3024 && !TREE_OVERFLOW (arg1))
757c219d 3025 {
3026 HOST_WIDE_INT n = TREE_INT_CST_LOW (arg1);
3027
3028 /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
3029 Otherwise, check the number of multiplications required. */
3030 if ((TREE_INT_CST_HIGH (arg1) == 0
3031 || TREE_INT_CST_HIGH (arg1) == -1)
3032 && ((n >= -1 && n <= 2)
3033 || (! optimize_size
3034 && powi_cost (n) <= POWI_MAX_MULTS)))
3035 {
1db6d067 3036 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
757c219d 3037 op0 = force_reg (mode, op0);
3038 return expand_powi (op0, mode, n);
3039 }
3040 }
3041
3042 /* Emit a libcall to libgcc. */
3043
c2f47e15 3044 /* Mode of the 2nd argument must match that of an int. */
d0405f40 3045 mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
3046
757c219d 3047 if (target == NULL_RTX)
3048 target = gen_reg_rtx (mode);
3049
1db6d067 3050 op0 = expand_expr (arg0, subtarget, mode, EXPAND_NORMAL);
757c219d 3051 if (GET_MODE (op0) != mode)
3052 op0 = convert_to_mode (mode, op0, 0);
1db6d067 3053 op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
d0405f40 3054 if (GET_MODE (op1) != mode2)
3055 op1 = convert_to_mode (mode2, op1, 0);
757c219d 3056
f36b9f69 3057 target = emit_library_call_value (optab_libfunc (powi_optab, mode),
2dd6f9ed 3058 target, LCT_CONST, mode, 2,
d0405f40 3059 op0, mode, op1, mode2);
757c219d 3060
3061 return target;
3062}
3063
c2f47e15 3064/* Expand expression EXP which is a call to the strlen builtin. Return
3065 NULL_RTX if we failed the caller should emit a normal call, otherwise
aed0bd19 3066 try to get the result in TARGET, if convenient. */
f7c44134 3067
53800dbe 3068static rtx
c2f47e15 3069expand_builtin_strlen (tree exp, rtx target,
aecda0d6 3070 enum machine_mode target_mode)
53800dbe 3071{
c2f47e15 3072 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
3073 return NULL_RTX;
53800dbe 3074 else
3075 {
911c0150 3076 rtx pat;
c2f47e15 3077 tree len;
3078 tree src = CALL_EXPR_ARG (exp, 0);
911c0150 3079 rtx result, src_reg, char_rtx, before_strlen;
80cd7a5e 3080 enum machine_mode insn_mode = target_mode, char_mode;
ef2c4a29 3081 enum insn_code icode = CODE_FOR_nothing;
6248e345 3082 int align;
3083
3084 /* If the length can be computed at compile-time, return it. */
681fab1e 3085 len = c_strlen (src, 0);
6248e345 3086 if (len)
80cd7a5e 3087 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
6248e345 3088
681fab1e 3089 /* If the length can be computed at compile-time and is constant
3090 integer, but there are side-effects in src, evaluate
3091 src for side-effects, then return len.
3092 E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
3093 can be optimized into: i++; x = 3; */
3094 len = c_strlen (src, 1);
3095 if (len && TREE_CODE (len) == INTEGER_CST)
3096 {
3097 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
3098 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
3099 }
3100
6248e345 3101 align = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
53800dbe 3102
53800dbe 3103 /* If SRC is not a pointer type, don't do this operation inline. */
3104 if (align == 0)
c2f47e15 3105 return NULL_RTX;
53800dbe 3106
911c0150 3107 /* Bail out if we can't compute strlen in the right mode. */
53800dbe 3108 while (insn_mode != VOIDmode)
3109 {
99bdde56 3110 icode = optab_handler (strlen_optab, insn_mode)->insn_code;
53800dbe 3111 if (icode != CODE_FOR_nothing)
c28ae87f 3112 break;
53800dbe 3113
3114 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
3115 }
3116 if (insn_mode == VOIDmode)
c2f47e15 3117 return NULL_RTX;
53800dbe 3118
3119 /* Make a place to write the result of the instruction. */
3120 result = target;
3121 if (! (result != 0
8ad4c111 3122 && REG_P (result)
53800dbe 3123 && GET_MODE (result) == insn_mode
3124 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3125 result = gen_reg_rtx (insn_mode);
3126
911c0150 3127 /* Make a place to hold the source address. We will not expand
3128 the actual source until we are sure that the expansion will
3129 not fail -- there are trees that cannot be expanded twice. */
3130 src_reg = gen_reg_rtx (Pmode);
53800dbe 3131
911c0150 3132 /* Mark the beginning of the strlen sequence so we can emit the
3133 source operand later. */
f0ce3b1f 3134 before_strlen = get_last_insn ();
53800dbe 3135
53800dbe 3136 char_rtx = const0_rtx;
f7c44134 3137 char_mode = insn_data[(int) icode].operand[2].mode;
3138 if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
3139 char_mode))
53800dbe 3140 char_rtx = copy_to_mode_reg (char_mode, char_rtx);
3141
911c0150 3142 pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
3143 char_rtx, GEN_INT (align));
3144 if (! pat)
c2f47e15 3145 return NULL_RTX;
911c0150 3146 emit_insn (pat);
3147
3148 /* Now that we are assured of success, expand the source. */
3149 start_sequence ();
c5aba89c 3150 pat = expand_expr (src, src_reg, ptr_mode, EXPAND_NORMAL);
911c0150 3151 if (pat != src_reg)
3152 emit_move_insn (src_reg, pat);
31d3e01c 3153 pat = get_insns ();
911c0150 3154 end_sequence ();
bceb0d1f 3155
3156 if (before_strlen)
3157 emit_insn_after (pat, before_strlen);
3158 else
3159 emit_insn_before (pat, get_insns ());
53800dbe 3160
3161 /* Return the value in the proper mode for this function. */
80cd7a5e 3162 if (GET_MODE (result) == target_mode)
911c0150 3163 target = result;
53800dbe 3164 else if (target != 0)
911c0150 3165 convert_move (target, result, 0);
53800dbe 3166 else
80cd7a5e 3167 target = convert_to_mode (target_mode, result, 0);
911c0150 3168
3169 return target;
53800dbe 3170 }
3171}
3172
c2f47e15 3173/* Expand a call to the strstr builtin. Return NULL_RTX if we failed the
17f5ea87 3174 caller should emit a normal call, otherwise try to get the result
3175 in TARGET, if convenient (and in mode MODE if that's convenient). */
3176
3177static rtx
c2f47e15 3178expand_builtin_strstr (tree exp, rtx target, enum machine_mode mode)
17f5ea87 3179{
c2f47e15 3180 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
17f5ea87 3181 {
c2f47e15 3182 tree type = TREE_TYPE (exp);
3183 tree result = fold_builtin_strstr (CALL_EXPR_ARG (exp, 0),
3184 CALL_EXPR_ARG (exp, 1), type);
2c84ee37 3185 if (result)
3186 return expand_expr (result, target, mode, EXPAND_NORMAL);
17f5ea87 3187 }
c2f47e15 3188 return NULL_RTX;
17f5ea87 3189}
3190
c2f47e15 3191/* Expand a call to the strchr builtin. Return NULL_RTX if we failed the
46f3a74a 3192 caller should emit a normal call, otherwise try to get the result
3193 in TARGET, if convenient (and in mode MODE if that's convenient). */
3194
3195static rtx
c2f47e15 3196expand_builtin_strchr (tree exp, rtx target, enum machine_mode mode)
46f3a74a 3197{
c2f47e15 3198 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
46f3a74a 3199 {
c2f47e15 3200 tree type = TREE_TYPE (exp);
3201 tree result = fold_builtin_strchr (CALL_EXPR_ARG (exp, 0),
3202 CALL_EXPR_ARG (exp, 1), type);
2c84ee37 3203 if (result)
3204 return expand_expr (result, target, mode, EXPAND_NORMAL);
83d79705 3205
2c84ee37 3206 /* FIXME: Should use strchrM optab so that ports can optimize this. */
83d79705 3207 }
c2f47e15 3208 return NULL_RTX;
83d79705 3209}
3210
c2f47e15 3211/* Expand a call to the strrchr builtin. Return NULL_RTX if we failed the
83d79705 3212 caller should emit a normal call, otherwise try to get the result
3213 in TARGET, if convenient (and in mode MODE if that's convenient). */
3214
3215static rtx
c2f47e15 3216expand_builtin_strrchr (tree exp, rtx target, enum machine_mode mode)
83d79705 3217{
c2f47e15 3218 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
83d79705 3219 {
c2f47e15 3220 tree type = TREE_TYPE (exp);
3221 tree result = fold_builtin_strrchr (CALL_EXPR_ARG (exp, 0),
3222 CALL_EXPR_ARG (exp, 1), type);
2c84ee37 3223 if (result)
3224 return expand_expr (result, target, mode, EXPAND_NORMAL);
83d79705 3225 }
c2f47e15 3226 return NULL_RTX;
83d79705 3227}
3228
c2f47e15 3229/* Expand a call to the strpbrk builtin. Return NULL_RTX if we failed the
83d79705 3230 caller should emit a normal call, otherwise try to get the result
3231 in TARGET, if convenient (and in mode MODE if that's convenient). */
3232
3233static rtx
c2f47e15 3234expand_builtin_strpbrk (tree exp, rtx target, enum machine_mode mode)
83d79705 3235{
c2f47e15 3236 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
83d79705 3237 {
c2f47e15 3238 tree type = TREE_TYPE (exp);
3239 tree result = fold_builtin_strpbrk (CALL_EXPR_ARG (exp, 0),
3240 CALL_EXPR_ARG (exp, 1), type);
2c84ee37 3241 if (result)
3242 return expand_expr (result, target, mode, EXPAND_NORMAL);
46f3a74a 3243 }
c2f47e15 3244 return NULL_RTX;
46f3a74a 3245}
3246
6840589f 3247/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3248 bytes from constant string DATA + OFFSET and return it as target
3249 constant. */
3250
3251static rtx
aecda0d6 3252builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
3253 enum machine_mode mode)
6840589f 3254{
3255 const char *str = (const char *) data;
3256
64db345d 3257 gcc_assert (offset >= 0
3258 && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
3259 <= strlen (str) + 1));
6840589f 3260
3261 return c_readstr (str + offset, mode);
3262}
3263
c2f47e15 3264/* Expand a call EXP to the memcpy builtin.
3265 Return NULL_RTX if we failed, the caller should emit a normal call,
3b824fa6 3266 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3267 mode MODE if that's convenient). */
c2f47e15 3268
53800dbe 3269static rtx
5a0de151 3270expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode)
53800dbe 3271{
8e76ec06 3272 tree fndecl = get_callee_fndecl (exp);
c2f47e15 3273
3274 if (!validate_arglist (exp,
3275 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3276 return NULL_RTX;
53800dbe 3277 else
3278 {
c2f47e15 3279 tree dest = CALL_EXPR_ARG (exp, 0);
3280 tree src = CALL_EXPR_ARG (exp, 1);
3281 tree len = CALL_EXPR_ARG (exp, 2);
6840589f 3282 const char *src_str;
27d0c333 3283 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3284 unsigned int dest_align
3285 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
53800dbe 3286 rtx dest_mem, src_mem, dest_addr, len_rtx;
c2f47e15 3287 tree result = fold_builtin_memory_op (dest, src, len,
3288 TREE_TYPE (TREE_TYPE (fndecl)),
4f46f2b9 3289 false, /*endp=*/0);
162719b3 3290 HOST_WIDE_INT expected_size = -1;
3291 unsigned int expected_align = 0;
5a0de151 3292
3293 if (result)
4f46f2b9 3294 {
3295 while (TREE_CODE (result) == COMPOUND_EXPR)
3296 {
3297 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3298 EXPAND_NORMAL);
3299 result = TREE_OPERAND (result, 1);
3300 }
3301 return expand_expr (result, target, mode, EXPAND_NORMAL);
3302 }
53800dbe 3303
6f428e8b 3304 /* If DEST is not a pointer type, call the normal function. */
3305 if (dest_align == 0)
c2f47e15 3306 return NULL_RTX;
6f428e8b 3307
6f428e8b 3308 /* If either SRC is not a pointer type, don't do this
a0c938f0 3309 operation in-line. */
6f428e8b 3310 if (src_align == 0)
c2f47e15 3311 return NULL_RTX;
162719b3 3312
3313 stringop_block_profile (exp, &expected_align, &expected_size);
3314 if (expected_align < dest_align)
3315 expected_align = dest_align;
d8ae1baa 3316 dest_mem = get_memory_rtx (dest, len);
2a631e19 3317 set_mem_align (dest_mem, dest_align);
8ec3c5c2 3318 len_rtx = expand_normal (len);
6840589f 3319 src_str = c_getstr (src);
3320
3321 /* If SRC is a string constant and block move would be done
3322 by pieces, we can avoid loading the string from memory
3323 and only stored the computed constants. */
3324 if (src_str
6840589f 3325 && GET_CODE (len_rtx) == CONST_INT
3326 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3327 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3328 CONST_CAST (char *, src_str),
3329 dest_align, false))
6840589f 3330 {
9fe0e1b8 3331 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3332 builtin_memcpy_read_str,
364c0c59 3333 CONST_CAST (char *, src_str),
3334 dest_align, false, 0);
e5716f7e 3335 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3336 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3337 return dest_mem;
6840589f 3338 }
3339
d8ae1baa 3340 src_mem = get_memory_rtx (src, len);
2a631e19 3341 set_mem_align (src_mem, src_align);
53800dbe 3342
53800dbe 3343 /* Copy word part most expediently. */
162719b3 3344 dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
3345 CALL_EXPR_TAILCALL (exp)
3346 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3347 expected_align, expected_size);
53800dbe 3348
3349 if (dest_addr == 0)
e5716f7e 3350 {
3351 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3352 dest_addr = convert_memory_address (ptr_mode, dest_addr);
e5716f7e 3353 }
9fe0e1b8 3354 return dest_addr;
53800dbe 3355 }
3356}
3357
c2f47e15 3358/* Expand a call EXP to the mempcpy builtin.
3359 Return NULL_RTX if we failed; the caller should emit a normal call,
647661c6 3360 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3361 mode MODE if that's convenient). If ENDP is 0 return the
3362 destination pointer, if ENDP is 1 return the end pointer ala
3363 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3364 stpcpy. */
647661c6 3365
3366static rtx
c2f47e15 3367expand_builtin_mempcpy(tree exp, rtx target, enum machine_mode mode)
647661c6 3368{
c2f47e15 3369 if (!validate_arglist (exp,
3370 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3371 return NULL_RTX;
3372 else
3373 {
3374 tree dest = CALL_EXPR_ARG (exp, 0);
3375 tree src = CALL_EXPR_ARG (exp, 1);
3376 tree len = CALL_EXPR_ARG (exp, 2);
3377 return expand_builtin_mempcpy_args (dest, src, len,
3378 TREE_TYPE (exp),
3379 target, mode, /*endp=*/ 1);
3380 }
3381}
3382
3383/* Helper function to do the actual work for expand_builtin_mempcpy. The
3384 arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out
3385 so that this can also be called without constructing an actual CALL_EXPR.
3386 TYPE is the return type of the call. The other arguments and return value
3387 are the same as for expand_builtin_mempcpy. */
3388
3389static rtx
3390expand_builtin_mempcpy_args (tree dest, tree src, tree len, tree type,
3391 rtx target, enum machine_mode mode, int endp)
3392{
3393 /* If return value is ignored, transform mempcpy into memcpy. */
3394 if (target == const0_rtx)
9fe0e1b8 3395 {
3396 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
3397
3398 if (!fn)
c2f47e15 3399 return NULL_RTX;
9fe0e1b8 3400
c2f47e15 3401 return expand_expr (build_call_expr (fn, 3, dest, src, len),
9fe0e1b8 3402 target, mode, EXPAND_NORMAL);
3403 }
647661c6 3404 else
3405 {
9fe0e1b8 3406 const char *src_str;
3407 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3408 unsigned int dest_align
3409 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3410 rtx dest_mem, src_mem, len_rtx;
c2f47e15 3411 tree result = fold_builtin_memory_op (dest, src, len, type, false, endp);
9fe0e1b8 3412
7da1412b 3413 if (result)
4f46f2b9 3414 {
3415 while (TREE_CODE (result) == COMPOUND_EXPR)
3416 {
3417 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3418 EXPAND_NORMAL);
3419 result = TREE_OPERAND (result, 1);
3420 }
3421 return expand_expr (result, target, mode, EXPAND_NORMAL);
3422 }
a0c938f0 3423
7da1412b 3424 /* If either SRC or DEST is not a pointer type, don't do this
a0c938f0 3425 operation in-line. */
7da1412b 3426 if (dest_align == 0 || src_align == 0)
c2f47e15 3427 return NULL_RTX;
9fe0e1b8 3428
6217c238 3429 /* If LEN is not constant, call the normal function. */
3430 if (! host_integerp (len, 1))
c2f47e15 3431 return NULL_RTX;
0862b7e9 3432
8ec3c5c2 3433 len_rtx = expand_normal (len);
9fe0e1b8 3434 src_str = c_getstr (src);
647661c6 3435
9fe0e1b8 3436 /* If SRC is a string constant and block move would be done
3437 by pieces, we can avoid loading the string from memory
3438 and only stored the computed constants. */
3439 if (src_str
3440 && GET_CODE (len_rtx) == CONST_INT
3441 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3442 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3443 CONST_CAST (char *, src_str),
3444 dest_align, false))
9fe0e1b8 3445 {
d8ae1baa 3446 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3447 set_mem_align (dest_mem, dest_align);
3448 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3449 builtin_memcpy_read_str,
364c0c59 3450 CONST_CAST (char *, src_str),
3451 dest_align, false, endp);
9fe0e1b8 3452 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3453 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3454 return dest_mem;
647661c6 3455 }
3456
9fe0e1b8 3457 if (GET_CODE (len_rtx) == CONST_INT
3458 && can_move_by_pieces (INTVAL (len_rtx),
3459 MIN (dest_align, src_align)))
3460 {
d8ae1baa 3461 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3462 set_mem_align (dest_mem, dest_align);
d8ae1baa 3463 src_mem = get_memory_rtx (src, len);
9fe0e1b8 3464 set_mem_align (src_mem, src_align);
3465 dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
3466 MIN (dest_align, src_align), endp);
3467 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3468 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3469 return dest_mem;
3470 }
3471
c2f47e15 3472 return NULL_RTX;
647661c6 3473 }
3474}
3475
c2f47e15 3476/* Expand expression EXP, which is a call to the memmove builtin. Return
3477 NULL_RTX if we failed; the caller should emit a normal call. */
c4950093 3478
3479static rtx
c2f47e15 3480expand_builtin_memmove (tree exp, rtx target, enum machine_mode mode, int ignore)
c4950093 3481{
c2f47e15 3482 if (!validate_arglist (exp,
3483 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3484 return NULL_RTX;
c4950093 3485 else
3486 {
c2f47e15 3487 tree dest = CALL_EXPR_ARG (exp, 0);
3488 tree src = CALL_EXPR_ARG (exp, 1);
3489 tree len = CALL_EXPR_ARG (exp, 2);
3490 return expand_builtin_memmove_args (dest, src, len, TREE_TYPE (exp),
3491 target, mode, ignore);
3492 }
3493}
7e72af53 3494
c2f47e15 3495/* Helper function to do the actual work for expand_builtin_memmove. The
3496 arguments to the builtin_memmove call DEST, SRC, and LEN are broken out
3497 so that this can also be called without constructing an actual CALL_EXPR.
3498 TYPE is the return type of the call. The other arguments and return value
3499 are the same as for expand_builtin_memmove. */
3500
3501static rtx
3502expand_builtin_memmove_args (tree dest, tree src, tree len,
3503 tree type, rtx target, enum machine_mode mode,
3504 int ignore)
3505{
3506 tree result = fold_builtin_memory_op (dest, src, len, type, ignore, /*endp=*/3);
3507
3508 if (result)
3509 {
05be68f3 3510 STRIP_TYPE_NOPS (result);
c2f47e15 3511 while (TREE_CODE (result) == COMPOUND_EXPR)
4f46f2b9 3512 {
c2f47e15 3513 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3514 EXPAND_NORMAL);
3515 result = TREE_OPERAND (result, 1);
4f46f2b9 3516 }
c2f47e15 3517 return expand_expr (result, target, mode, EXPAND_NORMAL);
3518 }
3519
3520 /* Otherwise, call the normal function. */
3521 return NULL_RTX;
c4950093 3522}
3523
c2f47e15 3524/* Expand expression EXP, which is a call to the bcopy builtin. Return
3525 NULL_RTX if we failed the caller should emit a normal call. */
c4950093 3526
3527static rtx
c2f47e15 3528expand_builtin_bcopy (tree exp, int ignore)
c4950093 3529{
0b25db21 3530 tree type = TREE_TYPE (exp);
c2f47e15 3531 tree src, dest, size;
c4950093 3532
c2f47e15 3533 if (!validate_arglist (exp,
3534 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
c4950093 3535 return NULL_RTX;
3536
c2f47e15 3537 src = CALL_EXPR_ARG (exp, 0);
3538 dest = CALL_EXPR_ARG (exp, 1);
3539 size = CALL_EXPR_ARG (exp, 2);
c4950093 3540
c2f47e15 3541 /* Transform bcopy(ptr x, ptr y, int z) to memmove(ptr y, ptr x, size_t z).
3542 This is done this way so that if it isn't expanded inline, we fall
3543 back to calling bcopy instead of memmove. */
3544 return expand_builtin_memmove_args (dest, src,
3545 fold_convert (sizetype, size),
3546 type, const0_rtx, VOIDmode,
3547 ignore);
c4950093 3548}
3549
727c62dd 3550#ifndef HAVE_movstr
3551# define HAVE_movstr 0
3552# define CODE_FOR_movstr CODE_FOR_nothing
3553#endif
3554
c2f47e15 3555/* Expand into a movstr instruction, if one is available. Return NULL_RTX if
727c62dd 3556 we failed, the caller should emit a normal call, otherwise try to
3557 get the result in TARGET, if convenient. If ENDP is 0 return the
3558 destination pointer, if ENDP is 1 return the end pointer ala
3559 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3560 stpcpy. */
3561
3562static rtx
3563expand_movstr (tree dest, tree src, rtx target, int endp)
3564{
3565 rtx end;
3566 rtx dest_mem;
3567 rtx src_mem;
3568 rtx insn;
3569 const struct insn_data * data;
3570
3571 if (!HAVE_movstr)
c2f47e15 3572 return NULL_RTX;
727c62dd 3573
d8ae1baa 3574 dest_mem = get_memory_rtx (dest, NULL);
3575 src_mem = get_memory_rtx (src, NULL);
727c62dd 3576 if (!endp)
3577 {
3578 target = force_reg (Pmode, XEXP (dest_mem, 0));
3579 dest_mem = replace_equiv_address (dest_mem, target);
3580 end = gen_reg_rtx (Pmode);
3581 }
3582 else
3583 {
3584 if (target == 0 || target == const0_rtx)
3585 {
3586 end = gen_reg_rtx (Pmode);
3587 if (target == 0)
3588 target = end;
3589 }
3590 else
3591 end = target;
3592 }
3593
3594 data = insn_data + CODE_FOR_movstr;
3595
3596 if (data->operand[0].mode != VOIDmode)
3597 end = gen_lowpart (data->operand[0].mode, end);
3598
3599 insn = data->genfun (end, dest_mem, src_mem);
3600
64db345d 3601 gcc_assert (insn);
727c62dd 3602
3603 emit_insn (insn);
3604
3605 /* movstr is supposed to set end to the address of the NUL
3606 terminator. If the caller requested a mempcpy-like return value,
3607 adjust it. */
3608 if (endp == 1 && target != const0_rtx)
c5aba89c 3609 {
3610 rtx tem = plus_constant (gen_lowpart (GET_MODE (target), end), 1);
3611 emit_move_insn (target, force_operand (tem, NULL_RTX));
3612 }
727c62dd 3613
3614 return target;
3615}
3616
c2f47e15 3617/* Expand expression EXP, which is a call to the strcpy builtin. Return
3618 NULL_RTX if we failed the caller should emit a normal call, otherwise
3619 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3620 convenient). */
902de8ed 3621
53800dbe 3622static rtx
c2f47e15 3623expand_builtin_strcpy (tree fndecl, tree exp, rtx target, enum machine_mode mode)
53800dbe 3624{
c2f47e15 3625 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3626 {
3627 tree dest = CALL_EXPR_ARG (exp, 0);
3628 tree src = CALL_EXPR_ARG (exp, 1);
3629 return expand_builtin_strcpy_args (fndecl, dest, src, target, mode);
3630 }
3631 return NULL_RTX;
3632}
3633
3634/* Helper function to do the actual work for expand_builtin_strcpy. The
3635 arguments to the builtin_strcpy call DEST and SRC are broken out
3636 so that this can also be called without constructing an actual CALL_EXPR.
3637 The other arguments and return value are the same as for
3638 expand_builtin_strcpy. */
3639
3640static rtx
3641expand_builtin_strcpy_args (tree fndecl, tree dest, tree src,
3642 rtx target, enum machine_mode mode)
3643{
3644 tree result = fold_builtin_strcpy (fndecl, dest, src, 0);
3645 if (result)
3646 return expand_expr (result, target, mode, EXPAND_NORMAL);
3647 return expand_movstr (dest, src, target, /*endp=*/0);
902de8ed 3648
53800dbe 3649}
3650
c2f47e15 3651/* Expand a call EXP to the stpcpy builtin.
3652 Return NULL_RTX if we failed the caller should emit a normal call,
3b824fa6 3653 otherwise try to get the result in TARGET, if convenient (and in
3654 mode MODE if that's convenient). */
3655
3656static rtx
dc369150 3657expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
3b824fa6 3658{
c2f47e15 3659 tree dst, src;
3660
3661 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3662 return NULL_RTX;
3663
3664 dst = CALL_EXPR_ARG (exp, 0);
3665 src = CALL_EXPR_ARG (exp, 1);
3666
727c62dd 3667 /* If return value is ignored, transform stpcpy into strcpy. */
3668 if (target == const0_rtx)
978836e5 3669 {
3670 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
3671 if (!fn)
c2f47e15 3672 return NULL_RTX;
978836e5 3673
c2f47e15 3674 return expand_expr (build_call_expr (fn, 2, dst, src),
3675 target, mode, EXPAND_NORMAL);
978836e5 3676 }
3b824fa6 3677 else
3678 {
c2f47e15 3679 tree len, lenp1;
727c62dd 3680 rtx ret;
647661c6 3681
9fe0e1b8 3682 /* Ensure we get an actual string whose length can be evaluated at
a0c938f0 3683 compile-time, not an expression containing a string. This is
3684 because the latter will potentially produce pessimized code
3685 when used to produce the return value. */
681fab1e 3686 if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
c2f47e15 3687 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3688
7d705727 3689 lenp1 = size_binop (PLUS_EXPR, len, ssize_int (1));
c2f47e15 3690 ret = expand_builtin_mempcpy_args (dst, src, lenp1, TREE_TYPE (exp),
3691 target, mode, /*endp=*/2);
727c62dd 3692
3693 if (ret)
3694 return ret;
3695
3696 if (TREE_CODE (len) == INTEGER_CST)
3697 {
8ec3c5c2 3698 rtx len_rtx = expand_normal (len);
727c62dd 3699
3700 if (GET_CODE (len_rtx) == CONST_INT)
3701 {
c2f47e15 3702 ret = expand_builtin_strcpy_args (get_callee_fndecl (exp),
3703 dst, src, target, mode);
727c62dd 3704
3705 if (ret)
3706 {
3707 if (! target)
7ac87324 3708 {
3709 if (mode != VOIDmode)
3710 target = gen_reg_rtx (mode);
3711 else
3712 target = gen_reg_rtx (GET_MODE (ret));
3713 }
727c62dd 3714 if (GET_MODE (target) != GET_MODE (ret))
3715 ret = gen_lowpart (GET_MODE (target), ret);
3716
c5aba89c 3717 ret = plus_constant (ret, INTVAL (len_rtx));
3718 ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
64db345d 3719 gcc_assert (ret);
727c62dd 3720
3721 return target;
3722 }
3723 }
3724 }
3725
c2f47e15 3726 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3727 }
3728}
3729
6840589f 3730/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3731 bytes from constant string DATA + OFFSET and return it as target
3732 constant. */
3733
09879952 3734rtx
aecda0d6 3735builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
3736 enum machine_mode mode)
6840589f 3737{
3738 const char *str = (const char *) data;
3739
3740 if ((unsigned HOST_WIDE_INT) offset > strlen (str))
3741 return const0_rtx;
3742
3743 return c_readstr (str + offset, mode);
3744}
3745
c2f47e15 3746/* Expand expression EXP, which is a call to the strncpy builtin. Return
3747 NULL_RTX if we failed the caller should emit a normal call. */
ed09096d 3748
3749static rtx
8ff6a5cd 3750expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode)
ed09096d 3751{
ea726109 3752 tree fndecl = get_callee_fndecl (exp);
c2f47e15 3753
3754 if (validate_arglist (exp,
3755 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
ed09096d 3756 {
c2f47e15 3757 tree dest = CALL_EXPR_ARG (exp, 0);
3758 tree src = CALL_EXPR_ARG (exp, 1);
3759 tree len = CALL_EXPR_ARG (exp, 2);
3760 tree slen = c_strlen (src, 1);
3761 tree result = fold_builtin_strncpy (fndecl, dest, src, len, slen);
a0c938f0 3762
8ff6a5cd 3763 if (result)
4f46f2b9 3764 {
3765 while (TREE_CODE (result) == COMPOUND_EXPR)
3766 {
3767 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3768 EXPAND_NORMAL);
3769 result = TREE_OPERAND (result, 1);
3770 }
3771 return expand_expr (result, target, mode, EXPAND_NORMAL);
3772 }
6840589f 3773
8ff6a5cd 3774 /* We must be passed a constant len and src parameter. */
3775 if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
c2f47e15 3776 return NULL_RTX;
ed09096d 3777
3778 slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
3779
3780 /* We're required to pad with trailing zeros if the requested
a0c938f0 3781 len is greater than strlen(s2)+1. In that case try to
6840589f 3782 use store_by_pieces, if it fails, punt. */
ed09096d 3783 if (tree_int_cst_lt (slen, len))
6840589f 3784 {
27d0c333 3785 unsigned int dest_align
3786 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
c2f47e15 3787 const char *p = c_getstr (src);
6840589f 3788 rtx dest_mem;
3789
27d0c333 3790 if (!p || dest_align == 0 || !host_integerp (len, 1)
3791 || !can_store_by_pieces (tree_low_cst (len, 1),
6840589f 3792 builtin_strncpy_read_str,
364c0c59 3793 CONST_CAST (char *, p),
3794 dest_align, false))
c2f47e15 3795 return NULL_RTX;
6840589f 3796
d8ae1baa 3797 dest_mem = get_memory_rtx (dest, len);
27d0c333 3798 store_by_pieces (dest_mem, tree_low_cst (len, 1),
6840589f 3799 builtin_strncpy_read_str,
364c0c59 3800 CONST_CAST (char *, p), dest_align, false, 0);
e5716f7e 3801 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3802 dest_mem = convert_memory_address (ptr_mode, dest_mem);
e5716f7e 3803 return dest_mem;
6840589f 3804 }
ed09096d 3805 }
c2f47e15 3806 return NULL_RTX;
ed09096d 3807}
3808
ecc318ff 3809/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3810 bytes from constant string DATA + OFFSET and return it as target
3811 constant. */
3812
f656b751 3813rtx
aecda0d6 3814builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3815 enum machine_mode mode)
ecc318ff 3816{
3817 const char *c = (const char *) data;
364c0c59 3818 char *p = XALLOCAVEC (char, GET_MODE_SIZE (mode));
ecc318ff 3819
3820 memset (p, *c, GET_MODE_SIZE (mode));
3821
3822 return c_readstr (p, mode);
3823}
3824
a7ec6974 3825/* Callback routine for store_by_pieces. Return the RTL of a register
3826 containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
3827 char value given in the RTL register data. For example, if mode is
3828 4 bytes wide, return the RTL for 0x01010101*data. */
3829
3830static rtx
aecda0d6 3831builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3832 enum machine_mode mode)
a7ec6974 3833{
3834 rtx target, coeff;
3835 size_t size;
3836 char *p;
3837
3838 size = GET_MODE_SIZE (mode);
f0ce3b1f 3839 if (size == 1)
3840 return (rtx) data;
a7ec6974 3841
364c0c59 3842 p = XALLOCAVEC (char, size);
a7ec6974 3843 memset (p, 1, size);
3844 coeff = c_readstr (p, mode);
3845
f0ce3b1f 3846 target = convert_to_mode (mode, (rtx) data, 1);
a7ec6974 3847 target = expand_mult (mode, target, coeff, NULL_RTX, 1);
3848 return force_reg (mode, target);
3849}
3850
c2f47e15 3851/* Expand expression EXP, which is a call to the memset builtin. Return
3852 NULL_RTX if we failed the caller should emit a normal call, otherwise
3853 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3854 convenient). */
902de8ed 3855
53800dbe 3856static rtx
c2f47e15 3857expand_builtin_memset (tree exp, rtx target, enum machine_mode mode)
53800dbe 3858{
c2f47e15 3859 if (!validate_arglist (exp,
3860 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
3861 return NULL_RTX;
53800dbe 3862 else
3863 {
c2f47e15 3864 tree dest = CALL_EXPR_ARG (exp, 0);
3865 tree val = CALL_EXPR_ARG (exp, 1);
3866 tree len = CALL_EXPR_ARG (exp, 2);
3867 return expand_builtin_memset_args (dest, val, len, target, mode, exp);
3868 }
3869}
53800dbe 3870
c2f47e15 3871/* Helper function to do the actual work for expand_builtin_memset. The
3872 arguments to the builtin_memset call DEST, VAL, and LEN are broken out
3873 so that this can also be called without constructing an actual CALL_EXPR.
3874 The other arguments and return value are the same as for
3875 expand_builtin_memset. */
6b961939 3876
c2f47e15 3877static rtx
3878expand_builtin_memset_args (tree dest, tree val, tree len,
3879 rtx target, enum machine_mode mode, tree orig_exp)
3880{
3881 tree fndecl, fn;
3882 enum built_in_function fcode;
3883 char c;
3884 unsigned int dest_align;
3885 rtx dest_mem, dest_addr, len_rtx;
3886 HOST_WIDE_INT expected_size = -1;
3887 unsigned int expected_align = 0;
53800dbe 3888
c2f47e15 3889 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
162719b3 3890
c2f47e15 3891 /* If DEST is not a pointer type, don't do this operation in-line. */
3892 if (dest_align == 0)
3893 return NULL_RTX;
6f428e8b 3894
c2f47e15 3895 stringop_block_profile (orig_exp, &expected_align, &expected_size);
3896 if (expected_align < dest_align)
3897 expected_align = dest_align;
6b961939 3898
c2f47e15 3899 /* If the LEN parameter is zero, return DEST. */
3900 if (integer_zerop (len))
3901 {
3902 /* Evaluate and ignore VAL in case it has side-effects. */
3903 expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
3904 return expand_expr (dest, target, mode, EXPAND_NORMAL);
3905 }
7a3e5564 3906
c2f47e15 3907 /* Stabilize the arguments in case we fail. */
3908 dest = builtin_save_expr (dest);
3909 val = builtin_save_expr (val);
3910 len = builtin_save_expr (len);
a7ec6974 3911
c2f47e15 3912 len_rtx = expand_normal (len);
3913 dest_mem = get_memory_rtx (dest, len);
a7ec6974 3914
c2f47e15 3915 if (TREE_CODE (val) != INTEGER_CST)
3916 {
3917 rtx val_rtx;
a7ec6974 3918
c2f47e15 3919 val_rtx = expand_normal (val);
3920 val_rtx = convert_to_mode (TYPE_MODE (unsigned_char_type_node),
3921 val_rtx, 0);
53800dbe 3922
c2f47e15 3923 /* Assume that we can memset by pieces if we can store
3924 * the coefficients by pieces (in the required modes).
3925 * We can't pass builtin_memset_gen_str as that emits RTL. */
3926 c = 1;
3927 if (host_integerp (len, 1)
c2f47e15 3928 && can_store_by_pieces (tree_low_cst (len, 1),
4b297e2e 3929 builtin_memset_read_str, &c, dest_align,
3930 true))
c2f47e15 3931 {
3932 val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
3933 val_rtx);
3934 store_by_pieces (dest_mem, tree_low_cst (len, 1),
4b297e2e 3935 builtin_memset_gen_str, val_rtx, dest_align,
3936 true, 0);
c2f47e15 3937 }
3938 else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
3939 dest_align, expected_align,
3940 expected_size))
6b961939 3941 goto do_libcall;
c2f47e15 3942
3943 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3944 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3945 return dest_mem;
3946 }
53800dbe 3947
c2f47e15 3948 if (target_char_cast (val, &c))
3949 goto do_libcall;
ecc318ff 3950
c2f47e15 3951 if (c)
3952 {
3953 if (host_integerp (len, 1)
c2f47e15 3954 && can_store_by_pieces (tree_low_cst (len, 1),
4b297e2e 3955 builtin_memset_read_str, &c, dest_align,
3956 true))
c2f47e15 3957 store_by_pieces (dest_mem, tree_low_cst (len, 1),
4b297e2e 3958 builtin_memset_read_str, &c, dest_align, true, 0);
c2f47e15 3959 else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
3960 dest_align, expected_align,
3961 expected_size))
3962 goto do_libcall;
3963
3964 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3965 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3966 return dest_mem;
3967 }
ecc318ff 3968
c2f47e15 3969 set_mem_align (dest_mem, dest_align);
3970 dest_addr = clear_storage_hints (dest_mem, len_rtx,
3971 CALL_EXPR_TAILCALL (orig_exp)
3972 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3973 expected_align, expected_size);
53800dbe 3974
c2f47e15 3975 if (dest_addr == 0)
3976 {
3977 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3978 dest_addr = convert_memory_address (ptr_mode, dest_addr);
3979 }
53800dbe 3980
c2f47e15 3981 return dest_addr;
6b961939 3982
c2f47e15 3983 do_libcall:
3984 fndecl = get_callee_fndecl (orig_exp);
3985 fcode = DECL_FUNCTION_CODE (fndecl);
3986 if (fcode == BUILT_IN_MEMSET)
3987 fn = build_call_expr (fndecl, 3, dest, val, len);
3988 else if (fcode == BUILT_IN_BZERO)
3989 fn = build_call_expr (fndecl, 2, dest, len);
3990 else
3991 gcc_unreachable ();
3992 if (TREE_CODE (fn) == CALL_EXPR)
3993 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
3994 return expand_call (fn, target, target == const0_rtx);
53800dbe 3995}
3996
c2f47e15 3997/* Expand expression EXP, which is a call to the bzero builtin. Return
3998 NULL_RTX if we failed the caller should emit a normal call. */
27d0c333 3999
ffc83088 4000static rtx
0b25db21 4001expand_builtin_bzero (tree exp)
ffc83088 4002{
c2f47e15 4003 tree dest, size;
ffc83088 4004
c2f47e15 4005 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
7369e7ba 4006 return NULL_RTX;
ffc83088 4007
c2f47e15 4008 dest = CALL_EXPR_ARG (exp, 0);
4009 size = CALL_EXPR_ARG (exp, 1);
bf8e3599 4010
7369e7ba 4011 /* New argument list transforming bzero(ptr x, int y) to
6f428e8b 4012 memset(ptr x, int 0, size_t y). This is done this way
4013 so that if it isn't expanded inline, we fallback to
4014 calling bzero instead of memset. */
bf8e3599 4015
c2f47e15 4016 return expand_builtin_memset_args (dest, integer_zero_node,
4017 fold_convert (sizetype, size),
4018 const0_rtx, VOIDmode, exp);
ffc83088 4019}
4020
7959b13b 4021/* Expand a call to the memchr builtin. Return NULL_RTX if we failed the
4022 caller should emit a normal call, otherwise try to get the result
4023 in TARGET, if convenient (and in mode MODE if that's convenient). */
4024
4025static rtx
4026expand_builtin_memchr (tree exp, rtx target, enum machine_mode mode)
4027{
4028 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE,
4029 INTEGER_TYPE, VOID_TYPE))
4030 {
4031 tree type = TREE_TYPE (exp);
4032 tree result = fold_builtin_memchr (CALL_EXPR_ARG (exp, 0),
4033 CALL_EXPR_ARG (exp, 1),
4034 CALL_EXPR_ARG (exp, 2), type);
4035 if (result)
4036 return expand_expr (result, target, mode, EXPAND_NORMAL);
4037 }
4038 return NULL_RTX;
4039}
4040
7a3f89b5 4041/* Expand expression EXP, which is a call to the memcmp built-in function.
c2f47e15 4042 Return NULL_RTX if we failed and the
53800dbe 4043 caller should emit a normal call, otherwise try to get the result in
6f428e8b 4044 TARGET, if convenient (and in mode MODE, if that's convenient). */
27d0c333 4045
53800dbe 4046static rtx
c2f47e15 4047expand_builtin_memcmp (tree exp, rtx target, enum machine_mode mode)
53800dbe 4048{
c2f47e15 4049 if (!validate_arglist (exp,
4050 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4051 return NULL_RTX;
218bc19e 4052 else
6f428e8b 4053 {
c2f47e15 4054 tree result = fold_builtin_memcmp (CALL_EXPR_ARG (exp, 0),
4055 CALL_EXPR_ARG (exp, 1),
4056 CALL_EXPR_ARG (exp, 2));
218bc19e 4057 if (result)
4058 return expand_expr (result, target, mode, EXPAND_NORMAL);
6f428e8b 4059 }
4060
6ac5504b 4061#if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi
53800dbe 4062 {
0cd832f0 4063 rtx arg1_rtx, arg2_rtx, arg3_rtx;
53800dbe 4064 rtx result;
0cd832f0 4065 rtx insn;
c2f47e15 4066 tree arg1 = CALL_EXPR_ARG (exp, 0);
4067 tree arg2 = CALL_EXPR_ARG (exp, 1);
4068 tree len = CALL_EXPR_ARG (exp, 2);
53800dbe 4069
4070 int arg1_align
4071 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4072 int arg2_align
4073 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
b428c0a5 4074 enum machine_mode insn_mode;
4075
4076#ifdef HAVE_cmpmemsi
4077 if (HAVE_cmpmemsi)
4078 insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
4079 else
4080#endif
6ac5504b 4081#ifdef HAVE_cmpstrnsi
4082 if (HAVE_cmpstrnsi)
4083 insn_mode = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
b428c0a5 4084 else
4085#endif
c2f47e15 4086 return NULL_RTX;
53800dbe 4087
4088 /* If we don't have POINTER_TYPE, call the function. */
4089 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4090 return NULL_RTX;
53800dbe 4091
4092 /* Make a place to write the result of the instruction. */
4093 result = target;
4094 if (! (result != 0
8ad4c111 4095 && REG_P (result) && GET_MODE (result) == insn_mode
53800dbe 4096 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4097 result = gen_reg_rtx (insn_mode);
4098
d8ae1baa 4099 arg1_rtx = get_memory_rtx (arg1, len);
4100 arg2_rtx = get_memory_rtx (arg2, len);
8ec3c5c2 4101 arg3_rtx = expand_normal (len);
83f88f8e 4102
4103 /* Set MEM_SIZE as appropriate. */
4104 if (GET_CODE (arg3_rtx) == CONST_INT)
4105 {
4106 set_mem_size (arg1_rtx, arg3_rtx);
4107 set_mem_size (arg2_rtx, arg3_rtx);
4108 }
4109
b428c0a5 4110#ifdef HAVE_cmpmemsi
4111 if (HAVE_cmpmemsi)
4112 insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4113 GEN_INT (MIN (arg1_align, arg2_align)));
0cd832f0 4114 else
b428c0a5 4115#endif
6ac5504b 4116#ifdef HAVE_cmpstrnsi
4117 if (HAVE_cmpstrnsi)
4118 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4119 GEN_INT (MIN (arg1_align, arg2_align)));
b428c0a5 4120 else
4121#endif
64db345d 4122 gcc_unreachable ();
0cd832f0 4123
4124 if (insn)
4125 emit_insn (insn);
4126 else
2dd6f9ed 4127 emit_library_call_value (memcmp_libfunc, result, LCT_PURE,
0cd832f0 4128 TYPE_MODE (integer_type_node), 3,
4129 XEXP (arg1_rtx, 0), Pmode,
4130 XEXP (arg2_rtx, 0), Pmode,
4131 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
78a8ed03 4132 TYPE_UNSIGNED (sizetype)),
0cd832f0 4133 TYPE_MODE (sizetype));
53800dbe 4134
4135 /* Return the value in the proper mode for this function. */
4136 mode = TYPE_MODE (TREE_TYPE (exp));
4137 if (GET_MODE (result) == mode)
4138 return result;
4139 else if (target != 0)
4140 {
4141 convert_move (target, result, 0);
4142 return target;
4143 }
4144 else
4145 return convert_to_mode (mode, result, 0);
4146 }
83d79705 4147#endif
53800dbe 4148
c2f47e15 4149 return NULL_RTX;
6f428e8b 4150}
4151
c2f47e15 4152/* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX
53800dbe 4153 if we failed the caller should emit a normal call, otherwise try to get
4154 the result in TARGET, if convenient. */
902de8ed 4155
53800dbe 4156static rtx
aecda0d6 4157expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
53800dbe 4158{
c2f47e15 4159 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4160 return NULL_RTX;
218bc19e 4161 else
ef6c187e 4162 {
c2f47e15 4163 tree result = fold_builtin_strcmp (CALL_EXPR_ARG (exp, 0),
4164 CALL_EXPR_ARG (exp, 1));
218bc19e 4165 if (result)
4166 return expand_expr (result, target, mode, EXPAND_NORMAL);
ef6c187e 4167 }
bf8e3599 4168
6ac5504b 4169#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
4170 if (cmpstr_optab[SImode] != CODE_FOR_nothing
4171 || cmpstrn_optab[SImode] != CODE_FOR_nothing)
4172 {
4173 rtx arg1_rtx, arg2_rtx;
4174 rtx result, insn = NULL_RTX;
4175 tree fndecl, fn;
c2f47e15 4176 tree arg1 = CALL_EXPR_ARG (exp, 0);
4177 tree arg2 = CALL_EXPR_ARG (exp, 1);
a0c938f0 4178
6ac5504b 4179 int arg1_align
4180 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4181 int arg2_align
4182 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4183
4184 /* If we don't have POINTER_TYPE, call the function. */
4185 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4186 return NULL_RTX;
7a3f89b5 4187
6ac5504b 4188 /* Stabilize the arguments in case gen_cmpstr(n)si fail. */
4189 arg1 = builtin_save_expr (arg1);
4190 arg2 = builtin_save_expr (arg2);
7a3f89b5 4191
d8ae1baa 4192 arg1_rtx = get_memory_rtx (arg1, NULL);
4193 arg2_rtx = get_memory_rtx (arg2, NULL);
53800dbe 4194
6ac5504b 4195#ifdef HAVE_cmpstrsi
4196 /* Try to call cmpstrsi. */
4197 if (HAVE_cmpstrsi)
4198 {
a0c938f0 4199 enum machine_mode insn_mode
6ac5504b 4200 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
4201
4202 /* Make a place to write the result of the instruction. */
4203 result = target;
4204 if (! (result != 0
4205 && REG_P (result) && GET_MODE (result) == insn_mode
4206 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4207 result = gen_reg_rtx (insn_mode);
4208
4209 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
4210 GEN_INT (MIN (arg1_align, arg2_align)));
4211 }
4212#endif
03fd9d2c 4213#ifdef HAVE_cmpstrnsi
6ac5504b 4214 /* Try to determine at least one length and call cmpstrnsi. */
a0c938f0 4215 if (!insn && HAVE_cmpstrnsi)
6ac5504b 4216 {
4217 tree len;
4218 rtx arg3_rtx;
4219
a0c938f0 4220 enum machine_mode insn_mode
6ac5504b 4221 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
4222 tree len1 = c_strlen (arg1, 1);
4223 tree len2 = c_strlen (arg2, 1);
4224
4225 if (len1)
4226 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
4227 if (len2)
4228 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
4229
4230 /* If we don't have a constant length for the first, use the length
4231 of the second, if we know it. We don't require a constant for
4232 this case; some cost analysis could be done if both are available
4233 but neither is constant. For now, assume they're equally cheap,
4234 unless one has side effects. If both strings have constant lengths,
4235 use the smaller. */
4236
4237 if (!len1)
4238 len = len2;
4239 else if (!len2)
4240 len = len1;
4241 else if (TREE_SIDE_EFFECTS (len1))
4242 len = len2;
4243 else if (TREE_SIDE_EFFECTS (len2))
4244 len = len1;
4245 else if (TREE_CODE (len1) != INTEGER_CST)
4246 len = len2;
4247 else if (TREE_CODE (len2) != INTEGER_CST)
4248 len = len1;
4249 else if (tree_int_cst_lt (len1, len2))
4250 len = len1;
4251 else
4252 len = len2;
4253
4254 /* If both arguments have side effects, we cannot optimize. */
4255 if (!len || TREE_SIDE_EFFECTS (len))
6b961939 4256 goto do_libcall;
53800dbe 4257
8ec3c5c2 4258 arg3_rtx = expand_normal (len);
902de8ed 4259
6ac5504b 4260 /* Make a place to write the result of the instruction. */
4261 result = target;
4262 if (! (result != 0
4263 && REG_P (result) && GET_MODE (result) == insn_mode
4264 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4265 result = gen_reg_rtx (insn_mode);
53800dbe 4266
6ac5504b 4267 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4268 GEN_INT (MIN (arg1_align, arg2_align)));
4269 }
4270#endif
3f8aefe2 4271
6ac5504b 4272 if (insn)
4273 {
4274 emit_insn (insn);
3f8aefe2 4275
6ac5504b 4276 /* Return the value in the proper mode for this function. */
4277 mode = TYPE_MODE (TREE_TYPE (exp));
4278 if (GET_MODE (result) == mode)
4279 return result;
4280 if (target == 0)
4281 return convert_to_mode (mode, result, 0);
4282 convert_move (target, result, 0);
4283 return target;
4284 }
902de8ed 4285
6ac5504b 4286 /* Expand the library call ourselves using a stabilized argument
4287 list to avoid re-evaluating the function's arguments twice. */
2694880e 4288#ifdef HAVE_cmpstrnsi
6b961939 4289 do_libcall:
2694880e 4290#endif
6ac5504b 4291 fndecl = get_callee_fndecl (exp);
c2f47e15 4292 fn = build_call_expr (fndecl, 2, arg1, arg2);
6ac5504b 4293 if (TREE_CODE (fn) == CALL_EXPR)
4294 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4295 return expand_call (fn, target, target == const0_rtx);
4296 }
7a3f89b5 4297#endif
c2f47e15 4298 return NULL_RTX;
83d79705 4299}
53800dbe 4300
c2f47e15 4301/* Expand expression EXP, which is a call to the strncmp builtin. Return
4302 NULL_RTX if we failed the caller should emit a normal call, otherwise try to get
ed09096d 4303 the result in TARGET, if convenient. */
27d0c333 4304
ed09096d 4305static rtx
aecda0d6 4306expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
ed09096d 4307{
c2f47e15 4308 if (!validate_arglist (exp,
4309 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4310 return NULL_RTX;
218bc19e 4311 else
ef6c187e 4312 {
c2f47e15 4313 tree result = fold_builtin_strncmp (CALL_EXPR_ARG (exp, 0),
4314 CALL_EXPR_ARG (exp, 1),
4315 CALL_EXPR_ARG (exp, 2));
218bc19e 4316 if (result)
4317 return expand_expr (result, target, mode, EXPAND_NORMAL);
ef6c187e 4318 }
ed09096d 4319
6e34e617 4320 /* If c_strlen can determine an expression for one of the string
6ac5504b 4321 lengths, and it doesn't have side effects, then emit cmpstrnsi
7a3f89b5 4322 using length MIN(strlen(string)+1, arg3). */
6ac5504b 4323#ifdef HAVE_cmpstrnsi
4324 if (HAVE_cmpstrnsi)
7a3f89b5 4325 {
4326 tree len, len1, len2;
4327 rtx arg1_rtx, arg2_rtx, arg3_rtx;
4328 rtx result, insn;
0b25db21 4329 tree fndecl, fn;
c2f47e15 4330 tree arg1 = CALL_EXPR_ARG (exp, 0);
4331 tree arg2 = CALL_EXPR_ARG (exp, 1);
4332 tree arg3 = CALL_EXPR_ARG (exp, 2);
6f428e8b 4333
7a3f89b5 4334 int arg1_align
4335 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4336 int arg2_align
4337 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4338 enum machine_mode insn_mode
6ac5504b 4339 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
bf8e3599 4340
681fab1e 4341 len1 = c_strlen (arg1, 1);
4342 len2 = c_strlen (arg2, 1);
7a3f89b5 4343
4344 if (len1)
4345 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
4346 if (len2)
4347 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
4348
4349 /* If we don't have a constant length for the first, use the length
4350 of the second, if we know it. We don't require a constant for
4351 this case; some cost analysis could be done if both are available
4352 but neither is constant. For now, assume they're equally cheap,
4353 unless one has side effects. If both strings have constant lengths,
4354 use the smaller. */
4355
4356 if (!len1)
4357 len = len2;
4358 else if (!len2)
4359 len = len1;
4360 else if (TREE_SIDE_EFFECTS (len1))
4361 len = len2;
4362 else if (TREE_SIDE_EFFECTS (len2))
4363 len = len1;
4364 else if (TREE_CODE (len1) != INTEGER_CST)
4365 len = len2;
4366 else if (TREE_CODE (len2) != INTEGER_CST)
4367 len = len1;
4368 else if (tree_int_cst_lt (len1, len2))
4369 len = len1;
4370 else
4371 len = len2;
6e34e617 4372
7a3f89b5 4373 /* If both arguments have side effects, we cannot optimize. */
4374 if (!len || TREE_SIDE_EFFECTS (len))
c2f47e15 4375 return NULL_RTX;
bf8e3599 4376
7a3f89b5 4377 /* The actual new length parameter is MIN(len,arg3). */
49d00087 4378 len = fold_build2 (MIN_EXPR, TREE_TYPE (len), len,
4379 fold_convert (TREE_TYPE (len), arg3));
7a3f89b5 4380
4381 /* If we don't have POINTER_TYPE, call the function. */
4382 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4383 return NULL_RTX;
7a3f89b5 4384
4385 /* Make a place to write the result of the instruction. */
4386 result = target;
4387 if (! (result != 0
8ad4c111 4388 && REG_P (result) && GET_MODE (result) == insn_mode
7a3f89b5 4389 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4390 result = gen_reg_rtx (insn_mode);
4391
6ac5504b 4392 /* Stabilize the arguments in case gen_cmpstrnsi fails. */
4ee9c684 4393 arg1 = builtin_save_expr (arg1);
4394 arg2 = builtin_save_expr (arg2);
4395 len = builtin_save_expr (len);
3f8aefe2 4396
d8ae1baa 4397 arg1_rtx = get_memory_rtx (arg1, len);
4398 arg2_rtx = get_memory_rtx (arg2, len);
8ec3c5c2 4399 arg3_rtx = expand_normal (len);
6ac5504b 4400 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4401 GEN_INT (MIN (arg1_align, arg2_align)));
3f8aefe2 4402 if (insn)
4403 {
4404 emit_insn (insn);
4405
4406 /* Return the value in the proper mode for this function. */
4407 mode = TYPE_MODE (TREE_TYPE (exp));
4408 if (GET_MODE (result) == mode)
4409 return result;
4410 if (target == 0)
4411 return convert_to_mode (mode, result, 0);
4412 convert_move (target, result, 0);
4413 return target;
4414 }
7a3f89b5 4415
3f8aefe2 4416 /* Expand the library call ourselves using a stabilized argument
4417 list to avoid re-evaluating the function's arguments twice. */
3f8aefe2 4418 fndecl = get_callee_fndecl (exp);
c2f47e15 4419 fn = build_call_expr (fndecl, 3, arg1, arg2, len);
0b25db21 4420 if (TREE_CODE (fn) == CALL_EXPR)
4421 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4422 return expand_call (fn, target, target == const0_rtx);
7a3f89b5 4423 }
4424#endif
c2f47e15 4425 return NULL_RTX;
ed09096d 4426}
4427
49f0327b 4428/* Expand expression EXP, which is a call to the strcat builtin.
c2f47e15 4429 Return NULL_RTX if we failed the caller should emit a normal call,
49f0327b 4430 otherwise try to get the result in TARGET, if convenient. */
27d0c333 4431
49f0327b 4432static rtx
c2f47e15 4433expand_builtin_strcat (tree fndecl, tree exp, rtx target, enum machine_mode mode)
49f0327b 4434{
c2f47e15 4435 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4436 return NULL_RTX;
49f0327b 4437 else
4438 {
c2f47e15 4439 tree dst = CALL_EXPR_ARG (exp, 0);
4440 tree src = CALL_EXPR_ARG (exp, 1);
49f0327b 4441 const char *p = c_getstr (src);
4442
1d89860b 4443 /* If the string length is zero, return the dst parameter. */
a0c938f0 4444 if (p && *p == '\0')
1d89860b 4445 return expand_expr (dst, target, mode, EXPAND_NORMAL);
a0c938f0 4446
1d89860b 4447 if (!optimize_size)
ca71f89b 4448 {
1d89860b 4449 /* See if we can store by pieces into (dst + strlen(dst)). */
4450 tree newsrc, newdst,
4451 strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
4452 rtx insns;
4453
4454 /* Stabilize the argument list. */
4455 newsrc = builtin_save_expr (src);
1d89860b 4456 dst = builtin_save_expr (dst);
4457
4458 start_sequence ();
4459
4460 /* Create strlen (dst). */
c2f47e15 4461 newdst = build_call_expr (strlen_fn, 1, dst);
0de36bdb 4462 /* Create (dst p+ strlen (dst)). */
1d89860b 4463
0de36bdb 4464 newdst = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
1d89860b 4465 newdst = builtin_save_expr (newdst);
1d89860b 4466
c2f47e15 4467 if (!expand_builtin_strcpy_args (fndecl, newdst, newsrc, target, mode))
ca71f89b 4468 {
1d89860b 4469 end_sequence (); /* Stop sequence. */
c2f47e15 4470 return NULL_RTX;
ca71f89b 4471 }
a0c938f0 4472
1d89860b 4473 /* Output the entire sequence. */
4474 insns = get_insns ();
4475 end_sequence ();
4476 emit_insn (insns);
a0c938f0 4477
1d89860b 4478 return expand_expr (dst, target, mode, EXPAND_NORMAL);
ca71f89b 4479 }
49f0327b 4480
c2f47e15 4481 return NULL_RTX;
49f0327b 4482 }
4483}
4484
4485/* Expand expression EXP, which is a call to the strncat builtin.
c2f47e15 4486 Return NULL_RTX if we failed the caller should emit a normal call,
49f0327b 4487 otherwise try to get the result in TARGET, if convenient. */
27d0c333 4488
49f0327b 4489static rtx
c2f47e15 4490expand_builtin_strncat (tree exp, rtx target, enum machine_mode mode)
49f0327b 4491{
c2f47e15 4492 if (validate_arglist (exp,
4493 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
49f0327b 4494 {
c2f47e15 4495 tree result = fold_builtin_strncat (CALL_EXPR_ARG (exp, 0),
4496 CALL_EXPR_ARG (exp, 1),
4497 CALL_EXPR_ARG (exp, 2));
2c84ee37 4498 if (result)
4499 return expand_expr (result, target, mode, EXPAND_NORMAL);
49f0327b 4500 }
c2f47e15 4501 return NULL_RTX;
49f0327b 4502}
4503
4504/* Expand expression EXP, which is a call to the strspn builtin.
c2f47e15 4505 Return NULL_RTX if we failed the caller should emit a normal call,
49f0327b 4506 otherwise try to get the result in TARGET, if convenient. */
27d0c333 4507
49f0327b 4508static rtx
c2f47e15 4509expand_builtin_strspn (tree exp, rtx target, enum machine_mode mode)
49f0327b 4510{
c2f47e15 4511 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
49f0327b 4512 {
c2f47e15 4513 tree result = fold_builtin_strspn (CALL_EXPR_ARG (exp, 0),
4514 CALL_EXPR_ARG (exp, 1));
2c84ee37 4515 if (result)
4516 return expand_expr (result, target, mode, EXPAND_NORMAL);
49f0327b 4517 }
c2f47e15 4518 return NULL_RTX;
49f0327b 4519}
4520
4521/* Expand expression EXP, which is a call to the strcspn builtin.
c2f47e15 4522 Return NULL_RTX if we failed the caller should emit a normal call,
49f0327b 4523 otherwise try to get the result in TARGET, if convenient. */
27d0c333 4524
49f0327b 4525static rtx
c2f47e15 4526expand_builtin_strcspn (tree exp, rtx target, enum machine_mode mode)
49f0327b 4527{
c2f47e15 4528 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
49f0327b 4529 {
c2f47e15 4530 tree result = fold_builtin_strcspn (CALL_EXPR_ARG (exp, 0),
4531 CALL_EXPR_ARG (exp, 1));
2c84ee37 4532 if (result)
4533 return expand_expr (result, target, mode, EXPAND_NORMAL);
49f0327b 4534 }
c2f47e15 4535 return NULL_RTX;
49f0327b 4536}
4537
a66c9326 4538/* Expand a call to __builtin_saveregs, generating the result in TARGET,
4539 if that's convenient. */
902de8ed 4540
a66c9326 4541rtx
aecda0d6 4542expand_builtin_saveregs (void)
53800dbe 4543{
a66c9326 4544 rtx val, seq;
53800dbe 4545
4546 /* Don't do __builtin_saveregs more than once in a function.
4547 Save the result of the first call and reuse it. */
4548 if (saveregs_value != 0)
4549 return saveregs_value;
53800dbe 4550
a66c9326 4551 /* When this function is called, it means that registers must be
4552 saved on entry to this function. So we migrate the call to the
4553 first insn of this function. */
4554
4555 start_sequence ();
53800dbe 4556
a66c9326 4557 /* Do whatever the machine needs done in this case. */
45550790 4558 val = targetm.calls.expand_builtin_saveregs ();
53800dbe 4559
a66c9326 4560 seq = get_insns ();
4561 end_sequence ();
53800dbe 4562
a66c9326 4563 saveregs_value = val;
53800dbe 4564
31d3e01c 4565 /* Put the insns after the NOTE that starts the function. If this
4566 is inside a start_sequence, make the outer-level insn chain current, so
a66c9326 4567 the code is placed at the start of the function. */
4568 push_topmost_sequence ();
0ec80471 4569 emit_insn_after (seq, entry_of_function ());
a66c9326 4570 pop_topmost_sequence ();
4571
4572 return val;
53800dbe 4573}
4574
4575/* __builtin_args_info (N) returns word N of the arg space info
4576 for the current function. The number and meanings of words
4577 is controlled by the definition of CUMULATIVE_ARGS. */
f7c44134 4578
53800dbe 4579static rtx
c2f47e15 4580expand_builtin_args_info (tree exp)
53800dbe 4581{
53800dbe 4582 int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
abe32cce 4583 int *word_ptr = (int *) &crtl->args.info;
53800dbe 4584
64db345d 4585 gcc_assert (sizeof (CUMULATIVE_ARGS) % sizeof (int) == 0);
53800dbe 4586
c2f47e15 4587 if (call_expr_nargs (exp) != 0)
53800dbe 4588 {
c2f47e15 4589 if (!host_integerp (CALL_EXPR_ARG (exp, 0), 0))
eb586f2c 4590 error ("argument of %<__builtin_args_info%> must be constant");
53800dbe 4591 else
4592 {
c2f47e15 4593 HOST_WIDE_INT wordnum = tree_low_cst (CALL_EXPR_ARG (exp, 0), 0);
53800dbe 4594
27d0c333 4595 if (wordnum < 0 || wordnum >= nwords)
eb586f2c 4596 error ("argument of %<__builtin_args_info%> out of range");
53800dbe 4597 else
4598 return GEN_INT (word_ptr[wordnum]);
4599 }
4600 }
4601 else
eb586f2c 4602 error ("missing argument in %<__builtin_args_info%>");
53800dbe 4603
4604 return const0_rtx;
53800dbe 4605}
4606
79012a9d 4607/* Expand a call to __builtin_next_arg. */
27d0c333 4608
53800dbe 4609static rtx
79012a9d 4610expand_builtin_next_arg (void)
53800dbe 4611{
79012a9d 4612 /* Checking arguments is already done in fold_builtin_next_arg
4613 that must be called before this function. */
940ddc5c 4614 return expand_binop (ptr_mode, add_optab,
abe32cce 4615 crtl->args.internal_arg_pointer,
4616 crtl->args.arg_offset_rtx,
53800dbe 4617 NULL_RTX, 0, OPTAB_LIB_WIDEN);
4618}
4619
a66c9326 4620/* Make it easier for the backends by protecting the valist argument
4621 from multiple evaluations. */
4622
4623static tree
aecda0d6 4624stabilize_va_list (tree valist, int needs_lvalue)
a66c9326 4625{
5f57a8b1 4626 tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
4627
4628 gcc_assert (vatype != NULL_TREE);
4629
4630 if (TREE_CODE (vatype) == ARRAY_TYPE)
a66c9326 4631 {
2d47cc32 4632 if (TREE_SIDE_EFFECTS (valist))
4633 valist = save_expr (valist);
11a61dea 4634
2d47cc32 4635 /* For this case, the backends will be expecting a pointer to
5f57a8b1 4636 vatype, but it's possible we've actually been given an array
4637 (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)).
2d47cc32 4638 So fix it. */
4639 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
8a15c04a 4640 {
5f57a8b1 4641 tree p1 = build_pointer_type (TREE_TYPE (vatype));
fcdd3ab3 4642 valist = build_fold_addr_expr_with_type (valist, p1);
8a15c04a 4643 }
a66c9326 4644 }
11a61dea 4645 else
a66c9326 4646 {
2d47cc32 4647 tree pt;
11a61dea 4648
2d47cc32 4649 if (! needs_lvalue)
4650 {
11a61dea 4651 if (! TREE_SIDE_EFFECTS (valist))
4652 return valist;
bf8e3599 4653
5f57a8b1 4654 pt = build_pointer_type (vatype);
49d00087 4655 valist = fold_build1 (ADDR_EXPR, pt, valist);
a66c9326 4656 TREE_SIDE_EFFECTS (valist) = 1;
a66c9326 4657 }
2d47cc32 4658
11a61dea 4659 if (TREE_SIDE_EFFECTS (valist))
2d47cc32 4660 valist = save_expr (valist);
fcdd3ab3 4661 valist = build_fold_indirect_ref (valist);
a66c9326 4662 }
4663
4664 return valist;
4665}
4666
2e15d750 4667/* The "standard" definition of va_list is void*. */
4668
4669tree
4670std_build_builtin_va_list (void)
4671{
4672 return ptr_type_node;
4673}
4674
5f57a8b1 4675/* The "standard" abi va_list is va_list_type_node. */
4676
4677tree
4678std_fn_abi_va_list (tree fndecl ATTRIBUTE_UNUSED)
4679{
4680 return va_list_type_node;
4681}
4682
4683/* The "standard" type of va_list is va_list_type_node. */
4684
4685tree
4686std_canonical_va_list_type (tree type)
4687{
4688 tree wtype, htype;
4689
4690 if (INDIRECT_REF_P (type))
4691 type = TREE_TYPE (type);
4692 else if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE(type)))
4693 type = TREE_TYPE (type);
5f57a8b1 4694 wtype = va_list_type_node;
4695 htype = type;
7b36f9ab 4696 /* Treat structure va_list types. */
4697 if (TREE_CODE (wtype) == RECORD_TYPE && POINTER_TYPE_P (htype))
4698 htype = TREE_TYPE (htype);
4699 else if (TREE_CODE (wtype) == ARRAY_TYPE)
5f57a8b1 4700 {
4701 /* If va_list is an array type, the argument may have decayed
4702 to a pointer type, e.g. by being passed to another function.
4703 In that case, unwrap both types so that we can compare the
4704 underlying records. */
4705 if (TREE_CODE (htype) == ARRAY_TYPE
4706 || POINTER_TYPE_P (htype))
4707 {
4708 wtype = TREE_TYPE (wtype);
4709 htype = TREE_TYPE (htype);
4710 }
4711 }
4712 if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype))
4713 return va_list_type_node;
4714
4715 return NULL_TREE;
4716}
4717
a66c9326 4718/* The "standard" implementation of va_start: just assign `nextarg' to
4719 the variable. */
27d0c333 4720
a66c9326 4721void
aecda0d6 4722std_expand_builtin_va_start (tree valist, rtx nextarg)
a66c9326 4723{
f03c17bc 4724 rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
4725 convert_move (va_r, nextarg, 0);
a66c9326 4726}
4727
c2f47e15 4728/* Expand EXP, a call to __builtin_va_start. */
27d0c333 4729
a66c9326 4730static rtx
c2f47e15 4731expand_builtin_va_start (tree exp)
a66c9326 4732{
4733 rtx nextarg;
c2f47e15 4734 tree valist;
a66c9326 4735
c2f47e15 4736 if (call_expr_nargs (exp) < 2)
cb166087 4737 {
4738 error ("too few arguments to function %<va_start%>");
4739 return const0_rtx;
4740 }
a66c9326 4741
c2f47e15 4742 if (fold_builtin_next_arg (exp, true))
79012a9d 4743 return const0_rtx;
7c2f0500 4744
79012a9d 4745 nextarg = expand_builtin_next_arg ();
c2f47e15 4746 valist = stabilize_va_list (CALL_EXPR_ARG (exp, 0), 1);
a66c9326 4747
8a58ed0a 4748 if (targetm.expand_builtin_va_start)
4749 targetm.expand_builtin_va_start (valist, nextarg);
4750 else
4751 std_expand_builtin_va_start (valist, nextarg);
a66c9326 4752
4753 return const0_rtx;
4754}
4755
a66c9326 4756/* The "standard" implementation of va_arg: read the value from the
4757 current (padded) address and increment by the (padded) size. */
f7c44134 4758
e0eca1fa 4759tree
4760std_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
fcdd3ab3 4761{
52cc2eeb 4762 tree addr, t, type_size, rounded_size, valist_tmp;
b8e8e485 4763 unsigned HOST_WIDE_INT align, boundary;
bef380a4 4764 bool indirect;
52cc2eeb 4765
4766#ifdef ARGS_GROW_DOWNWARD
4767 /* All of the alignment and movement below is for args-grow-up machines.
4768 As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
4769 implement their own specialized gimplify_va_arg_expr routines. */
64db345d 4770 gcc_unreachable ();
52cc2eeb 4771#endif
fcdd3ab3 4772
bef380a4 4773 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
4774 if (indirect)
4775 type = build_pointer_type (type);
4776
52cc2eeb 4777 align = PARM_BOUNDARY / BITS_PER_UNIT;
c8b779eb 4778 boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type);
4779
4780 /* When we align parameter on stack for caller, if the parameter
4781 alignment is beyond PREFERRED_STACK_BOUNDARY, it will be
4782 aligned at PREFERRED_STACK_BOUNDARY. We will match callee
4783 here with caller. */
4784 if (boundary > PREFERRED_STACK_BOUNDARY)
4785 boundary = PREFERRED_STACK_BOUNDARY;
4786
4787 boundary /= BITS_PER_UNIT;
fcdd3ab3 4788
52cc2eeb 4789 /* Hoist the valist value into a temporary for the moment. */
ecdeeb37 4790 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
4791
fcdd3ab3 4792 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
4793 requires greater alignment, we must perform dynamic alignment. */
85c1f587 4794 if (boundary > align
4795 && !integer_zerop (TYPE_SIZE (type)))
fcdd3ab3 4796 {
41076ef6 4797 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
0de36bdb 4798 fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (valist),
4799 valist_tmp, size_int (boundary - 1)));
52cc2eeb 4800 gimplify_and_add (t, pre_p);
4801
0de36bdb 4802 t = fold_convert (sizetype, valist_tmp);
41076ef6 4803 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
0de36bdb 4804 fold_convert (TREE_TYPE (valist),
4805 fold_build2 (BIT_AND_EXPR, sizetype, t,
4806 size_int (-boundary))));
ecdeeb37 4807 gimplify_and_add (t, pre_p);
fcdd3ab3 4808 }
c5dc0c32 4809 else
4810 boundary = align;
4811
4812 /* If the actual alignment is less than the alignment of the type,
4813 adjust the type accordingly so that we don't assume strict alignment
f0b5f617 4814 when dereferencing the pointer. */
c5dc0c32 4815 boundary *= BITS_PER_UNIT;
4816 if (boundary < TYPE_ALIGN (type))
4817 {
4818 type = build_variant_type_copy (type);
4819 TYPE_ALIGN (type) = boundary;
4820 }
fcdd3ab3 4821
bcff3604 4822 /* Compute the rounded size of the type. */
52cc2eeb 4823 type_size = size_in_bytes (type);
4824 rounded_size = round_up (type_size, align);
4825
fcdd3ab3 4826 /* Reduce rounded_size so it's sharable with the postqueue. */
4827 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
4828
4829 /* Get AP. */
ecdeeb37 4830 addr = valist_tmp;
52cc2eeb 4831 if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
fcdd3ab3 4832 {
4833 /* Small args are padded downward. */
49d00087 4834 t = fold_build2 (GT_EXPR, sizetype, rounded_size, size_int (align));
4835 t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
4836 size_binop (MINUS_EXPR, rounded_size, type_size));
0de36bdb 4837 addr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (addr), addr, t);
fcdd3ab3 4838 }
4839
fcdd3ab3 4840 /* Compute new value for AP. */
0de36bdb 4841 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (valist), valist_tmp, rounded_size);
41076ef6 4842 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
ecdeeb37 4843 gimplify_and_add (t, pre_p);
e0eca1fa 4844
4845 addr = fold_convert (build_pointer_type (type), addr);
fcdd3ab3 4846
bef380a4 4847 if (indirect)
f2462d6c 4848 addr = build_va_arg_indirect_ref (addr);
4849
4850 return build_va_arg_indirect_ref (addr);
4851}
a0930a69 4852
f2462d6c 4853/* Build an indirect-ref expression over the given TREE, which represents a
4854 piece of a va_arg() expansion. */
4855tree
4856build_va_arg_indirect_ref (tree addr)
4857{
a0930a69 4858 addr = build_fold_indirect_ref (addr);
f2462d6c 4859
a0930a69 4860 if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */
4861 mf_mark (addr);
bef380a4 4862
a0930a69 4863 return addr;
433006a9 4864}
4865
fcdd3ab3 4866/* Return a dummy expression of type TYPE in order to keep going after an
4867 error. */
4868
4869static tree
4870dummy_object (tree type)
4871{
535664e3 4872 tree t = build_int_cst (build_pointer_type (type), 0);
fcdd3ab3 4873 return build1 (INDIRECT_REF, type, t);
4874}
4875
2799a2b7 4876/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
4877 builtin function, but a very special sort of operator. */
fcdd3ab3 4878
4879enum gimplify_status
4880gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p)
4881{
5f57a8b1 4882 tree promoted_type, have_va_type;
fcdd3ab3 4883 tree valist = TREE_OPERAND (*expr_p, 0);
4884 tree type = TREE_TYPE (*expr_p);
4885 tree t;
4886
4887 /* Verify that valist is of the proper type. */
fcdd3ab3 4888 have_va_type = TREE_TYPE (valist);
f43dda35 4889 if (have_va_type == error_mark_node)
4890 return GS_ERROR;
5f57a8b1 4891 have_va_type = targetm.canonical_va_list_type (have_va_type);
f43dda35 4892
5f57a8b1 4893 if (have_va_type == NULL_TREE)
fcdd3ab3 4894 {
eb586f2c 4895 error ("first argument to %<va_arg%> not of type %<va_list%>");
e0eca1fa 4896 return GS_ERROR;
fcdd3ab3 4897 }
4898
4899 /* Generate a diagnostic for requesting data of a type that cannot
4900 be passed through `...' due to type promotion at the call site. */
5f57a8b1 4901 if ((promoted_type = lang_hooks.types.type_promotes_to (type))
fcdd3ab3 4902 != type)
4903 {
4904 static bool gave_help;
4905
4906 /* Unfortunately, this is merely undefined, rather than a constraint
4907 violation, so we cannot make this an error. If this call is never
4908 executed, the program is still strictly conforming. */
c3ceba8e 4909 warning (0, "%qT is promoted to %qT when passed through %<...%>",
fcdd3ab3 4910 type, promoted_type);
4911 if (! gave_help)
4912 {
4913 gave_help = true;
2006d7dc 4914 inform ("(so you should pass %qT not %qT to %<va_arg%>)",
fcdd3ab3 4915 promoted_type, type);
4916 }
4917
4918 /* We can, however, treat "undefined" any way we please.
4919 Call abort to encourage the user to fix the program. */
4920 inform ("if this code is reached, the program will abort");
c2f47e15 4921 t = build_call_expr (implicit_built_in_decls[BUILT_IN_TRAP], 0);
fcdd3ab3 4922 append_to_statement_list (t, pre_p);
4923
4924 /* This is dead code, but go ahead and finish so that the
4925 mode of the result comes out right. */
4926 *expr_p = dummy_object (type);
4927 return GS_ALL_DONE;
4928 }
4929 else
4930 {
4931 /* Make it easier for the backends by protecting the valist argument
a0c938f0 4932 from multiple evaluations. */
5f57a8b1 4933 if (TREE_CODE (have_va_type) == ARRAY_TYPE)
e0eca1fa 4934 {
4935 /* For this case, the backends will be expecting a pointer to
5f57a8b1 4936 TREE_TYPE (abi), but it's possible we've
4937 actually been given an array (an actual TARGET_FN_ABI_VA_LIST).
e0eca1fa 4938 So fix it. */
4939 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
4940 {
5f57a8b1 4941 tree p1 = build_pointer_type (TREE_TYPE (have_va_type));
e0eca1fa 4942 valist = build_fold_addr_expr_with_type (valist, p1);
4943 }
4944 gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
4945 }
4946 else
4947 gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
fcdd3ab3 4948
17a6380d 4949 if (!targetm.gimplify_va_arg_expr)
89f18f73 4950 /* FIXME:Once most targets are converted we should merely
4951 assert this is non-null. */
fcdd3ab3 4952 return GS_ALL_DONE;
4953
17a6380d 4954 *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
fcdd3ab3 4955 return GS_OK;
4956 }
4957}
4958
c2f47e15 4959/* Expand EXP, a call to __builtin_va_end. */
f7c44134 4960
a66c9326 4961static rtx
c2f47e15 4962expand_builtin_va_end (tree exp)
a66c9326 4963{
c2f47e15 4964 tree valist = CALL_EXPR_ARG (exp, 0);
8a15c04a 4965
8a15c04a 4966 /* Evaluate for side effects, if needed. I hate macros that don't
4967 do that. */
4968 if (TREE_SIDE_EFFECTS (valist))
4969 expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
a66c9326 4970
4971 return const0_rtx;
4972}
4973
c2f47e15 4974/* Expand EXP, a call to __builtin_va_copy. We do this as a
a66c9326 4975 builtin rather than just as an assignment in stdarg.h because of the
4976 nastiness of array-type va_list types. */
f7c44134 4977
a66c9326 4978static rtx
c2f47e15 4979expand_builtin_va_copy (tree exp)
a66c9326 4980{
4981 tree dst, src, t;
4982
c2f47e15 4983 dst = CALL_EXPR_ARG (exp, 0);
4984 src = CALL_EXPR_ARG (exp, 1);
a66c9326 4985
4986 dst = stabilize_va_list (dst, 1);
4987 src = stabilize_va_list (src, 0);
4988
5f57a8b1 4989 gcc_assert (cfun != NULL && cfun->decl != NULL_TREE);
4990
4991 if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE)
a66c9326 4992 {
5f57a8b1 4993 t = build2 (MODIFY_EXPR, targetm.fn_abi_va_list (cfun->decl), dst, src);
a66c9326 4994 TREE_SIDE_EFFECTS (t) = 1;
4995 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4996 }
4997 else
4998 {
11a61dea 4999 rtx dstb, srcb, size;
5000
5001 /* Evaluate to pointers. */
5002 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
5003 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
5f57a8b1 5004 size = expand_expr (TYPE_SIZE_UNIT (targetm.fn_abi_va_list (cfun->decl)),
5005 NULL_RTX, VOIDmode, EXPAND_NORMAL);
11a61dea 5006
85d654dd 5007 dstb = convert_memory_address (Pmode, dstb);
5008 srcb = convert_memory_address (Pmode, srcb);
726ec87c 5009
11a61dea 5010 /* "Dereference" to BLKmode memories. */
5011 dstb = gen_rtx_MEM (BLKmode, dstb);
ab6ab77e 5012 set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
5f57a8b1 5013 set_mem_align (dstb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 5014 srcb = gen_rtx_MEM (BLKmode, srcb);
ab6ab77e 5015 set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
5f57a8b1 5016 set_mem_align (srcb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 5017
5018 /* Copy. */
0378dbdc 5019 emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
a66c9326 5020 }
5021
5022 return const0_rtx;
5023}
5024
53800dbe 5025/* Expand a call to one of the builtin functions __builtin_frame_address or
5026 __builtin_return_address. */
27d0c333 5027
53800dbe 5028static rtx
c2f47e15 5029expand_builtin_frame_address (tree fndecl, tree exp)
53800dbe 5030{
53800dbe 5031 /* The argument must be a nonnegative integer constant.
5032 It counts the number of frames to scan up the stack.
5033 The value is the return address saved in that frame. */
c2f47e15 5034 if (call_expr_nargs (exp) == 0)
53800dbe 5035 /* Warning about missing arg was already issued. */
5036 return const0_rtx;
c2f47e15 5037 else if (! host_integerp (CALL_EXPR_ARG (exp, 0), 1))
53800dbe 5038 {
5039 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
07e3a3d2 5040 error ("invalid argument to %<__builtin_frame_address%>");
53800dbe 5041 else
07e3a3d2 5042 error ("invalid argument to %<__builtin_return_address%>");
53800dbe 5043 return const0_rtx;
5044 }
5045 else
5046 {
27d0c333 5047 rtx tem
5048 = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
c2f47e15 5049 tree_low_cst (CALL_EXPR_ARG (exp, 0), 1));
53800dbe 5050
5051 /* Some ports cannot access arbitrary stack frames. */
5052 if (tem == NULL)
5053 {
5054 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
c3ceba8e 5055 warning (0, "unsupported argument to %<__builtin_frame_address%>");
53800dbe 5056 else
c3ceba8e 5057 warning (0, "unsupported argument to %<__builtin_return_address%>");
53800dbe 5058 return const0_rtx;
5059 }
5060
5061 /* For __builtin_frame_address, return what we've got. */
5062 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
5063 return tem;
5064
8ad4c111 5065 if (!REG_P (tem)
53800dbe 5066 && ! CONSTANT_P (tem))
5067 tem = copy_to_mode_reg (Pmode, tem);
5068 return tem;
5069 }
5070}
5071
c2f47e15 5072/* Expand EXP, a call to the alloca builtin. Return NULL_RTX if
53800dbe 5073 we failed and the caller should emit a normal call, otherwise try to get
5074 the result in TARGET, if convenient. */
15c6cf6b 5075
53800dbe 5076static rtx
c2f47e15 5077expand_builtin_alloca (tree exp, rtx target)
53800dbe 5078{
5079 rtx op0;
15c6cf6b 5080 rtx result;
53800dbe 5081
4ee9c684 5082 /* In -fmudflap-instrumented code, alloca() and __builtin_alloca()
5083 should always expand to function calls. These can be intercepted
5084 in libmudflap. */
5085 if (flag_mudflap)
c2f47e15 5086 return NULL_RTX;
4ee9c684 5087
c2f47e15 5088 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
5089 return NULL_RTX;
53800dbe 5090
5091 /* Compute the argument. */
c2f47e15 5092 op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
53800dbe 5093
5094 /* Allocate the desired space. */
15c6cf6b 5095 result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
85d654dd 5096 result = convert_memory_address (ptr_mode, result);
15c6cf6b 5097
5098 return result;
53800dbe 5099}
5100
c2f47e15 5101/* Expand a call to a bswap builtin with argument ARG0. MODE
42791117 5102 is the mode to expand with. */
5103
5104static rtx
c2f47e15 5105expand_builtin_bswap (tree exp, rtx target, rtx subtarget)
42791117 5106{
5107 enum machine_mode mode;
5108 tree arg;
5109 rtx op0;
5110
c2f47e15 5111 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
5112 return NULL_RTX;
42791117 5113
c2f47e15 5114 arg = CALL_EXPR_ARG (exp, 0);
42791117 5115 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 5116 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
42791117 5117
5118 target = expand_unop (mode, bswap_optab, op0, target, 1);
5119
5120 gcc_assert (target);
5121
5122 return convert_to_mode (mode, target, 0);
5123}
5124
c2f47e15 5125/* Expand a call to a unary builtin in EXP.
5126 Return NULL_RTX if a normal call should be emitted rather than expanding the
53800dbe 5127 function in-line. If convenient, the result should be placed in TARGET.
5128 SUBTARGET may be used as the target for computing one of EXP's operands. */
15c6cf6b 5129
53800dbe 5130static rtx
c2f47e15 5131expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target,
aecda0d6 5132 rtx subtarget, optab op_optab)
53800dbe 5133{
5134 rtx op0;
c2f47e15 5135
5136 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
5137 return NULL_RTX;
53800dbe 5138
5139 /* Compute the argument. */
1db6d067 5140 op0 = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
5141 VOIDmode, EXPAND_NORMAL);
6a08d0ab 5142 /* Compute op, into TARGET if possible.
53800dbe 5143 Set TARGET to wherever the result comes back. */
c2f47e15 5144 target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
6a08d0ab 5145 op_optab, op0, target, 1);
64db345d 5146 gcc_assert (target);
7d3f6cc7 5147
efb070c8 5148 return convert_to_mode (target_mode, target, 0);
53800dbe 5149}
89cfe6e5 5150
df94cd3b 5151/* If the string passed to fputs is a constant and is one character
2c0e001b 5152 long, we attempt to transform this call into __builtin_fputc(). */
15c6cf6b 5153
df94cd3b 5154static rtx
c2f47e15 5155expand_builtin_fputs (tree exp, rtx target, bool unlocked)
df94cd3b 5156{
2c0e001b 5157 /* Verify the arguments in the original call. */
c2f47e15 5158 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
ce1b14f4 5159 {
c2f47e15 5160 tree result = fold_builtin_fputs (CALL_EXPR_ARG (exp, 0),
5161 CALL_EXPR_ARG (exp, 1),
5162 (target == const0_rtx),
2c84ee37 5163 unlocked, NULL_TREE);
5164 if (result)
5165 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
ce1b14f4 5166 }
c2f47e15 5167 return NULL_RTX;
3311f67b 5168}
5169
5a74f77e 5170/* Expand a call to __builtin_expect. We just return our argument
5171 as the builtin_expect semantic should've been already executed by
5172 tree branch prediction pass. */
89cfe6e5 5173
5174static rtx
c2f47e15 5175expand_builtin_expect (tree exp, rtx target)
89cfe6e5 5176{
c2f47e15 5177 tree arg, c;
89cfe6e5 5178
c2f47e15 5179 if (call_expr_nargs (exp) < 2)
89cfe6e5 5180 return const0_rtx;
c2f47e15 5181 arg = CALL_EXPR_ARG (exp, 0);
5182 c = CALL_EXPR_ARG (exp, 1);
89cfe6e5 5183
c2f47e15 5184 target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5a74f77e 5185 /* When guessing was done, the hints should be already stripped away. */
07311427 5186 gcc_assert (!flag_guess_branch_prob
5187 || optimize == 0 || errorcount || sorrycount);
89cfe6e5 5188 return target;
5189}
689df48e 5190
c22de3f0 5191void
aecda0d6 5192expand_builtin_trap (void)
a0ef1725 5193{
5194#ifdef HAVE_trap
5195 if (HAVE_trap)
5196 emit_insn (gen_trap ());
5197 else
5198#endif
5199 emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
5200 emit_barrier ();
5201}
78a74442 5202
c2f47e15 5203/* Expand EXP, a call to fabs, fabsf or fabsl.
5204 Return NULL_RTX if a normal call should be emitted rather than expanding
78a74442 5205 the function inline. If convenient, the result should be placed
5206 in TARGET. SUBTARGET may be used as the target for computing
5207 the operand. */
5208
5209static rtx
c2f47e15 5210expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
78a74442 5211{
5212 enum machine_mode mode;
5213 tree arg;
5214 rtx op0;
5215
c2f47e15 5216 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
5217 return NULL_RTX;
78a74442 5218
c2f47e15 5219 arg = CALL_EXPR_ARG (exp, 0);
c7f617c2 5220 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
78a74442 5221 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 5222 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
78a74442 5223 return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
5224}
5225
c2f47e15 5226/* Expand EXP, a call to copysign, copysignf, or copysignl.
270436f3 5227 Return NULL is a normal call should be emitted rather than expanding the
5228 function inline. If convenient, the result should be placed in TARGET.
5229 SUBTARGET may be used as the target for computing the operand. */
5230
5231static rtx
c2f47e15 5232expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
270436f3 5233{
5234 rtx op0, op1;
5235 tree arg;
5236
c2f47e15 5237 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
5238 return NULL_RTX;
270436f3 5239
c2f47e15 5240 arg = CALL_EXPR_ARG (exp, 0);
8ec3c5c2 5241 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
270436f3 5242
c2f47e15 5243 arg = CALL_EXPR_ARG (exp, 1);
8ec3c5c2 5244 op1 = expand_normal (arg);
270436f3 5245
5246 return expand_copysign (op0, op1, target);
5247}
5248
19bf118a 5249/* Create a new constant string literal and return a char* pointer to it.
5250 The STRING_CST value is the LEN characters at STR. */
1e8e9920 5251tree
19bf118a 5252build_string_literal (int len, const char *str)
5253{
5254 tree t, elem, index, type;
5255
5256 t = build_string (len, str);
5257 elem = build_type_variant (char_type_node, 1, 0);
40238f64 5258 index = build_index_type (size_int (len - 1));
19bf118a 5259 type = build_array_type (elem, index);
5260 TREE_TYPE (t) = type;
5261 TREE_CONSTANT (t) = 1;
5262 TREE_READONLY (t) = 1;
5263 TREE_STATIC (t) = 1;
5264
19bf118a 5265 type = build_pointer_type (elem);
40238f64 5266 t = build1 (ADDR_EXPR, type,
5267 build4 (ARRAY_REF, elem,
5268 t, integer_zero_node, NULL_TREE, NULL_TREE));
19bf118a 5269 return t;
5270}
5271
0b25db21 5272/* Expand EXP, a call to printf or printf_unlocked.
c2f47e15 5273 Return NULL_RTX if a normal call should be emitted rather than transforming
19bf118a 5274 the function inline. If convenient, the result should be placed in
0862b7e9 5275 TARGET with mode MODE. UNLOCKED indicates this is a printf_unlocked
19bf118a 5276 call. */
5277static rtx
0b25db21 5278expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
19bf118a 5279 bool unlocked)
5280{
6d77ed92 5281 /* If we're using an unlocked function, assume the other unlocked
5282 functions exist explicitly. */
5283 tree const fn_putchar = unlocked ? built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
5284 : implicit_built_in_decls[BUILT_IN_PUTCHAR];
5285 tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED]
5286 : implicit_built_in_decls[BUILT_IN_PUTS];
19bf118a 5287 const char *fmt_str;
c2f47e15 5288 tree fn = 0;
5289 tree fmt, arg;
5290 int nargs = call_expr_nargs (exp);
19bf118a 5291
5292 /* If the return value is used, don't do the transformation. */
5293 if (target != const0_rtx)
c2f47e15 5294 return NULL_RTX;
19bf118a 5295
5296 /* Verify the required arguments in the original call. */
c2f47e15 5297 if (nargs == 0)
5298 return NULL_RTX;
5299 fmt = CALL_EXPR_ARG (exp, 0);
552752f7 5300 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
c2f47e15 5301 return NULL_RTX;
19bf118a 5302
5303 /* Check whether the format is a literal string constant. */
5304 fmt_str = c_getstr (fmt);
5305 if (fmt_str == NULL)
c2f47e15 5306 return NULL_RTX;
19bf118a 5307
d4473c84 5308 if (!init_target_chars ())
c2f47e15 5309 return NULL_RTX;
a0c938f0 5310
19bf118a 5311 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
99eabcc1 5312 if (strcmp (fmt_str, target_percent_s_newline) == 0)
19bf118a 5313 {
c2f47e15 5314 if ((nargs != 2)
5315 || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (exp, 1))))
5316 return NULL_RTX;
5317 if (fn_puts)
5318 fn = build_call_expr (fn_puts, 1, CALL_EXPR_ARG (exp, 1));
19bf118a 5319 }
5320 /* If the format specifier was "%c", call __builtin_putchar(arg). */
99eabcc1 5321 else if (strcmp (fmt_str, target_percent_c) == 0)
19bf118a 5322 {
c2f47e15 5323 if ((nargs != 2)
5324 || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1))) != INTEGER_TYPE)
5325 return NULL_RTX;
5326 if (fn_putchar)
5327 fn = build_call_expr (fn_putchar, 1, CALL_EXPR_ARG (exp, 1));
19bf118a 5328 }
5329 else
5330 {
5331 /* We can't handle anything else with % args or %% ... yet. */
99eabcc1 5332 if (strchr (fmt_str, target_percent))
c2f47e15 5333 return NULL_RTX;
19bf118a 5334
c2f47e15 5335 if (nargs > 1)
5336 return NULL_RTX;
19bf118a 5337
5338 /* If the format specifier was "", printf does nothing. */
5339 if (fmt_str[0] == '\0')
5340 return const0_rtx;
5341 /* If the format specifier has length of 1, call putchar. */
5342 if (fmt_str[1] == '\0')
5343 {
5344 /* Given printf("c"), (where c is any one character,)
5345 convert "c"[0] to an int and pass that to the replacement
5346 function. */
7016c612 5347 arg = build_int_cst (NULL_TREE, fmt_str[0]);
c2f47e15 5348 if (fn_putchar)
5349 fn = build_call_expr (fn_putchar, 1, arg);
19bf118a 5350 }
5351 else
5352 {
5353 /* If the format specifier was "string\n", call puts("string"). */
5354 size_t len = strlen (fmt_str);
99eabcc1 5355 if ((unsigned char)fmt_str[len - 1] == target_newline)
19bf118a 5356 {
91c82c20 5357 /* Create a NUL-terminated string that's one char shorter
19bf118a 5358 than the original, stripping off the trailing '\n'. */
364c0c59 5359 char *newstr = XALLOCAVEC (char, len);
19bf118a 5360 memcpy (newstr, fmt_str, len - 1);
5361 newstr[len - 1] = 0;
19bf118a 5362 arg = build_string_literal (len, newstr);
c2f47e15 5363 if (fn_puts)
5364 fn = build_call_expr (fn_puts, 1, arg);
19bf118a 5365 }
5366 else
5367 /* We'd like to arrange to call fputs(string,stdout) here,
5368 but we need stdout and don't have a way to get it yet. */
c2f47e15 5369 return NULL_RTX;
19bf118a 5370 }
5371 }
5372
5373 if (!fn)
c2f47e15 5374 return NULL_RTX;
0b25db21 5375 if (TREE_CODE (fn) == CALL_EXPR)
5376 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
5377 return expand_expr (fn, target, mode, EXPAND_NORMAL);
19bf118a 5378}
5379
0b25db21 5380/* Expand EXP, a call to fprintf or fprintf_unlocked.
c2f47e15 5381 Return NULL_RTX if a normal call should be emitted rather than transforming
19bf118a 5382 the function inline. If convenient, the result should be placed in
0862b7e9 5383 TARGET with mode MODE. UNLOCKED indicates this is a fprintf_unlocked
19bf118a 5384 call. */
5385static rtx
0b25db21 5386expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
a0c938f0 5387 bool unlocked)
19bf118a 5388{
6d77ed92 5389 /* If we're using an unlocked function, assume the other unlocked
5390 functions exist explicitly. */
5391 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
5392 : implicit_built_in_decls[BUILT_IN_FPUTC];
5393 tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
5394 : implicit_built_in_decls[BUILT_IN_FPUTS];
19bf118a 5395 const char *fmt_str;
c2f47e15 5396 tree fn = 0;
5397 tree fmt, fp, arg;
5398 int nargs = call_expr_nargs (exp);
19bf118a 5399
5400 /* If the return value is used, don't do the transformation. */
5401 if (target != const0_rtx)
c2f47e15 5402 return NULL_RTX;
19bf118a 5403
5404 /* Verify the required arguments in the original call. */
c2f47e15 5405 if (nargs < 2)
5406 return NULL_RTX;
5407 fp = CALL_EXPR_ARG (exp, 0);
552752f7 5408 if (! POINTER_TYPE_P (TREE_TYPE (fp)))
c2f47e15 5409 return NULL_RTX;
5410 fmt = CALL_EXPR_ARG (exp, 1);
552752f7 5411 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
c2f47e15 5412 return NULL_RTX;
19bf118a 5413
5414 /* Check whether the format is a literal string constant. */
5415 fmt_str = c_getstr (fmt);
5416 if (fmt_str == NULL)
c2f47e15 5417 return NULL_RTX;
19bf118a 5418
d4473c84 5419 if (!init_target_chars ())
c2f47e15 5420 return NULL_RTX;
a0c938f0 5421
19bf118a 5422 /* If the format specifier was "%s", call __builtin_fputs(arg,fp). */
99eabcc1 5423 if (strcmp (fmt_str, target_percent_s) == 0)
19bf118a 5424 {
c2f47e15 5425 if ((nargs != 3)
5426 || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (exp, 2))))
5427 return NULL_RTX;
5428 arg = CALL_EXPR_ARG (exp, 2);
5429 if (fn_fputs)
5430 fn = build_call_expr (fn_fputs, 2, arg, fp);
19bf118a 5431 }
5432 /* If the format specifier was "%c", call __builtin_fputc(arg,fp). */
99eabcc1 5433 else if (strcmp (fmt_str, target_percent_c) == 0)
19bf118a 5434 {
c2f47e15 5435 if ((nargs != 3)
5436 || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2))) != INTEGER_TYPE)
5437 return NULL_RTX;
5438 arg = CALL_EXPR_ARG (exp, 2);
5439 if (fn_fputc)
5440 fn = build_call_expr (fn_fputc, 2, arg, fp);
19bf118a 5441 }
5442 else
5443 {
5444 /* We can't handle anything else with % args or %% ... yet. */
99eabcc1 5445 if (strchr (fmt_str, target_percent))
c2f47e15 5446 return NULL_RTX;
19bf118a 5447
c2f47e15 5448 if (nargs > 2)
5449 return NULL_RTX;
19bf118a 5450
5451 /* If the format specifier was "", fprintf does nothing. */
5452 if (fmt_str[0] == '\0')
5453 {
5454 /* Evaluate and ignore FILE* argument for side-effects. */
5455 expand_expr (fp, const0_rtx, VOIDmode, EXPAND_NORMAL);
5456 return const0_rtx;
5457 }
5458
5459 /* When "string" doesn't contain %, replace all cases of
5460 fprintf(stream,string) with fputs(string,stream). The fputs
5461 builtin will take care of special cases like length == 1. */
c2f47e15 5462 if (fn_fputs)
5463 fn = build_call_expr (fn_fputs, 2, fmt, fp);
19bf118a 5464 }
5465
5466 if (!fn)
c2f47e15 5467 return NULL_RTX;
0b25db21 5468 if (TREE_CODE (fn) == CALL_EXPR)
5469 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
5470 return expand_expr (fn, target, mode, EXPAND_NORMAL);
19bf118a 5471}
5472
c2f47e15 5473/* Expand a call EXP to sprintf. Return NULL_RTX if
6411575e 5474 a normal call should be emitted rather than expanding the function
5475 inline. If convenient, the result should be placed in TARGET with
5476 mode MODE. */
5477
5478static rtx
c2f47e15 5479expand_builtin_sprintf (tree exp, rtx target, enum machine_mode mode)
6411575e 5480{
c2f47e15 5481 tree dest, fmt;
a7a723f0 5482 const char *fmt_str;
c2f47e15 5483 int nargs = call_expr_nargs (exp);
6411575e 5484
5485 /* Verify the required arguments in the original call. */
c2f47e15 5486 if (nargs < 2)
5487 return NULL_RTX;
5488 dest = CALL_EXPR_ARG (exp, 0);
552752f7 5489 if (! POINTER_TYPE_P (TREE_TYPE (dest)))
c2f47e15 5490 return NULL_RTX;
5491 fmt = CALL_EXPR_ARG (exp, 0);
552752f7 5492 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
c2f47e15 5493 return NULL_RTX;
6411575e 5494
5495 /* Check whether the format is a literal string constant. */
a7a723f0 5496 fmt_str = c_getstr (fmt);
5497 if (fmt_str == NULL)
c2f47e15 5498 return NULL_RTX;
6411575e 5499
d4473c84 5500 if (!init_target_chars ())
c2f47e15 5501 return NULL_RTX;
99eabcc1 5502
6411575e 5503 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 5504 if (strchr (fmt_str, target_percent) == 0)
6411575e 5505 {
5506 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
5507 tree exp;
5508
c2f47e15 5509 if ((nargs > 2) || ! fn)
5510 return NULL_RTX;
5511 expand_expr (build_call_expr (fn, 2, dest, fmt),
6411575e 5512 const0_rtx, VOIDmode, EXPAND_NORMAL);
5513 if (target == const0_rtx)
5514 return const0_rtx;
7016c612 5515 exp = build_int_cst (NULL_TREE, strlen (fmt_str));
6411575e 5516 return expand_expr (exp, target, mode, EXPAND_NORMAL);
5517 }
a7a723f0 5518 /* If the format is "%s", use strcpy if the result isn't used. */
99eabcc1 5519 else if (strcmp (fmt_str, target_percent_s) == 0)
6411575e 5520 {
a7a723f0 5521 tree fn, arg, len;
5522 fn = implicit_built_in_decls[BUILT_IN_STRCPY];
6411575e 5523
a7a723f0 5524 if (! fn)
c2f47e15 5525 return NULL_RTX;
5526 if (nargs != 3)
5527 return NULL_RTX;
5528 arg = CALL_EXPR_ARG (exp, 2);
552752f7 5529 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
c2f47e15 5530 return NULL_RTX;
6411575e 5531
5532 if (target != const0_rtx)
5533 {
681fab1e 5534 len = c_strlen (arg, 1);
a7a723f0 5535 if (! len || TREE_CODE (len) != INTEGER_CST)
c2f47e15 5536 return NULL_RTX;
6411575e 5537 }
5538 else
a7a723f0 5539 len = NULL_TREE;
6411575e 5540
c2f47e15 5541 expand_expr (build_call_expr (fn, 2, dest, arg),
6411575e 5542 const0_rtx, VOIDmode, EXPAND_NORMAL);
5543
5544 if (target == const0_rtx)
5545 return const0_rtx;
a7a723f0 5546 return expand_expr (len, target, mode, EXPAND_NORMAL);
6411575e 5547 }
5548
c2f47e15 5549 return NULL_RTX;
6411575e 5550}
27f261ef 5551
4ee9c684 5552/* Expand a call to either the entry or exit function profiler. */
5553
5554static rtx
5555expand_builtin_profile_func (bool exitp)
5556{
5557 rtx this, which;
5558
5559 this = DECL_RTL (current_function_decl);
64db345d 5560 gcc_assert (MEM_P (this));
5561 this = XEXP (this, 0);
4ee9c684 5562
5563 if (exitp)
5564 which = profile_function_exit_libfunc;
5565 else
5566 which = profile_function_entry_libfunc;
5567
5568 emit_library_call (which, LCT_NORMAL, VOIDmode, 2, this, Pmode,
5569 expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
869d0ef0 5570 0),
4ee9c684 5571 Pmode);
5572
5573 return const0_rtx;
5574}
5575
ac8fb6db 5576/* Expand a call to __builtin___clear_cache. */
5577
5578static rtx
5579expand_builtin___clear_cache (tree exp ATTRIBUTE_UNUSED)
5580{
5581#ifndef HAVE_clear_cache
5582#ifdef CLEAR_INSN_CACHE
5583 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
5584 does something. Just do the default expansion to a call to
5585 __clear_cache(). */
5586 return NULL_RTX;
5587#else
5588 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
5589 does nothing. There is no need to call it. Do nothing. */
5590 return const0_rtx;
5591#endif /* CLEAR_INSN_CACHE */
5592#else
5593 /* We have a "clear_cache" insn, and it will handle everything. */
5594 tree begin, end;
5595 rtx begin_rtx, end_rtx;
5596 enum insn_code icode;
5597
5598 /* We must not expand to a library call. If we did, any
5599 fallback library function in libgcc that might contain a call to
5600 __builtin___clear_cache() would recurse infinitely. */
5601 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
5602 {
5603 error ("both arguments to %<__builtin___clear_cache%> must be pointers");
5604 return const0_rtx;
5605 }
5606
5607 if (HAVE_clear_cache)
5608 {
5609 icode = CODE_FOR_clear_cache;
5610
5611 begin = CALL_EXPR_ARG (exp, 0);
5612 begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
5613 begin_rtx = convert_memory_address (Pmode, begin_rtx);
5614 if (!insn_data[icode].operand[0].predicate (begin_rtx, Pmode))
5615 begin_rtx = copy_to_mode_reg (Pmode, begin_rtx);
5616
5617 end = CALL_EXPR_ARG (exp, 1);
5618 end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
5619 end_rtx = convert_memory_address (Pmode, end_rtx);
5620 if (!insn_data[icode].operand[1].predicate (end_rtx, Pmode))
5621 end_rtx = copy_to_mode_reg (Pmode, end_rtx);
5622
5623 emit_insn (gen_clear_cache (begin_rtx, end_rtx));
5624 }
5625 return const0_rtx;
5626#endif /* HAVE_clear_cache */
5627}
5628
4ee9c684 5629/* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
5630
5631static rtx
5632round_trampoline_addr (rtx tramp)
5633{
5634 rtx temp, addend, mask;
5635
5636 /* If we don't need too much alignment, we'll have been guaranteed
5637 proper alignment by get_trampoline_type. */
5638 if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
5639 return tramp;
5640
5641 /* Round address up to desired boundary. */
5642 temp = gen_reg_rtx (Pmode);
5643 addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
5644 mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
5645
5646 temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
5647 temp, 0, OPTAB_LIB_WIDEN);
5648 tramp = expand_simple_binop (Pmode, AND, temp, mask,
5649 temp, 0, OPTAB_LIB_WIDEN);
5650
5651 return tramp;
5652}
5653
5654static rtx
c2f47e15 5655expand_builtin_init_trampoline (tree exp)
4ee9c684 5656{
5657 tree t_tramp, t_func, t_chain;
5658 rtx r_tramp, r_func, r_chain;
5659#ifdef TRAMPOLINE_TEMPLATE
5660 rtx blktramp;
5661#endif
5662
c2f47e15 5663 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
4ee9c684 5664 POINTER_TYPE, VOID_TYPE))
5665 return NULL_RTX;
5666
c2f47e15 5667 t_tramp = CALL_EXPR_ARG (exp, 0);
5668 t_func = CALL_EXPR_ARG (exp, 1);
5669 t_chain = CALL_EXPR_ARG (exp, 2);
4ee9c684 5670
8ec3c5c2 5671 r_tramp = expand_normal (t_tramp);
5672 r_func = expand_normal (t_func);
5673 r_chain = expand_normal (t_chain);
4ee9c684 5674
5675 /* Generate insns to initialize the trampoline. */
5676 r_tramp = round_trampoline_addr (r_tramp);
5677#ifdef TRAMPOLINE_TEMPLATE
5678 blktramp = gen_rtx_MEM (BLKmode, r_tramp);
5679 set_mem_align (blktramp, TRAMPOLINE_ALIGNMENT);
5680 emit_block_move (blktramp, assemble_trampoline_template (),
5681 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
5682#endif
5683 trampolines_created = 1;
5684 INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain);
5685
5686 return const0_rtx;
5687}
5688
5689static rtx
c2f47e15 5690expand_builtin_adjust_trampoline (tree exp)
4ee9c684 5691{
5692 rtx tramp;
5693
c2f47e15 5694 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
4ee9c684 5695 return NULL_RTX;
5696
c2f47e15 5697 tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
4ee9c684 5698 tramp = round_trampoline_addr (tramp);
5699#ifdef TRAMPOLINE_ADJUST_ADDRESS
5700 TRAMPOLINE_ADJUST_ADDRESS (tramp);
5701#endif
5702
5703 return tramp;
5704}
5705
93f564d6 5706/* Expand the call EXP to the built-in signbit, signbitf or signbitl
5707 function. The function first checks whether the back end provides
5708 an insn to implement signbit for the respective mode. If not, it
5709 checks whether the floating point format of the value is such that
5710 the sign bit can be extracted. If that is not the case, the
5711 function returns NULL_RTX to indicate that a normal call should be
5712 emitted rather than expanding the function in-line. EXP is the
5713 expression that is a call to the builtin function; if convenient,
5714 the result should be placed in TARGET. */
27f261ef 5715static rtx
5716expand_builtin_signbit (tree exp, rtx target)
5717{
5718 const struct real_format *fmt;
5719 enum machine_mode fmode, imode, rmode;
5720 HOST_WIDE_INT hi, lo;
c2f47e15 5721 tree arg;
ca4f1f5b 5722 int word, bitpos;
27eda240 5723 enum insn_code icode;
27f261ef 5724 rtx temp;
5725
c2f47e15 5726 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
5727 return NULL_RTX;
27f261ef 5728
c2f47e15 5729 arg = CALL_EXPR_ARG (exp, 0);
27f261ef 5730 fmode = TYPE_MODE (TREE_TYPE (arg));
5731 rmode = TYPE_MODE (TREE_TYPE (exp));
5732 fmt = REAL_MODE_FORMAT (fmode);
5733
93f564d6 5734 arg = builtin_save_expr (arg);
5735
5736 /* Expand the argument yielding a RTX expression. */
5737 temp = expand_normal (arg);
5738
5739 /* Check if the back end provides an insn that handles signbit for the
5740 argument's mode. */
27eda240 5741 icode = signbit_optab->handlers [(int) fmode].insn_code;
5742 if (icode != CODE_FOR_nothing)
93f564d6 5743 {
5744 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
27eda240 5745 emit_unop_insn (icode, target, temp, UNKNOWN);
93f564d6 5746 return target;
5747 }
5748
27f261ef 5749 /* For floating point formats without a sign bit, implement signbit
5750 as "ARG < 0.0". */
8d564692 5751 bitpos = fmt->signbit_ro;
ca4f1f5b 5752 if (bitpos < 0)
27f261ef 5753 {
5754 /* But we can't do this if the format supports signed zero. */
5755 if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
c2f47e15 5756 return NULL_RTX;
27f261ef 5757
49d00087 5758 arg = fold_build2 (LT_EXPR, TREE_TYPE (exp), arg,
5759 build_real (TREE_TYPE (arg), dconst0));
27f261ef 5760 return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5761 }
5762
ca4f1f5b 5763 if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
27f261ef 5764 {
ca4f1f5b 5765 imode = int_mode_for_mode (fmode);
5766 if (imode == BLKmode)
c2f47e15 5767 return NULL_RTX;
ca4f1f5b 5768 temp = gen_lowpart (imode, temp);
24fd4260 5769 }
5770 else
5771 {
ca4f1f5b 5772 imode = word_mode;
5773 /* Handle targets with different FP word orders. */
5774 if (FLOAT_WORDS_BIG_ENDIAN)
a0c938f0 5775 word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
ca4f1f5b 5776 else
a0c938f0 5777 word = bitpos / BITS_PER_WORD;
ca4f1f5b 5778 temp = operand_subword_force (temp, word, fmode);
5779 bitpos = bitpos % BITS_PER_WORD;
5780 }
5781
44b0f1d0 5782 /* Force the intermediate word_mode (or narrower) result into a
5783 register. This avoids attempting to create paradoxical SUBREGs
5784 of floating point modes below. */
5785 temp = force_reg (imode, temp);
5786
ca4f1f5b 5787 /* If the bitpos is within the "result mode" lowpart, the operation
5788 can be implement with a single bitwise AND. Otherwise, we need
5789 a right shift and an AND. */
5790
5791 if (bitpos < GET_MODE_BITSIZE (rmode))
5792 {
24fd4260 5793 if (bitpos < HOST_BITS_PER_WIDE_INT)
27f261ef 5794 {
24fd4260 5795 hi = 0;
5796 lo = (HOST_WIDE_INT) 1 << bitpos;
27f261ef 5797 }
5798 else
24fd4260 5799 {
5800 hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
5801 lo = 0;
5802 }
27f261ef 5803
4a46f016 5804 if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
ca4f1f5b 5805 temp = gen_lowpart (rmode, temp);
24fd4260 5806 temp = expand_binop (rmode, and_optab, temp,
5807 immed_double_const (lo, hi, rmode),
ca4f1f5b 5808 NULL_RTX, 1, OPTAB_LIB_WIDEN);
27f261ef 5809 }
ca4f1f5b 5810 else
5811 {
5812 /* Perform a logical right shift to place the signbit in the least
a0c938f0 5813 significant bit, then truncate the result to the desired mode
ca4f1f5b 5814 and mask just this bit. */
5815 temp = expand_shift (RSHIFT_EXPR, imode, temp,
5816 build_int_cst (NULL_TREE, bitpos), NULL_RTX, 1);
5817 temp = gen_lowpart (rmode, temp);
5818 temp = expand_binop (rmode, and_optab, temp, const1_rtx,
5819 NULL_RTX, 1, OPTAB_LIB_WIDEN);
5820 }
5821
27f261ef 5822 return temp;
5823}
73673831 5824
5825/* Expand fork or exec calls. TARGET is the desired target of the
c2f47e15 5826 call. EXP is the call. FN is the
73673831 5827 identificator of the actual function. IGNORE is nonzero if the
5828 value is to be ignored. */
5829
5830static rtx
c2f47e15 5831expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
73673831 5832{
5833 tree id, decl;
5834 tree call;
5835
5836 /* If we are not profiling, just call the function. */
5837 if (!profile_arc_flag)
5838 return NULL_RTX;
5839
5840 /* Otherwise call the wrapper. This should be equivalent for the rest of
5841 compiler, so the code does not diverge, and the wrapper may run the
9c9bad97 5842 code necessary for keeping the profiling sane. */
73673831 5843
5844 switch (DECL_FUNCTION_CODE (fn))
5845 {
5846 case BUILT_IN_FORK:
5847 id = get_identifier ("__gcov_fork");
5848 break;
5849
5850 case BUILT_IN_EXECL:
5851 id = get_identifier ("__gcov_execl");
5852 break;
5853
5854 case BUILT_IN_EXECV:
5855 id = get_identifier ("__gcov_execv");
5856 break;
5857
5858 case BUILT_IN_EXECLP:
5859 id = get_identifier ("__gcov_execlp");
5860 break;
5861
5862 case BUILT_IN_EXECLE:
5863 id = get_identifier ("__gcov_execle");
5864 break;
5865
5866 case BUILT_IN_EXECVP:
5867 id = get_identifier ("__gcov_execvp");
5868 break;
5869
5870 case BUILT_IN_EXECVE:
5871 id = get_identifier ("__gcov_execve");
5872 break;
5873
5874 default:
64db345d 5875 gcc_unreachable ();
73673831 5876 }
5877
5878 decl = build_decl (FUNCTION_DECL, id, TREE_TYPE (fn));
5879 DECL_EXTERNAL (decl) = 1;
5880 TREE_PUBLIC (decl) = 1;
5881 DECL_ARTIFICIAL (decl) = 1;
5882 TREE_NOTHROW (decl) = 1;
e82d310b 5883 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
5884 DECL_VISIBILITY_SPECIFIED (decl) = 1;
c2f47e15 5885 call = rewrite_call_expr (exp, 0, decl, 0);
73673831 5886 return expand_call (call, target, ignore);
c2f47e15 5887 }
5888
b6a5fc45 5889
5890\f
3e272de8 5891/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
5892 the pointer in these functions is void*, the tree optimizers may remove
5893 casts. The mode computed in expand_builtin isn't reliable either, due
5894 to __sync_bool_compare_and_swap.
5895
5896 FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
5897 group of builtins. This gives us log2 of the mode size. */
5898
5899static inline enum machine_mode
5900get_builtin_sync_mode (int fcode_diff)
5901{
ad3a13b5 5902 /* The size is not negotiable, so ask not to get BLKmode in return
5903 if the target indicates that a smaller size would be better. */
5904 return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
3e272de8 5905}
5906
041e0215 5907/* Expand the memory expression LOC and return the appropriate memory operand
5908 for the builtin_sync operations. */
5909
5910static rtx
5911get_builtin_sync_mem (tree loc, enum machine_mode mode)
5912{
5913 rtx addr, mem;
5914
1db6d067 5915 addr = expand_expr (loc, NULL_RTX, Pmode, EXPAND_SUM);
041e0215 5916
5917 /* Note that we explicitly do not want any alias information for this
5918 memory, so that we kill all other live memories. Otherwise we don't
5919 satisfy the full barrier semantics of the intrinsic. */
5920 mem = validize_mem (gen_rtx_MEM (mode, addr));
5921
5922 set_mem_align (mem, get_pointer_alignment (loc, BIGGEST_ALIGNMENT));
c94cfd1c 5923 set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
041e0215 5924 MEM_VOLATILE_P (mem) = 1;
5925
5926 return mem;
5927}
5928
b6a5fc45 5929/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
c2f47e15 5930 EXP is the CALL_EXPR. CODE is the rtx code
b6a5fc45 5931 that corresponds to the arithmetic or logical operation from the name;
5932 an exception here is that NOT actually means NAND. TARGET is an optional
5933 place for us to store the results; AFTER is true if this is the
5934 fetch_and_xxx form. IGNORE is true if we don't actually care about
5935 the result of the operation at all. */
5936
5937static rtx
c2f47e15 5938expand_builtin_sync_operation (enum machine_mode mode, tree exp,
3e272de8 5939 enum rtx_code code, bool after,
b6a5fc45 5940 rtx target, bool ignore)
5941{
041e0215 5942 rtx val, mem;
a8bb7059 5943 enum machine_mode old_mode;
b6a5fc45 5944
5945 /* Expand the operands. */
c2f47e15 5946 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5947
1db6d067 5948 val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
a8bb7059 5949 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5950 of CONST_INTs, where we know the old_mode only from the call argument. */
5951 old_mode = GET_MODE (val);
5952 if (old_mode == VOIDmode)
5953 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5954 val = convert_modes (mode, old_mode, val, 1);
b6a5fc45 5955
b6a5fc45 5956 if (ignore)
5957 return expand_sync_operation (mem, val, code);
5958 else
5959 return expand_sync_fetch_operation (mem, val, code, after, target);
5960}
5961
5962/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
c2f47e15 5963 intrinsics. EXP is the CALL_EXPR. IS_BOOL is
b6a5fc45 5964 true if this is the boolean form. TARGET is a place for us to store the
5965 results; this is NOT optional if IS_BOOL is true. */
5966
5967static rtx
c2f47e15 5968expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
3e272de8 5969 bool is_bool, rtx target)
b6a5fc45 5970{
041e0215 5971 rtx old_val, new_val, mem;
a8bb7059 5972 enum machine_mode old_mode;
b6a5fc45 5973
5974 /* Expand the operands. */
c2f47e15 5975 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5976
c2f47e15 5977
1db6d067 5978 old_val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX,
5979 mode, EXPAND_NORMAL);
a8bb7059 5980 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5981 of CONST_INTs, where we know the old_mode only from the call argument. */
5982 old_mode = GET_MODE (old_val);
5983 if (old_mode == VOIDmode)
5984 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5985 old_val = convert_modes (mode, old_mode, old_val, 1);
b6a5fc45 5986
1db6d067 5987 new_val = expand_expr (CALL_EXPR_ARG (exp, 2), NULL_RTX,
5988 mode, EXPAND_NORMAL);
a8bb7059 5989 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5990 of CONST_INTs, where we know the old_mode only from the call argument. */
5991 old_mode = GET_MODE (new_val);
5992 if (old_mode == VOIDmode)
5993 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2)));
5994 new_val = convert_modes (mode, old_mode, new_val, 1);
b6a5fc45 5995
b6a5fc45 5996 if (is_bool)
5997 return expand_bool_compare_and_swap (mem, old_val, new_val, target);
5998 else
5999 return expand_val_compare_and_swap (mem, old_val, new_val, target);
6000}
6001
6002/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
6003 general form is actually an atomic exchange, and some targets only
6004 support a reduced form with the second argument being a constant 1.
c2f47e15 6005 EXP is the CALL_EXPR; TARGET is an optional place for us to store
6006 the results. */
b6a5fc45 6007
6008static rtx
c2f47e15 6009expand_builtin_lock_test_and_set (enum machine_mode mode, tree exp,
3e272de8 6010 rtx target)
b6a5fc45 6011{
041e0215 6012 rtx val, mem;
a8bb7059 6013 enum machine_mode old_mode;
b6a5fc45 6014
6015 /* Expand the operands. */
c2f47e15 6016 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1db6d067 6017 val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
a8bb7059 6018 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
6019 of CONST_INTs, where we know the old_mode only from the call argument. */
6020 old_mode = GET_MODE (val);
6021 if (old_mode == VOIDmode)
6022 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
6023 val = convert_modes (mode, old_mode, val, 1);
b6a5fc45 6024
b6a5fc45 6025 return expand_sync_lock_test_and_set (mem, val, target);
6026}
6027
6028/* Expand the __sync_synchronize intrinsic. */
6029
6030static void
6031expand_builtin_synchronize (void)
6032{
82e58396 6033 tree x;
b6a5fc45 6034
6035#ifdef HAVE_memory_barrier
6036 if (HAVE_memory_barrier)
6037 {
6038 emit_insn (gen_memory_barrier ());
6039 return;
6040 }
6041#endif
6042
047a7e40 6043 if (synchronize_libfunc != NULL_RTX)
6044 {
6045 emit_library_call (synchronize_libfunc, LCT_NORMAL, VOIDmode, 0);
6046 return;
6047 }
6048
82e58396 6049 /* If no explicit memory barrier instruction is available, create an
6050 empty asm stmt with a memory clobber. */
6051 x = build4 (ASM_EXPR, void_type_node, build_string (0, ""), NULL, NULL,
6052 tree_cons (NULL, build_string (6, "memory"), NULL));
6053 ASM_VOLATILE_P (x) = 1;
6054 expand_asm_expr (x);
b6a5fc45 6055}
6056
c2f47e15 6057/* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */
b6a5fc45 6058
6059static void
c2f47e15 6060expand_builtin_lock_release (enum machine_mode mode, tree exp)
b6a5fc45 6061{
b6a5fc45 6062 enum insn_code icode;
041e0215 6063 rtx mem, insn;
3e272de8 6064 rtx val = const0_rtx;
b6a5fc45 6065
6066 /* Expand the operands. */
c2f47e15 6067 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 6068
6069 /* If there is an explicit operation in the md file, use it. */
6070 icode = sync_lock_release[mode];
6071 if (icode != CODE_FOR_nothing)
6072 {
6073 if (!insn_data[icode].operand[1].predicate (val, mode))
6074 val = force_reg (mode, val);
6075
6076 insn = GEN_FCN (icode) (mem, val);
6077 if (insn)
6078 {
6079 emit_insn (insn);
6080 return;
6081 }
6082 }
6083
6084 /* Otherwise we can implement this operation by emitting a barrier
6085 followed by a store of zero. */
6086 expand_builtin_synchronize ();
6087 emit_move_insn (mem, val);
6088}
53800dbe 6089\f
6090/* Expand an expression EXP that calls a built-in function,
6091 with result going to TARGET if that's convenient
6092 (and in mode MODE if that's convenient).
6093 SUBTARGET may be used as the target for computing one of EXP's operands.
6094 IGNORE is nonzero if the value is to be ignored. */
6095
6096rtx
aecda0d6 6097expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
6098 int ignore)
53800dbe 6099{
c6e6ecb1 6100 tree fndecl = get_callee_fndecl (exp);
53800dbe 6101 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
efb070c8 6102 enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
53800dbe 6103
8305149e 6104 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
883b2e73 6105 return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
bf8e3599 6106
53800dbe 6107 /* When not optimizing, generate calls to library functions for a certain
6108 set of builtins. */
cd9ff771 6109 if (!optimize
b6a5fc45 6110 && !called_as_built_in (fndecl)
cd9ff771 6111 && DECL_ASSEMBLER_NAME_SET_P (fndecl)
6112 && fcode != BUILT_IN_ALLOCA)
6113 return expand_call (exp, target, ignore);
53800dbe 6114
8d6d7930 6115 /* The built-in function expanders test for target == const0_rtx
6116 to determine whether the function's result will be ignored. */
6117 if (ignore)
6118 target = const0_rtx;
6119
6120 /* If the result of a pure or const built-in function is ignored, and
6121 none of its arguments are volatile, we can avoid expanding the
6122 built-in call and just evaluate the arguments for side-effects. */
6123 if (target == const0_rtx
9c2a0c05 6124 && (DECL_PURE_P (fndecl) || TREE_READONLY (fndecl)))
8d6d7930 6125 {
6126 bool volatilep = false;
6127 tree arg;
c2f47e15 6128 call_expr_arg_iterator iter;
8d6d7930 6129
c2f47e15 6130 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
6131 if (TREE_THIS_VOLATILE (arg))
8d6d7930 6132 {
6133 volatilep = true;
6134 break;
6135 }
6136
6137 if (! volatilep)
6138 {
c2f47e15 6139 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
6140 expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
8d6d7930 6141 return const0_rtx;
6142 }
6143 }
6144
53800dbe 6145 switch (fcode)
6146 {
4f35b1fc 6147 CASE_FLT_FN (BUILT_IN_FABS):
c2f47e15 6148 target = expand_builtin_fabs (exp, target, subtarget);
78a74442 6149 if (target)
a0c938f0 6150 return target;
78a74442 6151 break;
6152
4f35b1fc 6153 CASE_FLT_FN (BUILT_IN_COPYSIGN):
c2f47e15 6154 target = expand_builtin_copysign (exp, target, subtarget);
270436f3 6155 if (target)
6156 return target;
6157 break;
6158
7d3f6cc7 6159 /* Just do a normal library call if we were unable to fold
6160 the values. */
4f35b1fc 6161 CASE_FLT_FN (BUILT_IN_CABS):
78a74442 6162 break;
53800dbe 6163
4f35b1fc 6164 CASE_FLT_FN (BUILT_IN_EXP):
6165 CASE_FLT_FN (BUILT_IN_EXP10):
6166 CASE_FLT_FN (BUILT_IN_POW10):
6167 CASE_FLT_FN (BUILT_IN_EXP2):
6168 CASE_FLT_FN (BUILT_IN_EXPM1):
6169 CASE_FLT_FN (BUILT_IN_LOGB):
4f35b1fc 6170 CASE_FLT_FN (BUILT_IN_LOG):
6171 CASE_FLT_FN (BUILT_IN_LOG10):
6172 CASE_FLT_FN (BUILT_IN_LOG2):
6173 CASE_FLT_FN (BUILT_IN_LOG1P):
6174 CASE_FLT_FN (BUILT_IN_TAN):
6175 CASE_FLT_FN (BUILT_IN_ASIN):
6176 CASE_FLT_FN (BUILT_IN_ACOS):
6177 CASE_FLT_FN (BUILT_IN_ATAN):
7f3be425 6178 /* Treat these like sqrt only if unsafe math optimizations are allowed,
6179 because of possible accuracy problems. */
6180 if (! flag_unsafe_math_optimizations)
53800dbe 6181 break;
4f35b1fc 6182 CASE_FLT_FN (BUILT_IN_SQRT):
6183 CASE_FLT_FN (BUILT_IN_FLOOR):
6184 CASE_FLT_FN (BUILT_IN_CEIL):
6185 CASE_FLT_FN (BUILT_IN_TRUNC):
6186 CASE_FLT_FN (BUILT_IN_ROUND):
6187 CASE_FLT_FN (BUILT_IN_NEARBYINT):
6188 CASE_FLT_FN (BUILT_IN_RINT):
53800dbe 6189 target = expand_builtin_mathfn (exp, target, subtarget);
6190 if (target)
6191 return target;
6192 break;
6193
a67a90e5 6194 CASE_FLT_FN (BUILT_IN_ILOGB):
6195 if (! flag_unsafe_math_optimizations)
6196 break;
69b779ea 6197 CASE_FLT_FN (BUILT_IN_ISINF):
cde061c1 6198 CASE_FLT_FN (BUILT_IN_FINITE):
6199 case BUILT_IN_ISFINITE:
8a1a9cb7 6200 case BUILT_IN_ISNORMAL:
a67a90e5 6201 target = expand_builtin_interclass_mathfn (exp, target, subtarget);
6202 if (target)
6203 return target;
6204 break;
6205
4f35b1fc 6206 CASE_FLT_FN (BUILT_IN_LCEIL):
6207 CASE_FLT_FN (BUILT_IN_LLCEIL):
6208 CASE_FLT_FN (BUILT_IN_LFLOOR):
6209 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 6210 target = expand_builtin_int_roundingfn (exp, target, subtarget);
6211 if (target)
6212 return target;
6213 break;
6214
7d3afc77 6215 CASE_FLT_FN (BUILT_IN_LRINT):
6216 CASE_FLT_FN (BUILT_IN_LLRINT):
ef2f1a10 6217 CASE_FLT_FN (BUILT_IN_LROUND):
6218 CASE_FLT_FN (BUILT_IN_LLROUND):
7d3afc77 6219 target = expand_builtin_int_roundingfn_2 (exp, target, subtarget);
6220 if (target)
6221 return target;
6222 break;
6223
4f35b1fc 6224 CASE_FLT_FN (BUILT_IN_POW):
f1b844c6 6225 target = expand_builtin_pow (exp, target, subtarget);
6226 if (target)
6227 return target;
6228 break;
6229
4f35b1fc 6230 CASE_FLT_FN (BUILT_IN_POWI):
757c219d 6231 target = expand_builtin_powi (exp, target, subtarget);
6232 if (target)
6233 return target;
6234 break;
6235
4f35b1fc 6236 CASE_FLT_FN (BUILT_IN_ATAN2):
6237 CASE_FLT_FN (BUILT_IN_LDEXP):
73a954a1 6238 CASE_FLT_FN (BUILT_IN_SCALB):
6239 CASE_FLT_FN (BUILT_IN_SCALBN):
6240 CASE_FLT_FN (BUILT_IN_SCALBLN):
0fd605a5 6241 if (! flag_unsafe_math_optimizations)
6242 break;
ef722005 6243
6244 CASE_FLT_FN (BUILT_IN_FMOD):
6245 CASE_FLT_FN (BUILT_IN_REMAINDER):
6246 CASE_FLT_FN (BUILT_IN_DREM):
0fd605a5 6247 target = expand_builtin_mathfn_2 (exp, target, subtarget);
6248 if (target)
6249 return target;
6250 break;
6251
d735c391 6252 CASE_FLT_FN (BUILT_IN_CEXPI):
6253 target = expand_builtin_cexpi (exp, target, subtarget);
6254 gcc_assert (target);
6255 return target;
6256
4f35b1fc 6257 CASE_FLT_FN (BUILT_IN_SIN):
6258 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 6259 if (! flag_unsafe_math_optimizations)
6260 break;
6261 target = expand_builtin_mathfn_3 (exp, target, subtarget);
6262 if (target)
6263 return target;
6264 break;
6265
c3147c1a 6266 CASE_FLT_FN (BUILT_IN_SINCOS):
6267 if (! flag_unsafe_math_optimizations)
6268 break;
6269 target = expand_builtin_sincos (exp);
6270 if (target)
6271 return target;
6272 break;
6273
53800dbe 6274 case BUILT_IN_APPLY_ARGS:
6275 return expand_builtin_apply_args ();
6276
6277 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
6278 FUNCTION with a copy of the parameters described by
6279 ARGUMENTS, and ARGSIZE. It returns a block of memory
6280 allocated on the stack into which is stored all the registers
6281 that might possibly be used for returning the result of a
6282 function. ARGUMENTS is the value returned by
6283 __builtin_apply_args. ARGSIZE is the number of bytes of
6284 arguments that must be copied. ??? How should this value be
6285 computed? We'll also need a safe worst case value for varargs
6286 functions. */
6287 case BUILT_IN_APPLY:
c2f47e15 6288 if (!validate_arglist (exp, POINTER_TYPE,
0eb671f7 6289 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
c2f47e15 6290 && !validate_arglist (exp, REFERENCE_TYPE,
0eb671f7 6291 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 6292 return const0_rtx;
6293 else
6294 {
53800dbe 6295 rtx ops[3];
6296
c2f47e15 6297 ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
6298 ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
6299 ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
53800dbe 6300
6301 return expand_builtin_apply (ops[0], ops[1], ops[2]);
6302 }
6303
6304 /* __builtin_return (RESULT) causes the function to return the
6305 value described by RESULT. RESULT is address of the block of
6306 memory returned by __builtin_apply. */
6307 case BUILT_IN_RETURN:
c2f47e15 6308 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
6309 expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
53800dbe 6310 return const0_rtx;
6311
6312 case BUILT_IN_SAVEREGS:
a66c9326 6313 return expand_builtin_saveregs ();
53800dbe 6314
6315 case BUILT_IN_ARGS_INFO:
c2f47e15 6316 return expand_builtin_args_info (exp);
53800dbe 6317
48dc2227 6318 case BUILT_IN_VA_ARG_PACK:
6319 /* All valid uses of __builtin_va_arg_pack () are removed during
6320 inlining. */
b8c23db3 6321 error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
48dc2227 6322 return const0_rtx;
6323
4e1d7ea4 6324 case BUILT_IN_VA_ARG_PACK_LEN:
6325 /* All valid uses of __builtin_va_arg_pack_len () are removed during
6326 inlining. */
b8c23db3 6327 error ("%Kinvalid use of %<__builtin_va_arg_pack_len ()%>", exp);
4e1d7ea4 6328 return const0_rtx;
6329
53800dbe 6330 /* Return the address of the first anonymous stack arg. */
6331 case BUILT_IN_NEXT_ARG:
c2f47e15 6332 if (fold_builtin_next_arg (exp, false))
a0c938f0 6333 return const0_rtx;
79012a9d 6334 return expand_builtin_next_arg ();
53800dbe 6335
ac8fb6db 6336 case BUILT_IN_CLEAR_CACHE:
6337 target = expand_builtin___clear_cache (exp);
6338 if (target)
6339 return target;
6340 break;
6341
53800dbe 6342 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 6343 return expand_builtin_classify_type (exp);
53800dbe 6344
6345 case BUILT_IN_CONSTANT_P:
4ee9c684 6346 return const0_rtx;
53800dbe 6347
6348 case BUILT_IN_FRAME_ADDRESS:
6349 case BUILT_IN_RETURN_ADDRESS:
c2f47e15 6350 return expand_builtin_frame_address (fndecl, exp);
53800dbe 6351
6352 /* Returns the address of the area where the structure is returned.
6353 0 otherwise. */
6354 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
c2f47e15 6355 if (call_expr_nargs (exp) != 0
9342ee68 6356 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
e16ceb8e 6357 || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
9342ee68 6358 return const0_rtx;
53800dbe 6359 else
9342ee68 6360 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
53800dbe 6361
6362 case BUILT_IN_ALLOCA:
c2f47e15 6363 target = expand_builtin_alloca (exp, target);
53800dbe 6364 if (target)
6365 return target;
6366 break;
6367
4ee9c684 6368 case BUILT_IN_STACK_SAVE:
6369 return expand_stack_save ();
6370
6371 case BUILT_IN_STACK_RESTORE:
c2f47e15 6372 expand_stack_restore (CALL_EXPR_ARG (exp, 0));
4ee9c684 6373 return const0_rtx;
6374
42791117 6375 case BUILT_IN_BSWAP32:
6376 case BUILT_IN_BSWAP64:
c2f47e15 6377 target = expand_builtin_bswap (exp, target, subtarget);
42791117 6378
6379 if (target)
6380 return target;
6381 break;
6382
4f35b1fc 6383 CASE_INT_FN (BUILT_IN_FFS):
5053259b 6384 case BUILT_IN_FFSIMAX:
c2f47e15 6385 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6386 subtarget, ffs_optab);
6a08d0ab 6387 if (target)
6388 return target;
6389 break;
6390
4f35b1fc 6391 CASE_INT_FN (BUILT_IN_CLZ):
5053259b 6392 case BUILT_IN_CLZIMAX:
c2f47e15 6393 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6394 subtarget, clz_optab);
6a08d0ab 6395 if (target)
6396 return target;
6397 break;
6398
4f35b1fc 6399 CASE_INT_FN (BUILT_IN_CTZ):
5053259b 6400 case BUILT_IN_CTZIMAX:
c2f47e15 6401 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6402 subtarget, ctz_optab);
6a08d0ab 6403 if (target)
6404 return target;
6405 break;
6406
4f35b1fc 6407 CASE_INT_FN (BUILT_IN_POPCOUNT):
5053259b 6408 case BUILT_IN_POPCOUNTIMAX:
c2f47e15 6409 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6410 subtarget, popcount_optab);
6a08d0ab 6411 if (target)
6412 return target;
6413 break;
6414
4f35b1fc 6415 CASE_INT_FN (BUILT_IN_PARITY):
5053259b 6416 case BUILT_IN_PARITYIMAX:
c2f47e15 6417 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6418 subtarget, parity_optab);
53800dbe 6419 if (target)
6420 return target;
6421 break;
6422
6423 case BUILT_IN_STRLEN:
c2f47e15 6424 target = expand_builtin_strlen (exp, target, target_mode);
53800dbe 6425 if (target)
6426 return target;
6427 break;
6428
6429 case BUILT_IN_STRCPY:
c2f47e15 6430 target = expand_builtin_strcpy (fndecl, exp, target, mode);
53800dbe 6431 if (target)
6432 return target;
6433 break;
bf8e3599 6434
ed09096d 6435 case BUILT_IN_STRNCPY:
8ff6a5cd 6436 target = expand_builtin_strncpy (exp, target, mode);
ed09096d 6437 if (target)
6438 return target;
6439 break;
bf8e3599 6440
3b824fa6 6441 case BUILT_IN_STPCPY:
dc369150 6442 target = expand_builtin_stpcpy (exp, target, mode);
3b824fa6 6443 if (target)
6444 return target;
6445 break;
6446
49f0327b 6447 case BUILT_IN_STRCAT:
c2f47e15 6448 target = expand_builtin_strcat (fndecl, exp, target, mode);
49f0327b 6449 if (target)
6450 return target;
6451 break;
bf8e3599 6452
49f0327b 6453 case BUILT_IN_STRNCAT:
c2f47e15 6454 target = expand_builtin_strncat (exp, target, mode);
49f0327b 6455 if (target)
6456 return target;
6457 break;
bf8e3599 6458
49f0327b 6459 case BUILT_IN_STRSPN:
c2f47e15 6460 target = expand_builtin_strspn (exp, target, mode);
49f0327b 6461 if (target)
6462 return target;
6463 break;
bf8e3599 6464
49f0327b 6465 case BUILT_IN_STRCSPN:
c2f47e15 6466 target = expand_builtin_strcspn (exp, target, mode);
49f0327b 6467 if (target)
6468 return target;
6469 break;
bf8e3599 6470
17f5ea87 6471 case BUILT_IN_STRSTR:
c2f47e15 6472 target = expand_builtin_strstr (exp, target, mode);
17f5ea87 6473 if (target)
6474 return target;
6475 break;
bf8e3599 6476
46f3a74a 6477 case BUILT_IN_STRPBRK:
c2f47e15 6478 target = expand_builtin_strpbrk (exp, target, mode);
46f3a74a 6479 if (target)
6480 return target;
6481 break;
bf8e3599 6482
398aae36 6483 case BUILT_IN_INDEX:
83d79705 6484 case BUILT_IN_STRCHR:
c2f47e15 6485 target = expand_builtin_strchr (exp, target, mode);
83d79705 6486 if (target)
6487 return target;
6488 break;
6489
398aae36 6490 case BUILT_IN_RINDEX:
83d79705 6491 case BUILT_IN_STRRCHR:
c2f47e15 6492 target = expand_builtin_strrchr (exp, target, mode);
83d79705 6493 if (target)
6494 return target;
6495 break;
6496
53800dbe 6497 case BUILT_IN_MEMCPY:
5a0de151 6498 target = expand_builtin_memcpy (exp, target, mode);
3b824fa6 6499 if (target)
6500 return target;
6501 break;
6502
6503 case BUILT_IN_MEMPCPY:
c2f47e15 6504 target = expand_builtin_mempcpy (exp, target, mode);
53800dbe 6505 if (target)
6506 return target;
6507 break;
6508
c4950093 6509 case BUILT_IN_MEMMOVE:
c2f47e15 6510 target = expand_builtin_memmove (exp, target, mode, ignore);
c4950093 6511 if (target)
6512 return target;
6513 break;
6514
6515 case BUILT_IN_BCOPY:
c2f47e15 6516 target = expand_builtin_bcopy (exp, ignore);
c4950093 6517 if (target)
6518 return target;
6519 break;
6520
53800dbe 6521 case BUILT_IN_MEMSET:
c2f47e15 6522 target = expand_builtin_memset (exp, target, mode);
53800dbe 6523 if (target)
6524 return target;
6525 break;
6526
ffc83088 6527 case BUILT_IN_BZERO:
0b25db21 6528 target = expand_builtin_bzero (exp);
ffc83088 6529 if (target)
6530 return target;
6531 break;
6532
53800dbe 6533 case BUILT_IN_STRCMP:
83d79705 6534 target = expand_builtin_strcmp (exp, target, mode);
53800dbe 6535 if (target)
6536 return target;
6537 break;
6538
ed09096d 6539 case BUILT_IN_STRNCMP:
6540 target = expand_builtin_strncmp (exp, target, mode);
6541 if (target)
6542 return target;
6543 break;
6544
7959b13b 6545 case BUILT_IN_MEMCHR:
6546 target = expand_builtin_memchr (exp, target, mode);
6547 if (target)
6548 return target;
6549 break;
6550
071f1696 6551 case BUILT_IN_BCMP:
53800dbe 6552 case BUILT_IN_MEMCMP:
c2f47e15 6553 target = expand_builtin_memcmp (exp, target, mode);
53800dbe 6554 if (target)
6555 return target;
6556 break;
53800dbe 6557
6558 case BUILT_IN_SETJMP:
2c8a1497 6559 /* This should have been lowered to the builtins below. */
6560 gcc_unreachable ();
6561
6562 case BUILT_IN_SETJMP_SETUP:
6563 /* __builtin_setjmp_setup is passed a pointer to an array of five words
6564 and the receiver label. */
c2f47e15 6565 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2c8a1497 6566 {
c2f47e15 6567 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
2c8a1497 6568 VOIDmode, EXPAND_NORMAL);
c2f47e15 6569 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
2c8a1497 6570 rtx label_r = label_rtx (label);
6571
6572 /* This is copied from the handling of non-local gotos. */
6573 expand_builtin_setjmp_setup (buf_addr, label_r);
6574 nonlocal_goto_handler_labels
6575 = gen_rtx_EXPR_LIST (VOIDmode, label_r,
6576 nonlocal_goto_handler_labels);
6577 /* ??? Do not let expand_label treat us as such since we would
6578 not want to be both on the list of non-local labels and on
6579 the list of forced labels. */
6580 FORCED_LABEL (label) = 0;
6581 return const0_rtx;
6582 }
6583 break;
6584
6585 case BUILT_IN_SETJMP_DISPATCHER:
6586 /* __builtin_setjmp_dispatcher is passed the dispatcher label. */
c2f47e15 6587 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6588 {
c2f47e15 6589 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6590 rtx label_r = label_rtx (label);
6591
6592 /* Remove the dispatcher label from the list of non-local labels
6593 since the receiver labels have been added to it above. */
6594 remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels);
6595 return const0_rtx;
6596 }
6597 break;
6598
6599 case BUILT_IN_SETJMP_RECEIVER:
6600 /* __builtin_setjmp_receiver is passed the receiver label. */
c2f47e15 6601 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6602 {
c2f47e15 6603 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6604 rtx label_r = label_rtx (label);
6605
6606 expand_builtin_setjmp_receiver (label_r);
6607 return const0_rtx;
6608 }
6b7f6858 6609 break;
53800dbe 6610
6611 /* __builtin_longjmp is passed a pointer to an array of five words.
6612 It's similar to the C library longjmp function but works with
6613 __builtin_setjmp above. */
6614 case BUILT_IN_LONGJMP:
c2f47e15 6615 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 6616 {
c2f47e15 6617 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
8ec3c5c2 6618 VOIDmode, EXPAND_NORMAL);
c2f47e15 6619 rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
53800dbe 6620
6621 if (value != const1_rtx)
6622 {
1e5fcbe2 6623 error ("%<__builtin_longjmp%> second argument must be 1");
53800dbe 6624 return const0_rtx;
6625 }
6626
6627 expand_builtin_longjmp (buf_addr, value);
6628 return const0_rtx;
6629 }
2c8a1497 6630 break;
53800dbe 6631
4ee9c684 6632 case BUILT_IN_NONLOCAL_GOTO:
c2f47e15 6633 target = expand_builtin_nonlocal_goto (exp);
4ee9c684 6634 if (target)
6635 return target;
6636 break;
6637
843d08a9 6638 /* This updates the setjmp buffer that is its argument with the value
6639 of the current stack pointer. */
6640 case BUILT_IN_UPDATE_SETJMP_BUF:
c2f47e15 6641 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
843d08a9 6642 {
6643 rtx buf_addr
c2f47e15 6644 = expand_normal (CALL_EXPR_ARG (exp, 0));
843d08a9 6645
6646 expand_builtin_update_setjmp_buf (buf_addr);
6647 return const0_rtx;
6648 }
6649 break;
6650
53800dbe 6651 case BUILT_IN_TRAP:
a0ef1725 6652 expand_builtin_trap ();
53800dbe 6653 return const0_rtx;
6654
19bf118a 6655 case BUILT_IN_PRINTF:
0b25db21 6656 target = expand_builtin_printf (exp, target, mode, false);
19bf118a 6657 if (target)
6658 return target;
6659 break;
6660
6661 case BUILT_IN_PRINTF_UNLOCKED:
0b25db21 6662 target = expand_builtin_printf (exp, target, mode, true);
19bf118a 6663 if (target)
6664 return target;
6665 break;
6666
df94cd3b 6667 case BUILT_IN_FPUTS:
c2f47e15 6668 target = expand_builtin_fputs (exp, target, false);
c013a46e 6669 if (target)
6670 return target;
6671 break;
6672 case BUILT_IN_FPUTS_UNLOCKED:
c2f47e15 6673 target = expand_builtin_fputs (exp, target, true);
19bf118a 6674 if (target)
6675 return target;
6676 break;
6677
6678 case BUILT_IN_FPRINTF:
0b25db21 6679 target = expand_builtin_fprintf (exp, target, mode, false);
19bf118a 6680 if (target)
6681 return target;
6682 break;
6683
6684 case BUILT_IN_FPRINTF_UNLOCKED:
0b25db21 6685 target = expand_builtin_fprintf (exp, target, mode, true);
df94cd3b 6686 if (target)
6687 return target;
6688 break;
bf8e3599 6689
6411575e 6690 case BUILT_IN_SPRINTF:
c2f47e15 6691 target = expand_builtin_sprintf (exp, target, mode);
6411575e 6692 if (target)
6693 return target;
6694 break;
6695
4f35b1fc 6696 CASE_FLT_FN (BUILT_IN_SIGNBIT):
004e23c4 6697 case BUILT_IN_SIGNBITD32:
6698 case BUILT_IN_SIGNBITD64:
6699 case BUILT_IN_SIGNBITD128:
27f261ef 6700 target = expand_builtin_signbit (exp, target);
6701 if (target)
6702 return target;
6703 break;
6704
53800dbe 6705 /* Various hooks for the DWARF 2 __throw routine. */
6706 case BUILT_IN_UNWIND_INIT:
6707 expand_builtin_unwind_init ();
6708 return const0_rtx;
6709 case BUILT_IN_DWARF_CFA:
6710 return virtual_cfa_rtx;
6711#ifdef DWARF2_UNWIND_INFO
f8f023a5 6712 case BUILT_IN_DWARF_SP_COLUMN:
6713 return expand_builtin_dwarf_sp_column ();
695e919b 6714 case BUILT_IN_INIT_DWARF_REG_SIZES:
c2f47e15 6715 expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
695e919b 6716 return const0_rtx;
53800dbe 6717#endif
6718 case BUILT_IN_FROB_RETURN_ADDR:
c2f47e15 6719 return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6720 case BUILT_IN_EXTRACT_RETURN_ADDR:
c2f47e15 6721 return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6722 case BUILT_IN_EH_RETURN:
c2f47e15 6723 expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
6724 CALL_EXPR_ARG (exp, 1));
53800dbe 6725 return const0_rtx;
df4b504c 6726#ifdef EH_RETURN_DATA_REGNO
6727 case BUILT_IN_EH_RETURN_DATA_REGNO:
c2f47e15 6728 return expand_builtin_eh_return_data_regno (exp);
df4b504c 6729#endif
26093bf4 6730 case BUILT_IN_EXTEND_POINTER:
c2f47e15 6731 return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
26093bf4 6732
7ccc713a 6733 case BUILT_IN_VA_START:
c2f47e15 6734 return expand_builtin_va_start (exp);
a66c9326 6735 case BUILT_IN_VA_END:
c2f47e15 6736 return expand_builtin_va_end (exp);
a66c9326 6737 case BUILT_IN_VA_COPY:
c2f47e15 6738 return expand_builtin_va_copy (exp);
89cfe6e5 6739 case BUILT_IN_EXPECT:
c2f47e15 6740 return expand_builtin_expect (exp, target);
5e3608d8 6741 case BUILT_IN_PREFETCH:
c2f47e15 6742 expand_builtin_prefetch (exp);
5e3608d8 6743 return const0_rtx;
6744
4ee9c684 6745 case BUILT_IN_PROFILE_FUNC_ENTER:
6746 return expand_builtin_profile_func (false);
6747 case BUILT_IN_PROFILE_FUNC_EXIT:
6748 return expand_builtin_profile_func (true);
6749
6750 case BUILT_IN_INIT_TRAMPOLINE:
c2f47e15 6751 return expand_builtin_init_trampoline (exp);
4ee9c684 6752 case BUILT_IN_ADJUST_TRAMPOLINE:
c2f47e15 6753 return expand_builtin_adjust_trampoline (exp);
4ee9c684 6754
73673831 6755 case BUILT_IN_FORK:
6756 case BUILT_IN_EXECL:
6757 case BUILT_IN_EXECV:
6758 case BUILT_IN_EXECLP:
6759 case BUILT_IN_EXECLE:
6760 case BUILT_IN_EXECVP:
6761 case BUILT_IN_EXECVE:
c2f47e15 6762 target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
73673831 6763 if (target)
6764 return target;
6765 break;
53800dbe 6766
b6a5fc45 6767 case BUILT_IN_FETCH_AND_ADD_1:
6768 case BUILT_IN_FETCH_AND_ADD_2:
6769 case BUILT_IN_FETCH_AND_ADD_4:
6770 case BUILT_IN_FETCH_AND_ADD_8:
27213ba3 6771 case BUILT_IN_FETCH_AND_ADD_16:
3e272de8 6772 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_ADD_1);
c2f47e15 6773 target = expand_builtin_sync_operation (mode, exp, PLUS,
b6a5fc45 6774 false, target, ignore);
6775 if (target)
6776 return target;
6777 break;
6778
6779 case BUILT_IN_FETCH_AND_SUB_1:
6780 case BUILT_IN_FETCH_AND_SUB_2:
6781 case BUILT_IN_FETCH_AND_SUB_4:
6782 case BUILT_IN_FETCH_AND_SUB_8:
27213ba3 6783 case BUILT_IN_FETCH_AND_SUB_16:
3e272de8 6784 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_SUB_1);
c2f47e15 6785 target = expand_builtin_sync_operation (mode, exp, MINUS,
b6a5fc45 6786 false, target, ignore);
6787 if (target)
6788 return target;
6789 break;
6790
6791 case BUILT_IN_FETCH_AND_OR_1:
6792 case BUILT_IN_FETCH_AND_OR_2:
6793 case BUILT_IN_FETCH_AND_OR_4:
6794 case BUILT_IN_FETCH_AND_OR_8:
27213ba3 6795 case BUILT_IN_FETCH_AND_OR_16:
3e272de8 6796 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_OR_1);
c2f47e15 6797 target = expand_builtin_sync_operation (mode, exp, IOR,
b6a5fc45 6798 false, target, ignore);
6799 if (target)
6800 return target;
6801 break;
6802
6803 case BUILT_IN_FETCH_AND_AND_1:
6804 case BUILT_IN_FETCH_AND_AND_2:
6805 case BUILT_IN_FETCH_AND_AND_4:
6806 case BUILT_IN_FETCH_AND_AND_8:
27213ba3 6807 case BUILT_IN_FETCH_AND_AND_16:
3e272de8 6808 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_AND_1);
c2f47e15 6809 target = expand_builtin_sync_operation (mode, exp, AND,
b6a5fc45 6810 false, target, ignore);
6811 if (target)
6812 return target;
6813 break;
6814
6815 case BUILT_IN_FETCH_AND_XOR_1:
6816 case BUILT_IN_FETCH_AND_XOR_2:
6817 case BUILT_IN_FETCH_AND_XOR_4:
6818 case BUILT_IN_FETCH_AND_XOR_8:
27213ba3 6819 case BUILT_IN_FETCH_AND_XOR_16:
3e272de8 6820 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_XOR_1);
c2f47e15 6821 target = expand_builtin_sync_operation (mode, exp, XOR,
b6a5fc45 6822 false, target, ignore);
6823 if (target)
6824 return target;
6825 break;
6826
6827 case BUILT_IN_FETCH_AND_NAND_1:
6828 case BUILT_IN_FETCH_AND_NAND_2:
6829 case BUILT_IN_FETCH_AND_NAND_4:
6830 case BUILT_IN_FETCH_AND_NAND_8:
27213ba3 6831 case BUILT_IN_FETCH_AND_NAND_16:
3e272de8 6832 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_NAND_1);
c2f47e15 6833 target = expand_builtin_sync_operation (mode, exp, NOT,
b6a5fc45 6834 false, target, ignore);
6835 if (target)
6836 return target;
6837 break;
6838
6839 case BUILT_IN_ADD_AND_FETCH_1:
6840 case BUILT_IN_ADD_AND_FETCH_2:
6841 case BUILT_IN_ADD_AND_FETCH_4:
6842 case BUILT_IN_ADD_AND_FETCH_8:
27213ba3 6843 case BUILT_IN_ADD_AND_FETCH_16:
3e272de8 6844 mode = get_builtin_sync_mode (fcode - BUILT_IN_ADD_AND_FETCH_1);
c2f47e15 6845 target = expand_builtin_sync_operation (mode, exp, PLUS,
b6a5fc45 6846 true, target, ignore);
6847 if (target)
6848 return target;
6849 break;
6850
6851 case BUILT_IN_SUB_AND_FETCH_1:
6852 case BUILT_IN_SUB_AND_FETCH_2:
6853 case BUILT_IN_SUB_AND_FETCH_4:
6854 case BUILT_IN_SUB_AND_FETCH_8:
27213ba3 6855 case BUILT_IN_SUB_AND_FETCH_16:
3e272de8 6856 mode = get_builtin_sync_mode (fcode - BUILT_IN_SUB_AND_FETCH_1);
c2f47e15 6857 target = expand_builtin_sync_operation (mode, exp, MINUS,
b6a5fc45 6858 true, target, ignore);
6859 if (target)
6860 return target;
6861 break;
6862
6863 case BUILT_IN_OR_AND_FETCH_1:
6864 case BUILT_IN_OR_AND_FETCH_2:
6865 case BUILT_IN_OR_AND_FETCH_4:
6866 case BUILT_IN_OR_AND_FETCH_8:
27213ba3 6867 case BUILT_IN_OR_AND_FETCH_16:
3e272de8 6868 mode = get_builtin_sync_mode (fcode - BUILT_IN_OR_AND_FETCH_1);
c2f47e15 6869 target = expand_builtin_sync_operation (mode, exp, IOR,
b6a5fc45 6870 true, target, ignore);
6871 if (target)
6872 return target;
6873 break;
6874
6875 case BUILT_IN_AND_AND_FETCH_1:
6876 case BUILT_IN_AND_AND_FETCH_2:
6877 case BUILT_IN_AND_AND_FETCH_4:
6878 case BUILT_IN_AND_AND_FETCH_8:
27213ba3 6879 case BUILT_IN_AND_AND_FETCH_16:
3e272de8 6880 mode = get_builtin_sync_mode (fcode - BUILT_IN_AND_AND_FETCH_1);
c2f47e15 6881 target = expand_builtin_sync_operation (mode, exp, AND,
b6a5fc45 6882 true, target, ignore);
6883 if (target)
6884 return target;
6885 break;
6886
6887 case BUILT_IN_XOR_AND_FETCH_1:
6888 case BUILT_IN_XOR_AND_FETCH_2:
6889 case BUILT_IN_XOR_AND_FETCH_4:
6890 case BUILT_IN_XOR_AND_FETCH_8:
27213ba3 6891 case BUILT_IN_XOR_AND_FETCH_16:
3e272de8 6892 mode = get_builtin_sync_mode (fcode - BUILT_IN_XOR_AND_FETCH_1);
c2f47e15 6893 target = expand_builtin_sync_operation (mode, exp, XOR,
b6a5fc45 6894 true, target, ignore);
6895 if (target)
6896 return target;
6897 break;
6898
6899 case BUILT_IN_NAND_AND_FETCH_1:
6900 case BUILT_IN_NAND_AND_FETCH_2:
6901 case BUILT_IN_NAND_AND_FETCH_4:
6902 case BUILT_IN_NAND_AND_FETCH_8:
27213ba3 6903 case BUILT_IN_NAND_AND_FETCH_16:
3e272de8 6904 mode = get_builtin_sync_mode (fcode - BUILT_IN_NAND_AND_FETCH_1);
c2f47e15 6905 target = expand_builtin_sync_operation (mode, exp, NOT,
b6a5fc45 6906 true, target, ignore);
6907 if (target)
6908 return target;
6909 break;
6910
6911 case BUILT_IN_BOOL_COMPARE_AND_SWAP_1:
6912 case BUILT_IN_BOOL_COMPARE_AND_SWAP_2:
6913 case BUILT_IN_BOOL_COMPARE_AND_SWAP_4:
6914 case BUILT_IN_BOOL_COMPARE_AND_SWAP_8:
27213ba3 6915 case BUILT_IN_BOOL_COMPARE_AND_SWAP_16:
a601d32a 6916 if (mode == VOIDmode)
6917 mode = TYPE_MODE (boolean_type_node);
b6a5fc45 6918 if (!target || !register_operand (target, mode))
6919 target = gen_reg_rtx (mode);
3e272de8 6920
6921 mode = get_builtin_sync_mode (fcode - BUILT_IN_BOOL_COMPARE_AND_SWAP_1);
c2f47e15 6922 target = expand_builtin_compare_and_swap (mode, exp, true, target);
b6a5fc45 6923 if (target)
6924 return target;
6925 break;
6926
6927 case BUILT_IN_VAL_COMPARE_AND_SWAP_1:
6928 case BUILT_IN_VAL_COMPARE_AND_SWAP_2:
6929 case BUILT_IN_VAL_COMPARE_AND_SWAP_4:
6930 case BUILT_IN_VAL_COMPARE_AND_SWAP_8:
27213ba3 6931 case BUILT_IN_VAL_COMPARE_AND_SWAP_16:
3e272de8 6932 mode = get_builtin_sync_mode (fcode - BUILT_IN_VAL_COMPARE_AND_SWAP_1);
c2f47e15 6933 target = expand_builtin_compare_and_swap (mode, exp, false, target);
b6a5fc45 6934 if (target)
6935 return target;
6936 break;
6937
6938 case BUILT_IN_LOCK_TEST_AND_SET_1:
6939 case BUILT_IN_LOCK_TEST_AND_SET_2:
6940 case BUILT_IN_LOCK_TEST_AND_SET_4:
6941 case BUILT_IN_LOCK_TEST_AND_SET_8:
27213ba3 6942 case BUILT_IN_LOCK_TEST_AND_SET_16:
3e272de8 6943 mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_TEST_AND_SET_1);
c2f47e15 6944 target = expand_builtin_lock_test_and_set (mode, exp, target);
b6a5fc45 6945 if (target)
6946 return target;
6947 break;
6948
6949 case BUILT_IN_LOCK_RELEASE_1:
6950 case BUILT_IN_LOCK_RELEASE_2:
6951 case BUILT_IN_LOCK_RELEASE_4:
6952 case BUILT_IN_LOCK_RELEASE_8:
27213ba3 6953 case BUILT_IN_LOCK_RELEASE_16:
3e272de8 6954 mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_RELEASE_1);
c2f47e15 6955 expand_builtin_lock_release (mode, exp);
b6a5fc45 6956 return const0_rtx;
6957
6958 case BUILT_IN_SYNCHRONIZE:
6959 expand_builtin_synchronize ();
6960 return const0_rtx;
6961
0a39fd54 6962 case BUILT_IN_OBJECT_SIZE:
6963 return expand_builtin_object_size (exp);
6964
6965 case BUILT_IN_MEMCPY_CHK:
6966 case BUILT_IN_MEMPCPY_CHK:
6967 case BUILT_IN_MEMMOVE_CHK:
6968 case BUILT_IN_MEMSET_CHK:
6969 target = expand_builtin_memory_chk (exp, target, mode, fcode);
6970 if (target)
6971 return target;
6972 break;
6973
6974 case BUILT_IN_STRCPY_CHK:
6975 case BUILT_IN_STPCPY_CHK:
6976 case BUILT_IN_STRNCPY_CHK:
6977 case BUILT_IN_STRCAT_CHK:
b356dfef 6978 case BUILT_IN_STRNCAT_CHK:
0a39fd54 6979 case BUILT_IN_SNPRINTF_CHK:
6980 case BUILT_IN_VSNPRINTF_CHK:
6981 maybe_emit_chk_warning (exp, fcode);
6982 break;
6983
6984 case BUILT_IN_SPRINTF_CHK:
6985 case BUILT_IN_VSPRINTF_CHK:
6986 maybe_emit_sprintf_chk_warning (exp, fcode);
6987 break;
6988
92482ee0 6989 default: /* just do library call, if unknown builtin */
146c1b4f 6990 break;
53800dbe 6991 }
6992
6993 /* The switch statement above can drop through to cause the function
6994 to be called normally. */
6995 return expand_call (exp, target, ignore);
6996}
650e4c94 6997
805e22b2 6998/* Determine whether a tree node represents a call to a built-in
52203a9d 6999 function. If the tree T is a call to a built-in function with
7000 the right number of arguments of the appropriate types, return
7001 the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
7002 Otherwise the return value is END_BUILTINS. */
aecda0d6 7003
805e22b2 7004enum built_in_function
b7bf20db 7005builtin_mathfn_code (const_tree t)
805e22b2 7006{
b7bf20db 7007 const_tree fndecl, arg, parmlist;
7008 const_tree argtype, parmtype;
7009 const_call_expr_arg_iterator iter;
805e22b2 7010
7011 if (TREE_CODE (t) != CALL_EXPR
c2f47e15 7012 || TREE_CODE (CALL_EXPR_FN (t)) != ADDR_EXPR)
805e22b2 7013 return END_BUILTINS;
7014
c6e6ecb1 7015 fndecl = get_callee_fndecl (t);
7016 if (fndecl == NULL_TREE
52203a9d 7017 || TREE_CODE (fndecl) != FUNCTION_DECL
805e22b2 7018 || ! DECL_BUILT_IN (fndecl)
7019 || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
7020 return END_BUILTINS;
7021
52203a9d 7022 parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
b7bf20db 7023 init_const_call_expr_arg_iterator (t, &iter);
52203a9d 7024 for (; parmlist; parmlist = TREE_CHAIN (parmlist))
e9f80ff5 7025 {
52203a9d 7026 /* If a function doesn't take a variable number of arguments,
7027 the last element in the list will have type `void'. */
7028 parmtype = TREE_VALUE (parmlist);
7029 if (VOID_TYPE_P (parmtype))
7030 {
b7bf20db 7031 if (more_const_call_expr_args_p (&iter))
52203a9d 7032 return END_BUILTINS;
7033 return DECL_FUNCTION_CODE (fndecl);
7034 }
7035
b7bf20db 7036 if (! more_const_call_expr_args_p (&iter))
e9f80ff5 7037 return END_BUILTINS;
c2f47e15 7038
b7bf20db 7039 arg = next_const_call_expr_arg (&iter);
c2f47e15 7040 argtype = TREE_TYPE (arg);
52203a9d 7041
7042 if (SCALAR_FLOAT_TYPE_P (parmtype))
7043 {
7044 if (! SCALAR_FLOAT_TYPE_P (argtype))
7045 return END_BUILTINS;
7046 }
7047 else if (COMPLEX_FLOAT_TYPE_P (parmtype))
7048 {
7049 if (! COMPLEX_FLOAT_TYPE_P (argtype))
7050 return END_BUILTINS;
7051 }
7052 else if (POINTER_TYPE_P (parmtype))
7053 {
7054 if (! POINTER_TYPE_P (argtype))
7055 return END_BUILTINS;
7056 }
7057 else if (INTEGRAL_TYPE_P (parmtype))
7058 {
7059 if (! INTEGRAL_TYPE_P (argtype))
7060 return END_BUILTINS;
7061 }
7062 else
e9f80ff5 7063 return END_BUILTINS;
e9f80ff5 7064 }
7065
52203a9d 7066 /* Variable-length argument list. */
805e22b2 7067 return DECL_FUNCTION_CODE (fndecl);
7068}
7069
c2f47e15 7070/* Fold a call to __builtin_constant_p, if we know its argument ARG will
7071 evaluate to a constant. */
650e4c94 7072
7073static tree
c2f47e15 7074fold_builtin_constant_p (tree arg)
650e4c94 7075{
650e4c94 7076 /* We return 1 for a numeric type that's known to be a constant
7077 value at compile-time or for an aggregate type that's a
7078 literal constant. */
c2f47e15 7079 STRIP_NOPS (arg);
650e4c94 7080
7081 /* If we know this is a constant, emit the constant of one. */
c2f47e15 7082 if (CONSTANT_CLASS_P (arg)
7083 || (TREE_CODE (arg) == CONSTRUCTOR
7084 && TREE_CONSTANT (arg)))
650e4c94 7085 return integer_one_node;
c2f47e15 7086 if (TREE_CODE (arg) == ADDR_EXPR)
adcfa3a3 7087 {
c2f47e15 7088 tree op = TREE_OPERAND (arg, 0);
adcfa3a3 7089 if (TREE_CODE (op) == STRING_CST
7090 || (TREE_CODE (op) == ARRAY_REF
7091 && integer_zerop (TREE_OPERAND (op, 1))
7092 && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
7093 return integer_one_node;
7094 }
650e4c94 7095
1fb4300c 7096 /* If this expression has side effects, show we don't know it to be a
7097 constant. Likewise if it's a pointer or aggregate type since in
7098 those case we only want literals, since those are only optimized
f97c71a1 7099 when generating RTL, not later.
7100 And finally, if we are compiling an initializer, not code, we
7101 need to return a definite result now; there's not going to be any
7102 more optimization done. */
c2f47e15 7103 if (TREE_SIDE_EFFECTS (arg)
7104 || AGGREGATE_TYPE_P (TREE_TYPE (arg))
7105 || POINTER_TYPE_P (TREE_TYPE (arg))
47be647d 7106 || cfun == 0
7107 || folding_initializer)
650e4c94 7108 return integer_zero_node;
7109
c2f47e15 7110 return NULL_TREE;
650e4c94 7111}
7112
76f5a783 7113/* Create builtin_expect with PRED and EXPECTED as its arguments and
7114 return it as a truthvalue. */
4ee9c684 7115
7116static tree
76f5a783 7117build_builtin_expect_predicate (tree pred, tree expected)
4ee9c684 7118{
76f5a783 7119 tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
4ee9c684 7120
76f5a783 7121 fn = built_in_decls[BUILT_IN_EXPECT];
7122 arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
7123 ret_type = TREE_TYPE (TREE_TYPE (fn));
7124 pred_type = TREE_VALUE (arg_types);
7125 expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
7126
7127 pred = fold_convert (pred_type, pred);
7128 expected = fold_convert (expected_type, expected);
7129 call_expr = build_call_expr (fn, 2, pred, expected);
7130
7131 return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
7132 build_int_cst (ret_type, 0));
7133}
7134
7135/* Fold a call to builtin_expect with arguments ARG0 and ARG1. Return
7136 NULL_TREE if no simplification is possible. */
7137
7138static tree
7139fold_builtin_expect (tree arg0, tree arg1)
7140{
7141 tree inner, fndecl;
7142 enum tree_code code;
7143
7144 /* If this is a builtin_expect within a builtin_expect keep the
7145 inner one. See through a comparison against a constant. It
7146 might have been added to create a thruthvalue. */
7147 inner = arg0;
7148 if (COMPARISON_CLASS_P (inner)
7149 && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST)
7150 inner = TREE_OPERAND (inner, 0);
7151
7152 if (TREE_CODE (inner) == CALL_EXPR
7153 && (fndecl = get_callee_fndecl (inner))
7154 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
7155 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT)
7156 return arg0;
7157
7158 /* Distribute the expected value over short-circuiting operators.
7159 See through the cast from truthvalue_type_node to long. */
7160 inner = arg0;
7161 while (TREE_CODE (inner) == NOP_EXPR
7162 && INTEGRAL_TYPE_P (TREE_TYPE (inner))
7163 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner, 0))))
7164 inner = TREE_OPERAND (inner, 0);
7165
7166 code = TREE_CODE (inner);
7167 if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
7168 {
7169 tree op0 = TREE_OPERAND (inner, 0);
7170 tree op1 = TREE_OPERAND (inner, 1);
7171
7172 op0 = build_builtin_expect_predicate (op0, arg1);
7173 op1 = build_builtin_expect_predicate (op1, arg1);
7174 inner = build2 (code, TREE_TYPE (inner), op0, op1);
7175
7176 return fold_convert (TREE_TYPE (arg0), inner);
7177 }
7178
7179 /* If the argument isn't invariant then there's nothing else we can do. */
c7d4e749 7180 if (!TREE_CONSTANT (arg0))
c2f47e15 7181 return NULL_TREE;
4ee9c684 7182
76f5a783 7183 /* If we expect that a comparison against the argument will fold to
7184 a constant return the constant. In practice, this means a true
7185 constant or the address of a non-weak symbol. */
7186 inner = arg0;
4ee9c684 7187 STRIP_NOPS (inner);
7188 if (TREE_CODE (inner) == ADDR_EXPR)
7189 {
7190 do
7191 {
7192 inner = TREE_OPERAND (inner, 0);
7193 }
7194 while (TREE_CODE (inner) == COMPONENT_REF
7195 || TREE_CODE (inner) == ARRAY_REF);
7196 if (DECL_P (inner) && DECL_WEAK (inner))
c2f47e15 7197 return NULL_TREE;
4ee9c684 7198 }
7199
76f5a783 7200 /* Otherwise, ARG0 already has the proper type for the return value. */
7201 return arg0;
4ee9c684 7202}
7203
c2f47e15 7204/* Fold a call to __builtin_classify_type with argument ARG. */
27d0c333 7205
539a3a92 7206static tree
c2f47e15 7207fold_builtin_classify_type (tree arg)
539a3a92 7208{
c2f47e15 7209 if (arg == 0)
7016c612 7210 return build_int_cst (NULL_TREE, no_type_class);
539a3a92 7211
c2f47e15 7212 return build_int_cst (NULL_TREE, type_to_class (TREE_TYPE (arg)));
539a3a92 7213}
7214
c2f47e15 7215/* Fold a call to __builtin_strlen with argument ARG. */
e6e27594 7216
7217static tree
c2f47e15 7218fold_builtin_strlen (tree arg)
e6e27594 7219{
c2f47e15 7220 if (!validate_arg (arg, POINTER_TYPE))
e6e27594 7221 return NULL_TREE;
7222 else
7223 {
c2f47e15 7224 tree len = c_strlen (arg, 0);
e6e27594 7225
7226 if (len)
7227 {
7228 /* Convert from the internal "sizetype" type to "size_t". */
7229 if (size_type_node)
7230 len = fold_convert (size_type_node, len);
7231 return len;
7232 }
7233
7234 return NULL_TREE;
7235 }
7236}
7237
92c43e3c 7238/* Fold a call to __builtin_inf or __builtin_huge_val. */
7239
7240static tree
aecda0d6 7241fold_builtin_inf (tree type, int warn)
92c43e3c 7242{
aa870c1b 7243 REAL_VALUE_TYPE real;
7244
40f4dbd5 7245 /* __builtin_inff is intended to be usable to define INFINITY on all
7246 targets. If an infinity is not available, INFINITY expands "to a
7247 positive constant of type float that overflows at translation
7248 time", footnote "In this case, using INFINITY will violate the
7249 constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
7250 Thus we pedwarn to ensure this constraint violation is
7251 diagnosed. */
92c43e3c 7252 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
40f4dbd5 7253 pedwarn ("target format does not support infinity");
92c43e3c 7254
aa870c1b 7255 real_inf (&real);
7256 return build_real (type, real);
92c43e3c 7257}
7258
c2f47e15 7259/* Fold a call to __builtin_nan or __builtin_nans with argument ARG. */
b0db7939 7260
7261static tree
c2f47e15 7262fold_builtin_nan (tree arg, tree type, int quiet)
b0db7939 7263{
7264 REAL_VALUE_TYPE real;
7265 const char *str;
7266
c2f47e15 7267 if (!validate_arg (arg, POINTER_TYPE))
7268 return NULL_TREE;
7269 str = c_getstr (arg);
b0db7939 7270 if (!str)
c2f47e15 7271 return NULL_TREE;
b0db7939 7272
7273 if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
c2f47e15 7274 return NULL_TREE;
b0db7939 7275
7276 return build_real (type, real);
7277}
7278
277f8dd2 7279/* Return true if the floating point expression T has an integer value.
7280 We also allow +Inf, -Inf and NaN to be considered integer values. */
7281
7282static bool
7283integer_valued_real_p (tree t)
7284{
7285 switch (TREE_CODE (t))
7286 {
7287 case FLOAT_EXPR:
7288 return true;
7289
7290 case ABS_EXPR:
7291 case SAVE_EXPR:
277f8dd2 7292 return integer_valued_real_p (TREE_OPERAND (t, 0));
7293
7294 case COMPOUND_EXPR:
41076ef6 7295 case MODIFY_EXPR:
277f8dd2 7296 case BIND_EXPR:
35cc02b5 7297 return integer_valued_real_p (GENERIC_TREE_OPERAND (t, 1));
277f8dd2 7298
7299 case PLUS_EXPR:
7300 case MINUS_EXPR:
7301 case MULT_EXPR:
7302 case MIN_EXPR:
7303 case MAX_EXPR:
7304 return integer_valued_real_p (TREE_OPERAND (t, 0))
7305 && integer_valued_real_p (TREE_OPERAND (t, 1));
7306
7307 case COND_EXPR:
7308 return integer_valued_real_p (TREE_OPERAND (t, 1))
7309 && integer_valued_real_p (TREE_OPERAND (t, 2));
7310
7311 case REAL_CST:
0570334c 7312 return real_isinteger (TREE_REAL_CST_PTR (t), TYPE_MODE (TREE_TYPE (t)));
277f8dd2 7313
7314 case NOP_EXPR:
7315 {
7316 tree type = TREE_TYPE (TREE_OPERAND (t, 0));
7317 if (TREE_CODE (type) == INTEGER_TYPE)
7318 return true;
7319 if (TREE_CODE (type) == REAL_TYPE)
7320 return integer_valued_real_p (TREE_OPERAND (t, 0));
7321 break;
7322 }
7323
7324 case CALL_EXPR:
7325 switch (builtin_mathfn_code (t))
7326 {
4f35b1fc 7327 CASE_FLT_FN (BUILT_IN_CEIL):
7328 CASE_FLT_FN (BUILT_IN_FLOOR):
7329 CASE_FLT_FN (BUILT_IN_NEARBYINT):
7330 CASE_FLT_FN (BUILT_IN_RINT):
7331 CASE_FLT_FN (BUILT_IN_ROUND):
7332 CASE_FLT_FN (BUILT_IN_TRUNC):
277f8dd2 7333 return true;
7334
d4a43a03 7335 CASE_FLT_FN (BUILT_IN_FMIN):
7336 CASE_FLT_FN (BUILT_IN_FMAX):
c2f47e15 7337 return integer_valued_real_p (CALL_EXPR_ARG (t, 0))
7338 && integer_valued_real_p (CALL_EXPR_ARG (t, 1));
d4a43a03 7339
277f8dd2 7340 default:
7341 break;
7342 }
7343 break;
7344
7345 default:
7346 break;
7347 }
7348 return false;
7349}
7350
c2f47e15 7351/* FNDECL is assumed to be a builtin where truncation can be propagated
6528f4f4 7352 across (for instance floor((double)f) == (double)floorf (f).
c2f47e15 7353 Do the transformation for a call with argument ARG. */
277f8dd2 7354
6528f4f4 7355static tree
c2f47e15 7356fold_trunc_transparent_mathfn (tree fndecl, tree arg)
6528f4f4 7357{
6528f4f4 7358 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
277f8dd2 7359
c2f47e15 7360 if (!validate_arg (arg, REAL_TYPE))
7361 return NULL_TREE;
6528f4f4 7362
277f8dd2 7363 /* Integer rounding functions are idempotent. */
7364 if (fcode == builtin_mathfn_code (arg))
7365 return arg;
7366
7367 /* If argument is already integer valued, and we don't need to worry
7368 about setting errno, there's no need to perform rounding. */
7369 if (! flag_errno_math && integer_valued_real_p (arg))
7370 return arg;
7371
7372 if (optimize)
6528f4f4 7373 {
277f8dd2 7374 tree arg0 = strip_float_extensions (arg);
2426241c 7375 tree ftype = TREE_TYPE (TREE_TYPE (fndecl));
6528f4f4 7376 tree newtype = TREE_TYPE (arg0);
7377 tree decl;
7378
7379 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7380 && (decl = mathfn_built_in (newtype, fcode)))
c2f47e15 7381 return fold_convert (ftype,
7382 build_call_expr (decl, 1,
7383 fold_convert (newtype, arg0)));
6528f4f4 7384 }
c2f47e15 7385 return NULL_TREE;
6528f4f4 7386}
7387
c2f47e15 7388/* FNDECL is assumed to be builtin which can narrow the FP type of
7389 the argument, for instance lround((double)f) -> lroundf (f).
7390 Do the transformation for a call with argument ARG. */
9ed65c7f 7391
7392static tree
c2f47e15 7393fold_fixed_mathfn (tree fndecl, tree arg)
9ed65c7f 7394{
9ed65c7f 7395 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9ed65c7f 7396
c2f47e15 7397 if (!validate_arg (arg, REAL_TYPE))
7398 return NULL_TREE;
9ed65c7f 7399
7400 /* If argument is already integer valued, and we don't need to worry
7401 about setting errno, there's no need to perform rounding. */
7402 if (! flag_errno_math && integer_valued_real_p (arg))
49d00087 7403 return fold_build1 (FIX_TRUNC_EXPR, TREE_TYPE (TREE_TYPE (fndecl)), arg);
9ed65c7f 7404
7405 if (optimize)
7406 {
7407 tree ftype = TREE_TYPE (arg);
7408 tree arg0 = strip_float_extensions (arg);
7409 tree newtype = TREE_TYPE (arg0);
7410 tree decl;
7411
7412 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7413 && (decl = mathfn_built_in (newtype, fcode)))
c2f47e15 7414 return build_call_expr (decl, 1, fold_convert (newtype, arg0));
9ed65c7f 7415 }
73a0da56 7416
7417 /* Canonicalize llround (x) to lround (x) on LP64 targets where
7418 sizeof (long long) == sizeof (long). */
7419 if (TYPE_PRECISION (long_long_integer_type_node)
7420 == TYPE_PRECISION (long_integer_type_node))
7421 {
7422 tree newfn = NULL_TREE;
7423 switch (fcode)
7424 {
7425 CASE_FLT_FN (BUILT_IN_LLCEIL):
7426 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
7427 break;
7428
7429 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7430 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
7431 break;
7432
7433 CASE_FLT_FN (BUILT_IN_LLROUND):
7434 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
7435 break;
7436
7437 CASE_FLT_FN (BUILT_IN_LLRINT):
7438 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
7439 break;
7440
7441 default:
7442 break;
7443 }
7444
7445 if (newfn)
7446 {
c2f47e15 7447 tree newcall = build_call_expr(newfn, 1, arg);
73a0da56 7448 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), newcall);
7449 }
7450 }
7451
c2f47e15 7452 return NULL_TREE;
9ed65c7f 7453}
7454
c2f47e15 7455/* Fold call to builtin cabs, cabsf or cabsl with argument ARG. TYPE is the
7456 return type. Return NULL_TREE if no simplification can be made. */
c63f4ad3 7457
7458static tree
c2f47e15 7459fold_builtin_cabs (tree arg, tree type, tree fndecl)
c63f4ad3 7460{
c2f47e15 7461 tree res;
c63f4ad3 7462
c63f4ad3 7463 if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
7464 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
7465 return NULL_TREE;
7466
b4725390 7467 /* Calculate the result when the argument is a constant. */
7468 if (TREE_CODE (arg) == COMPLEX_CST
7469 && (res = do_mpfr_arg2 (TREE_REALPART (arg), TREE_IMAGPART (arg),
7470 type, mpfr_hypot)))
7471 return res;
7472
1af0d139 7473 if (TREE_CODE (arg) == COMPLEX_EXPR)
7474 {
7475 tree real = TREE_OPERAND (arg, 0);
7476 tree imag = TREE_OPERAND (arg, 1);
7477
7478 /* If either part is zero, cabs is fabs of the other. */
7479 if (real_zerop (real))
7480 return fold_build1 (ABS_EXPR, type, imag);
7481 if (real_zerop (imag))
7482 return fold_build1 (ABS_EXPR, type, real);
7483
7484 /* cabs(x+xi) -> fabs(x)*sqrt(2). */
7485 if (flag_unsafe_math_optimizations
7486 && operand_equal_p (real, imag, OEP_PURE_SAME))
7487 {
2e7ca27b 7488 const REAL_VALUE_TYPE sqrt2_trunc
3fa759a9 7489 = real_value_truncate (TYPE_MODE (type),
7490 *get_real_const (rv_sqrt2));
1af0d139 7491 STRIP_NOPS (real);
7492 return fold_build2 (MULT_EXPR, type,
7493 fold_build1 (ABS_EXPR, type, real),
2e7ca27b 7494 build_real (type, sqrt2_trunc));
1af0d139 7495 }
7496 }
c63f4ad3 7497
749891b2 7498 /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */
7499 if (TREE_CODE (arg) == NEGATE_EXPR
7500 || TREE_CODE (arg) == CONJ_EXPR)
c2f47e15 7501 return build_call_expr (fndecl, 1, TREE_OPERAND (arg, 0));
749891b2 7502
7d3f6cc7 7503 /* Don't do this when optimizing for size. */
7504 if (flag_unsafe_math_optimizations
7505 && optimize && !optimize_size)
c63f4ad3 7506 {
0da0dbfa 7507 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
c63f4ad3 7508
7509 if (sqrtfn != NULL_TREE)
7510 {
c2f47e15 7511 tree rpart, ipart, result;
c63f4ad3 7512
4ee9c684 7513 arg = builtin_save_expr (arg);
29a6518e 7514
49d00087 7515 rpart = fold_build1 (REALPART_EXPR, type, arg);
7516 ipart = fold_build1 (IMAGPART_EXPR, type, arg);
c63f4ad3 7517
4ee9c684 7518 rpart = builtin_save_expr (rpart);
7519 ipart = builtin_save_expr (ipart);
c63f4ad3 7520
49d00087 7521 result = fold_build2 (PLUS_EXPR, type,
7522 fold_build2 (MULT_EXPR, type,
7523 rpart, rpart),
7524 fold_build2 (MULT_EXPR, type,
7525 ipart, ipart));
c63f4ad3 7526
c2f47e15 7527 return build_call_expr (sqrtfn, 1, result);
c63f4ad3 7528 }
7529 }
7530
7531 return NULL_TREE;
7532}
7533
c2f47e15 7534/* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG.
7535 Return NULL_TREE if no simplification can be made. */
e6e27594 7536
7537static tree
c2f47e15 7538fold_builtin_sqrt (tree arg, tree type)
e6e27594 7539{
7540
7541 enum built_in_function fcode;
b4e8ab0c 7542 tree res;
c2f47e15 7543
7544 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7545 return NULL_TREE;
7546
b4e8ab0c 7547 /* Calculate the result when the argument is a constant. */
7548 if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
7549 return res;
7550
e6e27594 7551 /* Optimize sqrt(expN(x)) = expN(x*0.5). */
7552 fcode = builtin_mathfn_code (arg);
7553 if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
7554 {
c2f47e15 7555 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
49d00087 7556 arg = fold_build2 (MULT_EXPR, type,
c2f47e15 7557 CALL_EXPR_ARG (arg, 0),
49d00087 7558 build_real (type, dconsthalf));
c2f47e15 7559 return build_call_expr (expfn, 1, arg);
e6e27594 7560 }
7561
7562 /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */
7563 if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
7564 {
7565 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7566
7567 if (powfn)
7568 {
c2f47e15 7569 tree arg0 = CALL_EXPR_ARG (arg, 0);
e6e27594 7570 tree tree_root;
7571 /* The inner root was either sqrt or cbrt. */
7572 REAL_VALUE_TYPE dconstroot =
3fa759a9 7573 BUILTIN_SQRT_P (fcode) ? dconsthalf : *get_real_const (rv_third);
e6e27594 7574
7575 /* Adjust for the outer root. */
7576 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7577 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7578 tree_root = build_real (type, dconstroot);
c2f47e15 7579 return build_call_expr (powfn, 2, arg0, tree_root);
e6e27594 7580 }
7581 }
7582
bc33117f 7583 /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
e6e27594 7584 if (flag_unsafe_math_optimizations
7585 && (fcode == BUILT_IN_POW
7586 || fcode == BUILT_IN_POWF
7587 || fcode == BUILT_IN_POWL))
7588 {
c2f47e15 7589 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
7590 tree arg0 = CALL_EXPR_ARG (arg, 0);
7591 tree arg1 = CALL_EXPR_ARG (arg, 1);
bc33117f 7592 tree narg1;
7593 if (!tree_expr_nonnegative_p (arg0))
7594 arg0 = build1 (ABS_EXPR, type, arg0);
49d00087 7595 narg1 = fold_build2 (MULT_EXPR, type, arg1,
7596 build_real (type, dconsthalf));
c2f47e15 7597 return build_call_expr (powfn, 2, arg0, narg1);
e6e27594 7598 }
7599
7600 return NULL_TREE;
7601}
7602
c2f47e15 7603/* Fold a builtin function call to cbrt, cbrtf, or cbrtl with argument ARG.
7604 Return NULL_TREE if no simplification can be made. */
7605
e6e27594 7606static tree
c2f47e15 7607fold_builtin_cbrt (tree arg, tree type)
e6e27594 7608{
e6e27594 7609 const enum built_in_function fcode = builtin_mathfn_code (arg);
29f4cd78 7610 tree res;
e6e27594 7611
c2f47e15 7612 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7613 return NULL_TREE;
7614
29f4cd78 7615 /* Calculate the result when the argument is a constant. */
7616 if ((res = do_mpfr_arg1 (arg, type, mpfr_cbrt, NULL, NULL, 0)))
7617 return res;
e6e27594 7618
cdfeb715 7619 if (flag_unsafe_math_optimizations)
e6e27594 7620 {
cdfeb715 7621 /* Optimize cbrt(expN(x)) -> expN(x/3). */
7622 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 7623 {
c2f47e15 7624 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7625 const REAL_VALUE_TYPE third_trunc =
3fa759a9 7626 real_value_truncate (TYPE_MODE (type), *get_real_const (rv_third));
49d00087 7627 arg = fold_build2 (MULT_EXPR, type,
c2f47e15 7628 CALL_EXPR_ARG (arg, 0),
49d00087 7629 build_real (type, third_trunc));
c2f47e15 7630 return build_call_expr (expfn, 1, arg);
cdfeb715 7631 }
e6e27594 7632
cdfeb715 7633 /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */
7634 if (BUILTIN_SQRT_P (fcode))
a0c938f0 7635 {
cdfeb715 7636 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
e6e27594 7637
cdfeb715 7638 if (powfn)
7639 {
c2f47e15 7640 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7641 tree tree_root;
3fa759a9 7642 REAL_VALUE_TYPE dconstroot = *get_real_const (rv_third);
cdfeb715 7643
7644 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7645 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7646 tree_root = build_real (type, dconstroot);
c2f47e15 7647 return build_call_expr (powfn, 2, arg0, tree_root);
cdfeb715 7648 }
e6e27594 7649 }
7650
cdfeb715 7651 /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */
7652 if (BUILTIN_CBRT_P (fcode))
a0c938f0 7653 {
c2f47e15 7654 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7655 if (tree_expr_nonnegative_p (arg0))
7656 {
7657 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7658
7659 if (powfn)
a0c938f0 7660 {
cdfeb715 7661 tree tree_root;
7662 REAL_VALUE_TYPE dconstroot;
a0c938f0 7663
3fa759a9 7664 real_arithmetic (&dconstroot, MULT_EXPR,
7665 get_real_const (rv_third),
7666 get_real_const (rv_third));
cdfeb715 7667 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7668 tree_root = build_real (type, dconstroot);
c2f47e15 7669 return build_call_expr (powfn, 2, arg0, tree_root);
cdfeb715 7670 }
7671 }
7672 }
a0c938f0 7673
cdfeb715 7674 /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */
c2f47e15 7675 if (fcode == BUILT_IN_POW
7676 || fcode == BUILT_IN_POWF
cdfeb715 7677 || fcode == BUILT_IN_POWL)
a0c938f0 7678 {
c2f47e15 7679 tree arg00 = CALL_EXPR_ARG (arg, 0);
7680 tree arg01 = CALL_EXPR_ARG (arg, 1);
cdfeb715 7681 if (tree_expr_nonnegative_p (arg00))
7682 {
c2f47e15 7683 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7684 const REAL_VALUE_TYPE dconstroot
3fa759a9 7685 = real_value_truncate (TYPE_MODE (type),
7686 *get_real_const (rv_third));
49d00087 7687 tree narg01 = fold_build2 (MULT_EXPR, type, arg01,
7688 build_real (type, dconstroot));
c2f47e15 7689 return build_call_expr (powfn, 2, arg00, narg01);
cdfeb715 7690 }
7691 }
e6e27594 7692 }
7693 return NULL_TREE;
7694}
7695
c2f47e15 7696/* Fold function call to builtin cos, cosf, or cosl with argument ARG.
7697 TYPE is the type of the return value. Return NULL_TREE if no
7698 simplification can be made. */
7699
e6e27594 7700static tree
c2f47e15 7701fold_builtin_cos (tree arg, tree type, tree fndecl)
e6e27594 7702{
e6ab33d8 7703 tree res, narg;
e6e27594 7704
c2f47e15 7705 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7706 return NULL_TREE;
7707
bffb7645 7708 /* Calculate the result when the argument is a constant. */
728bac60 7709 if ((res = do_mpfr_arg1 (arg, type, mpfr_cos, NULL, NULL, 0)))
bffb7645 7710 return res;
7711
e6e27594 7712 /* Optimize cos(-x) into cos (x). */
e6ab33d8 7713 if ((narg = fold_strip_sign_ops (arg)))
c2f47e15 7714 return build_call_expr (fndecl, 1, narg);
e6e27594 7715
7716 return NULL_TREE;
7717}
7718
c2f47e15 7719/* Fold function call to builtin cosh, coshf, or coshl with argument ARG.
7720 Return NULL_TREE if no simplification can be made. */
7721
cacdc1af 7722static tree
c2f47e15 7723fold_builtin_cosh (tree arg, tree type, tree fndecl)
cacdc1af 7724{
c2f47e15 7725 if (validate_arg (arg, REAL_TYPE))
cacdc1af 7726 {
cacdc1af 7727 tree res, narg;
7728
7729 /* Calculate the result when the argument is a constant. */
7730 if ((res = do_mpfr_arg1 (arg, type, mpfr_cosh, NULL, NULL, 0)))
7731 return res;
7732
7733 /* Optimize cosh(-x) into cosh (x). */
7734 if ((narg = fold_strip_sign_ops (arg)))
c2f47e15 7735 return build_call_expr (fndecl, 1, narg);
cacdc1af 7736 }
7737
7738 return NULL_TREE;
7739}
7740
c2f47e15 7741/* Fold function call to builtin tan, tanf, or tanl with argument ARG.
7742 Return NULL_TREE if no simplification can be made. */
7743
e6e27594 7744static tree
c2f47e15 7745fold_builtin_tan (tree arg, tree type)
e6e27594 7746{
7747 enum built_in_function fcode;
29f4cd78 7748 tree res;
e6e27594 7749
c2f47e15 7750 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7751 return NULL_TREE;
7752
bffb7645 7753 /* Calculate the result when the argument is a constant. */
728bac60 7754 if ((res = do_mpfr_arg1 (arg, type, mpfr_tan, NULL, NULL, 0)))
bffb7645 7755 return res;
7756
e6e27594 7757 /* Optimize tan(atan(x)) = x. */
7758 fcode = builtin_mathfn_code (arg);
7759 if (flag_unsafe_math_optimizations
7760 && (fcode == BUILT_IN_ATAN
7761 || fcode == BUILT_IN_ATANF
7762 || fcode == BUILT_IN_ATANL))
c2f47e15 7763 return CALL_EXPR_ARG (arg, 0);
e6e27594 7764
7765 return NULL_TREE;
7766}
7767
d735c391 7768/* Fold function call to builtin sincos, sincosf, or sincosl. Return
7769 NULL_TREE if no simplification can be made. */
7770
7771static tree
c2f47e15 7772fold_builtin_sincos (tree arg0, tree arg1, tree arg2)
d735c391 7773{
c2f47e15 7774 tree type;
d735c391 7775 tree res, fn, call;
7776
c2f47e15 7777 if (!validate_arg (arg0, REAL_TYPE)
7778 || !validate_arg (arg1, POINTER_TYPE)
7779 || !validate_arg (arg2, POINTER_TYPE))
d735c391 7780 return NULL_TREE;
7781
d735c391 7782 type = TREE_TYPE (arg0);
d735c391 7783
7784 /* Calculate the result when the argument is a constant. */
7785 if ((res = do_mpfr_sincos (arg0, arg1, arg2)))
7786 return res;
7787
7788 /* Canonicalize sincos to cexpi. */
2a6b4c77 7789 if (!TARGET_C99_FUNCTIONS)
7790 return NULL_TREE;
d735c391 7791 fn = mathfn_built_in (type, BUILT_IN_CEXPI);
7792 if (!fn)
7793 return NULL_TREE;
7794
c2f47e15 7795 call = build_call_expr (fn, 1, arg0);
d735c391 7796 call = builtin_save_expr (call);
7797
7798 return build2 (COMPOUND_EXPR, type,
7799 build2 (MODIFY_EXPR, void_type_node,
7800 build_fold_indirect_ref (arg1),
7801 build1 (IMAGPART_EXPR, type, call)),
7802 build2 (MODIFY_EXPR, void_type_node,
7803 build_fold_indirect_ref (arg2),
7804 build1 (REALPART_EXPR, type, call)));
7805}
7806
c5bb2c4b 7807/* Fold function call to builtin cexp, cexpf, or cexpl. Return
7808 NULL_TREE if no simplification can be made. */
7809
7810static tree
c2f47e15 7811fold_builtin_cexp (tree arg0, tree type)
c5bb2c4b 7812{
c2f47e15 7813 tree rtype;
c5bb2c4b 7814 tree realp, imagp, ifn;
7815
c2f47e15 7816 if (!validate_arg (arg0, COMPLEX_TYPE))
c5bb2c4b 7817 return NULL_TREE;
7818
c5bb2c4b 7819 rtype = TREE_TYPE (TREE_TYPE (arg0));
7820
7821 /* In case we can figure out the real part of arg0 and it is constant zero
7822 fold to cexpi. */
2a6b4c77 7823 if (!TARGET_C99_FUNCTIONS)
7824 return NULL_TREE;
c5bb2c4b 7825 ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI);
7826 if (!ifn)
7827 return NULL_TREE;
7828
7829 if ((realp = fold_unary (REALPART_EXPR, rtype, arg0))
7830 && real_zerop (realp))
7831 {
7832 tree narg = fold_build1 (IMAGPART_EXPR, rtype, arg0);
c2f47e15 7833 return build_call_expr (ifn, 1, narg);
c5bb2c4b 7834 }
7835
7836 /* In case we can easily decompose real and imaginary parts split cexp
7837 to exp (r) * cexpi (i). */
7838 if (flag_unsafe_math_optimizations
7839 && realp)
7840 {
7841 tree rfn, rcall, icall;
7842
7843 rfn = mathfn_built_in (rtype, BUILT_IN_EXP);
7844 if (!rfn)
7845 return NULL_TREE;
7846
7847 imagp = fold_unary (IMAGPART_EXPR, rtype, arg0);
7848 if (!imagp)
7849 return NULL_TREE;
7850
c2f47e15 7851 icall = build_call_expr (ifn, 1, imagp);
c5bb2c4b 7852 icall = builtin_save_expr (icall);
c2f47e15 7853 rcall = build_call_expr (rfn, 1, realp);
c5bb2c4b 7854 rcall = builtin_save_expr (rcall);
71bf42bb 7855 return fold_build2 (COMPLEX_EXPR, type,
7856 fold_build2 (MULT_EXPR, rtype,
7857 rcall,
7858 fold_build1 (REALPART_EXPR, rtype, icall)),
7859 fold_build2 (MULT_EXPR, rtype,
7860 rcall,
7861 fold_build1 (IMAGPART_EXPR, rtype, icall)));
c5bb2c4b 7862 }
7863
7864 return NULL_TREE;
7865}
7866
c2f47e15 7867/* Fold function call to builtin trunc, truncf or truncl with argument ARG.
7868 Return NULL_TREE if no simplification can be made. */
277f8dd2 7869
7870static tree
c2f47e15 7871fold_builtin_trunc (tree fndecl, tree arg)
277f8dd2 7872{
c2f47e15 7873 if (!validate_arg (arg, REAL_TYPE))
7874 return NULL_TREE;
277f8dd2 7875
7876 /* Optimize trunc of constant value. */
f96bd2bf 7877 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7878 {
7879 REAL_VALUE_TYPE r, x;
2426241c 7880 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7881
7882 x = TREE_REAL_CST (arg);
7883 real_trunc (&r, TYPE_MODE (type), &x);
7884 return build_real (type, r);
7885 }
7886
c2f47e15 7887 return fold_trunc_transparent_mathfn (fndecl, arg);
277f8dd2 7888}
7889
c2f47e15 7890/* Fold function call to builtin floor, floorf or floorl with argument ARG.
7891 Return NULL_TREE if no simplification can be made. */
277f8dd2 7892
7893static tree
c2f47e15 7894fold_builtin_floor (tree fndecl, tree arg)
277f8dd2 7895{
c2f47e15 7896 if (!validate_arg (arg, REAL_TYPE))
7897 return NULL_TREE;
277f8dd2 7898
7899 /* Optimize floor of constant value. */
f96bd2bf 7900 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7901 {
7902 REAL_VALUE_TYPE x;
7903
7904 x = TREE_REAL_CST (arg);
7905 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7906 {
2426241c 7907 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7908 REAL_VALUE_TYPE r;
7909
7910 real_floor (&r, TYPE_MODE (type), &x);
7911 return build_real (type, r);
7912 }
7913 }
7914
acc2b92e 7915 /* Fold floor (x) where x is nonnegative to trunc (x). */
7916 if (tree_expr_nonnegative_p (arg))
30fe8286 7917 {
7918 tree truncfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_TRUNC);
7919 if (truncfn)
c2f47e15 7920 return build_call_expr (truncfn, 1, arg);
30fe8286 7921 }
acc2b92e 7922
c2f47e15 7923 return fold_trunc_transparent_mathfn (fndecl, arg);
277f8dd2 7924}
7925
c2f47e15 7926/* Fold function call to builtin ceil, ceilf or ceill with argument ARG.
7927 Return NULL_TREE if no simplification can be made. */
277f8dd2 7928
7929static tree
c2f47e15 7930fold_builtin_ceil (tree fndecl, tree arg)
277f8dd2 7931{
c2f47e15 7932 if (!validate_arg (arg, REAL_TYPE))
7933 return NULL_TREE;
277f8dd2 7934
7935 /* Optimize ceil of constant value. */
f96bd2bf 7936 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7937 {
7938 REAL_VALUE_TYPE x;
7939
7940 x = TREE_REAL_CST (arg);
7941 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7942 {
2426241c 7943 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7944 REAL_VALUE_TYPE r;
7945
7946 real_ceil (&r, TYPE_MODE (type), &x);
7947 return build_real (type, r);
7948 }
7949 }
7950
c2f47e15 7951 return fold_trunc_transparent_mathfn (fndecl, arg);
277f8dd2 7952}
7953
c2f47e15 7954/* Fold function call to builtin round, roundf or roundl with argument ARG.
7955 Return NULL_TREE if no simplification can be made. */
89ab3887 7956
7957static tree
c2f47e15 7958fold_builtin_round (tree fndecl, tree arg)
89ab3887 7959{
c2f47e15 7960 if (!validate_arg (arg, REAL_TYPE))
7961 return NULL_TREE;
89ab3887 7962
34f17811 7963 /* Optimize round of constant value. */
f96bd2bf 7964 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
89ab3887 7965 {
7966 REAL_VALUE_TYPE x;
7967
7968 x = TREE_REAL_CST (arg);
7969 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7970 {
2426241c 7971 tree type = TREE_TYPE (TREE_TYPE (fndecl));
89ab3887 7972 REAL_VALUE_TYPE r;
7973
7974 real_round (&r, TYPE_MODE (type), &x);
7975 return build_real (type, r);
7976 }
7977 }
7978
c2f47e15 7979 return fold_trunc_transparent_mathfn (fndecl, arg);
89ab3887 7980}
7981
34f17811 7982/* Fold function call to builtin lround, lroundf or lroundl (or the
c2f47e15 7983 corresponding long long versions) and other rounding functions. ARG
7984 is the argument to the call. Return NULL_TREE if no simplification
7985 can be made. */
34f17811 7986
7987static tree
c2f47e15 7988fold_builtin_int_roundingfn (tree fndecl, tree arg)
34f17811 7989{
c2f47e15 7990 if (!validate_arg (arg, REAL_TYPE))
7991 return NULL_TREE;
34f17811 7992
7993 /* Optimize lround of constant value. */
f96bd2bf 7994 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
34f17811 7995 {
7996 const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
7997
776a7bab 7998 if (real_isfinite (&x))
34f17811 7999 {
2426241c 8000 tree itype = TREE_TYPE (TREE_TYPE (fndecl));
ca9b061d 8001 tree ftype = TREE_TYPE (arg);
8002 unsigned HOST_WIDE_INT lo2;
34f17811 8003 HOST_WIDE_INT hi, lo;
8004 REAL_VALUE_TYPE r;
8005
ad52b9b7 8006 switch (DECL_FUNCTION_CODE (fndecl))
8007 {
4f35b1fc 8008 CASE_FLT_FN (BUILT_IN_LFLOOR):
8009 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 8010 real_floor (&r, TYPE_MODE (ftype), &x);
8011 break;
8012
4f35b1fc 8013 CASE_FLT_FN (BUILT_IN_LCEIL):
8014 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 8015 real_ceil (&r, TYPE_MODE (ftype), &x);
8016 break;
8017
4f35b1fc 8018 CASE_FLT_FN (BUILT_IN_LROUND):
8019 CASE_FLT_FN (BUILT_IN_LLROUND):
ad52b9b7 8020 real_round (&r, TYPE_MODE (ftype), &x);
8021 break;
8022
8023 default:
8024 gcc_unreachable ();
8025 }
8026
34f17811 8027 REAL_VALUE_TO_INT (&lo, &hi, r);
ca9b061d 8028 if (!fit_double_type (lo, hi, &lo2, &hi, itype))
8029 return build_int_cst_wide (itype, lo2, hi);
34f17811 8030 }
8031 }
8032
acc2b92e 8033 switch (DECL_FUNCTION_CODE (fndecl))
8034 {
8035 CASE_FLT_FN (BUILT_IN_LFLOOR):
8036 CASE_FLT_FN (BUILT_IN_LLFLOOR):
8037 /* Fold lfloor (x) where x is nonnegative to FIX_TRUNC (x). */
8038 if (tree_expr_nonnegative_p (arg))
8039 return fold_build1 (FIX_TRUNC_EXPR, TREE_TYPE (TREE_TYPE (fndecl)),
8040 arg);
8041 break;
8042 default:;
8043 }
8044
c2f47e15 8045 return fold_fixed_mathfn (fndecl, arg);
34f17811 8046}
8047
70fb4c07 8048/* Fold function call to builtin ffs, clz, ctz, popcount and parity
c2f47e15 8049 and their long and long long variants (i.e. ffsl and ffsll). ARG is
8050 the argument to the call. Return NULL_TREE if no simplification can
8051 be made. */
70fb4c07 8052
8053static tree
c2f47e15 8054fold_builtin_bitop (tree fndecl, tree arg)
70fb4c07 8055{
c2f47e15 8056 if (!validate_arg (arg, INTEGER_TYPE))
70fb4c07 8057 return NULL_TREE;
8058
8059 /* Optimize for constant argument. */
f96bd2bf 8060 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
70fb4c07 8061 {
8062 HOST_WIDE_INT hi, width, result;
8063 unsigned HOST_WIDE_INT lo;
7c446c95 8064 tree type;
70fb4c07 8065
8066 type = TREE_TYPE (arg);
8067 width = TYPE_PRECISION (type);
8068 lo = TREE_INT_CST_LOW (arg);
8069
8070 /* Clear all the bits that are beyond the type's precision. */
8071 if (width > HOST_BITS_PER_WIDE_INT)
8072 {
8073 hi = TREE_INT_CST_HIGH (arg);
8074 if (width < 2 * HOST_BITS_PER_WIDE_INT)
8075 hi &= ~((HOST_WIDE_INT) (-1) >> (width - HOST_BITS_PER_WIDE_INT));
8076 }
8077 else
8078 {
8079 hi = 0;
8080 if (width < HOST_BITS_PER_WIDE_INT)
8081 lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
8082 }
8083
8084 switch (DECL_FUNCTION_CODE (fndecl))
8085 {
4f35b1fc 8086 CASE_INT_FN (BUILT_IN_FFS):
70fb4c07 8087 if (lo != 0)
8088 result = exact_log2 (lo & -lo) + 1;
8089 else if (hi != 0)
8090 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi) + 1;
8091 else
8092 result = 0;
8093 break;
8094
4f35b1fc 8095 CASE_INT_FN (BUILT_IN_CLZ):
70fb4c07 8096 if (hi != 0)
8097 result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
8098 else if (lo != 0)
8099 result = width - floor_log2 (lo) - 1;
8100 else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
8101 result = width;
8102 break;
8103
4f35b1fc 8104 CASE_INT_FN (BUILT_IN_CTZ):
70fb4c07 8105 if (lo != 0)
8106 result = exact_log2 (lo & -lo);
8107 else if (hi != 0)
8108 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi);
8109 else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
8110 result = width;
8111 break;
8112
4f35b1fc 8113 CASE_INT_FN (BUILT_IN_POPCOUNT):
70fb4c07 8114 result = 0;
8115 while (lo)
8116 result++, lo &= lo - 1;
8117 while (hi)
8118 result++, hi &= hi - 1;
8119 break;
8120
4f35b1fc 8121 CASE_INT_FN (BUILT_IN_PARITY):
70fb4c07 8122 result = 0;
8123 while (lo)
8124 result++, lo &= lo - 1;
8125 while (hi)
8126 result++, hi &= hi - 1;
8127 result &= 1;
8128 break;
8129
8130 default:
64db345d 8131 gcc_unreachable ();
70fb4c07 8132 }
8133
2426241c 8134 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
70fb4c07 8135 }
8136
8137 return NULL_TREE;
8138}
8139
42791117 8140/* Fold function call to builtin_bswap and the long and long long
8141 variants. Return NULL_TREE if no simplification can be made. */
8142static tree
c2f47e15 8143fold_builtin_bswap (tree fndecl, tree arg)
42791117 8144{
c2f47e15 8145 if (! validate_arg (arg, INTEGER_TYPE))
8146 return NULL_TREE;
42791117 8147
8148 /* Optimize constant value. */
f96bd2bf 8149 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
42791117 8150 {
8151 HOST_WIDE_INT hi, width, r_hi = 0;
8152 unsigned HOST_WIDE_INT lo, r_lo = 0;
8153 tree type;
8154
8155 type = TREE_TYPE (arg);
8156 width = TYPE_PRECISION (type);
8157 lo = TREE_INT_CST_LOW (arg);
8158 hi = TREE_INT_CST_HIGH (arg);
8159
8160 switch (DECL_FUNCTION_CODE (fndecl))
8161 {
8162 case BUILT_IN_BSWAP32:
8163 case BUILT_IN_BSWAP64:
8164 {
8165 int s;
8166
8167 for (s = 0; s < width; s += 8)
8168 {
8169 int d = width - s - 8;
8170 unsigned HOST_WIDE_INT byte;
8171
8172 if (s < HOST_BITS_PER_WIDE_INT)
8173 byte = (lo >> s) & 0xff;
8174 else
8175 byte = (hi >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff;
8176
8177 if (d < HOST_BITS_PER_WIDE_INT)
8178 r_lo |= byte << d;
8179 else
8180 r_hi |= byte << (d - HOST_BITS_PER_WIDE_INT);
8181 }
8182 }
8183
8184 break;
8185
8186 default:
8187 gcc_unreachable ();
8188 }
8189
8190 if (width < HOST_BITS_PER_WIDE_INT)
8191 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), r_lo);
8192 else
8193 return build_int_cst_wide (TREE_TYPE (TREE_TYPE (fndecl)), r_lo, r_hi);
8194 }
8195
8196 return NULL_TREE;
8197}
c2f47e15 8198
8918c507 8199/* Return true if EXPR is the real constant contained in VALUE. */
8200
8201static bool
8202real_dconstp (tree expr, const REAL_VALUE_TYPE *value)
8203{
8204 STRIP_NOPS (expr);
8205
8206 return ((TREE_CODE (expr) == REAL_CST
f96bd2bf 8207 && !TREE_OVERFLOW (expr)
a0c938f0 8208 && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), *value))
8209 || (TREE_CODE (expr) == COMPLEX_CST
8210 && real_dconstp (TREE_REALPART (expr), value)
8211 && real_zerop (TREE_IMAGPART (expr))));
8918c507 8212}
8213
8214/* A subroutine of fold_builtin to fold the various logarithmic
29f4cd78 8215 functions. Return NULL_TREE if no simplification can me made.
8216 FUNC is the corresponding MPFR logarithm function. */
8918c507 8217
8218static tree
c2f47e15 8219fold_builtin_logarithm (tree fndecl, tree arg,
29f4cd78 8220 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8221{
c2f47e15 8222 if (validate_arg (arg, REAL_TYPE))
8918c507 8223 {
8918c507 8224 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8225 tree res;
8918c507 8226 const enum built_in_function fcode = builtin_mathfn_code (arg);
0862b7e9 8227
29f4cd78 8228 /* Optimize log(e) = 1.0. We're never passed an exact 'e',
8229 instead we'll look for 'e' truncated to MODE. So only do
8230 this if flag_unsafe_math_optimizations is set. */
8231 if (flag_unsafe_math_optimizations && func == mpfr_log)
8232 {
8233 const REAL_VALUE_TYPE e_truncated =
3fa759a9 8234 real_value_truncate (TYPE_MODE (type), *get_real_const (rv_e));
29f4cd78 8235 if (real_dconstp (arg, &e_truncated))
1f5cb383 8236 return build_real (type, dconst1);
8237 }
0862b7e9 8238
29f4cd78 8239 /* Calculate the result when the argument is a constant. */
8240 if ((res = do_mpfr_arg1 (arg, type, func, &dconst0, NULL, false)))
8241 return res;
8242
8918c507 8243 /* Special case, optimize logN(expN(x)) = x. */
8244 if (flag_unsafe_math_optimizations
29f4cd78 8245 && ((func == mpfr_log
8918c507 8246 && (fcode == BUILT_IN_EXP
8247 || fcode == BUILT_IN_EXPF
8248 || fcode == BUILT_IN_EXPL))
29f4cd78 8249 || (func == mpfr_log2
8918c507 8250 && (fcode == BUILT_IN_EXP2
8251 || fcode == BUILT_IN_EXP2F
8252 || fcode == BUILT_IN_EXP2L))
29f4cd78 8253 || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode)))))
c2f47e15 8254 return fold_convert (type, CALL_EXPR_ARG (arg, 0));
8918c507 8255
ca273d4a 8256 /* Optimize logN(func()) for various exponential functions. We
a0c938f0 8257 want to determine the value "x" and the power "exponent" in
8258 order to transform logN(x**exponent) into exponent*logN(x). */
8918c507 8259 if (flag_unsafe_math_optimizations)
a0c938f0 8260 {
8918c507 8261 tree exponent = 0, x = 0;
0862b7e9 8262
8918c507 8263 switch (fcode)
8264 {
4f35b1fc 8265 CASE_FLT_FN (BUILT_IN_EXP):
8918c507 8266 /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
8918c507 8267 x = build_real (type,
3fa759a9 8268 real_value_truncate (TYPE_MODE (type),
8269 *get_real_const (rv_e)));
c2f47e15 8270 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8271 break;
4f35b1fc 8272 CASE_FLT_FN (BUILT_IN_EXP2):
8918c507 8273 /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */
8274 x = build_real (type, dconst2);
c2f47e15 8275 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8276 break;
4f35b1fc 8277 CASE_FLT_FN (BUILT_IN_EXP10):
8278 CASE_FLT_FN (BUILT_IN_POW10):
8918c507 8279 /* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */
3fa759a9 8280 {
8281 REAL_VALUE_TYPE dconst10;
8282 real_from_integer (&dconst10, VOIDmode, 10, 0, 0);
8283 x = build_real (type, dconst10);
8284 }
c2f47e15 8285 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8286 break;
4f35b1fc 8287 CASE_FLT_FN (BUILT_IN_SQRT):
8918c507 8288 /* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */
c2f47e15 8289 x = CALL_EXPR_ARG (arg, 0);
8918c507 8290 exponent = build_real (type, dconsthalf);
8291 break;
4f35b1fc 8292 CASE_FLT_FN (BUILT_IN_CBRT):
8918c507 8293 /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */
c2f47e15 8294 x = CALL_EXPR_ARG (arg, 0);
8918c507 8295 exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
3fa759a9 8296 *get_real_const (rv_third)));
8918c507 8297 break;
4f35b1fc 8298 CASE_FLT_FN (BUILT_IN_POW):
8918c507 8299 /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x). */
c2f47e15 8300 x = CALL_EXPR_ARG (arg, 0);
8301 exponent = CALL_EXPR_ARG (arg, 1);
8918c507 8302 break;
8303 default:
8304 break;
8305 }
8306
8307 /* Now perform the optimization. */
8308 if (x && exponent)
8309 {
c2f47e15 8310 tree logfn = build_call_expr (fndecl, 1, x);
49d00087 8311 return fold_build2 (MULT_EXPR, type, exponent, logfn);
8918c507 8312 }
8313 }
8314 }
8315
c2f47e15 8316 return NULL_TREE;
8918c507 8317}
0862b7e9 8318
f0c477f2 8319/* Fold a builtin function call to hypot, hypotf, or hypotl. Return
8320 NULL_TREE if no simplification can be made. */
8321
8322static tree
c2f47e15 8323fold_builtin_hypot (tree fndecl, tree arg0, tree arg1, tree type)
f0c477f2 8324{
e6ab33d8 8325 tree res, narg0, narg1;
f0c477f2 8326
c2f47e15 8327 if (!validate_arg (arg0, REAL_TYPE)
8328 || !validate_arg (arg1, REAL_TYPE))
f0c477f2 8329 return NULL_TREE;
8330
8331 /* Calculate the result when the argument is a constant. */
8332 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot)))
8333 return res;
8334
6c95f21c 8335 /* If either argument to hypot has a negate or abs, strip that off.
8336 E.g. hypot(-x,fabs(y)) -> hypot(x,y). */
e6ab33d8 8337 narg0 = fold_strip_sign_ops (arg0);
8338 narg1 = fold_strip_sign_ops (arg1);
8339 if (narg0 || narg1)
8340 {
c2f47e15 8341 return build_call_expr (fndecl, 2, narg0 ? narg0 : arg0,
8342 narg1 ? narg1 : arg1);
6c95f21c 8343 }
8344
f0c477f2 8345 /* If either argument is zero, hypot is fabs of the other. */
8346 if (real_zerop (arg0))
8347 return fold_build1 (ABS_EXPR, type, arg1);
8348 else if (real_zerop (arg1))
8349 return fold_build1 (ABS_EXPR, type, arg0);
8350
6c95f21c 8351 /* hypot(x,x) -> fabs(x)*sqrt(2). */
8352 if (flag_unsafe_math_optimizations
8353 && operand_equal_p (arg0, arg1, OEP_PURE_SAME))
f0c477f2 8354 {
2e7ca27b 8355 const REAL_VALUE_TYPE sqrt2_trunc
3fa759a9 8356 = real_value_truncate (TYPE_MODE (type), *get_real_const (rv_sqrt2));
6c95f21c 8357 return fold_build2 (MULT_EXPR, type,
8358 fold_build1 (ABS_EXPR, type, arg0),
2e7ca27b 8359 build_real (type, sqrt2_trunc));
f0c477f2 8360 }
8361
f0c477f2 8362 return NULL_TREE;
8363}
8364
8365
e6e27594 8366/* Fold a builtin function call to pow, powf, or powl. Return
8367 NULL_TREE if no simplification can be made. */
8368static tree
c2f47e15 8369fold_builtin_pow (tree fndecl, tree arg0, tree arg1, tree type)
e6e27594 8370{
f0c477f2 8371 tree res;
e6e27594 8372
c2f47e15 8373 if (!validate_arg (arg0, REAL_TYPE)
8374 || !validate_arg (arg1, REAL_TYPE))
e6e27594 8375 return NULL_TREE;
8376
f0c477f2 8377 /* Calculate the result when the argument is a constant. */
8378 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_pow)))
8379 return res;
8380
e6e27594 8381 /* Optimize pow(1.0,y) = 1.0. */
8382 if (real_onep (arg0))
8383 return omit_one_operand (type, build_real (type, dconst1), arg1);
8384
8385 if (TREE_CODE (arg1) == REAL_CST
f96bd2bf 8386 && !TREE_OVERFLOW (arg1))
e6e27594 8387 {
198d9bbe 8388 REAL_VALUE_TYPE cint;
e6e27594 8389 REAL_VALUE_TYPE c;
198d9bbe 8390 HOST_WIDE_INT n;
8391
e6e27594 8392 c = TREE_REAL_CST (arg1);
8393
8394 /* Optimize pow(x,0.0) = 1.0. */
8395 if (REAL_VALUES_EQUAL (c, dconst0))
8396 return omit_one_operand (type, build_real (type, dconst1),
8397 arg0);
8398
8399 /* Optimize pow(x,1.0) = x. */
8400 if (REAL_VALUES_EQUAL (c, dconst1))
8401 return arg0;
8402
8403 /* Optimize pow(x,-1.0) = 1.0/x. */
8404 if (REAL_VALUES_EQUAL (c, dconstm1))
49d00087 8405 return fold_build2 (RDIV_EXPR, type,
8406 build_real (type, dconst1), arg0);
e6e27594 8407
8408 /* Optimize pow(x,0.5) = sqrt(x). */
8409 if (flag_unsafe_math_optimizations
8410 && REAL_VALUES_EQUAL (c, dconsthalf))
8411 {
8412 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
8413
8414 if (sqrtfn != NULL_TREE)
c2f47e15 8415 return build_call_expr (sqrtfn, 1, arg0);
e6e27594 8416 }
8417
feb5b3eb 8418 /* Optimize pow(x,1.0/3.0) = cbrt(x). */
8419 if (flag_unsafe_math_optimizations)
8420 {
8421 const REAL_VALUE_TYPE dconstroot
3fa759a9 8422 = real_value_truncate (TYPE_MODE (type),
8423 *get_real_const (rv_third));
feb5b3eb 8424
8425 if (REAL_VALUES_EQUAL (c, dconstroot))
8426 {
8427 tree cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT);
8428 if (cbrtfn != NULL_TREE)
c2f47e15 8429 return build_call_expr (cbrtfn, 1, arg0);
feb5b3eb 8430 }
8431 }
8432
198d9bbe 8433 /* Check for an integer exponent. */
8434 n = real_to_integer (&c);
8435 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
8436 if (real_identical (&c, &cint))
e6e27594 8437 {
198d9bbe 8438 /* Attempt to evaluate pow at compile-time. */
8439 if (TREE_CODE (arg0) == REAL_CST
f96bd2bf 8440 && !TREE_OVERFLOW (arg0))
e6e27594 8441 {
8442 REAL_VALUE_TYPE x;
8443 bool inexact;
8444
8445 x = TREE_REAL_CST (arg0);
8446 inexact = real_powi (&x, TYPE_MODE (type), &x, n);
8447 if (flag_unsafe_math_optimizations || !inexact)
8448 return build_real (type, x);
8449 }
198d9bbe 8450
8451 /* Strip sign ops from even integer powers. */
8452 if ((n & 1) == 0 && flag_unsafe_math_optimizations)
8453 {
8454 tree narg0 = fold_strip_sign_ops (arg0);
8455 if (narg0)
c2f47e15 8456 return build_call_expr (fndecl, 2, narg0, arg1);
198d9bbe 8457 }
e6e27594 8458 }
8459 }
8460
cdfeb715 8461 if (flag_unsafe_math_optimizations)
e6e27594 8462 {
cdfeb715 8463 const enum built_in_function fcode = builtin_mathfn_code (arg0);
e6e27594 8464
cdfeb715 8465 /* Optimize pow(expN(x),y) = expN(x*y). */
8466 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 8467 {
c2f47e15 8468 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
8469 tree arg = CALL_EXPR_ARG (arg0, 0);
49d00087 8470 arg = fold_build2 (MULT_EXPR, type, arg, arg1);
c2f47e15 8471 return build_call_expr (expfn, 1, arg);
cdfeb715 8472 }
e6e27594 8473
cdfeb715 8474 /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
8475 if (BUILTIN_SQRT_P (fcode))
a0c938f0 8476 {
c2f47e15 8477 tree narg0 = CALL_EXPR_ARG (arg0, 0);
49d00087 8478 tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
8479 build_real (type, dconsthalf));
c2f47e15 8480 return build_call_expr (fndecl, 2, narg0, narg1);
cdfeb715 8481 }
8482
8483 /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */
8484 if (BUILTIN_CBRT_P (fcode))
a0c938f0 8485 {
c2f47e15 8486 tree arg = CALL_EXPR_ARG (arg0, 0);
cdfeb715 8487 if (tree_expr_nonnegative_p (arg))
8488 {
8489 const REAL_VALUE_TYPE dconstroot
3fa759a9 8490 = real_value_truncate (TYPE_MODE (type),
8491 *get_real_const (rv_third));
49d00087 8492 tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
8493 build_real (type, dconstroot));
c2f47e15 8494 return build_call_expr (fndecl, 2, arg, narg1);
cdfeb715 8495 }
8496 }
a0c938f0 8497
cdfeb715 8498 /* Optimize pow(pow(x,y),z) = pow(x,y*z). */
c2f47e15 8499 if (fcode == BUILT_IN_POW
8500 || fcode == BUILT_IN_POWF
8501 || fcode == BUILT_IN_POWL)
a0c938f0 8502 {
c2f47e15 8503 tree arg00 = CALL_EXPR_ARG (arg0, 0);
8504 tree arg01 = CALL_EXPR_ARG (arg0, 1);
49d00087 8505 tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1);
c2f47e15 8506 return build_call_expr (fndecl, 2, arg00, narg1);
cdfeb715 8507 }
e6e27594 8508 }
cdfeb715 8509
e6e27594 8510 return NULL_TREE;
8511}
8512
c2f47e15 8513/* Fold a builtin function call to powi, powif, or powil with argument ARG.
8514 Return NULL_TREE if no simplification can be made. */
b4d0c20c 8515static tree
c2f47e15 8516fold_builtin_powi (tree fndecl ATTRIBUTE_UNUSED,
8517 tree arg0, tree arg1, tree type)
b4d0c20c 8518{
c2f47e15 8519 if (!validate_arg (arg0, REAL_TYPE)
8520 || !validate_arg (arg1, INTEGER_TYPE))
b4d0c20c 8521 return NULL_TREE;
8522
8523 /* Optimize pow(1.0,y) = 1.0. */
8524 if (real_onep (arg0))
8525 return omit_one_operand (type, build_real (type, dconst1), arg1);
8526
8527 if (host_integerp (arg1, 0))
8528 {
8529 HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
8530
8531 /* Evaluate powi at compile-time. */
8532 if (TREE_CODE (arg0) == REAL_CST
f96bd2bf 8533 && !TREE_OVERFLOW (arg0))
b4d0c20c 8534 {
8535 REAL_VALUE_TYPE x;
8536 x = TREE_REAL_CST (arg0);
8537 real_powi (&x, TYPE_MODE (type), &x, c);
8538 return build_real (type, x);
8539 }
8540
8541 /* Optimize pow(x,0) = 1.0. */
8542 if (c == 0)
8543 return omit_one_operand (type, build_real (type, dconst1),
8544 arg0);
8545
8546 /* Optimize pow(x,1) = x. */
8547 if (c == 1)
8548 return arg0;
8549
8550 /* Optimize pow(x,-1) = 1.0/x. */
8551 if (c == -1)
49d00087 8552 return fold_build2 (RDIV_EXPR, type,
8553 build_real (type, dconst1), arg0);
b4d0c20c 8554 }
8555
8556 return NULL_TREE;
8557}
8558
8918c507 8559/* A subroutine of fold_builtin to fold the various exponent
c2f47e15 8560 functions. Return NULL_TREE if no simplification can be made.
debf9994 8561 FUNC is the corresponding MPFR exponent function. */
8918c507 8562
8563static tree
c2f47e15 8564fold_builtin_exponent (tree fndecl, tree arg,
debf9994 8565 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8566{
c2f47e15 8567 if (validate_arg (arg, REAL_TYPE))
8918c507 8568 {
8918c507 8569 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8570 tree res;
debf9994 8571
8572 /* Calculate the result when the argument is a constant. */
728bac60 8573 if ((res = do_mpfr_arg1 (arg, type, func, NULL, NULL, 0)))
debf9994 8574 return res;
8918c507 8575
8576 /* Optimize expN(logN(x)) = x. */
8577 if (flag_unsafe_math_optimizations)
a0c938f0 8578 {
8918c507 8579 const enum built_in_function fcode = builtin_mathfn_code (arg);
8580
debf9994 8581 if ((func == mpfr_exp
8918c507 8582 && (fcode == BUILT_IN_LOG
8583 || fcode == BUILT_IN_LOGF
8584 || fcode == BUILT_IN_LOGL))
debf9994 8585 || (func == mpfr_exp2
8918c507 8586 && (fcode == BUILT_IN_LOG2
8587 || fcode == BUILT_IN_LOG2F
8588 || fcode == BUILT_IN_LOG2L))
debf9994 8589 || (func == mpfr_exp10
8918c507 8590 && (fcode == BUILT_IN_LOG10
8591 || fcode == BUILT_IN_LOG10F
8592 || fcode == BUILT_IN_LOG10L)))
c2f47e15 8593 return fold_convert (type, CALL_EXPR_ARG (arg, 0));
8918c507 8594 }
8595 }
8596
c2f47e15 8597 return NULL_TREE;
8918c507 8598}
8599
e973ffcc 8600/* Return true if VAR is a VAR_DECL or a component thereof. */
8601
8602static bool
8603var_decl_component_p (tree var)
8604{
8605 tree inner = var;
8606 while (handled_component_p (inner))
8607 inner = TREE_OPERAND (inner, 0);
8608 return SSA_VAR_P (inner);
8609}
8610
4f46f2b9 8611/* Fold function call to builtin memset. Return
9c8a1629 8612 NULL_TREE if no simplification can be made. */
8613
8614static tree
c2f47e15 8615fold_builtin_memset (tree dest, tree c, tree len, tree type, bool ignore)
9c8a1629 8616{
c2f47e15 8617 tree var, ret;
4f46f2b9 8618 unsigned HOST_WIDE_INT length, cval;
9c8a1629 8619
c2f47e15 8620 if (! validate_arg (dest, POINTER_TYPE)
8621 || ! validate_arg (c, INTEGER_TYPE)
8622 || ! validate_arg (len, INTEGER_TYPE))
8623 return NULL_TREE;
9c8a1629 8624
4f46f2b9 8625 if (! host_integerp (len, 1))
c2f47e15 8626 return NULL_TREE;
4f46f2b9 8627
9c8a1629 8628 /* If the LEN parameter is zero, return DEST. */
8629 if (integer_zerop (len))
4f46f2b9 8630 return omit_one_operand (type, dest, c);
9c8a1629 8631
4f46f2b9 8632 if (! host_integerp (c, 1) || TREE_SIDE_EFFECTS (dest))
c2f47e15 8633 return NULL_TREE;
9c8a1629 8634
4f46f2b9 8635 var = dest;
8636 STRIP_NOPS (var);
8637 if (TREE_CODE (var) != ADDR_EXPR)
c2f47e15 8638 return NULL_TREE;
4f46f2b9 8639
8640 var = TREE_OPERAND (var, 0);
8641 if (TREE_THIS_VOLATILE (var))
c2f47e15 8642 return NULL_TREE;
4f46f2b9 8643
8644 if (!INTEGRAL_TYPE_P (TREE_TYPE (var))
8645 && !POINTER_TYPE_P (TREE_TYPE (var)))
c2f47e15 8646 return NULL_TREE;
4f46f2b9 8647
e973ffcc 8648 if (! var_decl_component_p (var))
c2f47e15 8649 return NULL_TREE;
e973ffcc 8650
4f46f2b9 8651 length = tree_low_cst (len, 1);
8652 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (var))) != length
8653 || get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
8654 < (int) length)
c2f47e15 8655 return NULL_TREE;
4f46f2b9 8656
8657 if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT)
c2f47e15 8658 return NULL_TREE;
4f46f2b9 8659
8660 if (integer_zerop (c))
8661 cval = 0;
8662 else
8663 {
8664 if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64)
c2f47e15 8665 return NULL_TREE;
4f46f2b9 8666
8667 cval = tree_low_cst (c, 1);
8668 cval &= 0xff;
8669 cval |= cval << 8;
8670 cval |= cval << 16;
8671 cval |= (cval << 31) << 1;
8672 }
8673
8674 ret = build_int_cst_type (TREE_TYPE (var), cval);
41076ef6 8675 ret = build2 (MODIFY_EXPR, TREE_TYPE (var), var, ret);
4f46f2b9 8676 if (ignore)
8677 return ret;
8678
8679 return omit_one_operand (type, dest, ret);
9c8a1629 8680}
8681
4f46f2b9 8682/* Fold function call to builtin memset. Return
9c8a1629 8683 NULL_TREE if no simplification can be made. */
8684
8685static tree
c2f47e15 8686fold_builtin_bzero (tree dest, tree size, bool ignore)
9c8a1629 8687{
c2f47e15 8688 if (! validate_arg (dest, POINTER_TYPE)
8689 || ! validate_arg (size, INTEGER_TYPE))
8690 return NULL_TREE;
9c8a1629 8691
4f46f2b9 8692 if (!ignore)
c2f47e15 8693 return NULL_TREE;
a0c938f0 8694
4f46f2b9 8695 /* New argument list transforming bzero(ptr x, int y) to
8696 memset(ptr x, int 0, size_t y). This is done this way
8697 so that if it isn't expanded inline, we fallback to
8698 calling bzero instead of memset. */
8699
c2f47e15 8700 return fold_builtin_memset (dest, integer_zero_node,
8701 fold_convert (sizetype, size),
8702 void_type_node, ignore);
9c8a1629 8703}
8704
4f46f2b9 8705/* Fold function call to builtin mem{{,p}cpy,move}. Return
8706 NULL_TREE if no simplification can be made.
8707 If ENDP is 0, return DEST (like memcpy).
8708 If ENDP is 1, return DEST+LEN (like mempcpy).
8709 If ENDP is 2, return DEST+LEN-1 (like stpcpy).
8710 If ENDP is 3, return DEST, additionally *SRC and *DEST may overlap
8711 (memmove). */
9c8a1629 8712
8713static tree
c2f47e15 8714fold_builtin_memory_op (tree dest, tree src, tree len, tree type, bool ignore, int endp)
9c8a1629 8715{
c2f47e15 8716 tree destvar, srcvar, expr;
9c8a1629 8717
c2f47e15 8718 if (! validate_arg (dest, POINTER_TYPE)
8719 || ! validate_arg (src, POINTER_TYPE)
8720 || ! validate_arg (len, INTEGER_TYPE))
8721 return NULL_TREE;
9c8a1629 8722
8723 /* If the LEN parameter is zero, return DEST. */
8724 if (integer_zerop (len))
7e72af53 8725 return omit_one_operand (type, dest, src);
9c8a1629 8726
4f46f2b9 8727 /* If SRC and DEST are the same (and not volatile), return
8728 DEST{,+LEN,+LEN-1}. */
9c8a1629 8729 if (operand_equal_p (src, dest, 0))
4f46f2b9 8730 expr = len;
8731 else
8732 {
5a84fdd6 8733 tree srctype, desttype;
3b1757a2 8734 if (endp == 3)
8735 {
5a84fdd6 8736 int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
8737 int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
8738
3b1757a2 8739 /* Both DEST and SRC must be pointer types.
8740 ??? This is what old code did. Is the testing for pointer types
8741 really mandatory?
8742
8743 If either SRC is readonly or length is 1, we can use memcpy. */
8744 if (dest_align && src_align
8745 && (readonly_data_expr (src)
5a84fdd6 8746 || (host_integerp (len, 1)
b4fc673b 8747 && (MIN (src_align, dest_align) / BITS_PER_UNIT >=
5a84fdd6 8748 tree_low_cst (len, 1)))))
3b1757a2 8749 {
8750 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8751 if (!fn)
c2f47e15 8752 return NULL_TREE;
8753 return build_call_expr (fn, 3, dest, src, len);
3b1757a2 8754 }
c2f47e15 8755 return NULL_TREE;
3b1757a2 8756 }
4f46f2b9 8757
5a84fdd6 8758 if (!host_integerp (len, 0))
c2f47e15 8759 return NULL_TREE;
5a84fdd6 8760 /* FIXME:
8761 This logic lose for arguments like (type *)malloc (sizeof (type)),
8762 since we strip the casts of up to VOID return value from malloc.
8763 Perhaps we ought to inherit type from non-VOID argument here? */
8764 STRIP_NOPS (src);
8765 STRIP_NOPS (dest);
8766 srctype = TREE_TYPE (TREE_TYPE (src));
8767 desttype = TREE_TYPE (TREE_TYPE (dest));
8768 if (!srctype || !desttype
8769 || !TYPE_SIZE_UNIT (srctype)
8770 || !TYPE_SIZE_UNIT (desttype)
8771 || TREE_CODE (TYPE_SIZE_UNIT (srctype)) != INTEGER_CST
8772 || TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST
92552a26 8773 || !tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len)
8774 || !tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
c2f47e15 8775 return NULL_TREE;
4f46f2b9 8776
5a84fdd6 8777 if (get_pointer_alignment (dest, BIGGEST_ALIGNMENT)
8778 < (int) TYPE_ALIGN (desttype)
8779 || (get_pointer_alignment (src, BIGGEST_ALIGNMENT)
8780 < (int) TYPE_ALIGN (srctype)))
c2f47e15 8781 return NULL_TREE;
e973ffcc 8782
5a84fdd6 8783 if (!ignore)
8784 dest = builtin_save_expr (dest);
4f46f2b9 8785
5a84fdd6 8786 srcvar = build_fold_indirect_ref (src);
4f46f2b9 8787 if (TREE_THIS_VOLATILE (srcvar))
c2f47e15 8788 return NULL_TREE;
92552a26 8789 if (!tree_int_cst_equal (lang_hooks.expr_size (srcvar), len))
c2f47e15 8790 return NULL_TREE;
5a84fdd6 8791 /* With memcpy, it is possible to bypass aliasing rules, so without
f0b5f617 8792 this check i.e. execute/20060930-2.c would be misoptimized, because
5a84fdd6 8793 it use conflicting alias set to hold argument for the memcpy call.
f0b5f617 8794 This check is probably unnecessary with -fno-strict-aliasing.
5a84fdd6 8795 Similarly for destvar. See also PR29286. */
8796 if (!var_decl_component_p (srcvar)
8797 /* Accept: memcpy (*char_var, "test", 1); that simplify
8798 to char_var='t'; */
8799 || is_gimple_min_invariant (srcvar)
8800 || readonly_data_expr (src))
c2f47e15 8801 return NULL_TREE;
4f46f2b9 8802
5a84fdd6 8803 destvar = build_fold_indirect_ref (dest);
8804 if (TREE_THIS_VOLATILE (destvar))
c2f47e15 8805 return NULL_TREE;
92552a26 8806 if (!tree_int_cst_equal (lang_hooks.expr_size (destvar), len))
c2f47e15 8807 return NULL_TREE;
5a84fdd6 8808 if (!var_decl_component_p (destvar))
c2f47e15 8809 return NULL_TREE;
4f46f2b9 8810
5a84fdd6 8811 if (srctype == desttype
2d04fd8d 8812 || (gimple_in_ssa_p (cfun)
548044d8 8813 && useless_type_conversion_p (desttype, srctype)))
5a84fdd6 8814 expr = srcvar;
8815 else if ((INTEGRAL_TYPE_P (TREE_TYPE (srcvar))
4f46f2b9 8816 || POINTER_TYPE_P (TREE_TYPE (srcvar)))
8817 && (INTEGRAL_TYPE_P (TREE_TYPE (destvar))
8818 || POINTER_TYPE_P (TREE_TYPE (destvar))))
8819 expr = fold_convert (TREE_TYPE (destvar), srcvar);
8820 else
8821 expr = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (destvar), srcvar);
41076ef6 8822 expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, expr);
4f46f2b9 8823 }
8824
8825 if (ignore)
8826 return expr;
8827
8828 if (endp == 0 || endp == 3)
8829 return omit_one_operand (type, dest, expr);
8830
8831 if (expr == len)
c2f47e15 8832 expr = NULL_TREE;
4f46f2b9 8833
8834 if (endp == 2)
8835 len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len,
8836 ssize_int (1));
8837
0de36bdb 8838 dest = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
4f46f2b9 8839 dest = fold_convert (type, dest);
8840 if (expr)
8841 dest = omit_one_operand (type, dest, expr);
8842 return dest;
8843}
8844
c2f47e15 8845/* Fold function call to builtin strcpy with arguments DEST and SRC.
8846 If LEN is not NULL, it represents the length of the string to be
8847 copied. Return NULL_TREE if no simplification can be made. */
9c8a1629 8848
f0613857 8849tree
c2f47e15 8850fold_builtin_strcpy (tree fndecl, tree dest, tree src, tree len)
9c8a1629 8851{
c2f47e15 8852 tree fn;
9c8a1629 8853
c2f47e15 8854 if (!validate_arg (dest, POINTER_TYPE)
8855 || !validate_arg (src, POINTER_TYPE))
8856 return NULL_TREE;
9c8a1629 8857
8858 /* If SRC and DEST are the same (and not volatile), return DEST. */
8859 if (operand_equal_p (src, dest, 0))
2426241c 8860 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
9c8a1629 8861
f0613857 8862 if (optimize_size)
c2f47e15 8863 return NULL_TREE;
f0613857 8864
8865 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8866 if (!fn)
c2f47e15 8867 return NULL_TREE;
f0613857 8868
8869 if (!len)
8870 {
8871 len = c_strlen (src, 1);
8872 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 8873 return NULL_TREE;
f0613857 8874 }
8875
8876 len = size_binop (PLUS_EXPR, len, ssize_int (1));
2426241c 8877 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
c2f47e15 8878 build_call_expr (fn, 3, dest, src, len));
9c8a1629 8879}
8880
c2f47e15 8881/* Fold function call to builtin strncpy with arguments DEST, SRC, and LEN.
8882 If SLEN is not NULL, it represents the length of the source string.
8883 Return NULL_TREE if no simplification can be made. */
9c8a1629 8884
f0613857 8885tree
c2f47e15 8886fold_builtin_strncpy (tree fndecl, tree dest, tree src, tree len, tree slen)
9c8a1629 8887{
c2f47e15 8888 tree fn;
9c8a1629 8889
c2f47e15 8890 if (!validate_arg (dest, POINTER_TYPE)
8891 || !validate_arg (src, POINTER_TYPE)
8892 || !validate_arg (len, INTEGER_TYPE))
8893 return NULL_TREE;
9c8a1629 8894
8895 /* If the LEN parameter is zero, return DEST. */
8896 if (integer_zerop (len))
2426241c 8897 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
9c8a1629 8898
19226313 8899 /* We can't compare slen with len as constants below if len is not a
8900 constant. */
8901 if (len == 0 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 8902 return NULL_TREE;
19226313 8903
f0613857 8904 if (!slen)
8905 slen = c_strlen (src, 1);
8906
8907 /* Now, we must be passed a constant src ptr parameter. */
8908 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
c2f47e15 8909 return NULL_TREE;
f0613857 8910
8911 slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
8912
8913 /* We do not support simplification of this case, though we do
8914 support it when expanding trees into RTL. */
8915 /* FIXME: generate a call to __builtin_memset. */
8916 if (tree_int_cst_lt (slen, len))
c2f47e15 8917 return NULL_TREE;
f0613857 8918
8919 /* OK transform into builtin memcpy. */
8920 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8921 if (!fn)
c2f47e15 8922 return NULL_TREE;
2426241c 8923 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
c2f47e15 8924 build_call_expr (fn, 3, dest, src, len));
9c8a1629 8925}
8926
7959b13b 8927/* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the
8928 arguments to the call, and TYPE is its return type.
8929 Return NULL_TREE if no simplification can be made. */
8930
8931static tree
8932fold_builtin_memchr (tree arg1, tree arg2, tree len, tree type)
8933{
8934 if (!validate_arg (arg1, POINTER_TYPE)
8935 || !validate_arg (arg2, INTEGER_TYPE)
8936 || !validate_arg (len, INTEGER_TYPE))
8937 return NULL_TREE;
8938 else
8939 {
8940 const char *p1;
8941
8942 if (TREE_CODE (arg2) != INTEGER_CST
8943 || !host_integerp (len, 1))
8944 return NULL_TREE;
8945
8946 p1 = c_getstr (arg1);
8947 if (p1 && compare_tree_int (len, strlen (p1) + 1) <= 0)
8948 {
8949 char c;
8950 const char *r;
8951 tree tem;
8952
8953 if (target_char_cast (arg2, &c))
8954 return NULL_TREE;
8955
364c0c59 8956 r = (char *) memchr (p1, c, tree_low_cst (len, 1));
7959b13b 8957
8958 if (r == NULL)
8959 return build_int_cst (TREE_TYPE (arg1), 0);
8960
0de36bdb 8961 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (arg1), arg1,
8962 size_int (r - p1));
7959b13b 8963 return fold_convert (type, tem);
8964 }
8965 return NULL_TREE;
8966 }
8967}
8968
c2f47e15 8969/* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
8970 Return NULL_TREE if no simplification can be made. */
9c8a1629 8971
8972static tree
c2f47e15 8973fold_builtin_memcmp (tree arg1, tree arg2, tree len)
9c8a1629 8974{
c4fef134 8975 const char *p1, *p2;
9c8a1629 8976
c2f47e15 8977 if (!validate_arg (arg1, POINTER_TYPE)
8978 || !validate_arg (arg2, POINTER_TYPE)
8979 || !validate_arg (len, INTEGER_TYPE))
8980 return NULL_TREE;
9c8a1629 8981
8982 /* If the LEN parameter is zero, return zero. */
8983 if (integer_zerop (len))
c4fef134 8984 return omit_two_operands (integer_type_node, integer_zero_node,
8985 arg1, arg2);
9c8a1629 8986
8987 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8988 if (operand_equal_p (arg1, arg2, 0))
c4fef134 8989 return omit_one_operand (integer_type_node, integer_zero_node, len);
8990
8991 p1 = c_getstr (arg1);
8992 p2 = c_getstr (arg2);
8993
8994 /* If all arguments are constant, and the value of len is not greater
8995 than the lengths of arg1 and arg2, evaluate at compile-time. */
8996 if (host_integerp (len, 1) && p1 && p2
8997 && compare_tree_int (len, strlen (p1) + 1) <= 0
8998 && compare_tree_int (len, strlen (p2) + 1) <= 0)
8999 {
9000 const int r = memcmp (p1, p2, tree_low_cst (len, 1));
9001
9002 if (r > 0)
9003 return integer_one_node;
9004 else if (r < 0)
9005 return integer_minus_one_node;
9006 else
9007 return integer_zero_node;
9008 }
9009
9010 /* If len parameter is one, return an expression corresponding to
9011 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
9012 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
9013 {
9014 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9015 tree cst_uchar_ptr_node
9016 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9017
c4fef134 9018 tree ind1 = fold_convert (integer_type_node,
9019 build1 (INDIRECT_REF, cst_uchar_node,
9020 fold_convert (cst_uchar_ptr_node,
9021 arg1)));
9022 tree ind2 = fold_convert (integer_type_node,
9023 build1 (INDIRECT_REF, cst_uchar_node,
9024 fold_convert (cst_uchar_ptr_node,
9025 arg2)));
49d00087 9026 return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
c4fef134 9027 }
9c8a1629 9028
c2f47e15 9029 return NULL_TREE;
9c8a1629 9030}
9031
c2f47e15 9032/* Fold function call to builtin strcmp with arguments ARG1 and ARG2.
9033 Return NULL_TREE if no simplification can be made. */
9c8a1629 9034
9035static tree
c2f47e15 9036fold_builtin_strcmp (tree arg1, tree arg2)
9c8a1629 9037{
9c8a1629 9038 const char *p1, *p2;
9039
c2f47e15 9040 if (!validate_arg (arg1, POINTER_TYPE)
9041 || !validate_arg (arg2, POINTER_TYPE))
9042 return NULL_TREE;
9c8a1629 9043
9044 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9045 if (operand_equal_p (arg1, arg2, 0))
c4fef134 9046 return integer_zero_node;
9c8a1629 9047
9048 p1 = c_getstr (arg1);
9049 p2 = c_getstr (arg2);
9050
9051 if (p1 && p2)
9052 {
9c8a1629 9053 const int i = strcmp (p1, p2);
9054 if (i < 0)
c4fef134 9055 return integer_minus_one_node;
9c8a1629 9056 else if (i > 0)
c4fef134 9057 return integer_one_node;
9c8a1629 9058 else
c4fef134 9059 return integer_zero_node;
9060 }
9061
9062 /* If the second arg is "", return *(const unsigned char*)arg1. */
9063 if (p2 && *p2 == '\0')
9064 {
9065 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9066 tree cst_uchar_ptr_node
9067 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9068
c4fef134 9069 return fold_convert (integer_type_node,
9070 build1 (INDIRECT_REF, cst_uchar_node,
9071 fold_convert (cst_uchar_ptr_node,
9072 arg1)));
9073 }
9074
9075 /* If the first arg is "", return -*(const unsigned char*)arg2. */
9076 if (p1 && *p1 == '\0')
9077 {
9078 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9079 tree cst_uchar_ptr_node
9080 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9081
c4fef134 9082 tree temp = fold_convert (integer_type_node,
9083 build1 (INDIRECT_REF, cst_uchar_node,
9084 fold_convert (cst_uchar_ptr_node,
9085 arg2)));
49d00087 9086 return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
9c8a1629 9087 }
9088
c2f47e15 9089 return NULL_TREE;
9c8a1629 9090}
9091
c2f47e15 9092/* Fold function call to builtin strncmp with arguments ARG1, ARG2, and LEN.
9093 Return NULL_TREE if no simplification can be made. */
9c8a1629 9094
9095static tree
c2f47e15 9096fold_builtin_strncmp (tree arg1, tree arg2, tree len)
9c8a1629 9097{
9c8a1629 9098 const char *p1, *p2;
9099
c2f47e15 9100 if (!validate_arg (arg1, POINTER_TYPE)
9101 || !validate_arg (arg2, POINTER_TYPE)
9102 || !validate_arg (len, INTEGER_TYPE))
9103 return NULL_TREE;
9c8a1629 9104
9105 /* If the LEN parameter is zero, return zero. */
9106 if (integer_zerop (len))
c4fef134 9107 return omit_two_operands (integer_type_node, integer_zero_node,
9108 arg1, arg2);
9c8a1629 9109
9110 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9111 if (operand_equal_p (arg1, arg2, 0))
c4fef134 9112 return omit_one_operand (integer_type_node, integer_zero_node, len);
9c8a1629 9113
9114 p1 = c_getstr (arg1);
9115 p2 = c_getstr (arg2);
9116
9117 if (host_integerp (len, 1) && p1 && p2)
9118 {
9c8a1629 9119 const int i = strncmp (p1, p2, tree_low_cst (len, 1));
c4fef134 9120 if (i > 0)
9121 return integer_one_node;
9122 else if (i < 0)
9123 return integer_minus_one_node;
9c8a1629 9124 else
c4fef134 9125 return integer_zero_node;
9126 }
9127
9128 /* If the second arg is "", and the length is greater than zero,
9129 return *(const unsigned char*)arg1. */
9130 if (p2 && *p2 == '\0'
9131 && TREE_CODE (len) == INTEGER_CST
9132 && tree_int_cst_sgn (len) == 1)
9133 {
9134 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9135 tree cst_uchar_ptr_node
9136 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9137
c4fef134 9138 return fold_convert (integer_type_node,
9139 build1 (INDIRECT_REF, cst_uchar_node,
9140 fold_convert (cst_uchar_ptr_node,
9141 arg1)));
9142 }
9143
9144 /* If the first arg is "", and the length is greater than zero,
9145 return -*(const unsigned char*)arg2. */
9146 if (p1 && *p1 == '\0'
9147 && TREE_CODE (len) == INTEGER_CST
9148 && tree_int_cst_sgn (len) == 1)
9149 {
9150 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9151 tree cst_uchar_ptr_node
9152 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9153
c4fef134 9154 tree temp = fold_convert (integer_type_node,
9155 build1 (INDIRECT_REF, cst_uchar_node,
9156 fold_convert (cst_uchar_ptr_node,
9157 arg2)));
49d00087 9158 return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
c4fef134 9159 }
9160
9161 /* If len parameter is one, return an expression corresponding to
9162 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
9163 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
9164 {
9165 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9166 tree cst_uchar_ptr_node
9167 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9168
c4fef134 9169 tree ind1 = fold_convert (integer_type_node,
9170 build1 (INDIRECT_REF, cst_uchar_node,
9171 fold_convert (cst_uchar_ptr_node,
9172 arg1)));
9173 tree ind2 = fold_convert (integer_type_node,
9174 build1 (INDIRECT_REF, cst_uchar_node,
9175 fold_convert (cst_uchar_ptr_node,
9176 arg2)));
49d00087 9177 return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
9c8a1629 9178 }
9179
c2f47e15 9180 return NULL_TREE;
9c8a1629 9181}
9182
c2f47e15 9183/* Fold function call to builtin signbit, signbitf or signbitl with argument
9184 ARG. Return NULL_TREE if no simplification can be made. */
27f261ef 9185
9186static tree
c2f47e15 9187fold_builtin_signbit (tree arg, tree type)
27f261ef 9188{
c2f47e15 9189 tree temp;
27f261ef 9190
c2f47e15 9191 if (!validate_arg (arg, REAL_TYPE))
27f261ef 9192 return NULL_TREE;
9193
27f261ef 9194 /* If ARG is a compile-time constant, determine the result. */
9195 if (TREE_CODE (arg) == REAL_CST
f96bd2bf 9196 && !TREE_OVERFLOW (arg))
27f261ef 9197 {
9198 REAL_VALUE_TYPE c;
9199
9200 c = TREE_REAL_CST (arg);
9201 temp = REAL_VALUE_NEGATIVE (c) ? integer_one_node : integer_zero_node;
2426241c 9202 return fold_convert (type, temp);
27f261ef 9203 }
9204
9205 /* If ARG is non-negative, the result is always zero. */
9206 if (tree_expr_nonnegative_p (arg))
2426241c 9207 return omit_one_operand (type, integer_zero_node, arg);
27f261ef 9208
9209 /* If ARG's format doesn't have signed zeros, return "arg < 0.0". */
9210 if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
49d00087 9211 return fold_build2 (LT_EXPR, type, arg,
9212 build_real (TREE_TYPE (arg), dconst0));
27f261ef 9213
9214 return NULL_TREE;
9215}
9216
c2f47e15 9217/* Fold function call to builtin copysign, copysignf or copysignl with
9218 arguments ARG1 and ARG2. Return NULL_TREE if no simplification can
9219 be made. */
467214fd 9220
9221static tree
c2f47e15 9222fold_builtin_copysign (tree fndecl, tree arg1, tree arg2, tree type)
467214fd 9223{
c2f47e15 9224 tree tem;
467214fd 9225
c2f47e15 9226 if (!validate_arg (arg1, REAL_TYPE)
9227 || !validate_arg (arg2, REAL_TYPE))
467214fd 9228 return NULL_TREE;
9229
467214fd 9230 /* copysign(X,X) is X. */
9231 if (operand_equal_p (arg1, arg2, 0))
9232 return fold_convert (type, arg1);
9233
9234 /* If ARG1 and ARG2 are compile-time constants, determine the result. */
9235 if (TREE_CODE (arg1) == REAL_CST
9236 && TREE_CODE (arg2) == REAL_CST
f96bd2bf 9237 && !TREE_OVERFLOW (arg1)
9238 && !TREE_OVERFLOW (arg2))
467214fd 9239 {
9240 REAL_VALUE_TYPE c1, c2;
9241
9242 c1 = TREE_REAL_CST (arg1);
9243 c2 = TREE_REAL_CST (arg2);
749680e2 9244 /* c1.sign := c2.sign. */
467214fd 9245 real_copysign (&c1, &c2);
9246 return build_real (type, c1);
467214fd 9247 }
9248
9249 /* copysign(X, Y) is fabs(X) when Y is always non-negative.
9250 Remember to evaluate Y for side-effects. */
9251 if (tree_expr_nonnegative_p (arg2))
9252 return omit_one_operand (type,
49d00087 9253 fold_build1 (ABS_EXPR, type, arg1),
467214fd 9254 arg2);
9255
198d9bbe 9256 /* Strip sign changing operations for the first argument. */
9257 tem = fold_strip_sign_ops (arg1);
9258 if (tem)
c2f47e15 9259 return build_call_expr (fndecl, 2, tem, arg2);
198d9bbe 9260
467214fd 9261 return NULL_TREE;
9262}
9263
c2f47e15 9264/* Fold a call to builtin isascii with argument ARG. */
d49367d4 9265
9266static tree
c2f47e15 9267fold_builtin_isascii (tree arg)
d49367d4 9268{
c2f47e15 9269 if (!validate_arg (arg, INTEGER_TYPE))
9270 return NULL_TREE;
d49367d4 9271 else
9272 {
9273 /* Transform isascii(c) -> ((c & ~0x7f) == 0). */
7c446c95 9274 arg = build2 (BIT_AND_EXPR, integer_type_node, arg,
9275 build_int_cst (NULL_TREE,
7016c612 9276 ~ (unsigned HOST_WIDE_INT) 0x7f));
f2532264 9277 return fold_build2 (EQ_EXPR, integer_type_node,
9278 arg, integer_zero_node);
d49367d4 9279 }
9280}
9281
c2f47e15 9282/* Fold a call to builtin toascii with argument ARG. */
d49367d4 9283
9284static tree
c2f47e15 9285fold_builtin_toascii (tree arg)
d49367d4 9286{
c2f47e15 9287 if (!validate_arg (arg, INTEGER_TYPE))
9288 return NULL_TREE;
9289
9290 /* Transform toascii(c) -> (c & 0x7f). */
9291 return fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
9292 build_int_cst (NULL_TREE, 0x7f));
d49367d4 9293}
9294
c2f47e15 9295/* Fold a call to builtin isdigit with argument ARG. */
df1cf42e 9296
9297static tree
c2f47e15 9298fold_builtin_isdigit (tree arg)
df1cf42e 9299{
c2f47e15 9300 if (!validate_arg (arg, INTEGER_TYPE))
9301 return NULL_TREE;
df1cf42e 9302 else
9303 {
9304 /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */
624d37a6 9305 /* According to the C standard, isdigit is unaffected by locale.
9306 However, it definitely is affected by the target character set. */
624d37a6 9307 unsigned HOST_WIDE_INT target_digit0
9308 = lang_hooks.to_target_charset ('0');
9309
9310 if (target_digit0 == 0)
9311 return NULL_TREE;
9312
c2f47e15 9313 arg = fold_convert (unsigned_type_node, arg);
05abc81b 9314 arg = build2 (MINUS_EXPR, unsigned_type_node, arg,
624d37a6 9315 build_int_cst (unsigned_type_node, target_digit0));
f2532264 9316 return fold_build2 (LE_EXPR, integer_type_node, arg,
9317 build_int_cst (unsigned_type_node, 9));
df1cf42e 9318 }
9319}
27f261ef 9320
c2f47e15 9321/* Fold a call to fabs, fabsf or fabsl with argument ARG. */
d1aade50 9322
9323static tree
c2f47e15 9324fold_builtin_fabs (tree arg, tree type)
d1aade50 9325{
c2f47e15 9326 if (!validate_arg (arg, REAL_TYPE))
9327 return NULL_TREE;
d1aade50 9328
9829e110 9329 arg = fold_convert (type, arg);
d1aade50 9330 if (TREE_CODE (arg) == REAL_CST)
9331 return fold_abs_const (arg, type);
49d00087 9332 return fold_build1 (ABS_EXPR, type, arg);
d1aade50 9333}
9334
c2f47e15 9335/* Fold a call to abs, labs, llabs or imaxabs with argument ARG. */
d1aade50 9336
9337static tree
c2f47e15 9338fold_builtin_abs (tree arg, tree type)
d1aade50 9339{
c2f47e15 9340 if (!validate_arg (arg, INTEGER_TYPE))
9341 return NULL_TREE;
d1aade50 9342
9829e110 9343 arg = fold_convert (type, arg);
d1aade50 9344 if (TREE_CODE (arg) == INTEGER_CST)
9345 return fold_abs_const (arg, type);
49d00087 9346 return fold_build1 (ABS_EXPR, type, arg);
d1aade50 9347}
9348
d4a43a03 9349/* Fold a call to builtin fmin or fmax. */
9350
9351static tree
c2f47e15 9352fold_builtin_fmin_fmax (tree arg0, tree arg1, tree type, bool max)
d4a43a03 9353{
c2f47e15 9354 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, REAL_TYPE))
d4a43a03 9355 {
d4a43a03 9356 /* Calculate the result when the argument is a constant. */
9357 tree res = do_mpfr_arg2 (arg0, arg1, type, (max ? mpfr_max : mpfr_min));
9358
9359 if (res)
9360 return res;
9361
61fe3555 9362 /* If either argument is NaN, return the other one. Avoid the
9363 transformation if we get (and honor) a signalling NaN. Using
9364 omit_one_operand() ensures we create a non-lvalue. */
9365 if (TREE_CODE (arg0) == REAL_CST
9366 && real_isnan (&TREE_REAL_CST (arg0))
9367 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
9368 || ! TREE_REAL_CST (arg0).signalling))
9369 return omit_one_operand (type, arg1, arg0);
9370 if (TREE_CODE (arg1) == REAL_CST
9371 && real_isnan (&TREE_REAL_CST (arg1))
9372 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
9373 || ! TREE_REAL_CST (arg1).signalling))
9374 return omit_one_operand (type, arg0, arg1);
9375
d4a43a03 9376 /* Transform fmin/fmax(x,x) -> x. */
9377 if (operand_equal_p (arg0, arg1, OEP_PURE_SAME))
9378 return omit_one_operand (type, arg0, arg1);
9379
9380 /* Convert fmin/fmax to MIN_EXPR/MAX_EXPR. C99 requires these
9381 functions to return the numeric arg if the other one is NaN.
9382 These tree codes don't honor that, so only transform if
9383 -ffinite-math-only is set. C99 doesn't require -0.0 to be
9384 handled, so we don't have to worry about it either. */
9385 if (flag_finite_math_only)
9386 return fold_build2 ((max ? MAX_EXPR : MIN_EXPR), type,
9387 fold_convert (type, arg0),
9388 fold_convert (type, arg1));
9389 }
9390 return NULL_TREE;
9391}
9392
abe4dcf6 9393/* Fold a call to builtin carg(a+bi) -> atan2(b,a). */
9394
9395static tree
c2f47e15 9396fold_builtin_carg (tree arg, tree type)
abe4dcf6 9397{
c2f47e15 9398 if (validate_arg (arg, COMPLEX_TYPE))
abe4dcf6 9399 {
9400 tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
9401
9402 if (atan2_fn)
9403 {
c2f47e15 9404 tree new_arg = builtin_save_expr (arg);
9405 tree r_arg = fold_build1 (REALPART_EXPR, type, new_arg);
9406 tree i_arg = fold_build1 (IMAGPART_EXPR, type, new_arg);
9407 return build_call_expr (atan2_fn, 2, i_arg, r_arg);
abe4dcf6 9408 }
9409 }
9410
9411 return NULL_TREE;
9412}
9413
cb2b9385 9414/* Fold a call to builtin logb/ilogb. */
9415
9416static tree
9417fold_builtin_logb (tree arg, tree rettype)
9418{
9419 if (! validate_arg (arg, REAL_TYPE))
9420 return NULL_TREE;
9421
9422 STRIP_NOPS (arg);
9423
9424 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9425 {
9426 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
9427
9428 switch (value->cl)
9429 {
9430 case rvc_nan:
9431 case rvc_inf:
9432 /* If arg is Inf or NaN and we're logb, return it. */
9433 if (TREE_CODE (rettype) == REAL_TYPE)
9434 return fold_convert (rettype, arg);
9435 /* Fall through... */
9436 case rvc_zero:
9437 /* Zero may set errno and/or raise an exception for logb, also
9438 for ilogb we don't know FP_ILOGB0. */
9439 return NULL_TREE;
9440 case rvc_normal:
9441 /* For normal numbers, proceed iff radix == 2. In GCC,
9442 normalized significands are in the range [0.5, 1.0). We
9443 want the exponent as if they were [1.0, 2.0) so get the
9444 exponent and subtract 1. */
9445 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
9446 return fold_convert (rettype, build_int_cst (NULL_TREE,
9447 REAL_EXP (value)-1));
9448 break;
9449 }
9450 }
9451
9452 return NULL_TREE;
9453}
9454
9455/* Fold a call to builtin significand, if radix == 2. */
9456
9457static tree
9458fold_builtin_significand (tree arg, tree rettype)
9459{
9460 if (! validate_arg (arg, REAL_TYPE))
9461 return NULL_TREE;
9462
9463 STRIP_NOPS (arg);
9464
9465 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9466 {
9467 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
9468
9469 switch (value->cl)
9470 {
9471 case rvc_zero:
9472 case rvc_nan:
9473 case rvc_inf:
9474 /* If arg is +-0, +-Inf or +-NaN, then return it. */
9475 return fold_convert (rettype, arg);
9476 case rvc_normal:
9477 /* For normal numbers, proceed iff radix == 2. */
9478 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
9479 {
9480 REAL_VALUE_TYPE result = *value;
9481 /* In GCC, normalized significands are in the range [0.5,
9482 1.0). We want them to be [1.0, 2.0) so set the
9483 exponent to 1. */
9484 SET_REAL_EXP (&result, 1);
9485 return build_real (rettype, result);
9486 }
9487 break;
9488 }
9489 }
9490
9491 return NULL_TREE;
9492}
9493
3838b9ae 9494/* Fold a call to builtin frexp, we can assume the base is 2. */
9495
9496static tree
9497fold_builtin_frexp (tree arg0, tree arg1, tree rettype)
9498{
9499 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9500 return NULL_TREE;
9501
9502 STRIP_NOPS (arg0);
9503
9504 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9505 return NULL_TREE;
9506
9507 arg1 = build_fold_indirect_ref (arg1);
9508
9509 /* Proceed if a valid pointer type was passed in. */
9510 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
9511 {
9512 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9513 tree frac, exp;
9514
9515 switch (value->cl)
9516 {
9517 case rvc_zero:
9518 /* For +-0, return (*exp = 0, +-0). */
9519 exp = integer_zero_node;
9520 frac = arg0;
9521 break;
9522 case rvc_nan:
9523 case rvc_inf:
9524 /* For +-NaN or +-Inf, *exp is unspecified, return arg0. */
9525 return omit_one_operand (rettype, arg0, arg1);
9526 case rvc_normal:
9527 {
9528 /* Since the frexp function always expects base 2, and in
9529 GCC normalized significands are already in the range
9530 [0.5, 1.0), we have exactly what frexp wants. */
9531 REAL_VALUE_TYPE frac_rvt = *value;
9532 SET_REAL_EXP (&frac_rvt, 0);
9533 frac = build_real (rettype, frac_rvt);
9534 exp = build_int_cst (NULL_TREE, REAL_EXP (value));
9535 }
9536 break;
9537 default:
9538 gcc_unreachable ();
9539 }
9540
9541 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
9542 arg1 = fold_build2 (MODIFY_EXPR, rettype, arg1, exp);
9543 TREE_SIDE_EFFECTS (arg1) = 1;
9544 return fold_build2 (COMPOUND_EXPR, rettype, arg1, frac);
9545 }
9546
9547 return NULL_TREE;
9548}
9549
7587301b 9550/* Fold a call to builtin ldexp or scalbn/scalbln. If LDEXP is true
9551 then we can assume the base is two. If it's false, then we have to
9552 check the mode of the TYPE parameter in certain cases. */
9553
9554static tree
9555fold_builtin_load_exponent (tree arg0, tree arg1, tree type, bool ldexp)
9556{
9557 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, INTEGER_TYPE))
9558 {
9559 STRIP_NOPS (arg0);
9560 STRIP_NOPS (arg1);
9561
9562 /* If arg0 is 0, Inf or NaN, or if arg1 is 0, then return arg0. */
9563 if (real_zerop (arg0) || integer_zerop (arg1)
9564 || (TREE_CODE (arg0) == REAL_CST
776a7bab 9565 && !real_isfinite (&TREE_REAL_CST (arg0))))
7587301b 9566 return omit_one_operand (type, arg0, arg1);
9567
9568 /* If both arguments are constant, then try to evaluate it. */
9569 if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2)
9570 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
9571 && host_integerp (arg1, 0))
9572 {
9573 /* Bound the maximum adjustment to twice the range of the
9574 mode's valid exponents. Use abs to ensure the range is
9575 positive as a sanity check. */
9576 const long max_exp_adj = 2 *
9577 labs (REAL_MODE_FORMAT (TYPE_MODE (type))->emax
9578 - REAL_MODE_FORMAT (TYPE_MODE (type))->emin);
9579
9580 /* Get the user-requested adjustment. */
9581 const HOST_WIDE_INT req_exp_adj = tree_low_cst (arg1, 0);
9582
9583 /* The requested adjustment must be inside this range. This
9584 is a preliminary cap to avoid things like overflow, we
9585 may still fail to compute the result for other reasons. */
9586 if (-max_exp_adj < req_exp_adj && req_exp_adj < max_exp_adj)
9587 {
9588 REAL_VALUE_TYPE initial_result;
9589
9590 real_ldexp (&initial_result, &TREE_REAL_CST (arg0), req_exp_adj);
9591
9592 /* Ensure we didn't overflow. */
9593 if (! real_isinf (&initial_result))
9594 {
9595 const REAL_VALUE_TYPE trunc_result
9596 = real_value_truncate (TYPE_MODE (type), initial_result);
9597
9598 /* Only proceed if the target mode can hold the
9599 resulting value. */
9600 if (REAL_VALUES_EQUAL (initial_result, trunc_result))
9601 return build_real (type, trunc_result);
9602 }
9603 }
9604 }
9605 }
9606
9607 return NULL_TREE;
9608}
9609
ebf8b4f5 9610/* Fold a call to builtin modf. */
9611
9612static tree
9613fold_builtin_modf (tree arg0, tree arg1, tree rettype)
9614{
9615 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9616 return NULL_TREE;
9617
9618 STRIP_NOPS (arg0);
9619
9620 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9621 return NULL_TREE;
9622
9623 arg1 = build_fold_indirect_ref (arg1);
9624
9625 /* Proceed if a valid pointer type was passed in. */
9626 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
9627 {
9628 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9629 REAL_VALUE_TYPE trunc, frac;
9630
9631 switch (value->cl)
9632 {
9633 case rvc_nan:
9634 case rvc_zero:
9635 /* For +-NaN or +-0, return (*arg1 = arg0, arg0). */
9636 trunc = frac = *value;
9637 break;
9638 case rvc_inf:
9639 /* For +-Inf, return (*arg1 = arg0, +-0). */
9640 frac = dconst0;
9641 frac.sign = value->sign;
9642 trunc = *value;
9643 break;
9644 case rvc_normal:
9645 /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)). */
9646 real_trunc (&trunc, VOIDmode, value);
9647 real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
9648 /* If the original number was negative and already
9649 integral, then the fractional part is -0.0. */
9650 if (value->sign && frac.cl == rvc_zero)
9651 frac.sign = value->sign;
9652 break;
9653 }
9654
9655 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
9656 arg1 = fold_build2 (MODIFY_EXPR, rettype, arg1,
9657 build_real (rettype, trunc));
9658 TREE_SIDE_EFFECTS (arg1) = 1;
9659 return fold_build2 (COMPOUND_EXPR, rettype, arg1,
9660 build_real (rettype, frac));
9661 }
9662
9663 return NULL_TREE;
9664}
9665
726069ba 9666/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
c2f47e15 9667 ARG is the argument for the call. */
726069ba 9668
9669static tree
c2f47e15 9670fold_builtin_classify (tree fndecl, tree arg, int builtin_index)
726069ba 9671{
726069ba 9672 tree type = TREE_TYPE (TREE_TYPE (fndecl));
726069ba 9673 REAL_VALUE_TYPE r;
9674
c2f47e15 9675 if (!validate_arg (arg, REAL_TYPE))
d43cee80 9676 return NULL_TREE;
726069ba 9677
726069ba 9678 switch (builtin_index)
9679 {
9680 case BUILT_IN_ISINF:
b70bfd00 9681 if (!HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
a0c938f0 9682 return omit_one_operand (type, integer_zero_node, arg);
726069ba 9683
9684 if (TREE_CODE (arg) == REAL_CST)
9685 {
9686 r = TREE_REAL_CST (arg);
9687 if (real_isinf (&r))
9688 return real_compare (GT_EXPR, &r, &dconst0)
9689 ? integer_one_node : integer_minus_one_node;
9690 else
9691 return integer_zero_node;
9692 }
9693
9694 return NULL_TREE;
9695
c319d56a 9696 case BUILT_IN_ISINF_SIGN:
9697 {
9698 /* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */
9699 /* In a boolean context, GCC will fold the inner COND_EXPR to
9700 1. So e.g. "if (isinf_sign(x))" would be folded to just
9701 "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
9702 tree signbit_fn = mathfn_built_in_1 (TREE_TYPE (arg), BUILT_IN_SIGNBIT, 0);
9703 tree isinf_fn = built_in_decls[BUILT_IN_ISINF];
9704 tree tmp = NULL_TREE;
9705
9706 arg = builtin_save_expr (arg);
9707
9708 if (signbit_fn && isinf_fn)
9709 {
9710 tree signbit_call = build_call_expr (signbit_fn, 1, arg);
9711 tree isinf_call = build_call_expr (isinf_fn, 1, arg);
9712
9713 signbit_call = fold_build2 (NE_EXPR, integer_type_node,
9714 signbit_call, integer_zero_node);
9715 isinf_call = fold_build2 (NE_EXPR, integer_type_node,
9716 isinf_call, integer_zero_node);
9717
9718 tmp = fold_build3 (COND_EXPR, integer_type_node, signbit_call,
9719 integer_minus_one_node, integer_one_node);
9720 tmp = fold_build3 (COND_EXPR, integer_type_node, isinf_call, tmp,
9721 integer_zero_node);
9722 }
9723
9724 return tmp;
9725 }
9726
cde061c1 9727 case BUILT_IN_ISFINITE:
b70bfd00 9728 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
9729 && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
34709e02 9730 return omit_one_operand (type, integer_one_node, arg);
726069ba 9731
9732 if (TREE_CODE (arg) == REAL_CST)
9733 {
9734 r = TREE_REAL_CST (arg);
776a7bab 9735 return real_isfinite (&r) ? integer_one_node : integer_zero_node;
726069ba 9736 }
9737
9738 return NULL_TREE;
9739
9740 case BUILT_IN_ISNAN:
b70bfd00 9741 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))))
a0c938f0 9742 return omit_one_operand (type, integer_zero_node, arg);
726069ba 9743
9744 if (TREE_CODE (arg) == REAL_CST)
9745 {
9746 r = TREE_REAL_CST (arg);
9747 return real_isnan (&r) ? integer_one_node : integer_zero_node;
9748 }
9749
9750 arg = builtin_save_expr (arg);
49d00087 9751 return fold_build2 (UNORDERED_EXPR, type, arg, arg);
726069ba 9752
9753 default:
64db345d 9754 gcc_unreachable ();
726069ba 9755 }
9756}
9757
19fbe3a4 9758/* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...).
9759 This builtin will generate code to return the appropriate floating
9760 point classification depending on the value of the floating point
9761 number passed in. The possible return values must be supplied as
921b27c0 9762 int arguments to the call in the following order: FP_NAN, FP_INFINITE,
19fbe3a4 9763 FP_NORMAL, FP_SUBNORMAL and FP_ZERO. The ellipses is for exactly
9764 one floating point argument which is "type generic". */
9765
9766static tree
9767fold_builtin_fpclassify (tree exp)
9768{
921b27c0 9769 tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
9770 arg, type, res, tmp;
19fbe3a4 9771 enum machine_mode mode;
9772 REAL_VALUE_TYPE r;
9773 char buf[128];
9774
9775 /* Verify the required arguments in the original call. */
9776 if (!validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE,
9777 INTEGER_TYPE, INTEGER_TYPE,
9778 INTEGER_TYPE, REAL_TYPE, VOID_TYPE))
9779 return NULL_TREE;
9780
9781 fp_nan = CALL_EXPR_ARG (exp, 0);
921b27c0 9782 fp_infinite = CALL_EXPR_ARG (exp, 1);
19fbe3a4 9783 fp_normal = CALL_EXPR_ARG (exp, 2);
9784 fp_subnormal = CALL_EXPR_ARG (exp, 3);
9785 fp_zero = CALL_EXPR_ARG (exp, 4);
9786 arg = CALL_EXPR_ARG (exp, 5);
9787 type = TREE_TYPE (arg);
9788 mode = TYPE_MODE (type);
9789 arg = builtin_save_expr (fold_build1 (ABS_EXPR, type, arg));
9790
9791 /* fpclassify(x) ->
9792 isnan(x) ? FP_NAN :
921b27c0 9793 (fabs(x) == Inf ? FP_INFINITE :
19fbe3a4 9794 (fabs(x) >= DBL_MIN ? FP_NORMAL :
9795 (x == 0 ? FP_ZERO : FP_SUBNORMAL))). */
9796
9797 tmp = fold_build2 (EQ_EXPR, integer_type_node, arg,
9798 build_real (type, dconst0));
9799 res = fold_build3 (COND_EXPR, integer_type_node, tmp, fp_zero, fp_subnormal);
9800
9801 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
9802 real_from_string (&r, buf);
9803 tmp = fold_build2 (GE_EXPR, integer_type_node, arg, build_real (type, r));
9804 res = fold_build3 (COND_EXPR, integer_type_node, tmp, fp_normal, res);
9805
9806 if (HONOR_INFINITIES (mode))
9807 {
9808 real_inf (&r);
9809 tmp = fold_build2 (EQ_EXPR, integer_type_node, arg,
9810 build_real (type, r));
921b27c0 9811 res = fold_build3 (COND_EXPR, integer_type_node, tmp, fp_infinite, res);
19fbe3a4 9812 }
9813
9814 if (HONOR_NANS (mode))
9815 {
9816 tmp = fold_build2 (ORDERED_EXPR, integer_type_node, arg, arg);
9817 res = fold_build3 (COND_EXPR, integer_type_node, tmp, res, fp_nan);
9818 }
9819
9820 return res;
9821}
9822
9bc9f15f 9823/* Fold a call to an unordered comparison function such as
d5019fe8 9824 __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function
c2f47e15 9825 being called and ARG0 and ARG1 are the arguments for the call.
726069ba 9826 UNORDERED_CODE and ORDERED_CODE are comparison codes that give
9827 the opposite of the desired result. UNORDERED_CODE is used
9828 for modes that can hold NaNs and ORDERED_CODE is used for
9829 the rest. */
9bc9f15f 9830
9831static tree
c2f47e15 9832fold_builtin_unordered_cmp (tree fndecl, tree arg0, tree arg1,
9bc9f15f 9833 enum tree_code unordered_code,
9834 enum tree_code ordered_code)
9835{
859f903a 9836 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9bc9f15f 9837 enum tree_code code;
6978db0d 9838 tree type0, type1;
9839 enum tree_code code0, code1;
9840 tree cmp_type = NULL_TREE;
9bc9f15f 9841
6978db0d 9842 type0 = TREE_TYPE (arg0);
9843 type1 = TREE_TYPE (arg1);
a0c938f0 9844
6978db0d 9845 code0 = TREE_CODE (type0);
9846 code1 = TREE_CODE (type1);
a0c938f0 9847
6978db0d 9848 if (code0 == REAL_TYPE && code1 == REAL_TYPE)
9849 /* Choose the wider of two real types. */
9850 cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
9851 ? type0 : type1;
9852 else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
9853 cmp_type = type0;
9854 else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
9855 cmp_type = type1;
a0c938f0 9856
6978db0d 9857 arg0 = fold_convert (cmp_type, arg0);
9858 arg1 = fold_convert (cmp_type, arg1);
859f903a 9859
9860 if (unordered_code == UNORDERED_EXPR)
9861 {
b70bfd00 9862 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
859f903a 9863 return omit_two_operands (type, integer_zero_node, arg0, arg1);
49d00087 9864 return fold_build2 (UNORDERED_EXPR, type, arg0, arg1);
859f903a 9865 }
9bc9f15f 9866
b70bfd00 9867 code = HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
9868 : ordered_code;
49d00087 9869 return fold_build1 (TRUTH_NOT_EXPR, type,
9870 fold_build2 (code, type, arg0, arg1));
9bc9f15f 9871}
9872
c2f47e15 9873/* Fold a call to built-in function FNDECL with 0 arguments.
9874 IGNORE is true if the result of the function call is ignored. This
9875 function returns NULL_TREE if no simplification was possible. */
650e4c94 9876
4ee9c684 9877static tree
c2f47e15 9878fold_builtin_0 (tree fndecl, bool ignore ATTRIBUTE_UNUSED)
650e4c94 9879{
e9f80ff5 9880 tree type = TREE_TYPE (TREE_TYPE (fndecl));
c2f47e15 9881 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
189b3398 9882 switch (fcode)
650e4c94 9883 {
c2f47e15 9884 CASE_FLT_FN (BUILT_IN_INF):
9885 case BUILT_IN_INFD32:
9886 case BUILT_IN_INFD64:
9887 case BUILT_IN_INFD128:
9888 return fold_builtin_inf (type, true);
7c2f0500 9889
c2f47e15 9890 CASE_FLT_FN (BUILT_IN_HUGE_VAL):
9891 return fold_builtin_inf (type, false);
7c2f0500 9892
c2f47e15 9893 case BUILT_IN_CLASSIFY_TYPE:
9894 return fold_builtin_classify_type (NULL_TREE);
7c2f0500 9895
c2f47e15 9896 default:
9897 break;
9898 }
9899 return NULL_TREE;
9900}
7c2f0500 9901
c2f47e15 9902/* Fold a call to built-in function FNDECL with 1 argument, ARG0.
9903 IGNORE is true if the result of the function call is ignored. This
9904 function returns NULL_TREE if no simplification was possible. */
7c2f0500 9905
c2f47e15 9906static tree
9907fold_builtin_1 (tree fndecl, tree arg0, bool ignore)
9908{
9909 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9910 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9911 switch (fcode)
9912 {
7c2f0500 9913
650e4c94 9914 case BUILT_IN_CONSTANT_P:
7c2f0500 9915 {
c2f47e15 9916 tree val = fold_builtin_constant_p (arg0);
7c2f0500 9917
7c2f0500 9918 /* Gimplification will pull the CALL_EXPR for the builtin out of
9919 an if condition. When not optimizing, we'll not CSE it back.
9920 To avoid link error types of regressions, return false now. */
9921 if (!val && !optimize)
9922 val = integer_zero_node;
9923
9924 return val;
9925 }
650e4c94 9926
539a3a92 9927 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 9928 return fold_builtin_classify_type (arg0);
539a3a92 9929
650e4c94 9930 case BUILT_IN_STRLEN:
c2f47e15 9931 return fold_builtin_strlen (arg0);
650e4c94 9932
4f35b1fc 9933 CASE_FLT_FN (BUILT_IN_FABS):
c2f47e15 9934 return fold_builtin_fabs (arg0, type);
d1aade50 9935
9936 case BUILT_IN_ABS:
9937 case BUILT_IN_LABS:
9938 case BUILT_IN_LLABS:
9939 case BUILT_IN_IMAXABS:
c2f47e15 9940 return fold_builtin_abs (arg0, type);
c63f4ad3 9941
4f35b1fc 9942 CASE_FLT_FN (BUILT_IN_CONJ):
c2f47e15 9943 if (validate_arg (arg0, COMPLEX_TYPE))
9944 return fold_build1 (CONJ_EXPR, type, arg0);
9945 break;
36d3581d 9946
4f35b1fc 9947 CASE_FLT_FN (BUILT_IN_CREAL):
c2f47e15 9948 if (validate_arg (arg0, COMPLEX_TYPE))
9949 return non_lvalue (fold_build1 (REALPART_EXPR, type, arg0));;
9950 break;
36d3581d 9951
4f35b1fc 9952 CASE_FLT_FN (BUILT_IN_CIMAG):
c2f47e15 9953 if (validate_arg (arg0, COMPLEX_TYPE))
9954 return non_lvalue (fold_build1 (IMAGPART_EXPR, type, arg0));
9955 break;
36d3581d 9956
503733d5 9957 CASE_FLT_FN (BUILT_IN_CCOS):
9958 CASE_FLT_FN (BUILT_IN_CCOSH):
9959 /* These functions are "even", i.e. f(x) == f(-x). */
c2f47e15 9960 if (validate_arg (arg0, COMPLEX_TYPE))
9961 {
9962 tree narg = fold_strip_sign_ops (arg0);
503733d5 9963 if (narg)
c2f47e15 9964 return build_call_expr (fndecl, 1, narg);
503733d5 9965 }
c2f47e15 9966 break;
503733d5 9967
4f35b1fc 9968 CASE_FLT_FN (BUILT_IN_CABS):
c2f47e15 9969 return fold_builtin_cabs (arg0, type, fndecl);
c63f4ad3 9970
abe4dcf6 9971 CASE_FLT_FN (BUILT_IN_CARG):
c2f47e15 9972 return fold_builtin_carg (arg0, type);
abe4dcf6 9973
4f35b1fc 9974 CASE_FLT_FN (BUILT_IN_SQRT):
c2f47e15 9975 return fold_builtin_sqrt (arg0, type);
805e22b2 9976
4f35b1fc 9977 CASE_FLT_FN (BUILT_IN_CBRT):
c2f47e15 9978 return fold_builtin_cbrt (arg0, type);
3bc5c41b 9979
728bac60 9980 CASE_FLT_FN (BUILT_IN_ASIN):
c2f47e15 9981 if (validate_arg (arg0, REAL_TYPE))
9982 return do_mpfr_arg1 (arg0, type, mpfr_asin,
728bac60 9983 &dconstm1, &dconst1, true);
9984 break;
9985
9986 CASE_FLT_FN (BUILT_IN_ACOS):
c2f47e15 9987 if (validate_arg (arg0, REAL_TYPE))
9988 return do_mpfr_arg1 (arg0, type, mpfr_acos,
728bac60 9989 &dconstm1, &dconst1, true);
9990 break;
9991
9992 CASE_FLT_FN (BUILT_IN_ATAN):
c2f47e15 9993 if (validate_arg (arg0, REAL_TYPE))
9994 return do_mpfr_arg1 (arg0, type, mpfr_atan, NULL, NULL, 0);
728bac60 9995 break;
9996
9997 CASE_FLT_FN (BUILT_IN_ASINH):
c2f47e15 9998 if (validate_arg (arg0, REAL_TYPE))
9999 return do_mpfr_arg1 (arg0, type, mpfr_asinh, NULL, NULL, 0);
728bac60 10000 break;
10001
10002 CASE_FLT_FN (BUILT_IN_ACOSH):
c2f47e15 10003 if (validate_arg (arg0, REAL_TYPE))
10004 return do_mpfr_arg1 (arg0, type, mpfr_acosh,
728bac60 10005 &dconst1, NULL, true);
10006 break;
10007
10008 CASE_FLT_FN (BUILT_IN_ATANH):
c2f47e15 10009 if (validate_arg (arg0, REAL_TYPE))
10010 return do_mpfr_arg1 (arg0, type, mpfr_atanh,
728bac60 10011 &dconstm1, &dconst1, false);
10012 break;
10013
4f35b1fc 10014 CASE_FLT_FN (BUILT_IN_SIN):
c2f47e15 10015 if (validate_arg (arg0, REAL_TYPE))
10016 return do_mpfr_arg1 (arg0, type, mpfr_sin, NULL, NULL, 0);
728bac60 10017 break;
77e89269 10018
4f35b1fc 10019 CASE_FLT_FN (BUILT_IN_COS):
c2f47e15 10020 return fold_builtin_cos (arg0, type, fndecl);
10021 break;
77e89269 10022
728bac60 10023 CASE_FLT_FN (BUILT_IN_TAN):
c2f47e15 10024 return fold_builtin_tan (arg0, type);
d735c391 10025
c5bb2c4b 10026 CASE_FLT_FN (BUILT_IN_CEXP):
c2f47e15 10027 return fold_builtin_cexp (arg0, type);
c5bb2c4b 10028
d735c391 10029 CASE_FLT_FN (BUILT_IN_CEXPI):
c2f47e15 10030 if (validate_arg (arg0, REAL_TYPE))
10031 return do_mpfr_sincos (arg0, NULL_TREE, NULL_TREE);
10032 break;
d92f994c 10033
728bac60 10034 CASE_FLT_FN (BUILT_IN_SINH):
c2f47e15 10035 if (validate_arg (arg0, REAL_TYPE))
10036 return do_mpfr_arg1 (arg0, type, mpfr_sinh, NULL, NULL, 0);
728bac60 10037 break;
10038
10039 CASE_FLT_FN (BUILT_IN_COSH):
c2f47e15 10040 return fold_builtin_cosh (arg0, type, fndecl);
728bac60 10041
10042 CASE_FLT_FN (BUILT_IN_TANH):
c2f47e15 10043 if (validate_arg (arg0, REAL_TYPE))
10044 return do_mpfr_arg1 (arg0, type, mpfr_tanh, NULL, NULL, 0);
728bac60 10045 break;
10046
29f4cd78 10047 CASE_FLT_FN (BUILT_IN_ERF):
c2f47e15 10048 if (validate_arg (arg0, REAL_TYPE))
10049 return do_mpfr_arg1 (arg0, type, mpfr_erf, NULL, NULL, 0);
29f4cd78 10050 break;
10051
10052 CASE_FLT_FN (BUILT_IN_ERFC):
c2f47e15 10053 if (validate_arg (arg0, REAL_TYPE))
10054 return do_mpfr_arg1 (arg0, type, mpfr_erfc, NULL, NULL, 0);
29f4cd78 10055 break;
10056
32dba52b 10057 CASE_FLT_FN (BUILT_IN_TGAMMA):
c2f47e15 10058 if (validate_arg (arg0, REAL_TYPE))
10059 return do_mpfr_arg1 (arg0, type, mpfr_gamma, NULL, NULL, 0);
32dba52b 10060 break;
10061
4f35b1fc 10062 CASE_FLT_FN (BUILT_IN_EXP):
c2f47e15 10063 return fold_builtin_exponent (fndecl, arg0, mpfr_exp);
467214fd 10064
4f35b1fc 10065 CASE_FLT_FN (BUILT_IN_EXP2):
c2f47e15 10066 return fold_builtin_exponent (fndecl, arg0, mpfr_exp2);
467214fd 10067
4f35b1fc 10068 CASE_FLT_FN (BUILT_IN_EXP10):
10069 CASE_FLT_FN (BUILT_IN_POW10):
c2f47e15 10070 return fold_builtin_exponent (fndecl, arg0, mpfr_exp10);
467214fd 10071
29f4cd78 10072 CASE_FLT_FN (BUILT_IN_EXPM1):
c2f47e15 10073 if (validate_arg (arg0, REAL_TYPE))
10074 return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0);
29f4cd78 10075 break;
10076
4f35b1fc 10077 CASE_FLT_FN (BUILT_IN_LOG):
c2f47e15 10078 return fold_builtin_logarithm (fndecl, arg0, mpfr_log);
467214fd 10079
4f35b1fc 10080 CASE_FLT_FN (BUILT_IN_LOG2):
c2f47e15 10081 return fold_builtin_logarithm (fndecl, arg0, mpfr_log2);
467214fd 10082
4f35b1fc 10083 CASE_FLT_FN (BUILT_IN_LOG10):
c2f47e15 10084 return fold_builtin_logarithm (fndecl, arg0, mpfr_log10);
29f4cd78 10085
10086 CASE_FLT_FN (BUILT_IN_LOG1P):
c2f47e15 10087 if (validate_arg (arg0, REAL_TYPE))
10088 return do_mpfr_arg1 (arg0, type, mpfr_log1p,
29f4cd78 10089 &dconstm1, NULL, false);
10090 break;
805e22b2 10091
65dd1378 10092#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
10093 CASE_FLT_FN (BUILT_IN_J0):
10094 if (validate_arg (arg0, REAL_TYPE))
10095 return do_mpfr_arg1 (arg0, type, mpfr_j0,
10096 NULL, NULL, 0);
10097 break;
10098
10099 CASE_FLT_FN (BUILT_IN_J1):
10100 if (validate_arg (arg0, REAL_TYPE))
10101 return do_mpfr_arg1 (arg0, type, mpfr_j1,
10102 NULL, NULL, 0);
10103 break;
6ff9eeff 10104
10105 CASE_FLT_FN (BUILT_IN_Y0):
10106 if (validate_arg (arg0, REAL_TYPE))
10107 return do_mpfr_arg1 (arg0, type, mpfr_y0,
10108 &dconst0, NULL, false);
10109 break;
10110
10111 CASE_FLT_FN (BUILT_IN_Y1):
10112 if (validate_arg (arg0, REAL_TYPE))
10113 return do_mpfr_arg1 (arg0, type, mpfr_y1,
10114 &dconst0, NULL, false);
10115 break;
65dd1378 10116#endif
10117
4f35b1fc 10118 CASE_FLT_FN (BUILT_IN_NAN):
c4503c0a 10119 case BUILT_IN_NAND32:
10120 case BUILT_IN_NAND64:
10121 case BUILT_IN_NAND128:
c2f47e15 10122 return fold_builtin_nan (arg0, type, true);
b0db7939 10123
4f35b1fc 10124 CASE_FLT_FN (BUILT_IN_NANS):
c2f47e15 10125 return fold_builtin_nan (arg0, type, false);
b0db7939 10126
4f35b1fc 10127 CASE_FLT_FN (BUILT_IN_FLOOR):
c2f47e15 10128 return fold_builtin_floor (fndecl, arg0);
277f8dd2 10129
4f35b1fc 10130 CASE_FLT_FN (BUILT_IN_CEIL):
c2f47e15 10131 return fold_builtin_ceil (fndecl, arg0);
277f8dd2 10132
4f35b1fc 10133 CASE_FLT_FN (BUILT_IN_TRUNC):
c2f47e15 10134 return fold_builtin_trunc (fndecl, arg0);
277f8dd2 10135
4f35b1fc 10136 CASE_FLT_FN (BUILT_IN_ROUND):
c2f47e15 10137 return fold_builtin_round (fndecl, arg0);
89ab3887 10138
4f35b1fc 10139 CASE_FLT_FN (BUILT_IN_NEARBYINT):
10140 CASE_FLT_FN (BUILT_IN_RINT):
c2f47e15 10141 return fold_trunc_transparent_mathfn (fndecl, arg0);
6528f4f4 10142
4f35b1fc 10143 CASE_FLT_FN (BUILT_IN_LCEIL):
10144 CASE_FLT_FN (BUILT_IN_LLCEIL):
10145 CASE_FLT_FN (BUILT_IN_LFLOOR):
10146 CASE_FLT_FN (BUILT_IN_LLFLOOR):
a0c938f0 10147 CASE_FLT_FN (BUILT_IN_LROUND):
4f35b1fc 10148 CASE_FLT_FN (BUILT_IN_LLROUND):
c2f47e15 10149 return fold_builtin_int_roundingfn (fndecl, arg0);
34f17811 10150
4f35b1fc 10151 CASE_FLT_FN (BUILT_IN_LRINT):
10152 CASE_FLT_FN (BUILT_IN_LLRINT):
c2f47e15 10153 return fold_fixed_mathfn (fndecl, arg0);
9ed65c7f 10154
42791117 10155 case BUILT_IN_BSWAP32:
10156 case BUILT_IN_BSWAP64:
c2f47e15 10157 return fold_builtin_bswap (fndecl, arg0);
42791117 10158
4f35b1fc 10159 CASE_INT_FN (BUILT_IN_FFS):
10160 CASE_INT_FN (BUILT_IN_CLZ):
10161 CASE_INT_FN (BUILT_IN_CTZ):
10162 CASE_INT_FN (BUILT_IN_POPCOUNT):
10163 CASE_INT_FN (BUILT_IN_PARITY):
c2f47e15 10164 return fold_builtin_bitop (fndecl, arg0);
9c8a1629 10165
4f35b1fc 10166 CASE_FLT_FN (BUILT_IN_SIGNBIT):
c2f47e15 10167 return fold_builtin_signbit (arg0, type);
27f261ef 10168
cb2b9385 10169 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
10170 return fold_builtin_significand (arg0, type);
10171
10172 CASE_FLT_FN (BUILT_IN_ILOGB):
10173 CASE_FLT_FN (BUILT_IN_LOGB):
10174 return fold_builtin_logb (arg0, type);
10175
d49367d4 10176 case BUILT_IN_ISASCII:
c2f47e15 10177 return fold_builtin_isascii (arg0);
d49367d4 10178
10179 case BUILT_IN_TOASCII:
c2f47e15 10180 return fold_builtin_toascii (arg0);
d49367d4 10181
df1cf42e 10182 case BUILT_IN_ISDIGIT:
c2f47e15 10183 return fold_builtin_isdigit (arg0);
467214fd 10184
4f35b1fc 10185 CASE_FLT_FN (BUILT_IN_FINITE):
c4503c0a 10186 case BUILT_IN_FINITED32:
10187 case BUILT_IN_FINITED64:
10188 case BUILT_IN_FINITED128:
cde061c1 10189 case BUILT_IN_ISFINITE:
10190 return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISFINITE);
726069ba 10191
4f35b1fc 10192 CASE_FLT_FN (BUILT_IN_ISINF):
c4503c0a 10193 case BUILT_IN_ISINFD32:
10194 case BUILT_IN_ISINFD64:
10195 case BUILT_IN_ISINFD128:
c2f47e15 10196 return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISINF);
726069ba 10197
c319d56a 10198 case BUILT_IN_ISINF_SIGN:
10199 return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISINF_SIGN);
10200
4f35b1fc 10201 CASE_FLT_FN (BUILT_IN_ISNAN):
c4503c0a 10202 case BUILT_IN_ISNAND32:
10203 case BUILT_IN_ISNAND64:
10204 case BUILT_IN_ISNAND128:
c2f47e15 10205 return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISNAN);
10206
10207 case BUILT_IN_PRINTF:
10208 case BUILT_IN_PRINTF_UNLOCKED:
10209 case BUILT_IN_VPRINTF:
10210 return fold_builtin_printf (fndecl, arg0, NULL_TREE, ignore, fcode);
10211
10212 default:
10213 break;
10214 }
10215
10216 return NULL_TREE;
10217
10218}
10219
10220/* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1.
10221 IGNORE is true if the result of the function call is ignored. This
10222 function returns NULL_TREE if no simplification was possible. */
10223
10224static tree
10225fold_builtin_2 (tree fndecl, tree arg0, tree arg1, bool ignore)
10226{
10227 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10228 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10229
10230 switch (fcode)
10231 {
65dd1378 10232#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
10233 CASE_FLT_FN (BUILT_IN_JN):
10234 if (validate_arg (arg0, INTEGER_TYPE)
10235 && validate_arg (arg1, REAL_TYPE))
10236 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_jn, NULL, 0);
10237 break;
6ff9eeff 10238
10239 CASE_FLT_FN (BUILT_IN_YN):
10240 if (validate_arg (arg0, INTEGER_TYPE)
10241 && validate_arg (arg1, REAL_TYPE))
10242 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_yn,
10243 &dconst0, false);
10244 break;
e5407ca6 10245
10246 CASE_FLT_FN (BUILT_IN_DREM):
10247 CASE_FLT_FN (BUILT_IN_REMAINDER):
10248 if (validate_arg (arg0, REAL_TYPE)
10249 && validate_arg(arg1, REAL_TYPE))
10250 return do_mpfr_arg2 (arg0, arg1, type, mpfr_remainder);
10251 break;
e84da7c1 10252
10253 CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
10254 CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
10255 if (validate_arg (arg0, REAL_TYPE)
10256 && validate_arg(arg1, POINTER_TYPE))
10257 return do_mpfr_lgamma_r (arg0, arg1, type);
10258 break;
65dd1378 10259#endif
c2f47e15 10260
10261 CASE_FLT_FN (BUILT_IN_ATAN2):
10262 if (validate_arg (arg0, REAL_TYPE)
10263 && validate_arg(arg1, REAL_TYPE))
10264 return do_mpfr_arg2 (arg0, arg1, type, mpfr_atan2);
10265 break;
10266
10267 CASE_FLT_FN (BUILT_IN_FDIM):
10268 if (validate_arg (arg0, REAL_TYPE)
10269 && validate_arg(arg1, REAL_TYPE))
10270 return do_mpfr_arg2 (arg0, arg1, type, mpfr_dim);
10271 break;
10272
10273 CASE_FLT_FN (BUILT_IN_HYPOT):
10274 return fold_builtin_hypot (fndecl, arg0, arg1, type);
10275
7587301b 10276 CASE_FLT_FN (BUILT_IN_LDEXP):
10277 return fold_builtin_load_exponent (arg0, arg1, type, /*ldexp=*/true);
10278 CASE_FLT_FN (BUILT_IN_SCALBN):
10279 CASE_FLT_FN (BUILT_IN_SCALBLN):
10280 return fold_builtin_load_exponent (arg0, arg1, type, /*ldexp=*/false);
10281
3838b9ae 10282 CASE_FLT_FN (BUILT_IN_FREXP):
10283 return fold_builtin_frexp (arg0, arg1, type);
10284
ebf8b4f5 10285 CASE_FLT_FN (BUILT_IN_MODF):
10286 return fold_builtin_modf (arg0, arg1, type);
10287
c2f47e15 10288 case BUILT_IN_BZERO:
10289 return fold_builtin_bzero (arg0, arg1, ignore);
10290
10291 case BUILT_IN_FPUTS:
10292 return fold_builtin_fputs (arg0, arg1, ignore, false, NULL_TREE);
10293
10294 case BUILT_IN_FPUTS_UNLOCKED:
10295 return fold_builtin_fputs (arg0, arg1, ignore, true, NULL_TREE);
10296
10297 case BUILT_IN_STRSTR:
10298 return fold_builtin_strstr (arg0, arg1, type);
10299
10300 case BUILT_IN_STRCAT:
10301 return fold_builtin_strcat (arg0, arg1);
10302
10303 case BUILT_IN_STRSPN:
10304 return fold_builtin_strspn (arg0, arg1);
10305
10306 case BUILT_IN_STRCSPN:
10307 return fold_builtin_strcspn (arg0, arg1);
10308
10309 case BUILT_IN_STRCHR:
10310 case BUILT_IN_INDEX:
10311 return fold_builtin_strchr (arg0, arg1, type);
10312
10313 case BUILT_IN_STRRCHR:
10314 case BUILT_IN_RINDEX:
10315 return fold_builtin_strrchr (arg0, arg1, type);
10316
10317 case BUILT_IN_STRCPY:
10318 return fold_builtin_strcpy (fndecl, arg0, arg1, NULL_TREE);
10319
10320 case BUILT_IN_STRCMP:
10321 return fold_builtin_strcmp (arg0, arg1);
10322
10323 case BUILT_IN_STRPBRK:
10324 return fold_builtin_strpbrk (arg0, arg1, type);
10325
10326 case BUILT_IN_EXPECT:
76f5a783 10327 return fold_builtin_expect (arg0, arg1);
c2f47e15 10328
10329 CASE_FLT_FN (BUILT_IN_POW):
10330 return fold_builtin_pow (fndecl, arg0, arg1, type);
10331
10332 CASE_FLT_FN (BUILT_IN_POWI):
10333 return fold_builtin_powi (fndecl, arg0, arg1, type);
10334
10335 CASE_FLT_FN (BUILT_IN_COPYSIGN):
10336 return fold_builtin_copysign (fndecl, arg0, arg1, type);
10337
10338 CASE_FLT_FN (BUILT_IN_FMIN):
10339 return fold_builtin_fmin_fmax (arg0, arg1, type, /*max=*/false);
10340
10341 CASE_FLT_FN (BUILT_IN_FMAX):
10342 return fold_builtin_fmin_fmax (arg0, arg1, type, /*max=*/true);
726069ba 10343
9bc9f15f 10344 case BUILT_IN_ISGREATER:
c2f47e15 10345 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNLE_EXPR, LE_EXPR);
9bc9f15f 10346 case BUILT_IN_ISGREATEREQUAL:
c2f47e15 10347 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNLT_EXPR, LT_EXPR);
9bc9f15f 10348 case BUILT_IN_ISLESS:
c2f47e15 10349 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNGE_EXPR, GE_EXPR);
9bc9f15f 10350 case BUILT_IN_ISLESSEQUAL:
c2f47e15 10351 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNGT_EXPR, GT_EXPR);
9bc9f15f 10352 case BUILT_IN_ISLESSGREATER:
c2f47e15 10353 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNEQ_EXPR, EQ_EXPR);
9bc9f15f 10354 case BUILT_IN_ISUNORDERED:
c2f47e15 10355 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNORDERED_EXPR,
d5019fe8 10356 NOP_EXPR);
9bc9f15f 10357
7c2f0500 10358 /* We do the folding for va_start in the expander. */
10359 case BUILT_IN_VA_START:
10360 break;
f0613857 10361
c2f47e15 10362 case BUILT_IN_SPRINTF:
10363 return fold_builtin_sprintf (arg0, arg1, NULL_TREE, ignore);
10364
0a39fd54 10365 case BUILT_IN_OBJECT_SIZE:
c2f47e15 10366 return fold_builtin_object_size (arg0, arg1);
0a39fd54 10367
10368 case BUILT_IN_PRINTF:
10369 case BUILT_IN_PRINTF_UNLOCKED:
10370 case BUILT_IN_VPRINTF:
c2f47e15 10371 return fold_builtin_printf (fndecl, arg0, arg1, ignore, fcode);
10372
0a39fd54 10373 case BUILT_IN_PRINTF_CHK:
10374 case BUILT_IN_VPRINTF_CHK:
c2f47e15 10375 if (!validate_arg (arg0, INTEGER_TYPE)
10376 || TREE_SIDE_EFFECTS (arg0))
10377 return NULL_TREE;
10378 else
10379 return fold_builtin_printf (fndecl, arg1, NULL_TREE, ignore, fcode);
10380 break;
0a39fd54 10381
10382 case BUILT_IN_FPRINTF:
10383 case BUILT_IN_FPRINTF_UNLOCKED:
10384 case BUILT_IN_VFPRINTF:
c2f47e15 10385 return fold_builtin_fprintf (fndecl, arg0, arg1, NULL_TREE,
10386 ignore, fcode);
10387
10388 default:
10389 break;
10390 }
10391 return NULL_TREE;
10392}
10393
10394/* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
10395 and ARG2. IGNORE is true if the result of the function call is ignored.
10396 This function returns NULL_TREE if no simplification was possible. */
10397
10398static tree
10399fold_builtin_3 (tree fndecl, tree arg0, tree arg1, tree arg2, bool ignore)
10400{
10401 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10402 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10403 switch (fcode)
10404 {
10405
10406 CASE_FLT_FN (BUILT_IN_SINCOS):
10407 return fold_builtin_sincos (arg0, arg1, arg2);
10408
10409 CASE_FLT_FN (BUILT_IN_FMA):
10410 if (validate_arg (arg0, REAL_TYPE)
10411 && validate_arg(arg1, REAL_TYPE)
10412 && validate_arg(arg2, REAL_TYPE))
10413 return do_mpfr_arg3 (arg0, arg1, arg2, type, mpfr_fma);
10414 break;
10415
e5407ca6 10416#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
10417 CASE_FLT_FN (BUILT_IN_REMQUO):
10418 if (validate_arg (arg0, REAL_TYPE)
10419 && validate_arg(arg1, REAL_TYPE)
10420 && validate_arg(arg2, POINTER_TYPE))
10421 return do_mpfr_remquo (arg0, arg1, arg2);
10422 break;
10423#endif
10424
c2f47e15 10425 case BUILT_IN_MEMSET:
10426 return fold_builtin_memset (arg0, arg1, arg2, type, ignore);
10427
10428 case BUILT_IN_BCOPY:
10429 return fold_builtin_memory_op (arg1, arg0, arg2, void_type_node, true, /*endp=*/3);
10430
10431 case BUILT_IN_MEMCPY:
10432 return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/0);
10433
10434 case BUILT_IN_MEMPCPY:
10435 return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/1);
10436
10437 case BUILT_IN_MEMMOVE:
10438 return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/3);
10439
10440 case BUILT_IN_STRNCAT:
10441 return fold_builtin_strncat (arg0, arg1, arg2);
10442
10443 case BUILT_IN_STRNCPY:
10444 return fold_builtin_strncpy (fndecl, arg0, arg1, arg2, NULL_TREE);
10445
10446 case BUILT_IN_STRNCMP:
10447 return fold_builtin_strncmp (arg0, arg1, arg2);
10448
7959b13b 10449 case BUILT_IN_MEMCHR:
10450 return fold_builtin_memchr (arg0, arg1, arg2, type);
10451
c2f47e15 10452 case BUILT_IN_BCMP:
10453 case BUILT_IN_MEMCMP:
10454 return fold_builtin_memcmp (arg0, arg1, arg2);;
10455
10456 case BUILT_IN_SPRINTF:
10457 return fold_builtin_sprintf (arg0, arg1, arg2, ignore);
10458
10459 case BUILT_IN_STRCPY_CHK:
10460 case BUILT_IN_STPCPY_CHK:
10461 return fold_builtin_stxcpy_chk (fndecl, arg0, arg1, arg2, NULL_TREE,
10462 ignore, fcode);
10463
10464 case BUILT_IN_STRCAT_CHK:
10465 return fold_builtin_strcat_chk (fndecl, arg0, arg1, arg2);
10466
10467 case BUILT_IN_PRINTF_CHK:
10468 case BUILT_IN_VPRINTF_CHK:
10469 if (!validate_arg (arg0, INTEGER_TYPE)
10470 || TREE_SIDE_EFFECTS (arg0))
10471 return NULL_TREE;
10472 else
10473 return fold_builtin_printf (fndecl, arg1, arg2, ignore, fcode);
10474 break;
10475
10476 case BUILT_IN_FPRINTF:
10477 case BUILT_IN_FPRINTF_UNLOCKED:
10478 case BUILT_IN_VFPRINTF:
10479 return fold_builtin_fprintf (fndecl, arg0, arg1, arg2, ignore, fcode);
10480
0a39fd54 10481 case BUILT_IN_FPRINTF_CHK:
10482 case BUILT_IN_VFPRINTF_CHK:
c2f47e15 10483 if (!validate_arg (arg1, INTEGER_TYPE)
10484 || TREE_SIDE_EFFECTS (arg1))
10485 return NULL_TREE;
10486 else
10487 return fold_builtin_fprintf (fndecl, arg0, arg2, NULL_TREE,
10488 ignore, fcode);
0a39fd54 10489
650e4c94 10490 default:
10491 break;
10492 }
c2f47e15 10493 return NULL_TREE;
10494}
650e4c94 10495
c2f47e15 10496/* Fold a call to built-in function FNDECL with 4 arguments, ARG0, ARG1,
10497 ARG2, and ARG3. IGNORE is true if the result of the function call is
10498 ignored. This function returns NULL_TREE if no simplification was
10499 possible. */
10500
10501static tree
10502fold_builtin_4 (tree fndecl, tree arg0, tree arg1, tree arg2, tree arg3,
10503 bool ignore)
10504{
10505 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10506
10507 switch (fcode)
10508 {
10509 case BUILT_IN_MEMCPY_CHK:
10510 case BUILT_IN_MEMPCPY_CHK:
10511 case BUILT_IN_MEMMOVE_CHK:
10512 case BUILT_IN_MEMSET_CHK:
10513 return fold_builtin_memory_chk (fndecl, arg0, arg1, arg2, arg3,
10514 NULL_TREE, ignore,
10515 DECL_FUNCTION_CODE (fndecl));
10516
10517 case BUILT_IN_STRNCPY_CHK:
10518 return fold_builtin_strncpy_chk (arg0, arg1, arg2, arg3, NULL_TREE);
10519
10520 case BUILT_IN_STRNCAT_CHK:
10521 return fold_builtin_strncat_chk (fndecl, arg0, arg1, arg2, arg3);
10522
10523 case BUILT_IN_FPRINTF_CHK:
10524 case BUILT_IN_VFPRINTF_CHK:
10525 if (!validate_arg (arg1, INTEGER_TYPE)
10526 || TREE_SIDE_EFFECTS (arg1))
10527 return NULL_TREE;
10528 else
10529 return fold_builtin_fprintf (fndecl, arg0, arg2, arg3,
10530 ignore, fcode);
10531 break;
10532
10533 default:
10534 break;
10535 }
10536 return NULL_TREE;
10537}
10538
10539/* Fold a call to built-in function FNDECL. ARGS is an array of NARGS
10540 arguments, where NARGS <= 4. IGNORE is true if the result of the
10541 function call is ignored. This function returns NULL_TREE if no
10542 simplification was possible. Note that this only folds builtins with
10543 fixed argument patterns. Foldings that do varargs-to-varargs
10544 transformations, or that match calls with more than 4 arguments,
10545 need to be handled with fold_builtin_varargs instead. */
10546
10547#define MAX_ARGS_TO_FOLD_BUILTIN 4
10548
10549static tree
10550fold_builtin_n (tree fndecl, tree *args, int nargs, bool ignore)
10551{
10552 tree ret = NULL_TREE;
a7f5bb2d 10553
c2f47e15 10554 switch (nargs)
10555 {
10556 case 0:
10557 ret = fold_builtin_0 (fndecl, ignore);
10558 break;
10559 case 1:
10560 ret = fold_builtin_1 (fndecl, args[0], ignore);
10561 break;
10562 case 2:
10563 ret = fold_builtin_2 (fndecl, args[0], args[1], ignore);
10564 break;
10565 case 3:
10566 ret = fold_builtin_3 (fndecl, args[0], args[1], args[2], ignore);
10567 break;
10568 case 4:
10569 ret = fold_builtin_4 (fndecl, args[0], args[1], args[2], args[3],
10570 ignore);
10571 break;
10572 default:
10573 break;
10574 }
10575 if (ret)
10576 {
10577 ret = build1 (NOP_EXPR, GENERIC_TREE_TYPE (ret), ret);
10578 TREE_NO_WARNING (ret) = 1;
10579 return ret;
10580 }
10581 return NULL_TREE;
10582}
10583
10584/* Builtins with folding operations that operate on "..." arguments
10585 need special handling; we need to store the arguments in a convenient
10586 data structure before attempting any folding. Fortunately there are
10587 only a few builtins that fall into this category. FNDECL is the
10588 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
10589 result of the function call is ignored. */
10590
10591static tree
10592fold_builtin_varargs (tree fndecl, tree exp, bool ignore ATTRIBUTE_UNUSED)
10593{
10594 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10595 tree ret = NULL_TREE;
10596
10597 switch (fcode)
10598 {
10599 case BUILT_IN_SPRINTF_CHK:
10600 case BUILT_IN_VSPRINTF_CHK:
10601 ret = fold_builtin_sprintf_chk (exp, fcode);
10602 break;
10603
10604 case BUILT_IN_SNPRINTF_CHK:
10605 case BUILT_IN_VSNPRINTF_CHK:
10606 ret = fold_builtin_snprintf_chk (exp, NULL_TREE, fcode);
19fbe3a4 10607 break;
10608
10609 case BUILT_IN_FPCLASSIFY:
10610 ret = fold_builtin_fpclassify (exp);
10611 break;
c2f47e15 10612
10613 default:
10614 break;
10615 }
10616 if (ret)
10617 {
10618 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
10619 TREE_NO_WARNING (ret) = 1;
10620 return ret;
10621 }
10622 return NULL_TREE;
650e4c94 10623}
7e15618b 10624
4ee9c684 10625/* A wrapper function for builtin folding that prevents warnings for
491e04ef 10626 "statement without effect" and the like, caused by removing the
4ee9c684 10627 call node earlier than the warning is generated. */
10628
10629tree
c2f47e15 10630fold_call_expr (tree exp, bool ignore)
4ee9c684 10631{
c2f47e15 10632 tree ret = NULL_TREE;
10633 tree fndecl = get_callee_fndecl (exp);
10634 if (fndecl
10635 && TREE_CODE (fndecl) == FUNCTION_DECL
48dc2227 10636 && DECL_BUILT_IN (fndecl)
10637 /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
10638 yet. Defer folding until we see all the arguments
10639 (after inlining). */
10640 && !CALL_EXPR_VA_ARG_PACK (exp))
10641 {
10642 int nargs = call_expr_nargs (exp);
10643
10644 /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
10645 instead last argument is __builtin_va_arg_pack (). Defer folding
10646 even in that case, until arguments are finalized. */
10647 if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
10648 {
10649 tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1));
10650 if (fndecl2
10651 && TREE_CODE (fndecl2) == FUNCTION_DECL
10652 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
10653 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
10654 return NULL_TREE;
10655 }
10656
c2f47e15 10657 /* FIXME: Don't use a list in this interface. */
10658 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
10659 return targetm.fold_builtin (fndecl, CALL_EXPR_ARGS (exp), ignore);
10660 else
10661 {
c2f47e15 10662 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
10663 {
10664 tree *args = CALL_EXPR_ARGP (exp);
10665 ret = fold_builtin_n (fndecl, args, nargs, ignore);
10666 }
10667 if (!ret)
10668 ret = fold_builtin_varargs (fndecl, exp, ignore);
10669 if (ret)
10670 {
10671 /* Propagate location information from original call to
10672 expansion of builtin. Otherwise things like
10673 maybe_emit_chk_warning, that operate on the expansion
10674 of a builtin, will use the wrong location information. */
10675 if (CAN_HAVE_LOCATION_P (exp) && EXPR_HAS_LOCATION (exp))
10676 {
10677 tree realret = ret;
10678 if (TREE_CODE (ret) == NOP_EXPR)
10679 realret = TREE_OPERAND (ret, 0);
10680 if (CAN_HAVE_LOCATION_P (realret)
10681 && !EXPR_HAS_LOCATION (realret))
10682 SET_EXPR_LOCATION (realret, EXPR_LOCATION (exp));
55c10931 10683 return realret;
c2f47e15 10684 }
10685 return ret;
10686 }
10687 }
4ee9c684 10688 }
c2f47e15 10689 return NULL_TREE;
10690}
10691
10692/* Conveniently construct a function call expression. FNDECL names the
10693 function to be called and ARGLIST is a TREE_LIST of arguments. */
10694
10695tree
10696build_function_call_expr (tree fndecl, tree arglist)
10697{
10698 tree fntype = TREE_TYPE (fndecl);
10699 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
d01f58f9 10700 int n = list_length (arglist);
10701 tree *argarray = (tree *) alloca (n * sizeof (tree));
10702 int i;
10703
10704 for (i = 0; i < n; i++, arglist = TREE_CHAIN (arglist))
10705 argarray[i] = TREE_VALUE (arglist);
10706 return fold_builtin_call_array (TREE_TYPE (fntype), fn, n, argarray);
c2f47e15 10707}
10708
10709/* Conveniently construct a function call expression. FNDECL names the
10710 function to be called, N is the number of arguments, and the "..."
10711 parameters are the argument expressions. */
10712
10713tree
10714build_call_expr (tree fndecl, int n, ...)
10715{
10716 va_list ap;
c2f47e15 10717 tree fntype = TREE_TYPE (fndecl);
10718 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
d01f58f9 10719 tree *argarray = (tree *) alloca (n * sizeof (tree));
10720 int i;
c2f47e15 10721
10722 va_start (ap, n);
d01f58f9 10723 for (i = 0; i < n; i++)
10724 argarray[i] = va_arg (ap, tree);
c2f47e15 10725 va_end (ap);
d01f58f9 10726 return fold_builtin_call_array (TREE_TYPE (fntype), fn, n, argarray);
4ee9c684 10727}
10728
c2f47e15 10729/* Construct a CALL_EXPR with type TYPE with FN as the function expression.
d01f58f9 10730 N arguments are passed in the array ARGARRAY. */
805e22b2 10731
10732tree
d01f58f9 10733fold_builtin_call_array (tree type,
10734 tree fn,
10735 int n,
10736 tree *argarray)
7e15618b 10737{
c2f47e15 10738 tree ret = NULL_TREE;
10739 int i;
10740 tree exp;
10741
10742 if (TREE_CODE (fn) == ADDR_EXPR)
10743 {
10744 tree fndecl = TREE_OPERAND (fn, 0);
10745 if (TREE_CODE (fndecl) == FUNCTION_DECL
10746 && DECL_BUILT_IN (fndecl))
10747 {
48dc2227 10748 /* If last argument is __builtin_va_arg_pack (), arguments to this
10749 function are not finalized yet. Defer folding until they are. */
10750 if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
10751 {
10752 tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
10753 if (fndecl2
10754 && TREE_CODE (fndecl2) == FUNCTION_DECL
10755 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
10756 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
10757 return build_call_array (type, fn, n, argarray);
10758 }
c2f47e15 10759 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
10760 {
10761 tree arglist = NULL_TREE;
d01f58f9 10762 for (i = n - 1; i >= 0; i--)
10763 arglist = tree_cons (NULL_TREE, argarray[i], arglist);
c2f47e15 10764 ret = targetm.fold_builtin (fndecl, arglist, false);
10765 if (ret)
10766 return ret;
10767 }
10768 else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
10769 {
10770 /* First try the transformations that don't require consing up
10771 an exp. */
d01f58f9 10772 ret = fold_builtin_n (fndecl, argarray, n, false);
c2f47e15 10773 if (ret)
10774 return ret;
10775 }
10776
10777 /* If we got this far, we need to build an exp. */
d01f58f9 10778 exp = build_call_array (type, fn, n, argarray);
c2f47e15 10779 ret = fold_builtin_varargs (fndecl, exp, false);
10780 return ret ? ret : exp;
10781 }
10782 }
10783
d01f58f9 10784 return build_call_array (type, fn, n, argarray);
c2f47e15 10785}
10786
10787/* Construct a new CALL_EXPR using the tail of the argument list of EXP
10788 along with N new arguments specified as the "..." parameters. SKIP
10789 is the number of arguments in EXP to be omitted. This function is used
10790 to do varargs-to-varargs transformations. */
10791
10792static tree
10793rewrite_call_expr (tree exp, int skip, tree fndecl, int n, ...)
10794{
10795 int oldnargs = call_expr_nargs (exp);
10796 int nargs = oldnargs - skip + n;
10797 tree fntype = TREE_TYPE (fndecl);
10798 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
10799 tree *buffer;
10800
10801 if (n > 0)
10802 {
10803 int i, j;
10804 va_list ap;
7e15618b 10805
364c0c59 10806 buffer = XALLOCAVEC (tree, nargs);
c2f47e15 10807 va_start (ap, n);
10808 for (i = 0; i < n; i++)
10809 buffer[i] = va_arg (ap, tree);
10810 va_end (ap);
10811 for (j = skip; j < oldnargs; j++, i++)
10812 buffer[i] = CALL_EXPR_ARG (exp, j);
10813 }
10814 else
10815 buffer = CALL_EXPR_ARGP (exp) + skip;
10816
10817 return fold (build_call_array (TREE_TYPE (exp), fn, nargs, buffer));
10818}
10819
10820/* Validate a single argument ARG against a tree code CODE representing
10821 a type. */
10822
10823static bool
b7bf20db 10824validate_arg (const_tree arg, enum tree_code code)
c2f47e15 10825{
10826 if (!arg)
10827 return false;
10828 else if (code == POINTER_TYPE)
10829 return POINTER_TYPE_P (TREE_TYPE (arg));
c7f617c2 10830 else if (code == INTEGER_TYPE)
10831 return INTEGRAL_TYPE_P (TREE_TYPE (arg));
c2f47e15 10832 return code == TREE_CODE (TREE_TYPE (arg));
7e15618b 10833}
0eb671f7 10834
10835/* This function validates the types of a function call argument list
c2f47e15 10836 against a specified list of tree_codes. If the last specifier is a 0,
10837 that represents an ellipses, otherwise the last specifier must be a
10838 VOID_TYPE. */
27d0c333 10839
c2f47e15 10840bool
b7bf20db 10841validate_arglist (const_tree callexpr, ...)
0eb671f7 10842{
0eb671f7 10843 enum tree_code code;
c2f47e15 10844 bool res = 0;
ee582a61 10845 va_list ap;
b7bf20db 10846 const_call_expr_arg_iterator iter;
10847 const_tree arg;
aecda0d6 10848
c2f47e15 10849 va_start (ap, callexpr);
b7bf20db 10850 init_const_call_expr_arg_iterator (callexpr, &iter);
0eb671f7 10851
f0ce3b1f 10852 do
0eb671f7 10853 {
f0ce3b1f 10854 code = va_arg (ap, enum tree_code);
10855 switch (code)
10856 {
10857 case 0:
10858 /* This signifies an ellipses, any further arguments are all ok. */
c2f47e15 10859 res = true;
f0ce3b1f 10860 goto end;
10861 case VOID_TYPE:
10862 /* This signifies an endlink, if no arguments remain, return
10863 true, otherwise return false. */
b7bf20db 10864 res = !more_const_call_expr_args_p (&iter);
f0ce3b1f 10865 goto end;
10866 default:
10867 /* If no parameters remain or the parameter's code does not
10868 match the specified code, return false. Otherwise continue
10869 checking any remaining arguments. */
b7bf20db 10870 arg = next_const_call_expr_arg (&iter);
c2f47e15 10871 if (!validate_arg (arg, code))
f0ce3b1f 10872 goto end;
10873 break;
10874 }
0eb671f7 10875 }
f0ce3b1f 10876 while (1);
0903457a 10877
10878 /* We need gotos here since we can only have one VA_CLOSE in a
10879 function. */
10880 end: ;
ee582a61 10881 va_end (ap);
0903457a 10882
10883 return res;
0eb671f7 10884}
fc2a2dcb 10885
fc2a2dcb 10886/* Default target-specific builtin expander that does nothing. */
10887
10888rtx
aecda0d6 10889default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
10890 rtx target ATTRIBUTE_UNUSED,
10891 rtx subtarget ATTRIBUTE_UNUSED,
10892 enum machine_mode mode ATTRIBUTE_UNUSED,
10893 int ignore ATTRIBUTE_UNUSED)
fc2a2dcb 10894{
10895 return NULL_RTX;
10896}
c7926a82 10897
01537105 10898/* Returns true is EXP represents data that would potentially reside
10899 in a readonly section. */
10900
10901static bool
10902readonly_data_expr (tree exp)
10903{
10904 STRIP_NOPS (exp);
10905
9ff0637e 10906 if (TREE_CODE (exp) != ADDR_EXPR)
10907 return false;
10908
10909 exp = get_base_address (TREE_OPERAND (exp, 0));
10910 if (!exp)
10911 return false;
10912
10913 /* Make sure we call decl_readonly_section only for trees it
10914 can handle (since it returns true for everything it doesn't
10915 understand). */
491e04ef 10916 if (TREE_CODE (exp) == STRING_CST
9ff0637e 10917 || TREE_CODE (exp) == CONSTRUCTOR
10918 || (TREE_CODE (exp) == VAR_DECL && TREE_STATIC (exp)))
10919 return decl_readonly_section (exp, 0);
01537105 10920 else
10921 return false;
10922}
4ee9c684 10923
c2f47e15 10924/* Simplify a call to the strstr builtin. S1 and S2 are the arguments
10925 to the call, and TYPE is its return type.
4ee9c684 10926
c2f47e15 10927 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10928 simplified form of the call as a tree.
10929
10930 The simplified form may be a constant or other expression which
10931 computes the same value, but in a more efficient manner (including
10932 calls to other builtin functions).
10933
10934 The call may contain arguments which need to be evaluated, but
10935 which are not useful to determine the result of the call. In
10936 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10937 COMPOUND_EXPR will be an argument which must be evaluated.
10938 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10939 COMPOUND_EXPR in the chain will contain the tree for the simplified
10940 form of the builtin function call. */
10941
10942static tree
c2f47e15 10943fold_builtin_strstr (tree s1, tree s2, tree type)
4ee9c684 10944{
c2f47e15 10945 if (!validate_arg (s1, POINTER_TYPE)
10946 || !validate_arg (s2, POINTER_TYPE))
10947 return NULL_TREE;
4ee9c684 10948 else
10949 {
4ee9c684 10950 tree fn;
10951 const char *p1, *p2;
10952
10953 p2 = c_getstr (s2);
10954 if (p2 == NULL)
c2f47e15 10955 return NULL_TREE;
4ee9c684 10956
10957 p1 = c_getstr (s1);
10958 if (p1 != NULL)
10959 {
10960 const char *r = strstr (p1, p2);
daa1d5f5 10961 tree tem;
4ee9c684 10962
4ee9c684 10963 if (r == NULL)
779b4c41 10964 return build_int_cst (TREE_TYPE (s1), 0);
c0c67e38 10965
10966 /* Return an offset into the constant string argument. */
0de36bdb 10967 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
10968 s1, size_int (r - p1));
daa1d5f5 10969 return fold_convert (type, tem);
4ee9c684 10970 }
10971
7efa231c 10972 /* The argument is const char *, and the result is char *, so we need
10973 a type conversion here to avoid a warning. */
4ee9c684 10974 if (p2[0] == '\0')
7efa231c 10975 return fold_convert (type, s1);
4ee9c684 10976
10977 if (p2[1] != '\0')
c2f47e15 10978 return NULL_TREE;
4ee9c684 10979
10980 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
10981 if (!fn)
c2f47e15 10982 return NULL_TREE;
4ee9c684 10983
10984 /* New argument list transforming strstr(s1, s2) to
10985 strchr(s1, s2[0]). */
c2f47e15 10986 return build_call_expr (fn, 2, s1, build_int_cst (NULL_TREE, p2[0]));
4ee9c684 10987 }
10988}
10989
c2f47e15 10990/* Simplify a call to the strchr builtin. S1 and S2 are the arguments to
10991 the call, and TYPE is its return type.
4ee9c684 10992
c2f47e15 10993 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10994 simplified form of the call as a tree.
10995
10996 The simplified form may be a constant or other expression which
10997 computes the same value, but in a more efficient manner (including
10998 calls to other builtin functions).
10999
11000 The call may contain arguments which need to be evaluated, but
11001 which are not useful to determine the result of the call. In
11002 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11003 COMPOUND_EXPR will be an argument which must be evaluated.
11004 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11005 COMPOUND_EXPR in the chain will contain the tree for the simplified
11006 form of the builtin function call. */
11007
11008static tree
c2f47e15 11009fold_builtin_strchr (tree s1, tree s2, tree type)
4ee9c684 11010{
c2f47e15 11011 if (!validate_arg (s1, POINTER_TYPE)
11012 || !validate_arg (s2, INTEGER_TYPE))
11013 return NULL_TREE;
4ee9c684 11014 else
11015 {
4ee9c684 11016 const char *p1;
11017
11018 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 11019 return NULL_TREE;
4ee9c684 11020
11021 p1 = c_getstr (s1);
11022 if (p1 != NULL)
11023 {
11024 char c;
11025 const char *r;
daa1d5f5 11026 tree tem;
4ee9c684 11027
11028 if (target_char_cast (s2, &c))
c2f47e15 11029 return NULL_TREE;
4ee9c684 11030
11031 r = strchr (p1, c);
11032
11033 if (r == NULL)
779b4c41 11034 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11035
11036 /* Return an offset into the constant string argument. */
0de36bdb 11037 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
11038 s1, size_int (r - p1));
daa1d5f5 11039 return fold_convert (type, tem);
4ee9c684 11040 }
c2f47e15 11041 return NULL_TREE;
4ee9c684 11042 }
11043}
11044
c2f47e15 11045/* Simplify a call to the strrchr builtin. S1 and S2 are the arguments to
11046 the call, and TYPE is its return type.
4ee9c684 11047
c2f47e15 11048 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11049 simplified form of the call as a tree.
11050
11051 The simplified form may be a constant or other expression which
11052 computes the same value, but in a more efficient manner (including
11053 calls to other builtin functions).
11054
11055 The call may contain arguments which need to be evaluated, but
11056 which are not useful to determine the result of the call. In
11057 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11058 COMPOUND_EXPR will be an argument which must be evaluated.
11059 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11060 COMPOUND_EXPR in the chain will contain the tree for the simplified
11061 form of the builtin function call. */
11062
11063static tree
c2f47e15 11064fold_builtin_strrchr (tree s1, tree s2, tree type)
4ee9c684 11065{
c2f47e15 11066 if (!validate_arg (s1, POINTER_TYPE)
11067 || !validate_arg (s2, INTEGER_TYPE))
11068 return NULL_TREE;
4ee9c684 11069 else
11070 {
4ee9c684 11071 tree fn;
11072 const char *p1;
11073
11074 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 11075 return NULL_TREE;
4ee9c684 11076
11077 p1 = c_getstr (s1);
11078 if (p1 != NULL)
11079 {
11080 char c;
11081 const char *r;
daa1d5f5 11082 tree tem;
4ee9c684 11083
11084 if (target_char_cast (s2, &c))
c2f47e15 11085 return NULL_TREE;
4ee9c684 11086
11087 r = strrchr (p1, c);
11088
11089 if (r == NULL)
779b4c41 11090 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11091
11092 /* Return an offset into the constant string argument. */
0de36bdb 11093 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
11094 s1, size_int (r - p1));
daa1d5f5 11095 return fold_convert (type, tem);
4ee9c684 11096 }
11097
11098 if (! integer_zerop (s2))
c2f47e15 11099 return NULL_TREE;
4ee9c684 11100
11101 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
11102 if (!fn)
c2f47e15 11103 return NULL_TREE;
4ee9c684 11104
11105 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
c2f47e15 11106 return build_call_expr (fn, 2, s1, s2);
4ee9c684 11107 }
11108}
11109
c2f47e15 11110/* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments
11111 to the call, and TYPE is its return type.
4ee9c684 11112
c2f47e15 11113 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11114 simplified form of the call as a tree.
11115
11116 The simplified form may be a constant or other expression which
11117 computes the same value, but in a more efficient manner (including
11118 calls to other builtin functions).
11119
11120 The call may contain arguments which need to be evaluated, but
11121 which are not useful to determine the result of the call. In
11122 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11123 COMPOUND_EXPR will be an argument which must be evaluated.
11124 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11125 COMPOUND_EXPR in the chain will contain the tree for the simplified
11126 form of the builtin function call. */
11127
11128static tree
c2f47e15 11129fold_builtin_strpbrk (tree s1, tree s2, tree type)
4ee9c684 11130{
c2f47e15 11131 if (!validate_arg (s1, POINTER_TYPE)
11132 || !validate_arg (s2, POINTER_TYPE))
11133 return NULL_TREE;
4ee9c684 11134 else
11135 {
4ee9c684 11136 tree fn;
11137 const char *p1, *p2;
11138
11139 p2 = c_getstr (s2);
11140 if (p2 == NULL)
c2f47e15 11141 return NULL_TREE;
4ee9c684 11142
11143 p1 = c_getstr (s1);
11144 if (p1 != NULL)
11145 {
11146 const char *r = strpbrk (p1, p2);
daa1d5f5 11147 tree tem;
4ee9c684 11148
11149 if (r == NULL)
779b4c41 11150 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11151
11152 /* Return an offset into the constant string argument. */
0de36bdb 11153 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
11154 s1, size_int (r - p1));
daa1d5f5 11155 return fold_convert (type, tem);
4ee9c684 11156 }
11157
11158 if (p2[0] == '\0')
05abc81b 11159 /* strpbrk(x, "") == NULL.
11160 Evaluate and ignore s1 in case it had side-effects. */
11161 return omit_one_operand (TREE_TYPE (s1), integer_zero_node, s1);
4ee9c684 11162
11163 if (p2[1] != '\0')
c2f47e15 11164 return NULL_TREE; /* Really call strpbrk. */
4ee9c684 11165
11166 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
11167 if (!fn)
c2f47e15 11168 return NULL_TREE;
4ee9c684 11169
11170 /* New argument list transforming strpbrk(s1, s2) to
11171 strchr(s1, s2[0]). */
c2f47e15 11172 return build_call_expr (fn, 2, s1, build_int_cst (NULL_TREE, p2[0]));
4ee9c684 11173 }
11174}
11175
c2f47e15 11176/* Simplify a call to the strcat builtin. DST and SRC are the arguments
11177 to the call.
4ee9c684 11178
c2f47e15 11179 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11180 simplified form of the call as a tree.
11181
11182 The simplified form may be a constant or other expression which
11183 computes the same value, but in a more efficient manner (including
11184 calls to other builtin functions).
11185
11186 The call may contain arguments which need to be evaluated, but
11187 which are not useful to determine the result of the call. In
11188 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11189 COMPOUND_EXPR will be an argument which must be evaluated.
11190 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11191 COMPOUND_EXPR in the chain will contain the tree for the simplified
11192 form of the builtin function call. */
11193
11194static tree
c2f47e15 11195fold_builtin_strcat (tree dst, tree src)
4ee9c684 11196{
c2f47e15 11197 if (!validate_arg (dst, POINTER_TYPE)
11198 || !validate_arg (src, POINTER_TYPE))
11199 return NULL_TREE;
4ee9c684 11200 else
11201 {
4ee9c684 11202 const char *p = c_getstr (src);
11203
11204 /* If the string length is zero, return the dst parameter. */
11205 if (p && *p == '\0')
11206 return dst;
11207
c2f47e15 11208 return NULL_TREE;
4ee9c684 11209 }
11210}
11211
c2f47e15 11212/* Simplify a call to the strncat builtin. DST, SRC, and LEN are the
11213 arguments to the call.
4ee9c684 11214
c2f47e15 11215 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11216 simplified form of the call as a tree.
11217
11218 The simplified form may be a constant or other expression which
11219 computes the same value, but in a more efficient manner (including
11220 calls to other builtin functions).
11221
11222 The call may contain arguments which need to be evaluated, but
11223 which are not useful to determine the result of the call. In
11224 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11225 COMPOUND_EXPR will be an argument which must be evaluated.
11226 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11227 COMPOUND_EXPR in the chain will contain the tree for the simplified
11228 form of the builtin function call. */
11229
11230static tree
c2f47e15 11231fold_builtin_strncat (tree dst, tree src, tree len)
4ee9c684 11232{
c2f47e15 11233 if (!validate_arg (dst, POINTER_TYPE)
11234 || !validate_arg (src, POINTER_TYPE)
11235 || !validate_arg (len, INTEGER_TYPE))
11236 return NULL_TREE;
4ee9c684 11237 else
11238 {
4ee9c684 11239 const char *p = c_getstr (src);
11240
11241 /* If the requested length is zero, or the src parameter string
0a39fd54 11242 length is zero, return the dst parameter. */
4ee9c684 11243 if (integer_zerop (len) || (p && *p == '\0'))
a0c938f0 11244 return omit_two_operands (TREE_TYPE (dst), dst, src, len);
4ee9c684 11245
11246 /* If the requested len is greater than or equal to the string
a0c938f0 11247 length, call strcat. */
4ee9c684 11248 if (TREE_CODE (len) == INTEGER_CST && p
11249 && compare_tree_int (len, strlen (p)) >= 0)
11250 {
4ee9c684 11251 tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
11252
11253 /* If the replacement _DECL isn't initialized, don't do the
11254 transformation. */
11255 if (!fn)
c2f47e15 11256 return NULL_TREE;
4ee9c684 11257
c2f47e15 11258 return build_call_expr (fn, 2, dst, src);
4ee9c684 11259 }
c2f47e15 11260 return NULL_TREE;
4ee9c684 11261 }
11262}
11263
c2f47e15 11264/* Simplify a call to the strspn builtin. S1 and S2 are the arguments
11265 to the call.
4ee9c684 11266
c2f47e15 11267 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11268 simplified form of the call as a tree.
11269
11270 The simplified form may be a constant or other expression which
11271 computes the same value, but in a more efficient manner (including
11272 calls to other builtin functions).
11273
11274 The call may contain arguments which need to be evaluated, but
11275 which are not useful to determine the result of the call. In
11276 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11277 COMPOUND_EXPR will be an argument which must be evaluated.
11278 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11279 COMPOUND_EXPR in the chain will contain the tree for the simplified
11280 form of the builtin function call. */
11281
11282static tree
c2f47e15 11283fold_builtin_strspn (tree s1, tree s2)
4ee9c684 11284{
c2f47e15 11285 if (!validate_arg (s1, POINTER_TYPE)
11286 || !validate_arg (s2, POINTER_TYPE))
11287 return NULL_TREE;
4ee9c684 11288 else
11289 {
4ee9c684 11290 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11291
11292 /* If both arguments are constants, evaluate at compile-time. */
11293 if (p1 && p2)
11294 {
11295 const size_t r = strspn (p1, p2);
11296 return size_int (r);
11297 }
11298
c2f47e15 11299 /* If either argument is "", return NULL_TREE. */
4ee9c684 11300 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9bc9f15f 11301 /* Evaluate and ignore both arguments in case either one has
11302 side-effects. */
11303 return omit_two_operands (integer_type_node, integer_zero_node,
11304 s1, s2);
c2f47e15 11305 return NULL_TREE;
4ee9c684 11306 }
11307}
11308
c2f47e15 11309/* Simplify a call to the strcspn builtin. S1 and S2 are the arguments
11310 to the call.
4ee9c684 11311
c2f47e15 11312 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11313 simplified form of the call as a tree.
11314
11315 The simplified form may be a constant or other expression which
11316 computes the same value, but in a more efficient manner (including
11317 calls to other builtin functions).
11318
11319 The call may contain arguments which need to be evaluated, but
11320 which are not useful to determine the result of the call. In
11321 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11322 COMPOUND_EXPR will be an argument which must be evaluated.
11323 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11324 COMPOUND_EXPR in the chain will contain the tree for the simplified
11325 form of the builtin function call. */
11326
11327static tree
c2f47e15 11328fold_builtin_strcspn (tree s1, tree s2)
4ee9c684 11329{
c2f47e15 11330 if (!validate_arg (s1, POINTER_TYPE)
11331 || !validate_arg (s2, POINTER_TYPE))
11332 return NULL_TREE;
4ee9c684 11333 else
11334 {
4ee9c684 11335 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11336
11337 /* If both arguments are constants, evaluate at compile-time. */
11338 if (p1 && p2)
11339 {
11340 const size_t r = strcspn (p1, p2);
11341 return size_int (r);
11342 }
11343
c2f47e15 11344 /* If the first argument is "", return NULL_TREE. */
4ee9c684 11345 if (p1 && *p1 == '\0')
11346 {
11347 /* Evaluate and ignore argument s2 in case it has
11348 side-effects. */
05abc81b 11349 return omit_one_operand (integer_type_node,
11350 integer_zero_node, s2);
4ee9c684 11351 }
11352
11353 /* If the second argument is "", return __builtin_strlen(s1). */
11354 if (p2 && *p2 == '\0')
11355 {
c2f47e15 11356 tree fn = implicit_built_in_decls[BUILT_IN_STRLEN];
4ee9c684 11357
11358 /* If the replacement _DECL isn't initialized, don't do the
11359 transformation. */
11360 if (!fn)
c2f47e15 11361 return NULL_TREE;
4ee9c684 11362
c2f47e15 11363 return build_call_expr (fn, 1, s1);
4ee9c684 11364 }
c2f47e15 11365 return NULL_TREE;
4ee9c684 11366 }
11367}
11368
c2f47e15 11369/* Fold a call to the fputs builtin. ARG0 and ARG1 are the arguments
11370 to the call. IGNORE is true if the value returned
f0613857 11371 by the builtin will be ignored. UNLOCKED is true is true if this
11372 actually a call to fputs_unlocked. If LEN in non-NULL, it represents
11373 the known length of the string. Return NULL_TREE if no simplification
11374 was possible. */
4ee9c684 11375
11376tree
c2f47e15 11377fold_builtin_fputs (tree arg0, tree arg1, bool ignore, bool unlocked, tree len)
4ee9c684 11378{
6d77ed92 11379 /* If we're using an unlocked function, assume the other unlocked
11380 functions exist explicitly. */
11381 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
4ee9c684 11382 : implicit_built_in_decls[BUILT_IN_FPUTC];
6d77ed92 11383 tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
4ee9c684 11384 : implicit_built_in_decls[BUILT_IN_FWRITE];
11385
c403edd4 11386 /* If the return value is used, don't do the transformation. */
11387 if (!ignore)
c2f47e15 11388 return NULL_TREE;
4ee9c684 11389
11390 /* Verify the arguments in the original call. */
c2f47e15 11391 if (!validate_arg (arg0, POINTER_TYPE)
11392 || !validate_arg (arg1, POINTER_TYPE))
11393 return NULL_TREE;
4ee9c684 11394
f0613857 11395 if (! len)
c2f47e15 11396 len = c_strlen (arg0, 0);
4ee9c684 11397
11398 /* Get the length of the string passed to fputs. If the length
11399 can't be determined, punt. */
11400 if (!len
11401 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 11402 return NULL_TREE;
4ee9c684 11403
11404 switch (compare_tree_int (len, 1))
11405 {
11406 case -1: /* length is 0, delete the call entirely . */
c2f47e15 11407 return omit_one_operand (integer_type_node, integer_zero_node, arg1);;
05abc81b 11408
4ee9c684 11409 case 0: /* length is 1, call fputc. */
11410 {
c2f47e15 11411 const char *p = c_getstr (arg0);
4ee9c684 11412
11413 if (p != NULL)
11414 {
c2f47e15 11415 if (fn_fputc)
11416 return build_call_expr (fn_fputc, 2,
11417 build_int_cst (NULL_TREE, p[0]), arg1);
11418 else
11419 return NULL_TREE;
4ee9c684 11420 }
11421 }
11422 /* FALLTHROUGH */
11423 case 1: /* length is greater than 1, call fwrite. */
11424 {
0bed3869 11425 /* If optimizing for size keep fputs. */
4ee9c684 11426 if (optimize_size)
c2f47e15 11427 return NULL_TREE;
4ee9c684 11428 /* New argument list transforming fputs(string, stream) to
11429 fwrite(string, 1, len, stream). */
c2f47e15 11430 if (fn_fwrite)
11431 return build_call_expr (fn_fwrite, 4, arg0, size_one_node, len, arg1);
11432 else
11433 return NULL_TREE;
4ee9c684 11434 }
11435 default:
64db345d 11436 gcc_unreachable ();
4ee9c684 11437 }
c2f47e15 11438 return NULL_TREE;
4ee9c684 11439}
11440
c2f47e15 11441/* Fold the next_arg or va_start call EXP. Returns true if there was an error
743b0c6a 11442 produced. False otherwise. This is done so that we don't output the error
11443 or warning twice or three times. */
11444bool
c2f47e15 11445fold_builtin_next_arg (tree exp, bool va_start_p)
4ee9c684 11446{
11447 tree fntype = TREE_TYPE (current_function_decl);
c2f47e15 11448 int nargs = call_expr_nargs (exp);
11449 tree arg;
4ee9c684 11450
11451 if (TYPE_ARG_TYPES (fntype) == 0
11452 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
11453 == void_type_node))
743b0c6a 11454 {
11455 error ("%<va_start%> used in function with fixed args");
11456 return true;
11457 }
c2f47e15 11458
11459 if (va_start_p)
79012a9d 11460 {
c2f47e15 11461 if (va_start_p && (nargs != 2))
11462 {
11463 error ("wrong number of arguments to function %<va_start%>");
11464 return true;
11465 }
11466 arg = CALL_EXPR_ARG (exp, 1);
79012a9d 11467 }
11468 /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
11469 when we checked the arguments and if needed issued a warning. */
c2f47e15 11470 else
4ee9c684 11471 {
c2f47e15 11472 if (nargs == 0)
11473 {
11474 /* Evidently an out of date version of <stdarg.h>; can't validate
11475 va_start's second argument, but can still work as intended. */
11476 warning (0, "%<__builtin_next_arg%> called without an argument");
11477 return true;
11478 }
11479 else if (nargs > 1)
a0c938f0 11480 {
c2f47e15 11481 error ("wrong number of arguments to function %<__builtin_next_arg%>");
a0c938f0 11482 return true;
11483 }
c2f47e15 11484 arg = CALL_EXPR_ARG (exp, 0);
11485 }
11486
11487 /* We destructively modify the call to be __builtin_va_start (ap, 0)
11488 or __builtin_next_arg (0) the first time we see it, after checking
11489 the arguments and if needed issuing a warning. */
11490 if (!integer_zerop (arg))
11491 {
11492 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
79012a9d 11493
4ee9c684 11494 /* Strip off all nops for the sake of the comparison. This
11495 is not quite the same as STRIP_NOPS. It does more.
11496 We must also strip off INDIRECT_EXPR for C++ reference
11497 parameters. */
72dd6141 11498 while (CONVERT_EXPR_P (arg)
4ee9c684 11499 || TREE_CODE (arg) == INDIRECT_REF)
11500 arg = TREE_OPERAND (arg, 0);
11501 if (arg != last_parm)
a0c938f0 11502 {
b08cf617 11503 /* FIXME: Sometimes with the tree optimizers we can get the
11504 not the last argument even though the user used the last
11505 argument. We just warn and set the arg to be the last
11506 argument so that we will get wrong-code because of
11507 it. */
c3ceba8e 11508 warning (0, "second parameter of %<va_start%> not last named argument");
743b0c6a 11509 }
79012a9d 11510 /* We want to verify the second parameter just once before the tree
a0c938f0 11511 optimizers are run and then avoid keeping it in the tree,
11512 as otherwise we could warn even for correct code like:
11513 void foo (int i, ...)
11514 { va_list ap; i++; va_start (ap, i); va_end (ap); } */
c2f47e15 11515 if (va_start_p)
11516 CALL_EXPR_ARG (exp, 1) = integer_zero_node;
11517 else
11518 CALL_EXPR_ARG (exp, 0) = integer_zero_node;
743b0c6a 11519 }
11520 return false;
4ee9c684 11521}
11522
11523
c2f47e15 11524/* Simplify a call to the sprintf builtin with arguments DEST, FMT, and ORIG.
11525 ORIG may be null if this is a 2-argument call. We don't attempt to
11526 simplify calls with more than 3 arguments.
4ee9c684 11527
c2f47e15 11528 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11529 simplified form of the call as a tree. If IGNORED is true, it means that
11530 the caller does not use the returned value of the function. */
11531
11532static tree
c2f47e15 11533fold_builtin_sprintf (tree dest, tree fmt, tree orig, int ignored)
4ee9c684 11534{
c2f47e15 11535 tree call, retval;
4ee9c684 11536 const char *fmt_str = NULL;
11537
11538 /* Verify the required arguments in the original call. We deal with two
11539 types of sprintf() calls: 'sprintf (str, fmt)' and
11540 'sprintf (dest, "%s", orig)'. */
c2f47e15 11541 if (!validate_arg (dest, POINTER_TYPE)
11542 || !validate_arg (fmt, POINTER_TYPE))
11543 return NULL_TREE;
11544 if (orig && !validate_arg (orig, POINTER_TYPE))
4ee9c684 11545 return NULL_TREE;
4ee9c684 11546
11547 /* Check whether the format is a literal string constant. */
11548 fmt_str = c_getstr (fmt);
11549 if (fmt_str == NULL)
11550 return NULL_TREE;
11551
11552 call = NULL_TREE;
11553 retval = NULL_TREE;
11554
d4473c84 11555 if (!init_target_chars ())
c2f47e15 11556 return NULL_TREE;
99eabcc1 11557
4ee9c684 11558 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 11559 if (strchr (fmt_str, target_percent) == NULL)
4ee9c684 11560 {
11561 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11562
11563 if (!fn)
11564 return NULL_TREE;
11565
72dfb3f2 11566 /* Don't optimize sprintf (buf, "abc", ptr++). */
c2f47e15 11567 if (orig)
72dfb3f2 11568 return NULL_TREE;
11569
4ee9c684 11570 /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
11571 'format' is known to contain no % formats. */
c2f47e15 11572 call = build_call_expr (fn, 2, dest, fmt);
4ee9c684 11573 if (!ignored)
7016c612 11574 retval = build_int_cst (NULL_TREE, strlen (fmt_str));
4ee9c684 11575 }
11576
11577 /* If the format is "%s", use strcpy if the result isn't used. */
99eabcc1 11578 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
4ee9c684 11579 {
c2f47e15 11580 tree fn;
4ee9c684 11581 fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11582
11583 if (!fn)
11584 return NULL_TREE;
11585
72dfb3f2 11586 /* Don't crash on sprintf (str1, "%s"). */
c2f47e15 11587 if (!orig)
72dfb3f2 11588 return NULL_TREE;
11589
4ee9c684 11590 /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2). */
4ee9c684 11591 if (!ignored)
11592 {
11593 retval = c_strlen (orig, 1);
11594 if (!retval || TREE_CODE (retval) != INTEGER_CST)
11595 return NULL_TREE;
11596 }
c2f47e15 11597 call = build_call_expr (fn, 2, dest, orig);
4ee9c684 11598 }
11599
11600 if (call && retval)
11601 {
e3b560a6 11602 retval = fold_convert
4ee9c684 11603 (TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])),
11604 retval);
05abc81b 11605 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
4ee9c684 11606 }
11607 else
11608 return call;
11609}
0a39fd54 11610
c2f47e15 11611/* Expand a call EXP to __builtin_object_size. */
0a39fd54 11612
11613rtx
11614expand_builtin_object_size (tree exp)
11615{
11616 tree ost;
11617 int object_size_type;
11618 tree fndecl = get_callee_fndecl (exp);
0a39fd54 11619
c2f47e15 11620 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
0a39fd54 11621 {
b8c23db3 11622 error ("%Kfirst argument of %D must be a pointer, second integer constant",
11623 exp, fndecl);
0a39fd54 11624 expand_builtin_trap ();
11625 return const0_rtx;
11626 }
11627
c2f47e15 11628 ost = CALL_EXPR_ARG (exp, 1);
0a39fd54 11629 STRIP_NOPS (ost);
11630
11631 if (TREE_CODE (ost) != INTEGER_CST
11632 || tree_int_cst_sgn (ost) < 0
11633 || compare_tree_int (ost, 3) > 0)
11634 {
b8c23db3 11635 error ("%Klast argument of %D is not integer constant between 0 and 3",
11636 exp, fndecl);
0a39fd54 11637 expand_builtin_trap ();
11638 return const0_rtx;
11639 }
11640
11641 object_size_type = tree_low_cst (ost, 0);
11642
11643 return object_size_type < 2 ? constm1_rtx : const0_rtx;
11644}
11645
11646/* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
11647 FCODE is the BUILT_IN_* to use.
c2f47e15 11648 Return NULL_RTX if we failed; the caller should emit a normal call,
0a39fd54 11649 otherwise try to get the result in TARGET, if convenient (and in
11650 mode MODE if that's convenient). */
11651
11652static rtx
11653expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
11654 enum built_in_function fcode)
11655{
0a39fd54 11656 tree dest, src, len, size;
11657
c2f47e15 11658 if (!validate_arglist (exp,
0a39fd54 11659 POINTER_TYPE,
11660 fcode == BUILT_IN_MEMSET_CHK
11661 ? INTEGER_TYPE : POINTER_TYPE,
11662 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
c2f47e15 11663 return NULL_RTX;
0a39fd54 11664
c2f47e15 11665 dest = CALL_EXPR_ARG (exp, 0);
11666 src = CALL_EXPR_ARG (exp, 1);
11667 len = CALL_EXPR_ARG (exp, 2);
11668 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11669
11670 if (! host_integerp (size, 1))
c2f47e15 11671 return NULL_RTX;
0a39fd54 11672
11673 if (host_integerp (len, 1) || integer_all_onesp (size))
11674 {
11675 tree fn;
11676
11677 if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
11678 {
b8c23db3 11679 warning (0, "%Kcall to %D will always overflow destination buffer",
11680 exp, get_callee_fndecl (exp));
c2f47e15 11681 return NULL_RTX;
0a39fd54 11682 }
11683
0a39fd54 11684 fn = NULL_TREE;
11685 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
11686 mem{cpy,pcpy,move,set} is available. */
11687 switch (fcode)
11688 {
11689 case BUILT_IN_MEMCPY_CHK:
11690 fn = built_in_decls[BUILT_IN_MEMCPY];
11691 break;
11692 case BUILT_IN_MEMPCPY_CHK:
11693 fn = built_in_decls[BUILT_IN_MEMPCPY];
11694 break;
11695 case BUILT_IN_MEMMOVE_CHK:
11696 fn = built_in_decls[BUILT_IN_MEMMOVE];
11697 break;
11698 case BUILT_IN_MEMSET_CHK:
11699 fn = built_in_decls[BUILT_IN_MEMSET];
11700 break;
11701 default:
11702 break;
11703 }
11704
11705 if (! fn)
c2f47e15 11706 return NULL_RTX;
0a39fd54 11707
c2f47e15 11708 fn = build_call_expr (fn, 3, dest, src, len);
6d54e886 11709 STRIP_TYPE_NOPS (fn);
11710 while (TREE_CODE (fn) == COMPOUND_EXPR)
11711 {
11712 expand_expr (TREE_OPERAND (fn, 0), const0_rtx, VOIDmode,
11713 EXPAND_NORMAL);
11714 fn = TREE_OPERAND (fn, 1);
11715 }
0a39fd54 11716 if (TREE_CODE (fn) == CALL_EXPR)
11717 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
11718 return expand_expr (fn, target, mode, EXPAND_NORMAL);
11719 }
11720 else if (fcode == BUILT_IN_MEMSET_CHK)
c2f47e15 11721 return NULL_RTX;
0a39fd54 11722 else
11723 {
11724 unsigned int dest_align
11725 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
11726
11727 /* If DEST is not a pointer type, call the normal function. */
11728 if (dest_align == 0)
c2f47e15 11729 return NULL_RTX;
0a39fd54 11730
11731 /* If SRC and DEST are the same (and not volatile), do nothing. */
11732 if (operand_equal_p (src, dest, 0))
11733 {
11734 tree expr;
11735
11736 if (fcode != BUILT_IN_MEMPCPY_CHK)
11737 {
11738 /* Evaluate and ignore LEN in case it has side-effects. */
11739 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
11740 return expand_expr (dest, target, mode, EXPAND_NORMAL);
11741 }
11742
0de36bdb 11743 expr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
0a39fd54 11744 return expand_expr (expr, target, mode, EXPAND_NORMAL);
11745 }
11746
11747 /* __memmove_chk special case. */
11748 if (fcode == BUILT_IN_MEMMOVE_CHK)
11749 {
11750 unsigned int src_align
11751 = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
11752
11753 if (src_align == 0)
c2f47e15 11754 return NULL_RTX;
0a39fd54 11755
11756 /* If src is categorized for a readonly section we can use
11757 normal __memcpy_chk. */
11758 if (readonly_data_expr (src))
11759 {
11760 tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
11761 if (!fn)
c2f47e15 11762 return NULL_RTX;
11763 fn = build_call_expr (fn, 4, dest, src, len, size);
6d54e886 11764 STRIP_TYPE_NOPS (fn);
11765 while (TREE_CODE (fn) == COMPOUND_EXPR)
11766 {
11767 expand_expr (TREE_OPERAND (fn, 0), const0_rtx, VOIDmode,
11768 EXPAND_NORMAL);
11769 fn = TREE_OPERAND (fn, 1);
11770 }
0a39fd54 11771 if (TREE_CODE (fn) == CALL_EXPR)
11772 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
11773 return expand_expr (fn, target, mode, EXPAND_NORMAL);
11774 }
11775 }
c2f47e15 11776 return NULL_RTX;
0a39fd54 11777 }
11778}
11779
11780/* Emit warning if a buffer overflow is detected at compile time. */
11781
11782static void
11783maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
11784{
c2f47e15 11785 int is_strlen = 0;
0a39fd54 11786 tree len, size;
0a39fd54 11787
11788 switch (fcode)
11789 {
11790 case BUILT_IN_STRCPY_CHK:
11791 case BUILT_IN_STPCPY_CHK:
11792 /* For __strcat_chk the warning will be emitted only if overflowing
11793 by at least strlen (dest) + 1 bytes. */
11794 case BUILT_IN_STRCAT_CHK:
c2f47e15 11795 len = CALL_EXPR_ARG (exp, 1);
11796 size = CALL_EXPR_ARG (exp, 2);
0a39fd54 11797 is_strlen = 1;
11798 break;
b356dfef 11799 case BUILT_IN_STRNCAT_CHK:
0a39fd54 11800 case BUILT_IN_STRNCPY_CHK:
c2f47e15 11801 len = CALL_EXPR_ARG (exp, 2);
11802 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11803 break;
11804 case BUILT_IN_SNPRINTF_CHK:
11805 case BUILT_IN_VSNPRINTF_CHK:
c2f47e15 11806 len = CALL_EXPR_ARG (exp, 1);
11807 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11808 break;
11809 default:
11810 gcc_unreachable ();
11811 }
11812
0a39fd54 11813 if (!len || !size)
11814 return;
11815
0a39fd54 11816 if (! host_integerp (size, 1) || integer_all_onesp (size))
11817 return;
11818
11819 if (is_strlen)
11820 {
11821 len = c_strlen (len, 1);
11822 if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
11823 return;
11824 }
b356dfef 11825 else if (fcode == BUILT_IN_STRNCAT_CHK)
11826 {
c2f47e15 11827 tree src = CALL_EXPR_ARG (exp, 1);
b356dfef 11828 if (! src || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
11829 return;
11830 src = c_strlen (src, 1);
11831 if (! src || ! host_integerp (src, 1))
11832 {
b8c23db3 11833 warning (0, "%Kcall to %D might overflow destination buffer",
11834 exp, get_callee_fndecl (exp));
b356dfef 11835 return;
11836 }
11837 else if (tree_int_cst_lt (src, size))
11838 return;
11839 }
0a39fd54 11840 else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
11841 return;
11842
b8c23db3 11843 warning (0, "%Kcall to %D will always overflow destination buffer",
11844 exp, get_callee_fndecl (exp));
0a39fd54 11845}
11846
11847/* Emit warning if a buffer overflow is detected at compile time
11848 in __sprintf_chk/__vsprintf_chk calls. */
11849
11850static void
11851maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
11852{
0a39fd54 11853 tree dest, size, len, fmt, flag;
11854 const char *fmt_str;
c2f47e15 11855 int nargs = call_expr_nargs (exp);
0a39fd54 11856
11857 /* Verify the required arguments in the original call. */
c2f47e15 11858
11859 if (nargs < 4)
0a39fd54 11860 return;
c2f47e15 11861 dest = CALL_EXPR_ARG (exp, 0);
11862 flag = CALL_EXPR_ARG (exp, 1);
11863 size = CALL_EXPR_ARG (exp, 2);
11864 fmt = CALL_EXPR_ARG (exp, 3);
0a39fd54 11865
11866 if (! host_integerp (size, 1) || integer_all_onesp (size))
11867 return;
11868
11869 /* Check whether the format is a literal string constant. */
11870 fmt_str = c_getstr (fmt);
11871 if (fmt_str == NULL)
11872 return;
11873
d4473c84 11874 if (!init_target_chars ())
99eabcc1 11875 return;
11876
0a39fd54 11877 /* If the format doesn't contain % args or %%, we know its size. */
99eabcc1 11878 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 11879 len = build_int_cstu (size_type_node, strlen (fmt_str));
11880 /* If the format is "%s" and first ... argument is a string literal,
11881 we know it too. */
c2f47e15 11882 else if (fcode == BUILT_IN_SPRINTF_CHK
11883 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 11884 {
11885 tree arg;
11886
c2f47e15 11887 if (nargs < 5)
0a39fd54 11888 return;
c2f47e15 11889 arg = CALL_EXPR_ARG (exp, 4);
0a39fd54 11890 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
11891 return;
11892
11893 len = c_strlen (arg, 1);
11894 if (!len || ! host_integerp (len, 1))
11895 return;
11896 }
11897 else
11898 return;
11899
11900 if (! tree_int_cst_lt (len, size))
11901 {
b8c23db3 11902 warning (0, "%Kcall to %D will always overflow destination buffer",
11903 exp, get_callee_fndecl (exp));
0a39fd54 11904 }
11905}
11906
c2f47e15 11907/* Fold a call to __builtin_object_size with arguments PTR and OST,
11908 if possible. */
0a39fd54 11909
11910tree
c2f47e15 11911fold_builtin_object_size (tree ptr, tree ost)
0a39fd54 11912{
c2f47e15 11913 tree ret = NULL_TREE;
0a39fd54 11914 int object_size_type;
11915
c2f47e15 11916 if (!validate_arg (ptr, POINTER_TYPE)
11917 || !validate_arg (ost, INTEGER_TYPE))
11918 return NULL_TREE;
0a39fd54 11919
0a39fd54 11920 STRIP_NOPS (ost);
11921
11922 if (TREE_CODE (ost) != INTEGER_CST
11923 || tree_int_cst_sgn (ost) < 0
11924 || compare_tree_int (ost, 3) > 0)
c2f47e15 11925 return NULL_TREE;
0a39fd54 11926
11927 object_size_type = tree_low_cst (ost, 0);
11928
11929 /* __builtin_object_size doesn't evaluate side-effects in its arguments;
11930 if there are any side-effects, it returns (size_t) -1 for types 0 and 1
11931 and (size_t) 0 for types 2 and 3. */
11932 if (TREE_SIDE_EFFECTS (ptr))
697bbc3f 11933 return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
0a39fd54 11934
11935 if (TREE_CODE (ptr) == ADDR_EXPR)
11936 ret = build_int_cstu (size_type_node,
697bbc3f 11937 compute_builtin_object_size (ptr, object_size_type));
0a39fd54 11938
11939 else if (TREE_CODE (ptr) == SSA_NAME)
11940 {
11941 unsigned HOST_WIDE_INT bytes;
11942
11943 /* If object size is not known yet, delay folding until
11944 later. Maybe subsequent passes will help determining
11945 it. */
11946 bytes = compute_builtin_object_size (ptr, object_size_type);
11947 if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2
11948 ? -1 : 0))
11949 ret = build_int_cstu (size_type_node, bytes);
11950 }
11951
11952 if (ret)
11953 {
697bbc3f 11954 unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (ret);
11955 HOST_WIDE_INT high = TREE_INT_CST_HIGH (ret);
11956 if (fit_double_type (low, high, &low, &high, TREE_TYPE (ret)))
11957 ret = NULL_TREE;
0a39fd54 11958 }
11959
11960 return ret;
11961}
11962
11963/* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
c2f47e15 11964 DEST, SRC, LEN, and SIZE are the arguments to the call.
0a39fd54 11965 IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_*
11966 code of the builtin. If MAXLEN is not NULL, it is maximum length
11967 passed as third argument. */
11968
11969tree
c2f47e15 11970fold_builtin_memory_chk (tree fndecl,
11971 tree dest, tree src, tree len, tree size,
11972 tree maxlen, bool ignore,
0a39fd54 11973 enum built_in_function fcode)
11974{
c2f47e15 11975 tree fn;
0a39fd54 11976
c2f47e15 11977 if (!validate_arg (dest, POINTER_TYPE)
11978 || !validate_arg (src,
11979 (fcode == BUILT_IN_MEMSET_CHK
11980 ? INTEGER_TYPE : POINTER_TYPE))
11981 || !validate_arg (len, INTEGER_TYPE)
11982 || !validate_arg (size, INTEGER_TYPE))
11983 return NULL_TREE;
0a39fd54 11984
11985 /* If SRC and DEST are the same (and not volatile), return DEST
11986 (resp. DEST+LEN for __mempcpy_chk). */
11987 if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
11988 {
11989 if (fcode != BUILT_IN_MEMPCPY_CHK)
11990 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
11991 else
11992 {
0de36bdb 11993 tree temp = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
0a39fd54 11994 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), temp);
11995 }
11996 }
11997
11998 if (! host_integerp (size, 1))
c2f47e15 11999 return NULL_TREE;
0a39fd54 12000
12001 if (! integer_all_onesp (size))
12002 {
12003 if (! host_integerp (len, 1))
12004 {
12005 /* If LEN is not constant, try MAXLEN too.
12006 For MAXLEN only allow optimizing into non-_ocs function
12007 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12008 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
12009 {
12010 if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
12011 {
12012 /* (void) __mempcpy_chk () can be optimized into
12013 (void) __memcpy_chk (). */
12014 fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
12015 if (!fn)
c2f47e15 12016 return NULL_TREE;
0a39fd54 12017
c2f47e15 12018 return build_call_expr (fn, 4, dest, src, len, size);
0a39fd54 12019 }
c2f47e15 12020 return NULL_TREE;
0a39fd54 12021 }
0a39fd54 12022 }
ad89623c 12023 else
12024 maxlen = len;
0a39fd54 12025
ad89623c 12026 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12027 return NULL_TREE;
0a39fd54 12028 }
12029
0a39fd54 12030 fn = NULL_TREE;
12031 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
12032 mem{cpy,pcpy,move,set} is available. */
12033 switch (fcode)
12034 {
12035 case BUILT_IN_MEMCPY_CHK:
12036 fn = built_in_decls[BUILT_IN_MEMCPY];
12037 break;
12038 case BUILT_IN_MEMPCPY_CHK:
12039 fn = built_in_decls[BUILT_IN_MEMPCPY];
12040 break;
12041 case BUILT_IN_MEMMOVE_CHK:
12042 fn = built_in_decls[BUILT_IN_MEMMOVE];
12043 break;
12044 case BUILT_IN_MEMSET_CHK:
12045 fn = built_in_decls[BUILT_IN_MEMSET];
12046 break;
12047 default:
12048 break;
12049 }
12050
12051 if (!fn)
c2f47e15 12052 return NULL_TREE;
0a39fd54 12053
c2f47e15 12054 return build_call_expr (fn, 3, dest, src, len);
0a39fd54 12055}
12056
12057/* Fold a call to the __st[rp]cpy_chk builtin.
c2f47e15 12058 DEST, SRC, and SIZE are the arguments to the call.
12059 IGNORE is true if return value can be ignored. FCODE is the BUILT_IN_*
0a39fd54 12060 code of the builtin. If MAXLEN is not NULL, it is maximum length of
12061 strings passed as second argument. */
12062
12063tree
c2f47e15 12064fold_builtin_stxcpy_chk (tree fndecl, tree dest, tree src, tree size,
12065 tree maxlen, bool ignore,
0a39fd54 12066 enum built_in_function fcode)
12067{
c2f47e15 12068 tree len, fn;
0a39fd54 12069
c2f47e15 12070 if (!validate_arg (dest, POINTER_TYPE)
12071 || !validate_arg (src, POINTER_TYPE)
12072 || !validate_arg (size, INTEGER_TYPE))
12073 return NULL_TREE;
0a39fd54 12074
12075 /* If SRC and DEST are the same (and not volatile), return DEST. */
12076 if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
12077 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
a0c938f0 12078
0a39fd54 12079 if (! host_integerp (size, 1))
c2f47e15 12080 return NULL_TREE;
0a39fd54 12081
12082 if (! integer_all_onesp (size))
12083 {
12084 len = c_strlen (src, 1);
12085 if (! len || ! host_integerp (len, 1))
12086 {
12087 /* If LEN is not constant, try MAXLEN too.
12088 For MAXLEN only allow optimizing into non-_ocs function
12089 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12090 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
12091 {
12092 if (fcode == BUILT_IN_STPCPY_CHK)
12093 {
12094 if (! ignore)
c2f47e15 12095 return NULL_TREE;
0a39fd54 12096
12097 /* If return value of __stpcpy_chk is ignored,
12098 optimize into __strcpy_chk. */
12099 fn = built_in_decls[BUILT_IN_STRCPY_CHK];
12100 if (!fn)
c2f47e15 12101 return NULL_TREE;
0a39fd54 12102
c2f47e15 12103 return build_call_expr (fn, 3, dest, src, size);
0a39fd54 12104 }
12105
12106 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 12107 return NULL_TREE;
0a39fd54 12108
12109 /* If c_strlen returned something, but not a constant,
12110 transform __strcpy_chk into __memcpy_chk. */
12111 fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
12112 if (!fn)
c2f47e15 12113 return NULL_TREE;
0a39fd54 12114
12115 len = size_binop (PLUS_EXPR, len, ssize_int (1));
0a39fd54 12116 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
c2f47e15 12117 build_call_expr (fn, 4,
12118 dest, src, len, size));
0a39fd54 12119 }
0a39fd54 12120 }
ad89623c 12121 else
12122 maxlen = len;
12123
12124 if (! tree_int_cst_lt (maxlen, size))
c2f47e15 12125 return NULL_TREE;
0a39fd54 12126 }
12127
0a39fd54 12128 /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available. */
12129 fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK
12130 ? BUILT_IN_STPCPY : BUILT_IN_STRCPY];
12131 if (!fn)
c2f47e15 12132 return NULL_TREE;
0a39fd54 12133
c2f47e15 12134 return build_call_expr (fn, 2, dest, src);
0a39fd54 12135}
12136
c2f47e15 12137/* Fold a call to the __strncpy_chk builtin. DEST, SRC, LEN, and SIZE
12138 are the arguments to the call. If MAXLEN is not NULL, it is maximum
12139 length passed as third argument. */
0a39fd54 12140
12141tree
c2f47e15 12142fold_builtin_strncpy_chk (tree dest, tree src, tree len, tree size,
12143 tree maxlen)
0a39fd54 12144{
c2f47e15 12145 tree fn;
0a39fd54 12146
c2f47e15 12147 if (!validate_arg (dest, POINTER_TYPE)
12148 || !validate_arg (src, POINTER_TYPE)
12149 || !validate_arg (len, INTEGER_TYPE)
12150 || !validate_arg (size, INTEGER_TYPE))
12151 return NULL_TREE;
0a39fd54 12152
12153 if (! host_integerp (size, 1))
c2f47e15 12154 return NULL_TREE;
0a39fd54 12155
12156 if (! integer_all_onesp (size))
12157 {
12158 if (! host_integerp (len, 1))
12159 {
12160 /* If LEN is not constant, try MAXLEN too.
12161 For MAXLEN only allow optimizing into non-_ocs function
12162 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12163 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 12164 return NULL_TREE;
0a39fd54 12165 }
ad89623c 12166 else
12167 maxlen = len;
0a39fd54 12168
ad89623c 12169 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12170 return NULL_TREE;
0a39fd54 12171 }
12172
0a39fd54 12173 /* If __builtin_strncpy_chk is used, assume strncpy is available. */
12174 fn = built_in_decls[BUILT_IN_STRNCPY];
12175 if (!fn)
c2f47e15 12176 return NULL_TREE;
0a39fd54 12177
c2f47e15 12178 return build_call_expr (fn, 3, dest, src, len);
0a39fd54 12179}
12180
c2f47e15 12181/* Fold a call to the __strcat_chk builtin FNDECL. DEST, SRC, and SIZE
12182 are the arguments to the call. */
0a39fd54 12183
12184static tree
c2f47e15 12185fold_builtin_strcat_chk (tree fndecl, tree dest, tree src, tree size)
0a39fd54 12186{
c2f47e15 12187 tree fn;
0a39fd54 12188 const char *p;
12189
c2f47e15 12190 if (!validate_arg (dest, POINTER_TYPE)
12191 || !validate_arg (src, POINTER_TYPE)
12192 || !validate_arg (size, INTEGER_TYPE))
12193 return NULL_TREE;
0a39fd54 12194
12195 p = c_getstr (src);
12196 /* If the SRC parameter is "", return DEST. */
12197 if (p && *p == '\0')
12198 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
12199
12200 if (! host_integerp (size, 1) || ! integer_all_onesp (size))
c2f47e15 12201 return NULL_TREE;
0a39fd54 12202
12203 /* If __builtin_strcat_chk is used, assume strcat is available. */
12204 fn = built_in_decls[BUILT_IN_STRCAT];
12205 if (!fn)
c2f47e15 12206 return NULL_TREE;
0a39fd54 12207
c2f47e15 12208 return build_call_expr (fn, 2, dest, src);
0a39fd54 12209}
12210
c2f47e15 12211/* Fold a call to the __strncat_chk builtin with arguments DEST, SRC,
12212 LEN, and SIZE. */
0a39fd54 12213
12214static tree
c2f47e15 12215fold_builtin_strncat_chk (tree fndecl,
12216 tree dest, tree src, tree len, tree size)
0a39fd54 12217{
c2f47e15 12218 tree fn;
0a39fd54 12219 const char *p;
12220
c2f47e15 12221 if (!validate_arg (dest, POINTER_TYPE)
12222 || !validate_arg (src, POINTER_TYPE)
12223 || !validate_arg (size, INTEGER_TYPE)
12224 || !validate_arg (size, INTEGER_TYPE))
12225 return NULL_TREE;
0a39fd54 12226
12227 p = c_getstr (src);
12228 /* If the SRC parameter is "" or if LEN is 0, return DEST. */
12229 if (p && *p == '\0')
12230 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
12231 else if (integer_zerop (len))
12232 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
12233
12234 if (! host_integerp (size, 1))
c2f47e15 12235 return NULL_TREE;
0a39fd54 12236
12237 if (! integer_all_onesp (size))
12238 {
12239 tree src_len = c_strlen (src, 1);
12240 if (src_len
12241 && host_integerp (src_len, 1)
12242 && host_integerp (len, 1)
12243 && ! tree_int_cst_lt (len, src_len))
12244 {
12245 /* If LEN >= strlen (SRC), optimize into __strcat_chk. */
12246 fn = built_in_decls[BUILT_IN_STRCAT_CHK];
12247 if (!fn)
c2f47e15 12248 return NULL_TREE;
0a39fd54 12249
c2f47e15 12250 return build_call_expr (fn, 3, dest, src, size);
0a39fd54 12251 }
c2f47e15 12252 return NULL_TREE;
0a39fd54 12253 }
12254
0a39fd54 12255 /* If __builtin_strncat_chk is used, assume strncat is available. */
12256 fn = built_in_decls[BUILT_IN_STRNCAT];
12257 if (!fn)
c2f47e15 12258 return NULL_TREE;
0a39fd54 12259
c2f47e15 12260 return build_call_expr (fn, 3, dest, src, len);
0a39fd54 12261}
12262
c2f47e15 12263/* Fold a call EXP to __{,v}sprintf_chk. Return NULL_TREE if
0a39fd54 12264 a normal call should be emitted rather than expanding the function
12265 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
12266
12267static tree
c2f47e15 12268fold_builtin_sprintf_chk (tree exp, enum built_in_function fcode)
0a39fd54 12269{
12270 tree dest, size, len, fn, fmt, flag;
12271 const char *fmt_str;
c2f47e15 12272 int nargs = call_expr_nargs (exp);
0a39fd54 12273
12274 /* Verify the required arguments in the original call. */
c2f47e15 12275 if (nargs < 4)
12276 return NULL_TREE;
12277 dest = CALL_EXPR_ARG (exp, 0);
12278 if (!validate_arg (dest, POINTER_TYPE))
12279 return NULL_TREE;
12280 flag = CALL_EXPR_ARG (exp, 1);
12281 if (!validate_arg (flag, INTEGER_TYPE))
12282 return NULL_TREE;
12283 size = CALL_EXPR_ARG (exp, 2);
12284 if (!validate_arg (size, INTEGER_TYPE))
12285 return NULL_TREE;
12286 fmt = CALL_EXPR_ARG (exp, 3);
12287 if (!validate_arg (fmt, POINTER_TYPE))
12288 return NULL_TREE;
0a39fd54 12289
12290 if (! host_integerp (size, 1))
c2f47e15 12291 return NULL_TREE;
0a39fd54 12292
12293 len = NULL_TREE;
12294
d4473c84 12295 if (!init_target_chars ())
c2f47e15 12296 return NULL_TREE;
99eabcc1 12297
0a39fd54 12298 /* Check whether the format is a literal string constant. */
12299 fmt_str = c_getstr (fmt);
12300 if (fmt_str != NULL)
12301 {
12302 /* If the format doesn't contain % args or %%, we know the size. */
99eabcc1 12303 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 12304 {
c2f47e15 12305 if (fcode != BUILT_IN_SPRINTF_CHK || nargs == 4)
0a39fd54 12306 len = build_int_cstu (size_type_node, strlen (fmt_str));
12307 }
12308 /* If the format is "%s" and first ... argument is a string literal,
12309 we know the size too. */
c2f47e15 12310 else if (fcode == BUILT_IN_SPRINTF_CHK
12311 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12312 {
12313 tree arg;
12314
c2f47e15 12315 if (nargs == 5)
0a39fd54 12316 {
c2f47e15 12317 arg = CALL_EXPR_ARG (exp, 4);
12318 if (validate_arg (arg, POINTER_TYPE))
0a39fd54 12319 {
12320 len = c_strlen (arg, 1);
12321 if (! len || ! host_integerp (len, 1))
12322 len = NULL_TREE;
12323 }
12324 }
12325 }
12326 }
12327
12328 if (! integer_all_onesp (size))
12329 {
12330 if (! len || ! tree_int_cst_lt (len, size))
c2f47e15 12331 return NULL_TREE;
0a39fd54 12332 }
12333
12334 /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
12335 or if format doesn't contain % chars or is "%s". */
12336 if (! integer_zerop (flag))
12337 {
12338 if (fmt_str == NULL)
c2f47e15 12339 return NULL_TREE;
12340 if (strchr (fmt_str, target_percent) != NULL
12341 && strcmp (fmt_str, target_percent_s))
12342 return NULL_TREE;
0a39fd54 12343 }
12344
0a39fd54 12345 /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
12346 fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
12347 ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
12348 if (!fn)
c2f47e15 12349 return NULL_TREE;
0a39fd54 12350
c2f47e15 12351 return rewrite_call_expr (exp, 4, fn, 2, dest, fmt);
0a39fd54 12352}
12353
c2f47e15 12354/* Fold a call EXP to {,v}snprintf. Return NULL_TREE if
0a39fd54 12355 a normal call should be emitted rather than expanding the function
12356 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
12357 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
12358 passed as second argument. */
12359
12360tree
c2f47e15 12361fold_builtin_snprintf_chk (tree exp, tree maxlen,
0a39fd54 12362 enum built_in_function fcode)
12363{
12364 tree dest, size, len, fn, fmt, flag;
12365 const char *fmt_str;
12366
12367 /* Verify the required arguments in the original call. */
c2f47e15 12368 if (call_expr_nargs (exp) < 5)
12369 return NULL_TREE;
12370 dest = CALL_EXPR_ARG (exp, 0);
12371 if (!validate_arg (dest, POINTER_TYPE))
12372 return NULL_TREE;
12373 len = CALL_EXPR_ARG (exp, 1);
12374 if (!validate_arg (len, INTEGER_TYPE))
12375 return NULL_TREE;
12376 flag = CALL_EXPR_ARG (exp, 2);
12377 if (!validate_arg (flag, INTEGER_TYPE))
12378 return NULL_TREE;
12379 size = CALL_EXPR_ARG (exp, 3);
12380 if (!validate_arg (size, INTEGER_TYPE))
12381 return NULL_TREE;
12382 fmt = CALL_EXPR_ARG (exp, 4);
12383 if (!validate_arg (fmt, POINTER_TYPE))
12384 return NULL_TREE;
0a39fd54 12385
12386 if (! host_integerp (size, 1))
c2f47e15 12387 return NULL_TREE;
0a39fd54 12388
12389 if (! integer_all_onesp (size))
12390 {
12391 if (! host_integerp (len, 1))
12392 {
12393 /* If LEN is not constant, try MAXLEN too.
12394 For MAXLEN only allow optimizing into non-_ocs function
12395 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12396 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 12397 return NULL_TREE;
0a39fd54 12398 }
ad89623c 12399 else
12400 maxlen = len;
0a39fd54 12401
ad89623c 12402 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12403 return NULL_TREE;
0a39fd54 12404 }
12405
d4473c84 12406 if (!init_target_chars ())
c2f47e15 12407 return NULL_TREE;
99eabcc1 12408
0a39fd54 12409 /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
12410 or if format doesn't contain % chars or is "%s". */
12411 if (! integer_zerop (flag))
12412 {
12413 fmt_str = c_getstr (fmt);
12414 if (fmt_str == NULL)
c2f47e15 12415 return NULL_TREE;
12416 if (strchr (fmt_str, target_percent) != NULL
12417 && strcmp (fmt_str, target_percent_s))
12418 return NULL_TREE;
0a39fd54 12419 }
12420
0a39fd54 12421 /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
12422 available. */
12423 fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
12424 ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
12425 if (!fn)
c2f47e15 12426 return NULL_TREE;
0a39fd54 12427
c2f47e15 12428 return rewrite_call_expr (exp, 5, fn, 3, dest, len, fmt);
0a39fd54 12429}
12430
12431/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 12432 FMT and ARG are the arguments to the call; we don't fold cases with
12433 more than 2 arguments, and ARG may be null if this is a 1-argument case.
0a39fd54 12434
c2f47e15 12435 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 12436 simplified form of the call as a tree. FCODE is the BUILT_IN_*
12437 code of the function to be simplified. */
12438
12439static tree
c2f47e15 12440fold_builtin_printf (tree fndecl, tree fmt, tree arg, bool ignore,
0a39fd54 12441 enum built_in_function fcode)
12442{
c2f47e15 12443 tree fn_putchar, fn_puts, newarg, call = NULL_TREE;
0a39fd54 12444 const char *fmt_str = NULL;
12445
12446 /* If the return value is used, don't do the transformation. */
12447 if (! ignore)
c2f47e15 12448 return NULL_TREE;
0a39fd54 12449
12450 /* Verify the required arguments in the original call. */
c2f47e15 12451 if (!validate_arg (fmt, POINTER_TYPE))
12452 return NULL_TREE;
0a39fd54 12453
12454 /* Check whether the format is a literal string constant. */
12455 fmt_str = c_getstr (fmt);
12456 if (fmt_str == NULL)
12457 return NULL_TREE;
12458
12459 if (fcode == BUILT_IN_PRINTF_UNLOCKED)
12460 {
6d77ed92 12461 /* If we're using an unlocked function, assume the other
12462 unlocked functions exist explicitly. */
12463 fn_putchar = built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED];
12464 fn_puts = built_in_decls[BUILT_IN_PUTS_UNLOCKED];
0a39fd54 12465 }
12466 else
12467 {
12468 fn_putchar = implicit_built_in_decls[BUILT_IN_PUTCHAR];
12469 fn_puts = implicit_built_in_decls[BUILT_IN_PUTS];
12470 }
12471
d4473c84 12472 if (!init_target_chars ())
c2f47e15 12473 return NULL_TREE;
a0c938f0 12474
c2f47e15 12475 if (strcmp (fmt_str, target_percent_s) == 0
12476 || strchr (fmt_str, target_percent) == NULL)
0a39fd54 12477 {
12478 const char *str;
12479
99eabcc1 12480 if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12481 {
12482 if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 12483 return NULL_TREE;
0a39fd54 12484
c2f47e15 12485 if (!arg || !validate_arg (arg, POINTER_TYPE))
12486 return NULL_TREE;
0a39fd54 12487
c2f47e15 12488 str = c_getstr (arg);
0a39fd54 12489 if (str == NULL)
c2f47e15 12490 return NULL_TREE;
0a39fd54 12491 }
12492 else
12493 {
12494 /* The format specifier doesn't contain any '%' characters. */
12495 if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
c2f47e15 12496 && arg)
12497 return NULL_TREE;
0a39fd54 12498 str = fmt_str;
12499 }
12500
12501 /* If the string was "", printf does nothing. */
12502 if (str[0] == '\0')
12503 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
12504
12505 /* If the string has length of 1, call putchar. */
12506 if (str[1] == '\0')
12507 {
12508 /* Given printf("c"), (where c is any one character,)
12509 convert "c"[0] to an int and pass that to the replacement
12510 function. */
c2f47e15 12511 newarg = build_int_cst (NULL_TREE, str[0]);
12512 if (fn_putchar)
12513 call = build_call_expr (fn_putchar, 1, newarg);
0a39fd54 12514 }
12515 else
12516 {
12517 /* If the string was "string\n", call puts("string"). */
12518 size_t len = strlen (str);
99eabcc1 12519 if ((unsigned char)str[len - 1] == target_newline)
0a39fd54 12520 {
12521 /* Create a NUL-terminated string that's one char shorter
12522 than the original, stripping off the trailing '\n'. */
364c0c59 12523 char *newstr = XALLOCAVEC (char, len);
0a39fd54 12524 memcpy (newstr, str, len - 1);
12525 newstr[len - 1] = 0;
12526
c2f47e15 12527 newarg = build_string_literal (len, newstr);
12528 if (fn_puts)
12529 call = build_call_expr (fn_puts, 1, newarg);
0a39fd54 12530 }
12531 else
12532 /* We'd like to arrange to call fputs(string,stdout) here,
12533 but we need stdout and don't have a way to get it yet. */
c2f47e15 12534 return NULL_TREE;
0a39fd54 12535 }
12536 }
12537
12538 /* The other optimizations can be done only on the non-va_list variants. */
12539 else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 12540 return NULL_TREE;
0a39fd54 12541
12542 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
99eabcc1 12543 else if (strcmp (fmt_str, target_percent_s_newline) == 0)
0a39fd54 12544 {
c2f47e15 12545 if (!arg || !validate_arg (arg, POINTER_TYPE))
12546 return NULL_TREE;
12547 if (fn_puts)
12548 call = build_call_expr (fn_puts, 1, arg);
0a39fd54 12549 }
12550
12551 /* If the format specifier was "%c", call __builtin_putchar(arg). */
99eabcc1 12552 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 12553 {
c2f47e15 12554 if (!arg || !validate_arg (arg, INTEGER_TYPE))
12555 return NULL_TREE;
12556 if (fn_putchar)
12557 call = build_call_expr (fn_putchar, 1, arg);
0a39fd54 12558 }
12559
c2f47e15 12560 if (!call)
12561 return NULL_TREE;
0a39fd54 12562
0a39fd54 12563 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
12564}
12565
12566/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 12567 FP, FMT, and ARG are the arguments to the call. We don't fold calls with
12568 more than 3 arguments, and ARG may be null in the 2-argument case.
0a39fd54 12569
c2f47e15 12570 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 12571 simplified form of the call as a tree. FCODE is the BUILT_IN_*
12572 code of the function to be simplified. */
12573
12574static tree
c2f47e15 12575fold_builtin_fprintf (tree fndecl, tree fp, tree fmt, tree arg, bool ignore,
0a39fd54 12576 enum built_in_function fcode)
12577{
c2f47e15 12578 tree fn_fputc, fn_fputs, call = NULL_TREE;
0a39fd54 12579 const char *fmt_str = NULL;
12580
12581 /* If the return value is used, don't do the transformation. */
12582 if (! ignore)
c2f47e15 12583 return NULL_TREE;
0a39fd54 12584
12585 /* Verify the required arguments in the original call. */
c2f47e15 12586 if (!validate_arg (fp, POINTER_TYPE))
12587 return NULL_TREE;
12588 if (!validate_arg (fmt, POINTER_TYPE))
12589 return NULL_TREE;
0a39fd54 12590
12591 /* Check whether the format is a literal string constant. */
12592 fmt_str = c_getstr (fmt);
12593 if (fmt_str == NULL)
12594 return NULL_TREE;
12595
12596 if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
12597 {
6d77ed92 12598 /* If we're using an unlocked function, assume the other
12599 unlocked functions exist explicitly. */
12600 fn_fputc = built_in_decls[BUILT_IN_FPUTC_UNLOCKED];
12601 fn_fputs = built_in_decls[BUILT_IN_FPUTS_UNLOCKED];
0a39fd54 12602 }
12603 else
12604 {
12605 fn_fputc = implicit_built_in_decls[BUILT_IN_FPUTC];
12606 fn_fputs = implicit_built_in_decls[BUILT_IN_FPUTS];
12607 }
12608
d4473c84 12609 if (!init_target_chars ())
c2f47e15 12610 return NULL_TREE;
a0c938f0 12611
0a39fd54 12612 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 12613 if (strchr (fmt_str, target_percent) == NULL)
0a39fd54 12614 {
12615 if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
c2f47e15 12616 && arg)
12617 return NULL_TREE;
0a39fd54 12618
12619 /* If the format specifier was "", fprintf does nothing. */
12620 if (fmt_str[0] == '\0')
12621 {
12622 /* If FP has side-effects, just wait until gimplification is
12623 done. */
12624 if (TREE_SIDE_EFFECTS (fp))
c2f47e15 12625 return NULL_TREE;
0a39fd54 12626
12627 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
12628 }
12629
12630 /* When "string" doesn't contain %, replace all cases of
12631 fprintf (fp, string) with fputs (string, fp). The fputs
12632 builtin will take care of special cases like length == 1. */
c2f47e15 12633 if (fn_fputs)
12634 call = build_call_expr (fn_fputs, 2, fmt, fp);
0a39fd54 12635 }
12636
12637 /* The other optimizations can be done only on the non-va_list variants. */
12638 else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
c2f47e15 12639 return NULL_TREE;
0a39fd54 12640
12641 /* If the format specifier was "%s", call __builtin_fputs (arg, fp). */
99eabcc1 12642 else if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12643 {
c2f47e15 12644 if (!arg || !validate_arg (arg, POINTER_TYPE))
12645 return NULL_TREE;
12646 if (fn_fputs)
12647 call = build_call_expr (fn_fputs, 2, arg, fp);
0a39fd54 12648 }
12649
12650 /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */
99eabcc1 12651 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 12652 {
c2f47e15 12653 if (!arg || !validate_arg (arg, INTEGER_TYPE))
12654 return NULL_TREE;
12655 if (fn_fputc)
12656 call = build_call_expr (fn_fputc, 2, arg, fp);
0a39fd54 12657 }
12658
c2f47e15 12659 if (!call)
12660 return NULL_TREE;
0a39fd54 12661 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
12662}
99eabcc1 12663
12664/* Initialize format string characters in the target charset. */
12665
12666static bool
12667init_target_chars (void)
12668{
12669 static bool init;
12670 if (!init)
12671 {
12672 target_newline = lang_hooks.to_target_charset ('\n');
12673 target_percent = lang_hooks.to_target_charset ('%');
12674 target_c = lang_hooks.to_target_charset ('c');
12675 target_s = lang_hooks.to_target_charset ('s');
12676 if (target_newline == 0 || target_percent == 0 || target_c == 0
12677 || target_s == 0)
12678 return false;
12679
12680 target_percent_c[0] = target_percent;
12681 target_percent_c[1] = target_c;
12682 target_percent_c[2] = '\0';
12683
12684 target_percent_s[0] = target_percent;
12685 target_percent_s[1] = target_s;
12686 target_percent_s[2] = '\0';
12687
12688 target_percent_s_newline[0] = target_percent;
12689 target_percent_s_newline[1] = target_s;
12690 target_percent_s_newline[2] = target_newline;
12691 target_percent_s_newline[3] = '\0';
a0c938f0 12692
99eabcc1 12693 init = true;
12694 }
12695 return true;
12696}
bffb7645 12697
f0c477f2 12698/* Helper function for do_mpfr_arg*(). Ensure M is a normal number
12699 and no overflow/underflow occurred. INEXACT is true if M was not
fa7637bd 12700 exactly calculated. TYPE is the tree type for the result. This
f0c477f2 12701 function assumes that you cleared the MPFR flags and then
12702 calculated M to see if anything subsequently set a flag prior to
12703 entering this function. Return NULL_TREE if any checks fail. */
12704
12705static tree
d4473c84 12706do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
f0c477f2 12707{
12708 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
12709 overflow/underflow occurred. If -frounding-math, proceed iff the
12710 result of calling FUNC was exact. */
d4473c84 12711 if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
f0c477f2 12712 && (!flag_rounding_math || !inexact))
12713 {
12714 REAL_VALUE_TYPE rr;
12715
66fa16e6 12716 real_from_mpfr (&rr, m, type, GMP_RNDN);
f0c477f2 12717 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
12718 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
12719 but the mpft_t is not, then we underflowed in the
12720 conversion. */
776a7bab 12721 if (real_isfinite (&rr)
f0c477f2 12722 && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
12723 {
12724 REAL_VALUE_TYPE rmode;
12725
12726 real_convert (&rmode, TYPE_MODE (type), &rr);
12727 /* Proceed iff the specified mode can hold the value. */
12728 if (real_identical (&rmode, &rr))
12729 return build_real (type, rmode);
12730 }
12731 }
12732 return NULL_TREE;
12733}
12734
bffb7645 12735/* If argument ARG is a REAL_CST, call the one-argument mpfr function
12736 FUNC on it and return the resulting value as a tree with type TYPE.
728bac60 12737 If MIN and/or MAX are not NULL, then the supplied ARG must be
12738 within those bounds. If INCLUSIVE is true, then MIN/MAX are
12739 acceptable values, otherwise they are not. The mpfr precision is
12740 set to the precision of TYPE. We assume that function FUNC returns
12741 zero if the result could be calculated exactly within the requested
12742 precision. */
bffb7645 12743
12744static tree
728bac60 12745do_mpfr_arg1 (tree arg, tree type, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
12746 const REAL_VALUE_TYPE *min, const REAL_VALUE_TYPE *max,
12747 bool inclusive)
bffb7645 12748{
12749 tree result = NULL_TREE;
12750
12751 STRIP_NOPS (arg);
12752
bd7d6fa4 12753 /* To proceed, MPFR must exactly represent the target floating point
12754 format, which only happens when the target base equals two. */
12755 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12756 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
bffb7645 12757 {
f0c477f2 12758 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
bffb7645 12759
776a7bab 12760 if (real_isfinite (ra)
f0c477f2 12761 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min))
12762 && (!max || real_compare (inclusive ? LE_EXPR: LT_EXPR , ra, max)))
bffb7645 12763 {
f0c477f2 12764 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
debf9994 12765 int inexact;
bffb7645 12766 mpfr_t m;
12767
12768 mpfr_init2 (m, prec);
66fa16e6 12769 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 12770 mpfr_clear_flags ();
debf9994 12771 inexact = func (m, m, GMP_RNDN);
f0c477f2 12772 result = do_mpfr_ckconv (m, type, inexact);
bffb7645 12773 mpfr_clear (m);
12774 }
12775 }
12776
12777 return result;
12778}
f0c477f2 12779
12780/* If argument ARG is a REAL_CST, call the two-argument mpfr function
12781 FUNC on it and return the resulting value as a tree with type TYPE.
12782 The mpfr precision is set to the precision of TYPE. We assume that
12783 function FUNC returns zero if the result could be calculated
12784 exactly within the requested precision. */
12785
12786static tree
12787do_mpfr_arg2 (tree arg1, tree arg2, tree type,
12788 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
12789{
12790 tree result = NULL_TREE;
12791
12792 STRIP_NOPS (arg1);
12793 STRIP_NOPS (arg2);
12794
bd7d6fa4 12795 /* To proceed, MPFR must exactly represent the target floating point
12796 format, which only happens when the target base equals two. */
12797 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12798 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
12799 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
f0c477f2 12800 {
12801 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
12802 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
12803
776a7bab 12804 if (real_isfinite (ra1) && real_isfinite (ra2))
f0c477f2 12805 {
12806 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12807 int inexact;
12808 mpfr_t m1, m2;
12809
12810 mpfr_inits2 (prec, m1, m2, NULL);
66fa16e6 12811 mpfr_from_real (m1, ra1, GMP_RNDN);
12812 mpfr_from_real (m2, ra2, GMP_RNDN);
d4473c84 12813 mpfr_clear_flags ();
f0c477f2 12814 inexact = func (m1, m1, m2, GMP_RNDN);
12815 result = do_mpfr_ckconv (m1, type, inexact);
12816 mpfr_clears (m1, m2, NULL);
12817 }
12818 }
12819
12820 return result;
12821}
d92f994c 12822
9917422b 12823/* If argument ARG is a REAL_CST, call the three-argument mpfr function
12824 FUNC on it and return the resulting value as a tree with type TYPE.
12825 The mpfr precision is set to the precision of TYPE. We assume that
12826 function FUNC returns zero if the result could be calculated
12827 exactly within the requested precision. */
12828
12829static tree
12830do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type,
12831 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
12832{
12833 tree result = NULL_TREE;
12834
12835 STRIP_NOPS (arg1);
12836 STRIP_NOPS (arg2);
12837 STRIP_NOPS (arg3);
12838
bd7d6fa4 12839 /* To proceed, MPFR must exactly represent the target floating point
12840 format, which only happens when the target base equals two. */
12841 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12842 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
12843 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2)
12844 && TREE_CODE (arg3) == REAL_CST && !TREE_OVERFLOW (arg3))
9917422b 12845 {
12846 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
12847 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
12848 const REAL_VALUE_TYPE *const ra3 = &TREE_REAL_CST (arg3);
12849
776a7bab 12850 if (real_isfinite (ra1) && real_isfinite (ra2) && real_isfinite (ra3))
9917422b 12851 {
12852 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12853 int inexact;
12854 mpfr_t m1, m2, m3;
12855
12856 mpfr_inits2 (prec, m1, m2, m3, NULL);
66fa16e6 12857 mpfr_from_real (m1, ra1, GMP_RNDN);
12858 mpfr_from_real (m2, ra2, GMP_RNDN);
12859 mpfr_from_real (m3, ra3, GMP_RNDN);
d4473c84 12860 mpfr_clear_flags ();
9917422b 12861 inexact = func (m1, m1, m2, m3, GMP_RNDN);
12862 result = do_mpfr_ckconv (m1, type, inexact);
12863 mpfr_clears (m1, m2, m3, NULL);
12864 }
12865 }
12866
12867 return result;
12868}
12869
d92f994c 12870/* If argument ARG is a REAL_CST, call mpfr_sin_cos() on it and set
12871 the pointers *(ARG_SINP) and *(ARG_COSP) to the resulting values.
d735c391 12872 If ARG_SINP and ARG_COSP are NULL then the result is returned
12873 as a complex value.
d92f994c 12874 The type is taken from the type of ARG and is used for setting the
12875 precision of the calculation and results. */
12876
12877static tree
12878do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp)
12879{
bd7d6fa4 12880 tree const type = TREE_TYPE (arg);
d92f994c 12881 tree result = NULL_TREE;
12882
12883 STRIP_NOPS (arg);
12884
bd7d6fa4 12885 /* To proceed, MPFR must exactly represent the target floating point
12886 format, which only happens when the target base equals two. */
12887 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12888 && TREE_CODE (arg) == REAL_CST
12889 && !TREE_OVERFLOW (arg))
d92f994c 12890 {
12891 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
12892
776a7bab 12893 if (real_isfinite (ra))
d92f994c 12894 {
d92f994c 12895 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12896 tree result_s, result_c;
12897 int inexact;
12898 mpfr_t m, ms, mc;
12899
12900 mpfr_inits2 (prec, m, ms, mc, NULL);
66fa16e6 12901 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 12902 mpfr_clear_flags ();
d92f994c 12903 inexact = mpfr_sin_cos (ms, mc, m, GMP_RNDN);
12904 result_s = do_mpfr_ckconv (ms, type, inexact);
12905 result_c = do_mpfr_ckconv (mc, type, inexact);
12906 mpfr_clears (m, ms, mc, NULL);
12907 if (result_s && result_c)
12908 {
d735c391 12909 /* If we are to return in a complex value do so. */
12910 if (!arg_sinp && !arg_cosp)
12911 return build_complex (build_complex_type (type),
12912 result_c, result_s);
12913
d92f994c 12914 /* Dereference the sin/cos pointer arguments. */
12915 arg_sinp = build_fold_indirect_ref (arg_sinp);
12916 arg_cosp = build_fold_indirect_ref (arg_cosp);
12917 /* Proceed if valid pointer type were passed in. */
12918 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_sinp)) == TYPE_MAIN_VARIANT (type)
12919 && TYPE_MAIN_VARIANT (TREE_TYPE (arg_cosp)) == TYPE_MAIN_VARIANT (type))
12920 {
12921 /* Set the values. */
41076ef6 12922 result_s = fold_build2 (MODIFY_EXPR, type, arg_sinp,
35cc02b5 12923 result_s);
d92f994c 12924 TREE_SIDE_EFFECTS (result_s) = 1;
41076ef6 12925 result_c = fold_build2 (MODIFY_EXPR, type, arg_cosp,
35cc02b5 12926 result_c);
d92f994c 12927 TREE_SIDE_EFFECTS (result_c) = 1;
12928 /* Combine the assignments into a compound expr. */
12929 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
12930 result_s, result_c));
12931 }
12932 }
12933 }
12934 }
12935 return result;
12936}
65dd1378 12937
12938#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
12939/* If argument ARG1 is an INTEGER_CST and ARG2 is a REAL_CST, call the
12940 two-argument mpfr order N Bessel function FUNC on them and return
12941 the resulting value as a tree with type TYPE. The mpfr precision
12942 is set to the precision of TYPE. We assume that function FUNC
12943 returns zero if the result could be calculated exactly within the
12944 requested precision. */
12945static tree
12946do_mpfr_bessel_n (tree arg1, tree arg2, tree type,
12947 int (*func)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
12948 const REAL_VALUE_TYPE *min, bool inclusive)
12949{
12950 tree result = NULL_TREE;
12951
12952 STRIP_NOPS (arg1);
12953 STRIP_NOPS (arg2);
12954
12955 /* To proceed, MPFR must exactly represent the target floating point
12956 format, which only happens when the target base equals two. */
12957 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
12958 && host_integerp (arg1, 0)
12959 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
12960 {
12961 const HOST_WIDE_INT n = tree_low_cst(arg1, 0);
12962 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg2);
12963
12964 if (n == (long)n
776a7bab 12965 && real_isfinite (ra)
65dd1378 12966 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min)))
12967 {
12968 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12969 int inexact;
12970 mpfr_t m;
12971
12972 mpfr_init2 (m, prec);
12973 mpfr_from_real (m, ra, GMP_RNDN);
12974 mpfr_clear_flags ();
12975 inexact = func (m, n, m, GMP_RNDN);
12976 result = do_mpfr_ckconv (m, type, inexact);
12977 mpfr_clear (m);
12978 }
12979 }
12980
12981 return result;
12982}
e5407ca6 12983
12984/* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
12985 the pointer *(ARG_QUO) and return the result. The type is taken
12986 from the type of ARG0 and is used for setting the precision of the
12987 calculation and results. */
12988
12989static tree
12990do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
12991{
12992 tree const type = TREE_TYPE (arg0);
12993 tree result = NULL_TREE;
12994
12995 STRIP_NOPS (arg0);
12996 STRIP_NOPS (arg1);
12997
12998 /* To proceed, MPFR must exactly represent the target floating point
12999 format, which only happens when the target base equals two. */
13000 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13001 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
13002 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
13003 {
13004 const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
13005 const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
13006
776a7bab 13007 if (real_isfinite (ra0) && real_isfinite (ra1))
e5407ca6 13008 {
13009 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
13010 tree result_rem;
13011 long integer_quo;
13012 mpfr_t m0, m1;
13013
13014 mpfr_inits2 (prec, m0, m1, NULL);
13015 mpfr_from_real (m0, ra0, GMP_RNDN);
13016 mpfr_from_real (m1, ra1, GMP_RNDN);
13017 mpfr_clear_flags ();
13018 mpfr_remquo (m0, &integer_quo, m0, m1, GMP_RNDN);
13019 /* Remquo is independent of the rounding mode, so pass
13020 inexact=0 to do_mpfr_ckconv(). */
13021 result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
13022 mpfr_clears (m0, m1, NULL);
13023 if (result_rem)
13024 {
13025 /* MPFR calculates quo in the host's long so it may
13026 return more bits in quo than the target int can hold
13027 if sizeof(host long) > sizeof(target int). This can
13028 happen even for native compilers in LP64 mode. In
13029 these cases, modulo the quo value with the largest
13030 number that the target int can hold while leaving one
13031 bit for the sign. */
13032 if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
13033 integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
13034
13035 /* Dereference the quo pointer argument. */
13036 arg_quo = build_fold_indirect_ref (arg_quo);
13037 /* Proceed iff a valid pointer type was passed in. */
13038 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
13039 {
13040 /* Set the value. */
13041 tree result_quo = fold_build2 (MODIFY_EXPR,
13042 TREE_TYPE (arg_quo), arg_quo,
13043 build_int_cst (NULL, integer_quo));
13044 TREE_SIDE_EFFECTS (result_quo) = 1;
13045 /* Combine the quo assignment with the rem. */
13046 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13047 result_quo, result_rem));
13048 }
13049 }
13050 }
13051 }
13052 return result;
13053}
e84da7c1 13054
13055/* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
13056 resulting value as a tree with type TYPE. The mpfr precision is
13057 set to the precision of TYPE. We assume that this mpfr function
13058 returns zero if the result could be calculated exactly within the
13059 requested precision. In addition, the integer pointer represented
13060 by ARG_SG will be dereferenced and set to the appropriate signgam
13061 (-1,1) value. */
13062
13063static tree
13064do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
13065{
13066 tree result = NULL_TREE;
13067
13068 STRIP_NOPS (arg);
13069
13070 /* To proceed, MPFR must exactly represent the target floating point
13071 format, which only happens when the target base equals two. Also
13072 verify ARG is a constant and that ARG_SG is an int pointer. */
13073 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13074 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
13075 && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
13076 && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
13077 {
13078 const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
13079
13080 /* In addition to NaN and Inf, the argument cannot be zero or a
13081 negative integer. */
776a7bab 13082 if (real_isfinite (ra)
e84da7c1 13083 && ra->cl != rvc_zero
13084 && !(real_isneg(ra) && real_isinteger(ra, TYPE_MODE (type))))
13085 {
13086 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
13087 int inexact, sg;
13088 mpfr_t m;
13089 tree result_lg;
13090
13091 mpfr_init2 (m, prec);
13092 mpfr_from_real (m, ra, GMP_RNDN);
13093 mpfr_clear_flags ();
13094 inexact = mpfr_lgamma (m, &sg, m, GMP_RNDN);
13095 result_lg = do_mpfr_ckconv (m, type, inexact);
13096 mpfr_clear (m);
13097 if (result_lg)
13098 {
13099 tree result_sg;
13100
13101 /* Dereference the arg_sg pointer argument. */
13102 arg_sg = build_fold_indirect_ref (arg_sg);
13103 /* Assign the signgam value into *arg_sg. */
13104 result_sg = fold_build2 (MODIFY_EXPR,
13105 TREE_TYPE (arg_sg), arg_sg,
13106 build_int_cst (NULL, sg));
13107 TREE_SIDE_EFFECTS (result_sg) = 1;
13108 /* Combine the signgam assignment with the lgamma result. */
13109 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13110 result_sg, result_lg));
13111 }
13112 }
13113 }
13114
13115 return result;
13116}
65dd1378 13117#endif