]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/builtins.c
Properly remove.
[thirdparty/gcc.git] / gcc / builtins.c
CommitLineData
53800dbe 1/* Expand builtin functions.
61f1dccc 2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
f96bd2bf 3 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
4 Free Software Foundation, Inc.
53800dbe 5
f12b58b3 6This file is part of GCC.
53800dbe 7
f12b58b3 8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
8c4c00c1 10Software Foundation; either version 3, or (at your option) any later
f12b58b3 11version.
53800dbe 12
f12b58b3 13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
53800dbe 17
18You should have received a copy of the GNU General Public License
8c4c00c1 19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
53800dbe 21
22#include "config.h"
23#include "system.h"
805e22b2 24#include "coretypes.h"
25#include "tm.h"
53800dbe 26#include "machmode.h"
ef258422 27#include "real.h"
53800dbe 28#include "rtl.h"
29#include "tree.h"
9ff0637e 30#include "tree-gimple.h"
53800dbe 31#include "flags.h"
32#include "regs.h"
33#include "hard-reg-set.h"
34#include "except.h"
35#include "function.h"
53800dbe 36#include "insn-config.h"
37#include "expr.h"
d8fc4d0b 38#include "optabs.h"
39#include "libfuncs.h"
53800dbe 40#include "recog.h"
41#include "output.h"
42#include "typeclass.h"
53800dbe 43#include "toplev.h"
689df48e 44#include "predict.h"
1dd6c958 45#include "tm_p.h"
fc2a2dcb 46#include "target.h"
63c62881 47#include "langhooks.h"
0ec80471 48#include "basic-block.h"
fd62c19a 49#include "tree-mudflap.h"
5a84fdd6 50#include "tree-flow.h"
162719b3 51#include "value-prof.h"
07311427 52#include "diagnostic.h"
53800dbe 53
726e2588 54#ifndef PAD_VARARGS_DOWN
55#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
56#endif
57
ab7943b9 58/* Define the names of the builtin function types and codes. */
8934cb0c 59const char *const built_in_class_names[4]
ab7943b9 60 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
61
9cfddb70 62#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
0dfc45b5 63const char * built_in_names[(int) END_BUILTINS] =
4e9d90c7 64{
65#include "builtins.def"
66};
67#undef DEF_BUILTIN
ab7943b9 68
df94cd3b 69/* Setup an array of _DECL trees, make sure each element is
70 initialized to NULL_TREE. */
d2d4bdde 71tree built_in_decls[(int) END_BUILTINS];
0a68165a 72/* Declarations used when constructing the builtin implicitly in the compiler.
73 It may be NULL_TREE when this is invalid (for instance runtime is not
4ee9c684 74 required to implement the function call in all cases). */
0a68165a 75tree implicit_built_in_decls[(int) END_BUILTINS];
df94cd3b 76
aecda0d6 77static const char *c_getstr (tree);
78static rtx c_readstr (const char *, enum machine_mode);
79static int target_char_cast (tree, char *);
d8ae1baa 80static rtx get_memory_rtx (tree, tree);
aecda0d6 81static int apply_args_size (void);
82static int apply_result_size (void);
d8c9779c 83#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
aecda0d6 84static rtx result_vector (int, rtx);
d8c9779c 85#endif
843d08a9 86static void expand_builtin_update_setjmp_buf (rtx);
aecda0d6 87static void expand_builtin_prefetch (tree);
88static rtx expand_builtin_apply_args (void);
89static rtx expand_builtin_apply_args_1 (void);
90static rtx expand_builtin_apply (rtx, rtx, rtx);
91static void expand_builtin_return (rtx);
92static enum type_class type_to_class (tree);
93static rtx expand_builtin_classify_type (tree);
94static void expand_errno_check (tree, rtx);
95static rtx expand_builtin_mathfn (tree, rtx, rtx);
96static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
6b43bae4 97static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
a67a90e5 98static rtx expand_builtin_interclass_mathfn (tree, rtx, rtx);
c3147c1a 99static rtx expand_builtin_sincos (tree);
d735c391 100static rtx expand_builtin_cexpi (tree, rtx, rtx);
ad52b9b7 101static rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
7d3afc77 102static rtx expand_builtin_int_roundingfn_2 (tree, rtx, rtx);
aecda0d6 103static rtx expand_builtin_args_info (tree);
79012a9d 104static rtx expand_builtin_next_arg (void);
aecda0d6 105static rtx expand_builtin_va_start (tree);
106static rtx expand_builtin_va_end (tree);
107static rtx expand_builtin_va_copy (tree);
7959b13b 108static rtx expand_builtin_memchr (tree, rtx, enum machine_mode);
c2f47e15 109static rtx expand_builtin_memcmp (tree, rtx, enum machine_mode);
aecda0d6 110static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
111static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
112static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
7da1412b 113static rtx expand_builtin_strcat (tree, tree, rtx, enum machine_mode);
aecda0d6 114static rtx expand_builtin_strncat (tree, rtx, enum machine_mode);
115static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
116static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
117static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
c2f47e15 118static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode);
119static rtx expand_builtin_mempcpy_args (tree, tree, tree, tree, rtx,
120 enum machine_mode, int);
121static rtx expand_builtin_memmove (tree, rtx, enum machine_mode, int);
122static rtx expand_builtin_memmove_args (tree, tree, tree, tree, rtx,
123 enum machine_mode, int);
124static rtx expand_builtin_bcopy (tree, int);
1d89860b 125static rtx expand_builtin_strcpy (tree, tree, rtx, enum machine_mode);
c2f47e15 126static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx, enum machine_mode);
aecda0d6 127static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
128static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
129static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
aecda0d6 130static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
c2f47e15 131static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
132static rtx expand_builtin_memset_args (tree, tree, tree, rtx, enum machine_mode, tree);
aecda0d6 133static rtx expand_builtin_bzero (tree);
134static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
c2f47e15 135static rtx expand_builtin_strstr (tree, rtx, enum machine_mode);
136static rtx expand_builtin_strpbrk (tree, rtx, enum machine_mode);
137static rtx expand_builtin_strchr (tree, rtx, enum machine_mode);
138static rtx expand_builtin_strrchr (tree, rtx, enum machine_mode);
aecda0d6 139static rtx expand_builtin_alloca (tree, rtx);
140static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
141static rtx expand_builtin_frame_address (tree, tree);
19bf118a 142static rtx expand_builtin_fputs (tree, rtx, bool);
143static rtx expand_builtin_printf (tree, rtx, enum machine_mode, bool);
144static rtx expand_builtin_fprintf (tree, rtx, enum machine_mode, bool);
6411575e 145static rtx expand_builtin_sprintf (tree, rtx, enum machine_mode);
aecda0d6 146static tree stabilize_va_list (tree, int);
147static rtx expand_builtin_expect (tree, rtx);
148static tree fold_builtin_constant_p (tree);
c2f47e15 149static tree fold_builtin_expect (tree);
aecda0d6 150static tree fold_builtin_classify_type (tree);
e6e27594 151static tree fold_builtin_strlen (tree);
aecda0d6 152static tree fold_builtin_inf (tree, int);
153static tree fold_builtin_nan (tree, tree, int);
c2f47e15 154static tree rewrite_call_expr (tree, int, tree, int, ...);
b7bf20db 155static bool validate_arg (const_tree, enum tree_code code);
277f8dd2 156static bool integer_valued_real_p (tree);
76b9b24b 157static tree fold_trunc_transparent_mathfn (tree, tree);
aecda0d6 158static bool readonly_data_expr (tree);
159static rtx expand_builtin_fabs (tree, rtx, rtx);
27f261ef 160static rtx expand_builtin_signbit (tree, rtx);
e6e27594 161static tree fold_builtin_sqrt (tree, tree);
162static tree fold_builtin_cbrt (tree, tree);
c2f47e15 163static tree fold_builtin_pow (tree, tree, tree, tree);
164static tree fold_builtin_powi (tree, tree, tree, tree);
e6e27594 165static tree fold_builtin_cos (tree, tree, tree);
cacdc1af 166static tree fold_builtin_cosh (tree, tree, tree);
bffb7645 167static tree fold_builtin_tan (tree, tree);
7169af54 168static tree fold_builtin_trunc (tree, tree);
169static tree fold_builtin_floor (tree, tree);
170static tree fold_builtin_ceil (tree, tree);
171static tree fold_builtin_round (tree, tree);
ad52b9b7 172static tree fold_builtin_int_roundingfn (tree, tree);
10b9666f 173static tree fold_builtin_bitop (tree, tree);
c2f47e15 174static tree fold_builtin_memory_op (tree, tree, tree, tree, bool, int);
175static tree fold_builtin_strchr (tree, tree, tree);
7959b13b 176static tree fold_builtin_memchr (tree, tree, tree, tree);
c2f47e15 177static tree fold_builtin_memcmp (tree, tree, tree);
178static tree fold_builtin_strcmp (tree, tree);
179static tree fold_builtin_strncmp (tree, tree, tree);
64c18e8d 180static tree fold_builtin_signbit (tree, tree);
c2f47e15 181static tree fold_builtin_copysign (tree, tree, tree, tree);
467214fd 182static tree fold_builtin_isascii (tree);
183static tree fold_builtin_toascii (tree);
184static tree fold_builtin_isdigit (tree);
d1aade50 185static tree fold_builtin_fabs (tree, tree);
186static tree fold_builtin_abs (tree, tree);
c2f47e15 187static tree fold_builtin_unordered_cmp (tree, tree, tree, enum tree_code,
d5019fe8 188 enum tree_code);
c2f47e15 189static tree fold_builtin_n (tree, tree *, int, bool);
190static tree fold_builtin_0 (tree, bool);
3d3d84b8 191static tree fold_builtin_1 (tree, tree, bool);
c2f47e15 192static tree fold_builtin_2 (tree, tree, tree, bool);
193static tree fold_builtin_3 (tree, tree, tree, tree, bool);
194static tree fold_builtin_4 (tree, tree, tree, tree, tree, bool);
195static tree fold_builtin_varargs (tree, tree, bool);
196
197static tree fold_builtin_strpbrk (tree, tree, tree);
198static tree fold_builtin_strstr (tree, tree, tree);
199static tree fold_builtin_strrchr (tree, tree, tree);
200static tree fold_builtin_strcat (tree, tree);
201static tree fold_builtin_strncat (tree, tree, tree);
202static tree fold_builtin_strspn (tree, tree);
203static tree fold_builtin_strcspn (tree, tree);
204static tree fold_builtin_sprintf (tree, tree, tree, int);
4ee9c684 205
0a39fd54 206static rtx expand_builtin_object_size (tree);
207static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
208 enum built_in_function);
209static void maybe_emit_chk_warning (tree, enum built_in_function);
210static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
c2f47e15 211static tree fold_builtin_object_size (tree, tree);
212static tree fold_builtin_strcat_chk (tree, tree, tree, tree);
213static tree fold_builtin_strncat_chk (tree, tree, tree, tree, tree);
0a39fd54 214static tree fold_builtin_sprintf_chk (tree, enum built_in_function);
c2f47e15 215static tree fold_builtin_printf (tree, tree, tree, bool, enum built_in_function);
216static tree fold_builtin_fprintf (tree, tree, tree, tree, bool,
217 enum built_in_function);
99eabcc1 218static bool init_target_chars (void);
219
220static unsigned HOST_WIDE_INT target_newline;
221static unsigned HOST_WIDE_INT target_percent;
222static unsigned HOST_WIDE_INT target_c;
223static unsigned HOST_WIDE_INT target_s;
224static char target_percent_c[3];
225static char target_percent_s[3];
226static char target_percent_s_newline[4];
728bac60 227static tree do_mpfr_arg1 (tree, tree, int (*)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
228 const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, bool);
f0c477f2 229static tree do_mpfr_arg2 (tree, tree, tree,
230 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
9917422b 231static tree do_mpfr_arg3 (tree, tree, tree, tree,
232 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
d92f994c 233static tree do_mpfr_sincos (tree, tree, tree);
65dd1378 234#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
235static tree do_mpfr_bessel_n (tree, tree, tree,
236 int (*)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
237 const REAL_VALUE_TYPE *, bool);
e5407ca6 238static tree do_mpfr_remquo (tree, tree, tree);
e84da7c1 239static tree do_mpfr_lgamma_r (tree, tree, tree);
65dd1378 240#endif
0a39fd54 241
b6a5fc45 242/* Return true if NODE should be considered for inline expansion regardless
243 of the optimization level. This means whenever a function is invoked with
244 its "internal" name, which normally contains the prefix "__builtin". */
245
246static bool called_as_built_in (tree node)
247{
248 const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
249 if (strncmp (name, "__builtin_", 10) == 0)
250 return true;
251 if (strncmp (name, "__sync_", 7) == 0)
252 return true;
253 return false;
254}
4ee9c684 255
53800dbe 256/* Return the alignment in bits of EXP, a pointer valued expression.
257 But don't return more than MAX_ALIGN no matter what.
258 The alignment returned is, by default, the alignment of the thing that
27d0c333 259 EXP points to. If it is not a POINTER_TYPE, 0 is returned.
53800dbe 260
261 Otherwise, look at the expression to see if we can do better, i.e., if the
262 expression is actually pointing at an object whose alignment is tighter. */
263
f656b751 264int
aecda0d6 265get_pointer_alignment (tree exp, unsigned int max_align)
53800dbe 266{
27d0c333 267 unsigned int align, inner;
53800dbe 268
189575ff 269 /* We rely on TER to compute accurate alignment information. */
270 if (!(optimize && flag_tree_ter))
271 return 0;
272
535e2026 273 if (!POINTER_TYPE_P (TREE_TYPE (exp)))
274 return 0;
275
53800dbe 276 align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
277 align = MIN (align, max_align);
278
279 while (1)
280 {
281 switch (TREE_CODE (exp))
282 {
283 case NOP_EXPR:
284 case CONVERT_EXPR:
285 case NON_LVALUE_EXPR:
286 exp = TREE_OPERAND (exp, 0);
552752f7 287 if (! POINTER_TYPE_P (TREE_TYPE (exp)))
53800dbe 288 return align;
325d1c45 289
53800dbe 290 inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
291 align = MIN (inner, max_align);
292 break;
293
0de36bdb 294 case POINTER_PLUS_EXPR:
53800dbe 295 /* If sum of pointer + int, restrict our maximum alignment to that
296 imposed by the integer. If not, we can't do any better than
297 ALIGN. */
325d1c45 298 if (! host_integerp (TREE_OPERAND (exp, 1), 1))
53800dbe 299 return align;
300
0994d2ed 301 while (((tree_low_cst (TREE_OPERAND (exp, 1), 1))
302 & (max_align / BITS_PER_UNIT - 1))
53800dbe 303 != 0)
304 max_align >>= 1;
305
306 exp = TREE_OPERAND (exp, 0);
307 break;
308
309 case ADDR_EXPR:
310 /* See what we are pointing at and look at its alignment. */
311 exp = TREE_OPERAND (exp, 0);
3c15318e 312 inner = max_align;
d2df7679 313 if (handled_component_p (exp))
1eee24cf 314 {
d2df7679 315 HOST_WIDE_INT bitsize, bitpos;
316 tree offset;
317 enum machine_mode mode;
318 int unsignedp, volatilep;
319
320 exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
321 &mode, &unsignedp, &volatilep, true);
322 if (bitpos)
323 inner = MIN (inner, (unsigned) (bitpos & -bitpos));
324 if (offset && TREE_CODE (offset) == PLUS_EXPR
325 && host_integerp (TREE_OPERAND (offset, 1), 1))
326 {
327 /* Any overflow in calculating offset_bits won't change
328 the alignment. */
329 unsigned offset_bits
330 = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
331 * BITS_PER_UNIT);
332
333 if (offset_bits)
334 inner = MIN (inner, (offset_bits & -offset_bits));
335 offset = TREE_OPERAND (offset, 0);
336 }
337 if (offset && TREE_CODE (offset) == MULT_EXPR
338 && host_integerp (TREE_OPERAND (offset, 1), 1))
339 {
340 /* Any overflow in calculating offset_factor won't change
341 the alignment. */
342 unsigned offset_factor
343 = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
344 * BITS_PER_UNIT);
345
346 if (offset_factor)
347 inner = MIN (inner, (offset_factor & -offset_factor));
348 }
349 else if (offset)
350 inner = MIN (inner, BITS_PER_UNIT);
1eee24cf 351 }
6c96b31e 352 if (DECL_P (exp))
3c15318e 353 align = MIN (inner, DECL_ALIGN (exp));
53800dbe 354#ifdef CONSTANT_ALIGNMENT
ce45a448 355 else if (CONSTANT_CLASS_P (exp))
e068b646 356 align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align));
53800dbe 357#endif
d2df7679 358 else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR
359 || TREE_CODE (exp) == INDIRECT_REF)
360 align = MIN (TYPE_ALIGN (TREE_TYPE (exp)), inner);
3c15318e 361 else
362 align = MIN (align, inner);
363 return MIN (align, max_align);
53800dbe 364
365 default:
366 return align;
367 }
368 }
369}
370
371/* Compute the length of a C string. TREE_STRING_LENGTH is not the right
372 way, because it could contain a zero byte in the middle.
373 TREE_STRING_LENGTH is the size of the character array, not the string.
374
4172d65e 375 ONLY_VALUE should be nonzero if the result is not going to be emitted
c09841f6 376 into the instruction stream and zero if it is going to be expanded.
4172d65e 377 E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
681fab1e 378 is returned, otherwise NULL, since
379 len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
380 evaluate the side-effects.
381
902de8ed 382 The value returned is of type `ssizetype'.
383
53800dbe 384 Unfortunately, string_constant can't access the values of const char
385 arrays with initializers, so neither can we do so here. */
386
4ee9c684 387tree
681fab1e 388c_strlen (tree src, int only_value)
53800dbe 389{
390 tree offset_node;
27d0c333 391 HOST_WIDE_INT offset;
392 int max;
44acf429 393 const char *ptr;
53800dbe 394
681fab1e 395 STRIP_NOPS (src);
396 if (TREE_CODE (src) == COND_EXPR
397 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
398 {
399 tree len1, len2;
400
401 len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
402 len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
0862b7e9 403 if (tree_int_cst_equal (len1, len2))
681fab1e 404 return len1;
405 }
406
407 if (TREE_CODE (src) == COMPOUND_EXPR
408 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
409 return c_strlen (TREE_OPERAND (src, 1), only_value);
410
53800dbe 411 src = string_constant (src, &offset_node);
412 if (src == 0)
c2f47e15 413 return NULL_TREE;
902de8ed 414
83d79705 415 max = TREE_STRING_LENGTH (src) - 1;
53800dbe 416 ptr = TREE_STRING_POINTER (src);
902de8ed 417
53800dbe 418 if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
419 {
420 /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
421 compute the offset to the following null if we don't know where to
422 start searching for it. */
423 int i;
902de8ed 424
53800dbe 425 for (i = 0; i < max; i++)
426 if (ptr[i] == 0)
c2f47e15 427 return NULL_TREE;
902de8ed 428
53800dbe 429 /* We don't know the starting offset, but we do know that the string
430 has no internal zero bytes. We can assume that the offset falls
431 within the bounds of the string; otherwise, the programmer deserves
432 what he gets. Subtract the offset from the length of the string,
902de8ed 433 and return that. This would perhaps not be valid if we were dealing
434 with named arrays in addition to literal string constants. */
435
436 return size_diffop (size_int (max), offset_node);
53800dbe 437 }
438
439 /* We have a known offset into the string. Start searching there for
27d0c333 440 a null character if we can represent it as a single HOST_WIDE_INT. */
dabc4084 441 if (offset_node == 0)
53800dbe 442 offset = 0;
dabc4084 443 else if (! host_integerp (offset_node, 0))
444 offset = -1;
53800dbe 445 else
27d0c333 446 offset = tree_low_cst (offset_node, 0);
902de8ed 447
53800dbe 448 /* If the offset is known to be out of bounds, warn, and call strlen at
449 runtime. */
450 if (offset < 0 || offset > max)
451 {
c3ceba8e 452 warning (0, "offset outside bounds of constant string");
c2f47e15 453 return NULL_TREE;
53800dbe 454 }
902de8ed 455
53800dbe 456 /* Use strlen to search for the first zero byte. Since any strings
457 constructed with build_string will have nulls appended, we win even
458 if we get handed something like (char[4])"abcd".
459
460 Since OFFSET is our starting index into the string, no further
461 calculation is needed. */
902de8ed 462 return ssize_int (strlen (ptr + offset));
53800dbe 463}
464
83d79705 465/* Return a char pointer for a C string if it is a string constant
466 or sum of string constant and integer constant. */
467
468static const char *
aecda0d6 469c_getstr (tree src)
83d79705 470{
471 tree offset_node;
83d79705 472
473 src = string_constant (src, &offset_node);
474 if (src == 0)
475 return 0;
476
8c85fcb7 477 if (offset_node == 0)
478 return TREE_STRING_POINTER (src);
479 else if (!host_integerp (offset_node, 1)
480 || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
83d79705 481 return 0;
83d79705 482
8c85fcb7 483 return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
83d79705 484}
485
8c85fcb7 486/* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
487 GET_MODE_BITSIZE (MODE) bits from string constant STR. */
ecc318ff 488
6840589f 489static rtx
aecda0d6 490c_readstr (const char *str, enum machine_mode mode)
6840589f 491{
492 HOST_WIDE_INT c[2];
493 HOST_WIDE_INT ch;
494 unsigned int i, j;
495
64db345d 496 gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
7d3f6cc7 497
6840589f 498 c[0] = 0;
499 c[1] = 0;
500 ch = 1;
501 for (i = 0; i < GET_MODE_SIZE (mode); i++)
502 {
503 j = i;
504 if (WORDS_BIG_ENDIAN)
505 j = GET_MODE_SIZE (mode) - i - 1;
506 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
507 && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
508 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
509 j *= BITS_PER_UNIT;
64db345d 510 gcc_assert (j <= 2 * HOST_BITS_PER_WIDE_INT);
7d3f6cc7 511
6840589f 512 if (ch)
513 ch = (unsigned char) str[i];
514 c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
515 }
516 return immed_double_const (c[0], c[1], mode);
517}
518
ecc318ff 519/* Cast a target constant CST to target CHAR and if that value fits into
5206b159 520 host char type, return zero and put that value into variable pointed to by
ecc318ff 521 P. */
522
523static int
aecda0d6 524target_char_cast (tree cst, char *p)
ecc318ff 525{
526 unsigned HOST_WIDE_INT val, hostval;
527
27d0c333 528 if (!host_integerp (cst, 1)
ecc318ff 529 || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
530 return 1;
531
27d0c333 532 val = tree_low_cst (cst, 1);
ecc318ff 533 if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
534 val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
535
536 hostval = val;
537 if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
538 hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
539
540 if (val != hostval)
541 return 1;
542
543 *p = hostval;
544 return 0;
545}
546
4ee9c684 547/* Similar to save_expr, but assumes that arbitrary code is not executed
548 in between the multiple evaluations. In particular, we assume that a
549 non-addressable local variable will not be modified. */
550
551static tree
552builtin_save_expr (tree exp)
553{
554 if (TREE_ADDRESSABLE (exp) == 0
555 && (TREE_CODE (exp) == PARM_DECL
556 || (TREE_CODE (exp) == VAR_DECL && !TREE_STATIC (exp))))
557 return exp;
558
559 return save_expr (exp);
560}
561
53800dbe 562/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
563 times to get the address of either a higher stack frame, or a return
564 address located within it (depending on FNDECL_CODE). */
902de8ed 565
c626df3d 566static rtx
869d0ef0 567expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
53800dbe 568{
569 int i;
570
869d0ef0 571#ifdef INITIAL_FRAME_ADDRESS_RTX
572 rtx tem = INITIAL_FRAME_ADDRESS_RTX;
573#else
e3e15c50 574 rtx tem;
575
1b74fde7 576 /* For a zero count with __builtin_return_address, we don't care what
577 frame address we return, because target-specific definitions will
578 override us. Therefore frame pointer elimination is OK, and using
579 the soft frame pointer is OK.
580
fa7637bd 581 For a nonzero count, or a zero count with __builtin_frame_address,
1b74fde7 582 we require a stable offset from the current frame pointer to the
583 previous one, so we must use the hard frame pointer, and
e3e15c50 584 we must disable frame pointer elimination. */
1b74fde7 585 if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
e3e15c50 586 tem = frame_pointer_rtx;
a0c938f0 587 else
e3e15c50 588 {
589 tem = hard_frame_pointer_rtx;
590
591 /* Tell reload not to eliminate the frame pointer. */
592 current_function_accesses_prior_frames = 1;
593 }
869d0ef0 594#endif
595
53800dbe 596 /* Some machines need special handling before we can access
3a69c60c 597 arbitrary frames. For example, on the SPARC, we must first flush
53800dbe 598 all register windows to the stack. */
599#ifdef SETUP_FRAME_ADDRESSES
600 if (count > 0)
601 SETUP_FRAME_ADDRESSES ();
602#endif
603
3a69c60c 604 /* On the SPARC, the return address is not in the frame, it is in a
53800dbe 605 register. There is no way to access it off of the current frame
606 pointer, but it can be accessed off the previous frame pointer by
607 reading the value from the register window save area. */
608#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
609 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
610 count--;
611#endif
612
613 /* Scan back COUNT frames to the specified frame. */
614 for (i = 0; i < count; i++)
615 {
616 /* Assume the dynamic chain pointer is in the word that the
617 frame address points to, unless otherwise specified. */
618#ifdef DYNAMIC_CHAIN_ADDRESS
619 tem = DYNAMIC_CHAIN_ADDRESS (tem);
620#endif
621 tem = memory_address (Pmode, tem);
00060fc2 622 tem = gen_frame_mem (Pmode, tem);
83fc1478 623 tem = copy_to_reg (tem);
53800dbe 624 }
625
3a69c60c 626 /* For __builtin_frame_address, return what we've got. But, on
627 the SPARC for example, we may have to add a bias. */
53800dbe 628 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
3a69c60c 629#ifdef FRAME_ADDR_RTX
630 return FRAME_ADDR_RTX (tem);
631#else
53800dbe 632 return tem;
3a69c60c 633#endif
53800dbe 634
3a69c60c 635 /* For __builtin_return_address, get the return address from that frame. */
53800dbe 636#ifdef RETURN_ADDR_RTX
637 tem = RETURN_ADDR_RTX (count, tem);
638#else
639 tem = memory_address (Pmode,
640 plus_constant (tem, GET_MODE_SIZE (Pmode)));
00060fc2 641 tem = gen_frame_mem (Pmode, tem);
53800dbe 642#endif
643 return tem;
644}
645
f7c44134 646/* Alias set used for setjmp buffer. */
32c2fdea 647static alias_set_type setjmp_alias_set = -1;
f7c44134 648
6b7f6858 649/* Construct the leading half of a __builtin_setjmp call. Control will
2c8a1497 650 return to RECEIVER_LABEL. This is also called directly by the SJLJ
651 exception handling code. */
53800dbe 652
6b7f6858 653void
aecda0d6 654expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
53800dbe 655{
53800dbe 656 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
53800dbe 657 rtx stack_save;
f7c44134 658 rtx mem;
53800dbe 659
f7c44134 660 if (setjmp_alias_set == -1)
661 setjmp_alias_set = new_alias_set ();
662
85d654dd 663 buf_addr = convert_memory_address (Pmode, buf_addr);
53800dbe 664
37ae8504 665 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
53800dbe 666
6b7f6858 667 /* We store the frame pointer and the address of receiver_label in
668 the buffer and use the rest of it for the stack save area, which
669 is machine-dependent. */
53800dbe 670
f7c44134 671 mem = gen_rtx_MEM (Pmode, buf_addr);
ab6ab77e 672 set_mem_alias_set (mem, setjmp_alias_set);
e3e026e8 673 emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
f7c44134 674
675 mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
ab6ab77e 676 set_mem_alias_set (mem, setjmp_alias_set);
f7c44134 677
678 emit_move_insn (validize_mem (mem),
6b7f6858 679 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
53800dbe 680
681 stack_save = gen_rtx_MEM (sa_mode,
682 plus_constant (buf_addr,
683 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 684 set_mem_alias_set (stack_save, setjmp_alias_set);
53800dbe 685 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
686
687 /* If there is further processing to do, do it. */
688#ifdef HAVE_builtin_setjmp_setup
689 if (HAVE_builtin_setjmp_setup)
690 emit_insn (gen_builtin_setjmp_setup (buf_addr));
691#endif
692
6b7f6858 693 /* Tell optimize_save_area_alloca that extra work is going to
694 need to go on during alloca. */
3b0fa6b6 695 current_function_calls_setjmp = 1;
80ab81b9 696
29f09705 697 /* We have a nonlocal label. */
80ab81b9 698 current_function_has_nonlocal_label = 1;
6b7f6858 699}
53800dbe 700
2c8a1497 701/* Construct the trailing part of a __builtin_setjmp call. This is
702 also called directly by the SJLJ exception handling code. */
6b7f6858 703
704void
aecda0d6 705expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
6b7f6858 706{
53800dbe 707 /* Clobber the FP when we get here, so we have to make sure it's
708 marked as used by this function. */
709 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
710
711 /* Mark the static chain as clobbered here so life information
712 doesn't get messed up for it. */
713 emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
714
715 /* Now put in the code to restore the frame pointer, and argument
491e04ef 716 pointer, if needed. */
53800dbe 717#ifdef HAVE_nonlocal_goto
718 if (! HAVE_nonlocal_goto)
719#endif
5a1c3f40 720 {
721 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
722 /* This might change the hard frame pointer in ways that aren't
723 apparent to early optimization passes, so force a clobber. */
724 emit_insn (gen_rtx_CLOBBER (VOIDmode, hard_frame_pointer_rtx));
725 }
53800dbe 726
727#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
728 if (fixed_regs[ARG_POINTER_REGNUM])
729 {
730#ifdef ELIMINABLE_REGS
731 size_t i;
e99c3a1d 732 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
53800dbe 733
3098b2d3 734 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
53800dbe 735 if (elim_regs[i].from == ARG_POINTER_REGNUM
736 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
737 break;
738
3098b2d3 739 if (i == ARRAY_SIZE (elim_regs))
53800dbe 740#endif
741 {
742 /* Now restore our arg pointer from the address at which it
05927e40 743 was saved in our stack frame. */
53800dbe 744 emit_move_insn (virtual_incoming_args_rtx,
05927e40 745 copy_to_reg (get_arg_pointer_save_area (cfun)));
53800dbe 746 }
747 }
748#endif
749
750#ifdef HAVE_builtin_setjmp_receiver
751 if (HAVE_builtin_setjmp_receiver)
6b7f6858 752 emit_insn (gen_builtin_setjmp_receiver (receiver_label));
53800dbe 753 else
754#endif
755#ifdef HAVE_nonlocal_goto_receiver
756 if (HAVE_nonlocal_goto_receiver)
757 emit_insn (gen_nonlocal_goto_receiver ());
758 else
759#endif
6b7f6858 760 { /* Nothing */ }
57f6bb94 761
3072d30e 762 /* We must not allow the code we just generated to be reordered by
763 scheduling. Specifically, the update of the frame pointer must
764 happen immediately, not later. */
765 emit_insn (gen_blockage ());
6b7f6858 766}
53800dbe 767
53800dbe 768/* __builtin_longjmp is passed a pointer to an array of five words (not
769 all will be used on all machines). It operates similarly to the C
770 library function of the same name, but is more efficient. Much of
2c8a1497 771 the code below is copied from the handling of non-local gotos. */
53800dbe 772
c626df3d 773static void
aecda0d6 774expand_builtin_longjmp (rtx buf_addr, rtx value)
53800dbe 775{
4712c7d6 776 rtx fp, lab, stack, insn, last;
53800dbe 777 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
778
f7c44134 779 if (setjmp_alias_set == -1)
780 setjmp_alias_set = new_alias_set ();
781
85d654dd 782 buf_addr = convert_memory_address (Pmode, buf_addr);
479e4d5e 783
53800dbe 784 buf_addr = force_reg (Pmode, buf_addr);
785
786 /* We used to store value in static_chain_rtx, but that fails if pointers
787 are smaller than integers. We instead require that the user must pass
788 a second argument of 1, because that is what builtin_setjmp will
789 return. This also makes EH slightly more efficient, since we are no
790 longer copying around a value that we don't care about. */
64db345d 791 gcc_assert (value == const1_rtx);
53800dbe 792
4712c7d6 793 last = get_last_insn ();
53800dbe 794#ifdef HAVE_builtin_longjmp
795 if (HAVE_builtin_longjmp)
796 emit_insn (gen_builtin_longjmp (buf_addr));
797 else
798#endif
799 {
800 fp = gen_rtx_MEM (Pmode, buf_addr);
801 lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
802 GET_MODE_SIZE (Pmode)));
803
804 stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
805 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 806 set_mem_alias_set (fp, setjmp_alias_set);
807 set_mem_alias_set (lab, setjmp_alias_set);
808 set_mem_alias_set (stack, setjmp_alias_set);
53800dbe 809
810 /* Pick up FP, label, and SP from the block and jump. This code is
811 from expand_goto in stmt.c; see there for detailed comments. */
03fd9d2c 812#ifdef HAVE_nonlocal_goto
53800dbe 813 if (HAVE_nonlocal_goto)
814 /* We have to pass a value to the nonlocal_goto pattern that will
815 get copied into the static_chain pointer, but it does not matter
816 what that value is, because builtin_setjmp does not use it. */
28d202a8 817 emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
53800dbe 818 else
819#endif
820 {
821 lab = copy_to_reg (lab);
822
2a871ad1 823 emit_insn (gen_rtx_CLOBBER (VOIDmode,
824 gen_rtx_MEM (BLKmode,
825 gen_rtx_SCRATCH (VOIDmode))));
826 emit_insn (gen_rtx_CLOBBER (VOIDmode,
827 gen_rtx_MEM (BLKmode,
828 hard_frame_pointer_rtx)));
829
53800dbe 830 emit_move_insn (hard_frame_pointer_rtx, fp);
831 emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
832
833 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
834 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
835 emit_indirect_jump (lab);
836 }
837 }
615166bb 838
839 /* Search backwards and mark the jump insn as a non-local goto.
840 Note that this precludes the use of __builtin_longjmp to a
841 __builtin_setjmp target in the same function. However, we've
842 already cautioned the user that these functions are for
843 internal exception handling use only. */
449c0509 844 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
845 {
64db345d 846 gcc_assert (insn != last);
7d3f6cc7 847
6d7dc5b9 848 if (JUMP_P (insn))
449c0509 849 {
850 REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
851 REG_NOTES (insn));
852 break;
853 }
6d7dc5b9 854 else if (CALL_P (insn))
9342ee68 855 break;
449c0509 856 }
53800dbe 857}
858
4ee9c684 859/* Expand a call to __builtin_nonlocal_goto. We're passed the target label
860 and the address of the save area. */
861
862static rtx
c2f47e15 863expand_builtin_nonlocal_goto (tree exp)
4ee9c684 864{
865 tree t_label, t_save_area;
866 rtx r_label, r_save_area, r_fp, r_sp, insn;
867
c2f47e15 868 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4ee9c684 869 return NULL_RTX;
870
c2f47e15 871 t_label = CALL_EXPR_ARG (exp, 0);
872 t_save_area = CALL_EXPR_ARG (exp, 1);
4ee9c684 873
8ec3c5c2 874 r_label = expand_normal (t_label);
3dce56cc 875 r_label = convert_memory_address (Pmode, r_label);
8ec3c5c2 876 r_save_area = expand_normal (t_save_area);
3dce56cc 877 r_save_area = convert_memory_address (Pmode, 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
882 current_function_has_nonlocal_goto = 1;
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
893 emit_insn (gen_rtx_CLOBBER (VOIDmode,
894 gen_rtx_MEM (BLKmode,
895 gen_rtx_SCRATCH (VOIDmode))));
896
897 emit_insn (gen_rtx_CLOBBER (VOIDmode,
898 gen_rtx_MEM (BLKmode,
899 hard_frame_pointer_rtx)));
491e04ef 900
4ee9c684 901 /* Restore frame pointer for containing function.
902 This sets the actual hard register used for the frame pointer
903 to the location of the function's incoming static chain info.
904 The non-local goto handler will then adjust it to contain the
905 proper value and reload the argument pointer, if needed. */
906 emit_move_insn (hard_frame_pointer_rtx, r_fp);
907 emit_stack_restore (SAVE_NONLOCAL, r_sp, NULL_RTX);
491e04ef 908
4ee9c684 909 /* USE of hard_frame_pointer_rtx added for consistency;
910 not clear if really needed. */
911 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
912 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
913 emit_indirect_jump (r_label);
914 }
491e04ef 915
4ee9c684 916 /* Search backwards to the jump insn and mark it as a
917 non-local goto. */
918 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
919 {
6d7dc5b9 920 if (JUMP_P (insn))
4ee9c684 921 {
922 REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO,
923 const0_rtx, REG_NOTES (insn));
924 break;
925 }
6d7dc5b9 926 else if (CALL_P (insn))
4ee9c684 927 break;
928 }
929
930 return const0_rtx;
931}
932
843d08a9 933/* __builtin_update_setjmp_buf is passed a pointer to an array of five words
934 (not all will be used on all machines) that was passed to __builtin_setjmp.
935 It updates the stack pointer in that block to correspond to the current
936 stack pointer. */
937
938static void
939expand_builtin_update_setjmp_buf (rtx buf_addr)
940{
941 enum machine_mode sa_mode = Pmode;
942 rtx stack_save;
943
944
945#ifdef HAVE_save_stack_nonlocal
946 if (HAVE_save_stack_nonlocal)
947 sa_mode = insn_data[(int) CODE_FOR_save_stack_nonlocal].operand[0].mode;
948#endif
949#ifdef STACK_SAVEAREA_MODE
950 sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
951#endif
952
953 stack_save
954 = gen_rtx_MEM (sa_mode,
955 memory_address
956 (sa_mode,
957 plus_constant (buf_addr, 2 * GET_MODE_SIZE (Pmode))));
958
959#ifdef HAVE_setjmp
960 if (HAVE_setjmp)
961 emit_insn (gen_setjmp ());
962#endif
963
964 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
965}
966
5e3608d8 967/* Expand a call to __builtin_prefetch. For a target that does not support
968 data prefetch, evaluate the memory address argument in case it has side
969 effects. */
970
971static void
c2f47e15 972expand_builtin_prefetch (tree exp)
5e3608d8 973{
974 tree arg0, arg1, arg2;
c2f47e15 975 int nargs;
5e3608d8 976 rtx op0, op1, op2;
977
c2f47e15 978 if (!validate_arglist (exp, POINTER_TYPE, 0))
26a5cadb 979 return;
980
c2f47e15 981 arg0 = CALL_EXPR_ARG (exp, 0);
982
26a5cadb 983 /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
984 zero (read) and argument 2 (locality) defaults to 3 (high degree of
985 locality). */
c2f47e15 986 nargs = call_expr_nargs (exp);
987 if (nargs > 1)
988 arg1 = CALL_EXPR_ARG (exp, 1);
26a5cadb 989 else
c2f47e15 990 arg1 = integer_zero_node;
991 if (nargs > 2)
992 arg2 = CALL_EXPR_ARG (exp, 2);
993 else
994 arg2 = build_int_cst (NULL_TREE, 3);
5e3608d8 995
996 /* Argument 0 is an address. */
997 op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
998
999 /* Argument 1 (read/write flag) must be a compile-time constant int. */
1000 if (TREE_CODE (arg1) != INTEGER_CST)
1001 {
07e3a3d2 1002 error ("second argument to %<__builtin_prefetch%> must be a constant");
9342ee68 1003 arg1 = integer_zero_node;
5e3608d8 1004 }
8ec3c5c2 1005 op1 = expand_normal (arg1);
5e3608d8 1006 /* Argument 1 must be either zero or one. */
1007 if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
1008 {
c3ceba8e 1009 warning (0, "invalid second argument to %<__builtin_prefetch%>;"
07e3a3d2 1010 " using zero");
5e3608d8 1011 op1 = const0_rtx;
1012 }
1013
1014 /* Argument 2 (locality) must be a compile-time constant int. */
1015 if (TREE_CODE (arg2) != INTEGER_CST)
1016 {
07e3a3d2 1017 error ("third argument to %<__builtin_prefetch%> must be a constant");
5e3608d8 1018 arg2 = integer_zero_node;
1019 }
8ec3c5c2 1020 op2 = expand_normal (arg2);
5e3608d8 1021 /* Argument 2 must be 0, 1, 2, or 3. */
1022 if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
1023 {
c3ceba8e 1024 warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
5e3608d8 1025 op2 = const0_rtx;
1026 }
1027
1028#ifdef HAVE_prefetch
1029 if (HAVE_prefetch)
1030 {
f0ce3b1f 1031 if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate)
4cd21437 1032 (op0,
f0ce3b1f 1033 insn_data[(int) CODE_FOR_prefetch].operand[0].mode))
19bf118a 1034 || (GET_MODE (op0) != Pmode))
9342ee68 1035 {
85d654dd 1036 op0 = convert_memory_address (Pmode, op0);
9342ee68 1037 op0 = force_reg (Pmode, op0);
1038 }
5e3608d8 1039 emit_insn (gen_prefetch (op0, op1, op2));
1040 }
5e3608d8 1041#endif
0a534ba7 1042
f0ce3b1f 1043 /* Don't do anything with direct references to volatile memory, but
1044 generate code to handle other side effects. */
e16ceb8e 1045 if (!MEM_P (op0) && side_effects_p (op0))
f0ce3b1f 1046 emit_insn (op0);
5e3608d8 1047}
1048
f7c44134 1049/* Get a MEM rtx for expression EXP which is the address of an operand
d8ae1baa 1050 to be used in a string instruction (cmpstrsi, movmemsi, ..). LEN is
1051 the maximum length of the block of memory that might be accessed or
1052 NULL if unknown. */
f7c44134 1053
53800dbe 1054static rtx
d8ae1baa 1055get_memory_rtx (tree exp, tree len)
53800dbe 1056{
bb2327a8 1057 rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
1058 rtx mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
2a631e19 1059
f7c44134 1060 /* Get an expression we can use to find the attributes to assign to MEM.
1061 If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
1062 we can. First remove any nops. */
1063 while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
f0ce3b1f 1064 || TREE_CODE (exp) == NON_LVALUE_EXPR)
f7c44134 1065 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
1066 exp = TREE_OPERAND (exp, 0);
1067
1068 if (TREE_CODE (exp) == ADDR_EXPR)
a1a25d19 1069 exp = TREE_OPERAND (exp, 0);
f7c44134 1070 else if (POINTER_TYPE_P (TREE_TYPE (exp)))
a1a25d19 1071 exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
1072 else
1073 exp = NULL;
1074
1075 /* Honor attributes derived from exp, except for the alias set
1076 (as builtin stringops may alias with anything) and the size
1077 (as stringops may access multiple array elements). */
1078 if (exp)
eec8e941 1079 {
a1a25d19 1080 set_mem_attributes (mem, exp, 0);
d8ae1baa 1081
1082 /* Allow the string and memory builtins to overflow from one
1083 field into another, see http://gcc.gnu.org/PR23561.
1084 Thus avoid COMPONENT_REFs in MEM_EXPR unless we know the whole
1085 memory accessed by the string or memory builtin will fit
1086 within the field. */
1087 if (MEM_EXPR (mem) && TREE_CODE (MEM_EXPR (mem)) == COMPONENT_REF)
1088 {
1089 tree mem_expr = MEM_EXPR (mem);
1090 HOST_WIDE_INT offset = -1, length = -1;
1091 tree inner = exp;
1092
1093 while (TREE_CODE (inner) == ARRAY_REF
1094 || TREE_CODE (inner) == NOP_EXPR
1095 || TREE_CODE (inner) == CONVERT_EXPR
1096 || TREE_CODE (inner) == NON_LVALUE_EXPR
1097 || TREE_CODE (inner) == VIEW_CONVERT_EXPR
1098 || TREE_CODE (inner) == SAVE_EXPR)
1099 inner = TREE_OPERAND (inner, 0);
1100
1101 gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
1102
1103 if (MEM_OFFSET (mem)
1104 && GET_CODE (MEM_OFFSET (mem)) == CONST_INT)
1105 offset = INTVAL (MEM_OFFSET (mem));
1106
1107 if (offset >= 0 && len && host_integerp (len, 0))
1108 length = tree_low_cst (len, 0);
1109
1110 while (TREE_CODE (inner) == COMPONENT_REF)
1111 {
1112 tree field = TREE_OPERAND (inner, 1);
1113 gcc_assert (! DECL_BIT_FIELD (field));
1114 gcc_assert (TREE_CODE (mem_expr) == COMPONENT_REF);
1115 gcc_assert (field == TREE_OPERAND (mem_expr, 1));
1116
1117 if (length >= 0
1118 && TYPE_SIZE_UNIT (TREE_TYPE (inner))
1119 && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0))
1120 {
1121 HOST_WIDE_INT size
1122 = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0);
1123 /* If we can prove the memory starting at XEXP (mem, 0)
1124 and ending at XEXP (mem, 0) + LENGTH will fit into
1125 this field, we can keep that COMPONENT_REF in MEM_EXPR. */
1126 if (offset <= size
1127 && length <= size
1128 && offset + length <= size)
1129 break;
1130 }
1131
1132 if (offset >= 0
1133 && host_integerp (DECL_FIELD_OFFSET (field), 0))
1134 offset += tree_low_cst (DECL_FIELD_OFFSET (field), 0)
1135 + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
1136 / BITS_PER_UNIT;
1137 else
1138 {
1139 offset = -1;
1140 length = -1;
1141 }
1142
1143 mem_expr = TREE_OPERAND (mem_expr, 0);
1144 inner = TREE_OPERAND (inner, 0);
d8ae1baa 1145 }
1146
1147 if (mem_expr == NULL)
1148 offset = -1;
1149 if (mem_expr != MEM_EXPR (mem))
1150 {
1151 set_mem_expr (mem, mem_expr);
1152 set_mem_offset (mem, offset >= 0 ? GEN_INT (offset) : NULL_RTX);
1153 }
1154 }
eec8e941 1155 set_mem_alias_set (mem, 0);
a1a25d19 1156 set_mem_size (mem, NULL_RTX);
eec8e941 1157 }
53800dbe 1158
53800dbe 1159 return mem;
1160}
1161\f
1162/* Built-in functions to perform an untyped call and return. */
1163
1164/* For each register that may be used for calling a function, this
1165 gives a mode used to copy the register's value. VOIDmode indicates
1166 the register is not used for calling a function. If the machine
1167 has register windows, this gives only the outbound registers.
1168 INCOMING_REGNO gives the corresponding inbound register. */
1169static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
1170
1171/* For each register that may be used for returning values, this gives
1172 a mode used to copy the register's value. VOIDmode indicates the
1173 register is not used for returning values. If the machine has
1174 register windows, this gives only the outbound registers.
1175 INCOMING_REGNO gives the corresponding inbound register. */
1176static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
1177
1178/* For each register that may be used for calling a function, this
1179 gives the offset of that register into the block returned by
1180 __builtin_apply_args. 0 indicates that the register is not
1181 used for calling a function. */
1182static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
1183
53800dbe 1184/* Return the size required for the block returned by __builtin_apply_args,
1185 and initialize apply_args_mode. */
1186
1187static int
aecda0d6 1188apply_args_size (void)
53800dbe 1189{
1190 static int size = -1;
58e9ce8f 1191 int align;
1192 unsigned int regno;
53800dbe 1193 enum machine_mode mode;
1194
1195 /* The values computed by this function never change. */
1196 if (size < 0)
1197 {
1198 /* The first value is the incoming arg-pointer. */
1199 size = GET_MODE_SIZE (Pmode);
1200
1201 /* The second value is the structure value address unless this is
1202 passed as an "invisible" first argument. */
6812c89e 1203 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1204 size += GET_MODE_SIZE (Pmode);
1205
1206 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1207 if (FUNCTION_ARG_REGNO_P (regno))
1208 {
0862b7e9 1209 mode = reg_raw_mode[regno];
1210
64db345d 1211 gcc_assert (mode != VOIDmode);
53800dbe 1212
1213 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1214 if (size % align != 0)
1215 size = CEIL (size, align) * align;
1216 apply_args_reg_offset[regno] = size;
1217 size += GET_MODE_SIZE (mode);
1218 apply_args_mode[regno] = mode;
1219 }
1220 else
1221 {
1222 apply_args_mode[regno] = VOIDmode;
1223 apply_args_reg_offset[regno] = 0;
1224 }
1225 }
1226 return size;
1227}
1228
1229/* Return the size required for the block returned by __builtin_apply,
1230 and initialize apply_result_mode. */
1231
1232static int
aecda0d6 1233apply_result_size (void)
53800dbe 1234{
1235 static int size = -1;
1236 int align, regno;
1237 enum machine_mode mode;
1238
1239 /* The values computed by this function never change. */
1240 if (size < 0)
1241 {
1242 size = 0;
1243
1244 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1245 if (FUNCTION_VALUE_REGNO_P (regno))
1246 {
0862b7e9 1247 mode = reg_raw_mode[regno];
1248
64db345d 1249 gcc_assert (mode != VOIDmode);
53800dbe 1250
1251 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1252 if (size % align != 0)
1253 size = CEIL (size, align) * align;
1254 size += GET_MODE_SIZE (mode);
1255 apply_result_mode[regno] = mode;
1256 }
1257 else
1258 apply_result_mode[regno] = VOIDmode;
1259
1260 /* Allow targets that use untyped_call and untyped_return to override
1261 the size so that machine-specific information can be stored here. */
1262#ifdef APPLY_RESULT_SIZE
1263 size = APPLY_RESULT_SIZE;
1264#endif
1265 }
1266 return size;
1267}
1268
1269#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1270/* Create a vector describing the result block RESULT. If SAVEP is true,
1271 the result block is used to save the values; otherwise it is used to
1272 restore the values. */
1273
1274static rtx
aecda0d6 1275result_vector (int savep, rtx result)
53800dbe 1276{
1277 int regno, size, align, nelts;
1278 enum machine_mode mode;
1279 rtx reg, mem;
f0af5a88 1280 rtx *savevec = alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
bf8e3599 1281
53800dbe 1282 size = nelts = 0;
1283 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1284 if ((mode = apply_result_mode[regno]) != VOIDmode)
1285 {
1286 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1287 if (size % align != 0)
1288 size = CEIL (size, align) * align;
1289 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
e513d163 1290 mem = adjust_address (result, mode, size);
53800dbe 1291 savevec[nelts++] = (savep
1292 ? gen_rtx_SET (VOIDmode, mem, reg)
1293 : gen_rtx_SET (VOIDmode, reg, mem));
1294 size += GET_MODE_SIZE (mode);
1295 }
1296 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1297}
1298#endif /* HAVE_untyped_call or HAVE_untyped_return */
1299
1300/* Save the state required to perform an untyped call with the same
1301 arguments as were passed to the current function. */
1302
1303static rtx
aecda0d6 1304expand_builtin_apply_args_1 (void)
53800dbe 1305{
1c7e61a7 1306 rtx registers, tem;
53800dbe 1307 int size, align, regno;
1308 enum machine_mode mode;
6812c89e 1309 rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
53800dbe 1310
1311 /* Create a block where the arg-pointer, structure value address,
1312 and argument registers can be saved. */
1313 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1314
1315 /* Walk past the arg-pointer and structure value address. */
1316 size = GET_MODE_SIZE (Pmode);
6812c89e 1317 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1318 size += GET_MODE_SIZE (Pmode);
1319
1320 /* Save each register used in calling a function to the block. */
1321 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1322 if ((mode = apply_args_mode[regno]) != VOIDmode)
1323 {
53800dbe 1324 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1325 if (size % align != 0)
1326 size = CEIL (size, align) * align;
1327
1328 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1329
e513d163 1330 emit_move_insn (adjust_address (registers, mode, size), tem);
53800dbe 1331 size += GET_MODE_SIZE (mode);
1332 }
1333
1334 /* Save the arg pointer to the block. */
1c7e61a7 1335 tem = copy_to_reg (virtual_incoming_args_rtx);
f083a92b 1336#ifdef STACK_GROWS_DOWNWARD
1c7e61a7 1337 /* We need the pointer as the caller actually passed them to us, not
9d4b544c 1338 as we might have pretended they were passed. Make sure it's a valid
1339 operand, as emit_move_insn isn't expected to handle a PLUS. */
1340 tem
1341 = force_operand (plus_constant (tem, current_function_pretend_args_size),
1342 NULL_RTX);
1c7e61a7 1343#endif
1344 emit_move_insn (adjust_address (registers, Pmode, 0), tem);
0862b7e9 1345
53800dbe 1346 size = GET_MODE_SIZE (Pmode);
1347
1348 /* Save the structure value address unless this is passed as an
1349 "invisible" first argument. */
45550790 1350 if (struct_incoming_value)
53800dbe 1351 {
e513d163 1352 emit_move_insn (adjust_address (registers, Pmode, size),
45550790 1353 copy_to_reg (struct_incoming_value));
53800dbe 1354 size += GET_MODE_SIZE (Pmode);
1355 }
1356
1357 /* Return the address of the block. */
1358 return copy_addr_to_reg (XEXP (registers, 0));
1359}
1360
1361/* __builtin_apply_args returns block of memory allocated on
1362 the stack into which is stored the arg pointer, structure
1363 value address, static chain, and all the registers that might
1364 possibly be used in performing a function call. The code is
1365 moved to the start of the function so the incoming values are
1366 saved. */
27d0c333 1367
53800dbe 1368static rtx
aecda0d6 1369expand_builtin_apply_args (void)
53800dbe 1370{
1371 /* Don't do __builtin_apply_args more than once in a function.
1372 Save the result of the first call and reuse it. */
1373 if (apply_args_value != 0)
1374 return apply_args_value;
1375 {
1376 /* When this function is called, it means that registers must be
1377 saved on entry to this function. So we migrate the
1378 call to the first insn of this function. */
1379 rtx temp;
1380 rtx seq;
1381
1382 start_sequence ();
1383 temp = expand_builtin_apply_args_1 ();
1384 seq = get_insns ();
1385 end_sequence ();
1386
1387 apply_args_value = temp;
1388
31d3e01c 1389 /* Put the insns after the NOTE that starts the function.
1390 If this is inside a start_sequence, make the outer-level insn
53800dbe 1391 chain current, so the code is placed at the start of the
1392 function. */
1393 push_topmost_sequence ();
0ec80471 1394 emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
53800dbe 1395 pop_topmost_sequence ();
1396 return temp;
1397 }
1398}
1399
1400/* Perform an untyped call and save the state required to perform an
1401 untyped return of whatever value was returned by the given function. */
1402
1403static rtx
aecda0d6 1404expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
53800dbe 1405{
1406 int size, align, regno;
1407 enum machine_mode mode;
2a631e19 1408 rtx incoming_args, result, reg, dest, src, call_insn;
53800dbe 1409 rtx old_stack_level = 0;
1410 rtx call_fusage = 0;
6812c89e 1411 rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
53800dbe 1412
85d654dd 1413 arguments = convert_memory_address (Pmode, arguments);
726ec87c 1414
53800dbe 1415 /* Create a block where the return registers can be saved. */
1416 result = assign_stack_local (BLKmode, apply_result_size (), -1);
1417
53800dbe 1418 /* Fetch the arg pointer from the ARGUMENTS block. */
1419 incoming_args = gen_reg_rtx (Pmode);
726ec87c 1420 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
53800dbe 1421#ifndef STACK_GROWS_DOWNWARD
ad99e708 1422 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1423 incoming_args, 0, OPTAB_LIB_WIDEN);
53800dbe 1424#endif
1425
04a46d40 1426 /* Push a new argument block and copy the arguments. Do not allow
1427 the (potential) memcpy call below to interfere with our stack
1428 manipulations. */
53800dbe 1429 do_pending_stack_adjust ();
04a46d40 1430 NO_DEFER_POP;
53800dbe 1431
2358393e 1432 /* Save the stack with nonlocal if available. */
53800dbe 1433#ifdef HAVE_save_stack_nonlocal
1434 if (HAVE_save_stack_nonlocal)
1435 emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
1436 else
1437#endif
1438 emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
1439
59647703 1440 /* Allocate a block of memory onto the stack and copy the memory
1441 arguments to the outgoing arguments address. */
1442 allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
1443 dest = virtual_outgoing_args_rtx;
1444#ifndef STACK_GROWS_DOWNWARD
1445 if (GET_CODE (argsize) == CONST_INT)
1446 dest = plus_constant (dest, -INTVAL (argsize));
1447 else
1448 dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1449#endif
2a631e19 1450 dest = gen_rtx_MEM (BLKmode, dest);
1451 set_mem_align (dest, PARM_BOUNDARY);
1452 src = gen_rtx_MEM (BLKmode, incoming_args);
1453 set_mem_align (src, PARM_BOUNDARY);
0378dbdc 1454 emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
53800dbe 1455
1456 /* Refer to the argument block. */
1457 apply_args_size ();
1458 arguments = gen_rtx_MEM (BLKmode, arguments);
2a631e19 1459 set_mem_align (arguments, PARM_BOUNDARY);
53800dbe 1460
1461 /* Walk past the arg-pointer and structure value address. */
1462 size = GET_MODE_SIZE (Pmode);
45550790 1463 if (struct_value)
53800dbe 1464 size += GET_MODE_SIZE (Pmode);
1465
1466 /* Restore each of the registers previously saved. Make USE insns
1467 for each of these registers for use in making the call. */
1468 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1469 if ((mode = apply_args_mode[regno]) != VOIDmode)
1470 {
1471 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1472 if (size % align != 0)
1473 size = CEIL (size, align) * align;
1474 reg = gen_rtx_REG (mode, regno);
e513d163 1475 emit_move_insn (reg, adjust_address (arguments, mode, size));
53800dbe 1476 use_reg (&call_fusage, reg);
1477 size += GET_MODE_SIZE (mode);
1478 }
1479
1480 /* Restore the structure value address unless this is passed as an
1481 "invisible" first argument. */
1482 size = GET_MODE_SIZE (Pmode);
45550790 1483 if (struct_value)
53800dbe 1484 {
1485 rtx value = gen_reg_rtx (Pmode);
e513d163 1486 emit_move_insn (value, adjust_address (arguments, Pmode, size));
45550790 1487 emit_move_insn (struct_value, value);
8ad4c111 1488 if (REG_P (struct_value))
45550790 1489 use_reg (&call_fusage, struct_value);
53800dbe 1490 size += GET_MODE_SIZE (Pmode);
1491 }
1492
1493 /* All arguments and registers used for the call are set up by now! */
4ee9c684 1494 function = prepare_call_address (function, NULL, &call_fusage, 0, 0);
53800dbe 1495
1496 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1497 and we don't want to load it into a register as an optimization,
1498 because prepare_call_address already did it if it should be done. */
1499 if (GET_CODE (function) != SYMBOL_REF)
1500 function = memory_address (FUNCTION_MODE, function);
1501
1502 /* Generate the actual call instruction and save the return value. */
1503#ifdef HAVE_untyped_call
1504 if (HAVE_untyped_call)
1505 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1506 result, result_vector (1, result)));
1507 else
1508#endif
1509#ifdef HAVE_call_value
1510 if (HAVE_call_value)
1511 {
1512 rtx valreg = 0;
1513
1514 /* Locate the unique return register. It is not possible to
1515 express a call that sets more than one return register using
1516 call_value; use untyped_call for that. In fact, untyped_call
1517 only needs to save the return registers in the given block. */
1518 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1519 if ((mode = apply_result_mode[regno]) != VOIDmode)
1520 {
64db345d 1521 gcc_assert (!valreg); /* HAVE_untyped_call required. */
7d3f6cc7 1522
53800dbe 1523 valreg = gen_rtx_REG (mode, regno);
1524 }
1525
2ed6c343 1526 emit_call_insn (GEN_CALL_VALUE (valreg,
53800dbe 1527 gen_rtx_MEM (FUNCTION_MODE, function),
1528 const0_rtx, NULL_RTX, const0_rtx));
1529
e513d163 1530 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
53800dbe 1531 }
1532 else
1533#endif
64db345d 1534 gcc_unreachable ();
53800dbe 1535
d5f9786f 1536 /* Find the CALL insn we just emitted, and attach the register usage
1537 information. */
1538 call_insn = last_call_insn ();
1539 add_function_usage_to (call_insn, call_fusage);
53800dbe 1540
1541 /* Restore the stack. */
1542#ifdef HAVE_save_stack_nonlocal
1543 if (HAVE_save_stack_nonlocal)
1544 emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1545 else
1546#endif
1547 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1548
04a46d40 1549 OK_DEFER_POP;
1550
53800dbe 1551 /* Return the address of the result block. */
85d654dd 1552 result = copy_addr_to_reg (XEXP (result, 0));
1553 return convert_memory_address (ptr_mode, result);
53800dbe 1554}
1555
1556/* Perform an untyped return. */
1557
1558static void
aecda0d6 1559expand_builtin_return (rtx result)
53800dbe 1560{
1561 int size, align, regno;
1562 enum machine_mode mode;
1563 rtx reg;
1564 rtx call_fusage = 0;
1565
85d654dd 1566 result = convert_memory_address (Pmode, result);
726ec87c 1567
53800dbe 1568 apply_result_size ();
1569 result = gen_rtx_MEM (BLKmode, result);
1570
1571#ifdef HAVE_untyped_return
1572 if (HAVE_untyped_return)
1573 {
1574 emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1575 emit_barrier ();
1576 return;
1577 }
1578#endif
1579
1580 /* Restore the return value and note that each value is used. */
1581 size = 0;
1582 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1583 if ((mode = apply_result_mode[regno]) != VOIDmode)
1584 {
1585 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1586 if (size % align != 0)
1587 size = CEIL (size, align) * align;
1588 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
e513d163 1589 emit_move_insn (reg, adjust_address (result, mode, size));
53800dbe 1590
1591 push_to_sequence (call_fusage);
1592 emit_insn (gen_rtx_USE (VOIDmode, reg));
1593 call_fusage = get_insns ();
1594 end_sequence ();
1595 size += GET_MODE_SIZE (mode);
1596 }
1597
1598 /* Put the USE insns before the return. */
31d3e01c 1599 emit_insn (call_fusage);
53800dbe 1600
1601 /* Return whatever values was restored by jumping directly to the end
1602 of the function. */
62380d2d 1603 expand_naked_return ();
53800dbe 1604}
1605
539a3a92 1606/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
27d0c333 1607
539a3a92 1608static enum type_class
aecda0d6 1609type_to_class (tree type)
539a3a92 1610{
1611 switch (TREE_CODE (type))
1612 {
1613 case VOID_TYPE: return void_type_class;
1614 case INTEGER_TYPE: return integer_type_class;
539a3a92 1615 case ENUMERAL_TYPE: return enumeral_type_class;
1616 case BOOLEAN_TYPE: return boolean_type_class;
1617 case POINTER_TYPE: return pointer_type_class;
1618 case REFERENCE_TYPE: return reference_type_class;
1619 case OFFSET_TYPE: return offset_type_class;
1620 case REAL_TYPE: return real_type_class;
1621 case COMPLEX_TYPE: return complex_type_class;
1622 case FUNCTION_TYPE: return function_type_class;
1623 case METHOD_TYPE: return method_type_class;
1624 case RECORD_TYPE: return record_type_class;
1625 case UNION_TYPE:
1626 case QUAL_UNION_TYPE: return union_type_class;
1627 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1628 ? string_type_class : array_type_class);
539a3a92 1629 case LANG_TYPE: return lang_type_class;
1630 default: return no_type_class;
1631 }
1632}
bf8e3599 1633
c2f47e15 1634/* Expand a call EXP to __builtin_classify_type. */
27d0c333 1635
53800dbe 1636static rtx
c2f47e15 1637expand_builtin_classify_type (tree exp)
53800dbe 1638{
c2f47e15 1639 if (call_expr_nargs (exp))
1640 return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0))));
53800dbe 1641 return GEN_INT (no_type_class);
1642}
1643
07976da7 1644/* This helper macro, meant to be used in mathfn_built_in below,
1645 determines which among a set of three builtin math functions is
1646 appropriate for a given type mode. The `F' and `L' cases are
1647 automatically generated from the `double' case. */
1648#define CASE_MATHFN(BUILT_IN_MATHFN) \
1649 case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1650 fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1651 fcodel = BUILT_IN_MATHFN##L ; break;
cd2656b0 1652/* Similar to above, but appends _R after any F/L suffix. */
1653#define CASE_MATHFN_REENT(BUILT_IN_MATHFN) \
1654 case BUILT_IN_MATHFN##_R: case BUILT_IN_MATHFN##F_R: case BUILT_IN_MATHFN##L_R: \
1655 fcode = BUILT_IN_MATHFN##_R; fcodef = BUILT_IN_MATHFN##F_R ; \
1656 fcodel = BUILT_IN_MATHFN##L_R ; break;
07976da7 1657
1658/* Return mathematic function equivalent to FN but operating directly
1659 on TYPE, if available. If we can't do the conversion, return zero. */
0a68165a 1660tree
aecda0d6 1661mathfn_built_in (tree type, enum built_in_function fn)
0a68165a 1662{
07976da7 1663 enum built_in_function fcode, fcodef, fcodel;
1664
1665 switch (fn)
1666 {
746114e8 1667 CASE_MATHFN (BUILT_IN_ACOS)
1668 CASE_MATHFN (BUILT_IN_ACOSH)
1669 CASE_MATHFN (BUILT_IN_ASIN)
1670 CASE_MATHFN (BUILT_IN_ASINH)
07976da7 1671 CASE_MATHFN (BUILT_IN_ATAN)
746114e8 1672 CASE_MATHFN (BUILT_IN_ATAN2)
1673 CASE_MATHFN (BUILT_IN_ATANH)
1674 CASE_MATHFN (BUILT_IN_CBRT)
07976da7 1675 CASE_MATHFN (BUILT_IN_CEIL)
d735c391 1676 CASE_MATHFN (BUILT_IN_CEXPI)
746114e8 1677 CASE_MATHFN (BUILT_IN_COPYSIGN)
07976da7 1678 CASE_MATHFN (BUILT_IN_COS)
746114e8 1679 CASE_MATHFN (BUILT_IN_COSH)
1680 CASE_MATHFN (BUILT_IN_DREM)
1681 CASE_MATHFN (BUILT_IN_ERF)
1682 CASE_MATHFN (BUILT_IN_ERFC)
07976da7 1683 CASE_MATHFN (BUILT_IN_EXP)
746114e8 1684 CASE_MATHFN (BUILT_IN_EXP10)
1685 CASE_MATHFN (BUILT_IN_EXP2)
1686 CASE_MATHFN (BUILT_IN_EXPM1)
1687 CASE_MATHFN (BUILT_IN_FABS)
1688 CASE_MATHFN (BUILT_IN_FDIM)
07976da7 1689 CASE_MATHFN (BUILT_IN_FLOOR)
746114e8 1690 CASE_MATHFN (BUILT_IN_FMA)
1691 CASE_MATHFN (BUILT_IN_FMAX)
1692 CASE_MATHFN (BUILT_IN_FMIN)
1693 CASE_MATHFN (BUILT_IN_FMOD)
1694 CASE_MATHFN (BUILT_IN_FREXP)
1695 CASE_MATHFN (BUILT_IN_GAMMA)
cd2656b0 1696 CASE_MATHFN_REENT (BUILT_IN_GAMMA) /* GAMMA_R */
746114e8 1697 CASE_MATHFN (BUILT_IN_HUGE_VAL)
1698 CASE_MATHFN (BUILT_IN_HYPOT)
1699 CASE_MATHFN (BUILT_IN_ILOGB)
1700 CASE_MATHFN (BUILT_IN_INF)
69b779ea 1701 CASE_MATHFN (BUILT_IN_ISINF)
746114e8 1702 CASE_MATHFN (BUILT_IN_J0)
1703 CASE_MATHFN (BUILT_IN_J1)
1704 CASE_MATHFN (BUILT_IN_JN)
ac148751 1705 CASE_MATHFN (BUILT_IN_LCEIL)
746114e8 1706 CASE_MATHFN (BUILT_IN_LDEXP)
ad52b9b7 1707 CASE_MATHFN (BUILT_IN_LFLOOR)
746114e8 1708 CASE_MATHFN (BUILT_IN_LGAMMA)
cd2656b0 1709 CASE_MATHFN_REENT (BUILT_IN_LGAMMA) /* LGAMMA_R */
ac148751 1710 CASE_MATHFN (BUILT_IN_LLCEIL)
ad52b9b7 1711 CASE_MATHFN (BUILT_IN_LLFLOOR)
746114e8 1712 CASE_MATHFN (BUILT_IN_LLRINT)
1713 CASE_MATHFN (BUILT_IN_LLROUND)
07976da7 1714 CASE_MATHFN (BUILT_IN_LOG)
746114e8 1715 CASE_MATHFN (BUILT_IN_LOG10)
1716 CASE_MATHFN (BUILT_IN_LOG1P)
1717 CASE_MATHFN (BUILT_IN_LOG2)
1718 CASE_MATHFN (BUILT_IN_LOGB)
1719 CASE_MATHFN (BUILT_IN_LRINT)
1720 CASE_MATHFN (BUILT_IN_LROUND)
1721 CASE_MATHFN (BUILT_IN_MODF)
1722 CASE_MATHFN (BUILT_IN_NAN)
1723 CASE_MATHFN (BUILT_IN_NANS)
07976da7 1724 CASE_MATHFN (BUILT_IN_NEARBYINT)
746114e8 1725 CASE_MATHFN (BUILT_IN_NEXTAFTER)
1726 CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1727 CASE_MATHFN (BUILT_IN_POW)
757c219d 1728 CASE_MATHFN (BUILT_IN_POWI)
746114e8 1729 CASE_MATHFN (BUILT_IN_POW10)
1730 CASE_MATHFN (BUILT_IN_REMAINDER)
1731 CASE_MATHFN (BUILT_IN_REMQUO)
1732 CASE_MATHFN (BUILT_IN_RINT)
07976da7 1733 CASE_MATHFN (BUILT_IN_ROUND)
746114e8 1734 CASE_MATHFN (BUILT_IN_SCALB)
1735 CASE_MATHFN (BUILT_IN_SCALBLN)
1736 CASE_MATHFN (BUILT_IN_SCALBN)
1737 CASE_MATHFN (BUILT_IN_SIGNIFICAND)
07976da7 1738 CASE_MATHFN (BUILT_IN_SIN)
746114e8 1739 CASE_MATHFN (BUILT_IN_SINCOS)
1740 CASE_MATHFN (BUILT_IN_SINH)
07976da7 1741 CASE_MATHFN (BUILT_IN_SQRT)
1742 CASE_MATHFN (BUILT_IN_TAN)
746114e8 1743 CASE_MATHFN (BUILT_IN_TANH)
1744 CASE_MATHFN (BUILT_IN_TGAMMA)
07976da7 1745 CASE_MATHFN (BUILT_IN_TRUNC)
746114e8 1746 CASE_MATHFN (BUILT_IN_Y0)
1747 CASE_MATHFN (BUILT_IN_Y1)
1748 CASE_MATHFN (BUILT_IN_YN)
07976da7 1749
0a68165a 1750 default:
c2f47e15 1751 return NULL_TREE;
0a68165a 1752 }
07976da7 1753
96b9f485 1754 if (TYPE_MAIN_VARIANT (type) == double_type_node)
07976da7 1755 return implicit_built_in_decls[fcode];
96b9f485 1756 else if (TYPE_MAIN_VARIANT (type) == float_type_node)
07976da7 1757 return implicit_built_in_decls[fcodef];
96b9f485 1758 else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
07976da7 1759 return implicit_built_in_decls[fcodel];
1760 else
c2f47e15 1761 return NULL_TREE;
0a68165a 1762}
1763
0fd605a5 1764/* If errno must be maintained, expand the RTL to check if the result,
1765 TARGET, of a built-in function call, EXP, is NaN, and if so set
1766 errno to EDOM. */
1767
1768static void
aecda0d6 1769expand_errno_check (tree exp, rtx target)
0fd605a5 1770{
7f05340e 1771 rtx lab = gen_label_rtx ();
0fd605a5 1772
7f05340e 1773 /* Test the result; if it is NaN, set errno=EDOM because
1774 the argument was not in the domain. */
1775 emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
1776 0, lab);
0fd605a5 1777
1778#ifdef TARGET_EDOM
7f05340e 1779 /* If this built-in doesn't throw an exception, set errno directly. */
c2f47e15 1780 if (TREE_NOTHROW (TREE_OPERAND (CALL_EXPR_FN (exp), 0)))
7f05340e 1781 {
0fd605a5 1782#ifdef GEN_ERRNO_RTX
7f05340e 1783 rtx errno_rtx = GEN_ERRNO_RTX;
0fd605a5 1784#else
7f05340e 1785 rtx errno_rtx
0fd605a5 1786 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1787#endif
7f05340e 1788 emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
0fd605a5 1789 emit_label (lab);
7f05340e 1790 return;
0fd605a5 1791 }
7f05340e 1792#endif
1793
1794 /* We can't set errno=EDOM directly; let the library call do it.
1795 Pop the arguments right away in case the call gets deleted. */
1796 NO_DEFER_POP;
1797 expand_call (exp, target, 0);
1798 OK_DEFER_POP;
1799 emit_label (lab);
0fd605a5 1800}
1801
6b43bae4 1802/* Expand a call to one of the builtin math functions (sqrt, exp, or log).
c2f47e15 1803 Return NULL_RTX if a normal call should be emitted rather than expanding
1804 the function in-line. EXP is the expression that is a call to the builtin
53800dbe 1805 function; if convenient, the result should be placed in TARGET.
1806 SUBTARGET may be used as the target for computing one of EXP's operands. */
27d0c333 1807
53800dbe 1808static rtx
aecda0d6 1809expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
53800dbe 1810{
bf8e3599 1811 optab builtin_optab;
bd421108 1812 rtx op0, insns, before_call;
c6e6ecb1 1813 tree fndecl = get_callee_fndecl (exp);
7f05340e 1814 enum machine_mode mode;
528ee710 1815 bool errno_set = false;
68e6cb9d 1816 tree arg, narg;
53800dbe 1817
c2f47e15 1818 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
1819 return NULL_RTX;
53800dbe 1820
c2f47e15 1821 arg = CALL_EXPR_ARG (exp, 0);
53800dbe 1822
1823 switch (DECL_FUNCTION_CODE (fndecl))
1824 {
4f35b1fc 1825 CASE_FLT_FN (BUILT_IN_SQRT):
7f05340e 1826 errno_set = ! tree_expr_nonnegative_p (arg);
1827 builtin_optab = sqrt_optab;
1828 break;
4f35b1fc 1829 CASE_FLT_FN (BUILT_IN_EXP):
528ee710 1830 errno_set = true; builtin_optab = exp_optab; break;
4f35b1fc 1831 CASE_FLT_FN (BUILT_IN_EXP10):
1832 CASE_FLT_FN (BUILT_IN_POW10):
750ef9f5 1833 errno_set = true; builtin_optab = exp10_optab; break;
4f35b1fc 1834 CASE_FLT_FN (BUILT_IN_EXP2):
750ef9f5 1835 errno_set = true; builtin_optab = exp2_optab; break;
4f35b1fc 1836 CASE_FLT_FN (BUILT_IN_EXPM1):
a6b4eed2 1837 errno_set = true; builtin_optab = expm1_optab; break;
4f35b1fc 1838 CASE_FLT_FN (BUILT_IN_LOGB):
4efbc641 1839 errno_set = true; builtin_optab = logb_optab; break;
4f35b1fc 1840 CASE_FLT_FN (BUILT_IN_LOG):
528ee710 1841 errno_set = true; builtin_optab = log_optab; break;
4f35b1fc 1842 CASE_FLT_FN (BUILT_IN_LOG10):
d3cd9bde 1843 errno_set = true; builtin_optab = log10_optab; break;
4f35b1fc 1844 CASE_FLT_FN (BUILT_IN_LOG2):
d3cd9bde 1845 errno_set = true; builtin_optab = log2_optab; break;
4f35b1fc 1846 CASE_FLT_FN (BUILT_IN_LOG1P):
f474cd93 1847 errno_set = true; builtin_optab = log1p_optab; break;
4f35b1fc 1848 CASE_FLT_FN (BUILT_IN_ASIN):
8de2f465 1849 builtin_optab = asin_optab; break;
4f35b1fc 1850 CASE_FLT_FN (BUILT_IN_ACOS):
8de2f465 1851 builtin_optab = acos_optab; break;
4f35b1fc 1852 CASE_FLT_FN (BUILT_IN_TAN):
528ee710 1853 builtin_optab = tan_optab; break;
4f35b1fc 1854 CASE_FLT_FN (BUILT_IN_ATAN):
528ee710 1855 builtin_optab = atan_optab; break;
4f35b1fc 1856 CASE_FLT_FN (BUILT_IN_FLOOR):
528ee710 1857 builtin_optab = floor_optab; break;
4f35b1fc 1858 CASE_FLT_FN (BUILT_IN_CEIL):
528ee710 1859 builtin_optab = ceil_optab; break;
4f35b1fc 1860 CASE_FLT_FN (BUILT_IN_TRUNC):
a7cc195f 1861 builtin_optab = btrunc_optab; break;
4f35b1fc 1862 CASE_FLT_FN (BUILT_IN_ROUND):
528ee710 1863 builtin_optab = round_optab; break;
4f35b1fc 1864 CASE_FLT_FN (BUILT_IN_NEARBYINT):
0ddf4ad9 1865 builtin_optab = nearbyint_optab;
1866 if (flag_trapping_math)
1867 break;
1868 /* Else fallthrough and expand as rint. */
4f35b1fc 1869 CASE_FLT_FN (BUILT_IN_RINT):
aef94a0f 1870 builtin_optab = rint_optab; break;
42721db0 1871 default:
64db345d 1872 gcc_unreachable ();
53800dbe 1873 }
1874
7f05340e 1875 /* Make a suitable register to place result in. */
1876 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 1877
7f05340e 1878 if (! flag_errno_math || ! HONOR_NANS (mode))
1879 errno_set = false;
1880
bd421108 1881 /* Before working hard, check whether the instruction is available. */
99bdde56 1882 if (optab_handler (builtin_optab, mode)->insn_code != CODE_FOR_nothing)
68e6cb9d 1883 {
bd421108 1884 target = gen_reg_rtx (mode);
7f05340e 1885
bd421108 1886 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
1887 need to expand the argument again. This way, we will not perform
1888 side-effects more the once. */
4ee9c684 1889 narg = builtin_save_expr (arg);
bd421108 1890 if (narg != arg)
1891 {
9a5acb98 1892 arg = narg;
c2f47e15 1893 exp = build_call_expr (fndecl, 1, arg);
bd421108 1894 }
7f05340e 1895
1db6d067 1896 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
7f05340e 1897
bd421108 1898 start_sequence ();
53800dbe 1899
bd421108 1900 /* Compute into TARGET.
1901 Set TARGET to wherever the result comes back. */
1902 target = expand_unop (mode, builtin_optab, op0, target, 0);
1903
1904 if (target != 0)
1905 {
1906 if (errno_set)
1907 expand_errno_check (exp, target);
1908
1909 /* Output the entire sequence. */
1910 insns = get_insns ();
1911 end_sequence ();
1912 emit_insn (insns);
1913 return target;
1914 }
1915
1916 /* If we were unable to expand via the builtin, stop the sequence
1917 (without outputting the insns) and call to the library function
1918 with the stabilized argument list. */
53800dbe 1919 end_sequence ();
53800dbe 1920 }
1921
bd421108 1922 before_call = get_last_insn ();
1923
1924 target = expand_call (exp, target, target == const0_rtx);
53800dbe 1925
bd421108 1926 /* If this is a sqrt operation and we don't care about errno, try to
1927 attach a REG_EQUAL note with a SQRT rtx to the emitted libcall.
1928 This allows the semantics of the libcall to be visible to the RTL
1929 optimizers. */
1930 if (builtin_optab == sqrt_optab && !errno_set)
1931 {
1932 /* Search backwards through the insns emitted by expand_call looking
1933 for the instruction with the REG_RETVAL note. */
1934 rtx last = get_last_insn ();
1935 while (last != before_call)
1936 {
1937 if (find_reg_note (last, REG_RETVAL, NULL))
1938 {
1939 rtx note = find_reg_note (last, REG_EQUAL, NULL);
1940 /* Check that the REQ_EQUAL note is an EXPR_LIST with
1941 two elements, i.e. symbol_ref(sqrt) and the operand. */
1942 if (note
1943 && GET_CODE (note) == EXPR_LIST
1944 && GET_CODE (XEXP (note, 0)) == EXPR_LIST
1945 && XEXP (XEXP (note, 0), 1) != NULL_RTX
1946 && XEXP (XEXP (XEXP (note, 0), 1), 1) == NULL_RTX)
1947 {
1948 rtx operand = XEXP (XEXP (XEXP (note, 0), 1), 0);
1949 /* Check operand is a register with expected mode. */
1950 if (operand
8ad4c111 1951 && REG_P (operand)
bd421108 1952 && GET_MODE (operand) == mode)
1953 {
1954 /* Replace the REG_EQUAL note with a SQRT rtx. */
1955 rtx equiv = gen_rtx_SQRT (mode, operand);
1956 set_unique_reg_note (last, REG_EQUAL, equiv);
1957 }
1958 }
1959 break;
1960 }
1961 last = PREV_INSN (last);
1962 }
1963 }
0fd605a5 1964
1965 return target;
1966}
1967
1968/* Expand a call to the builtin binary math functions (pow and atan2).
c2f47e15 1969 Return NULL_RTX if a normal call should be emitted rather than expanding the
0fd605a5 1970 function in-line. EXP is the expression that is a call to the builtin
1971 function; if convenient, the result should be placed in TARGET.
1972 SUBTARGET may be used as the target for computing one of EXP's
1973 operands. */
1974
1975static rtx
aecda0d6 1976expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
0fd605a5 1977{
1978 optab builtin_optab;
1979 rtx op0, op1, insns;
4737caf2 1980 int op1_type = REAL_TYPE;
c6e6ecb1 1981 tree fndecl = get_callee_fndecl (exp);
c2f47e15 1982 tree arg0, arg1, narg;
7f05340e 1983 enum machine_mode mode;
0fd605a5 1984 bool errno_set = true;
1985 bool stable = true;
1986
73a954a1 1987 switch (DECL_FUNCTION_CODE (fndecl))
1988 {
1989 CASE_FLT_FN (BUILT_IN_SCALBN):
1990 CASE_FLT_FN (BUILT_IN_SCALBLN):
1991 CASE_FLT_FN (BUILT_IN_LDEXP):
1992 op1_type = INTEGER_TYPE;
1993 default:
1994 break;
1995 }
4737caf2 1996
c2f47e15 1997 if (!validate_arglist (exp, REAL_TYPE, op1_type, VOID_TYPE))
1998 return NULL_RTX;
0fd605a5 1999
c2f47e15 2000 arg0 = CALL_EXPR_ARG (exp, 0);
2001 arg1 = CALL_EXPR_ARG (exp, 1);
0fd605a5 2002
0fd605a5 2003 switch (DECL_FUNCTION_CODE (fndecl))
2004 {
4f35b1fc 2005 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 2006 builtin_optab = pow_optab; break;
4f35b1fc 2007 CASE_FLT_FN (BUILT_IN_ATAN2):
0fd605a5 2008 builtin_optab = atan2_optab; break;
73a954a1 2009 CASE_FLT_FN (BUILT_IN_SCALB):
2010 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2011 return 0;
2012 builtin_optab = scalb_optab; break;
2013 CASE_FLT_FN (BUILT_IN_SCALBN):
2014 CASE_FLT_FN (BUILT_IN_SCALBLN):
2015 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2016 return 0;
2017 /* Fall through... */
4f35b1fc 2018 CASE_FLT_FN (BUILT_IN_LDEXP):
4737caf2 2019 builtin_optab = ldexp_optab; break;
4f35b1fc 2020 CASE_FLT_FN (BUILT_IN_FMOD):
80ed5c06 2021 builtin_optab = fmod_optab; break;
ef722005 2022 CASE_FLT_FN (BUILT_IN_REMAINDER):
4f35b1fc 2023 CASE_FLT_FN (BUILT_IN_DREM):
ef722005 2024 builtin_optab = remainder_optab; break;
0fd605a5 2025 default:
64db345d 2026 gcc_unreachable ();
0fd605a5 2027 }
2028
7f05340e 2029 /* Make a suitable register to place result in. */
2030 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2031
2032 /* Before working hard, check whether the instruction is available. */
99bdde56 2033 if (optab_handler (builtin_optab, mode)->insn_code == CODE_FOR_nothing)
c2f47e15 2034 return NULL_RTX;
fc4eef90 2035
7f05340e 2036 target = gen_reg_rtx (mode);
2037
2038 if (! flag_errno_math || ! HONOR_NANS (mode))
2039 errno_set = false;
2040
4ee9c684 2041 /* Always stabilize the argument list. */
2042 narg = builtin_save_expr (arg1);
68e6cb9d 2043 if (narg != arg1)
7f05340e 2044 {
9a5acb98 2045 arg1 = narg;
68e6cb9d 2046 stable = false;
2047 }
4ee9c684 2048 narg = builtin_save_expr (arg0);
68e6cb9d 2049 if (narg != arg0)
2050 {
9a5acb98 2051 arg0 = narg;
68e6cb9d 2052 stable = false;
7f05340e 2053 }
68e6cb9d 2054
2055 if (! stable)
c2f47e15 2056 exp = build_call_expr (fndecl, 2, arg0, arg1);
7f05340e 2057
8ec3c5c2 2058 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2059 op1 = expand_normal (arg1);
7f05340e 2060
7f05340e 2061 start_sequence ();
2062
0fd605a5 2063 /* Compute into TARGET.
2064 Set TARGET to wherever the result comes back. */
7f05340e 2065 target = expand_binop (mode, builtin_optab, op0, op1,
0fd605a5 2066 target, 0, OPTAB_DIRECT);
53800dbe 2067
68e6cb9d 2068 /* If we were unable to expand via the builtin, stop the sequence
2069 (without outputting the insns) and call to the library function
2070 with the stabilized argument list. */
0fd605a5 2071 if (target == 0)
2072 {
2073 end_sequence ();
68e6cb9d 2074 return expand_call (exp, target, target == const0_rtx);
53800dbe 2075 }
2076
a4356fb9 2077 if (errno_set)
2078 expand_errno_check (exp, target);
0fd605a5 2079
53800dbe 2080 /* Output the entire sequence. */
2081 insns = get_insns ();
2082 end_sequence ();
31d3e01c 2083 emit_insn (insns);
bf8e3599 2084
53800dbe 2085 return target;
2086}
2087
6b43bae4 2088/* Expand a call to the builtin sin and cos math functions.
c2f47e15 2089 Return NULL_RTX if a normal call should be emitted rather than expanding the
6b43bae4 2090 function in-line. EXP is the expression that is a call to the builtin
2091 function; if convenient, the result should be placed in TARGET.
2092 SUBTARGET may be used as the target for computing one of EXP's
2093 operands. */
2094
2095static rtx
2096expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
2097{
2098 optab builtin_optab;
7511b819 2099 rtx op0, insns;
6b43bae4 2100 tree fndecl = get_callee_fndecl (exp);
6b43bae4 2101 enum machine_mode mode;
6b43bae4 2102 tree arg, narg;
2103
c2f47e15 2104 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2105 return NULL_RTX;
6b43bae4 2106
c2f47e15 2107 arg = CALL_EXPR_ARG (exp, 0);
6b43bae4 2108
2109 switch (DECL_FUNCTION_CODE (fndecl))
2110 {
4f35b1fc 2111 CASE_FLT_FN (BUILT_IN_SIN):
2112 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2113 builtin_optab = sincos_optab; break;
2114 default:
64db345d 2115 gcc_unreachable ();
6b43bae4 2116 }
2117
2118 /* Make a suitable register to place result in. */
2119 mode = TYPE_MODE (TREE_TYPE (exp));
2120
6b43bae4 2121 /* Check if sincos insn is available, otherwise fallback
0bed3869 2122 to sin or cos insn. */
99bdde56 2123 if (optab_handler (builtin_optab, mode)->insn_code == CODE_FOR_nothing)
6b43bae4 2124 switch (DECL_FUNCTION_CODE (fndecl))
2125 {
4f35b1fc 2126 CASE_FLT_FN (BUILT_IN_SIN):
6b43bae4 2127 builtin_optab = sin_optab; break;
4f35b1fc 2128 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2129 builtin_optab = cos_optab; break;
2130 default:
64db345d 2131 gcc_unreachable ();
6b43bae4 2132 }
6b43bae4 2133
2134 /* Before working hard, check whether the instruction is available. */
99bdde56 2135 if (optab_handler (builtin_optab, mode)->insn_code != CODE_FOR_nothing)
6b43bae4 2136 {
2137 target = gen_reg_rtx (mode);
2138
2139 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2140 need to expand the argument again. This way, we will not perform
2141 side-effects more the once. */
2142 narg = save_expr (arg);
2143 if (narg != arg)
2144 {
9a5acb98 2145 arg = narg;
c2f47e15 2146 exp = build_call_expr (fndecl, 1, arg);
6b43bae4 2147 }
2148
1db6d067 2149 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
6b43bae4 2150
6b43bae4 2151 start_sequence ();
2152
2153 /* Compute into TARGET.
2154 Set TARGET to wherever the result comes back. */
2155 if (builtin_optab == sincos_optab)
2156 {
64db345d 2157 int result;
7d3f6cc7 2158
6b43bae4 2159 switch (DECL_FUNCTION_CODE (fndecl))
2160 {
4f35b1fc 2161 CASE_FLT_FN (BUILT_IN_SIN):
64db345d 2162 result = expand_twoval_unop (builtin_optab, op0, 0, target, 0);
6b43bae4 2163 break;
4f35b1fc 2164 CASE_FLT_FN (BUILT_IN_COS):
64db345d 2165 result = expand_twoval_unop (builtin_optab, op0, target, 0, 0);
6b43bae4 2166 break;
2167 default:
64db345d 2168 gcc_unreachable ();
6b43bae4 2169 }
64db345d 2170 gcc_assert (result);
6b43bae4 2171 }
2172 else
2173 {
2174 target = expand_unop (mode, builtin_optab, op0, target, 0);
2175 }
2176
2177 if (target != 0)
2178 {
6b43bae4 2179 /* Output the entire sequence. */
2180 insns = get_insns ();
2181 end_sequence ();
2182 emit_insn (insns);
2183 return target;
2184 }
2185
2186 /* If we were unable to expand via the builtin, stop the sequence
2187 (without outputting the insns) and call to the library function
2188 with the stabilized argument list. */
2189 end_sequence ();
2190 }
2191
6b43bae4 2192 target = expand_call (exp, target, target == const0_rtx);
2193
2194 return target;
2195}
2196
a67a90e5 2197/* Expand a call to one of the builtin math functions that operate on
2198 floating point argument and output an integer result (ilogb, isinf,
2199 isnan, etc).
2200 Return 0 if a normal call should be emitted rather than expanding the
2201 function in-line. EXP is the expression that is a call to the builtin
2202 function; if convenient, the result should be placed in TARGET.
2203 SUBTARGET may be used as the target for computing one of EXP's operands. */
2204
2205static rtx
2206expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
2207{
cde061c1 2208 optab builtin_optab = 0;
2209 enum insn_code icode = CODE_FOR_nothing;
a67a90e5 2210 rtx op0;
2211 tree fndecl = get_callee_fndecl (exp);
a67a90e5 2212 enum machine_mode mode;
2213 bool errno_set = false;
2214 tree arg, narg;
2215
c2f47e15 2216 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2217 return NULL_RTX;
a67a90e5 2218
c2f47e15 2219 arg = CALL_EXPR_ARG (exp, 0);
a67a90e5 2220
2221 switch (DECL_FUNCTION_CODE (fndecl))
2222 {
2223 CASE_FLT_FN (BUILT_IN_ILOGB):
2224 errno_set = true; builtin_optab = ilogb_optab; break;
69b779ea 2225 CASE_FLT_FN (BUILT_IN_ISINF):
2226 builtin_optab = isinf_optab; break;
8a1a9cb7 2227 case BUILT_IN_ISNORMAL:
cde061c1 2228 case BUILT_IN_ISFINITE:
2229 CASE_FLT_FN (BUILT_IN_FINITE):
2230 /* These builtins have no optabs (yet). */
2231 break;
a67a90e5 2232 default:
2233 gcc_unreachable ();
2234 }
2235
2236 /* There's no easy way to detect the case we need to set EDOM. */
2237 if (flag_errno_math && errno_set)
2238 return NULL_RTX;
2239
2240 /* Optab mode depends on the mode of the input argument. */
2241 mode = TYPE_MODE (TREE_TYPE (arg));
2242
cde061c1 2243 if (builtin_optab)
99bdde56 2244 icode = optab_handler (builtin_optab, mode)->insn_code;
a67a90e5 2245
2246 /* Before working hard, check whether the instruction is available. */
2247 if (icode != CODE_FOR_nothing)
2248 {
2249 /* Make a suitable register to place result in. */
2250 if (!target
2251 || GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
2252 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
2253
2254 gcc_assert (insn_data[icode].operand[0].predicate
2255 (target, GET_MODE (target)));
2256
2257 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2258 need to expand the argument again. This way, we will not perform
2259 side-effects more the once. */
2260 narg = builtin_save_expr (arg);
2261 if (narg != arg)
2262 {
2263 arg = narg;
c2f47e15 2264 exp = build_call_expr (fndecl, 1, arg);
a67a90e5 2265 }
2266
1db6d067 2267 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
a67a90e5 2268
2269 if (mode != GET_MODE (op0))
2270 op0 = convert_to_mode (mode, op0, 0);
2271
2272 /* Compute into TARGET.
2273 Set TARGET to wherever the result comes back. */
2274 emit_unop_insn (icode, target, op0, UNKNOWN);
2275 return target;
2276 }
2277
06f7a99d 2278 /* If there is no optab, try generic code. */
2279 switch (DECL_FUNCTION_CODE (fndecl))
2280 {
2281 tree result;
2282
2283 CASE_FLT_FN (BUILT_IN_ISINF):
2284 {
2285 /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
2286 tree const isgr_fn = built_in_decls[BUILT_IN_ISGREATER];
2287 tree const type = TREE_TYPE (arg);
2288 REAL_VALUE_TYPE r;
2289 char buf[128];
2290
2291 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
2292 real_from_string (&r, buf);
2293 result = build_call_expr (isgr_fn, 2,
2294 fold_build1 (ABS_EXPR, type, arg),
2295 build_real (type, r));
2296 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
2297 }
cde061c1 2298 CASE_FLT_FN (BUILT_IN_FINITE):
2299 case BUILT_IN_ISFINITE:
2300 {
2301 /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
2302 tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
2303 tree const type = TREE_TYPE (arg);
2304 REAL_VALUE_TYPE r;
2305 char buf[128];
2306
2307 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
2308 real_from_string (&r, buf);
2309 result = build_call_expr (isle_fn, 2,
2310 fold_build1 (ABS_EXPR, type, arg),
2311 build_real (type, r));
2312 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
2313 }
8a1a9cb7 2314 case BUILT_IN_ISNORMAL:
2315 {
2316 /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
2317 islessequal(fabs(x),DBL_MAX). */
2318 tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
2319 tree const isge_fn = built_in_decls[BUILT_IN_ISGREATEREQUAL];
2320 tree const type = TREE_TYPE (arg);
2321 REAL_VALUE_TYPE rmax, rmin;
2322 char buf[128];
2323
2324 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
2325 real_from_string (&rmax, buf);
2326 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
2327 real_from_string (&rmin, buf);
2328 arg = builtin_save_expr (fold_build1 (ABS_EXPR, type, arg));
2329 result = build_call_expr (isle_fn, 2, arg,
2330 build_real (type, rmax));
2331 result = fold_build2 (BIT_AND_EXPR, integer_type_node, result,
2332 build_call_expr (isge_fn, 2, arg,
2333 build_real (type, rmin)));
2334 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
2335 }
06f7a99d 2336 default:
2337 break;
2338 }
2339
a67a90e5 2340 target = expand_call (exp, target, target == const0_rtx);
2341
2342 return target;
2343}
2344
c3147c1a 2345/* Expand a call to the builtin sincos math function.
c2f47e15 2346 Return NULL_RTX if a normal call should be emitted rather than expanding the
c3147c1a 2347 function in-line. EXP is the expression that is a call to the builtin
2348 function. */
2349
2350static rtx
2351expand_builtin_sincos (tree exp)
2352{
2353 rtx op0, op1, op2, target1, target2;
c3147c1a 2354 enum machine_mode mode;
2355 tree arg, sinp, cosp;
2356 int result;
2357
c2f47e15 2358 if (!validate_arglist (exp, REAL_TYPE,
2359 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2360 return NULL_RTX;
c3147c1a 2361
c2f47e15 2362 arg = CALL_EXPR_ARG (exp, 0);
2363 sinp = CALL_EXPR_ARG (exp, 1);
2364 cosp = CALL_EXPR_ARG (exp, 2);
c3147c1a 2365
2366 /* Make a suitable register to place result in. */
2367 mode = TYPE_MODE (TREE_TYPE (arg));
2368
2369 /* Check if sincos insn is available, otherwise emit the call. */
99bdde56 2370 if (optab_handler (sincos_optab, mode)->insn_code == CODE_FOR_nothing)
c3147c1a 2371 return NULL_RTX;
2372
2373 target1 = gen_reg_rtx (mode);
2374 target2 = gen_reg_rtx (mode);
2375
8ec3c5c2 2376 op0 = expand_normal (arg);
2377 op1 = expand_normal (build_fold_indirect_ref (sinp));
2378 op2 = expand_normal (build_fold_indirect_ref (cosp));
c3147c1a 2379
2380 /* Compute into target1 and target2.
2381 Set TARGET to wherever the result comes back. */
2382 result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
2383 gcc_assert (result);
2384
2385 /* Move target1 and target2 to the memory locations indicated
2386 by op1 and op2. */
2387 emit_move_insn (op1, target1);
2388 emit_move_insn (op2, target2);
2389
2390 return const0_rtx;
2391}
2392
d735c391 2393/* Expand a call to the internal cexpi builtin to the sincos math function.
2394 EXP is the expression that is a call to the builtin function; if convenient,
2395 the result should be placed in TARGET. SUBTARGET may be used as the target
2396 for computing one of EXP's operands. */
2397
2398static rtx
2399expand_builtin_cexpi (tree exp, rtx target, rtx subtarget)
2400{
2401 tree fndecl = get_callee_fndecl (exp);
d735c391 2402 tree arg, type;
c2f47e15 2403 enum machine_mode mode;
d735c391 2404 rtx op0, op1, op2;
2405
c2f47e15 2406 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2407 return NULL_RTX;
d735c391 2408
c2f47e15 2409 arg = CALL_EXPR_ARG (exp, 0);
d735c391 2410 type = TREE_TYPE (arg);
2411 mode = TYPE_MODE (TREE_TYPE (arg));
2412
2413 /* Try expanding via a sincos optab, fall back to emitting a libcall
18b8d8ae 2414 to sincos or cexp. We are sure we have sincos or cexp because cexpi
2415 is only generated from sincos, cexp or if we have either of them. */
99bdde56 2416 if (optab_handler (sincos_optab, mode)->insn_code != CODE_FOR_nothing)
d735c391 2417 {
2418 op1 = gen_reg_rtx (mode);
2419 op2 = gen_reg_rtx (mode);
2420
1db6d067 2421 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
d735c391 2422
2423 /* Compute into op1 and op2. */
2424 expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
2425 }
18b8d8ae 2426 else if (TARGET_HAS_SINCOS)
d735c391 2427 {
c2f47e15 2428 tree call, fn = NULL_TREE;
d735c391 2429 tree top1, top2;
2430 rtx op1a, op2a;
2431
2432 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2433 fn = built_in_decls[BUILT_IN_SINCOSF];
2434 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2435 fn = built_in_decls[BUILT_IN_SINCOS];
2436 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2437 fn = built_in_decls[BUILT_IN_SINCOSL];
c2f47e15 2438 else
2439 gcc_unreachable ();
d735c391 2440
2441 op1 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
2442 op2 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
2443 op1a = copy_to_mode_reg (Pmode, XEXP (op1, 0));
2444 op2a = copy_to_mode_reg (Pmode, XEXP (op2, 0));
2445 top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
2446 top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
2447
d735c391 2448 /* Make sure not to fold the sincos call again. */
2449 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
c2f47e15 2450 expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
2451 call, 3, arg, top1, top2));
d735c391 2452 }
18b8d8ae 2453 else
2454 {
0ecbc158 2455 tree call, fn = NULL_TREE, narg;
18b8d8ae 2456 tree ctype = build_complex_type (type);
2457
0ecbc158 2458 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2459 fn = built_in_decls[BUILT_IN_CEXPF];
2460 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2461 fn = built_in_decls[BUILT_IN_CEXP];
2462 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2463 fn = built_in_decls[BUILT_IN_CEXPL];
c2f47e15 2464 else
2465 gcc_unreachable ();
fc0dfa6e 2466
2467 /* If we don't have a decl for cexp create one. This is the
2468 friendliest fallback if the user calls __builtin_cexpi
2469 without full target C99 function support. */
2470 if (fn == NULL_TREE)
2471 {
2472 tree fntype;
2473 const char *name = NULL;
2474
2475 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2476 name = "cexpf";
2477 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2478 name = "cexp";
2479 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2480 name = "cexpl";
2481
2482 fntype = build_function_type_list (ctype, ctype, NULL_TREE);
2483 fn = build_fn_decl (name, fntype);
2484 }
2485
18b8d8ae 2486 narg = fold_build2 (COMPLEX_EXPR, ctype,
2487 build_real (type, dconst0), arg);
2488
2489 /* Make sure not to fold the cexp call again. */
2490 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
3737e769 2491 return expand_expr (build_call_nary (ctype, call, 1, narg),
1db6d067 2492 target, VOIDmode, EXPAND_NORMAL);
18b8d8ae 2493 }
d735c391 2494
2495 /* Now build the proper return type. */
2496 return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
2497 make_tree (TREE_TYPE (arg), op2),
2498 make_tree (TREE_TYPE (arg), op1)),
1db6d067 2499 target, VOIDmode, EXPAND_NORMAL);
d735c391 2500}
2501
7d3afc77 2502/* Expand a call to one of the builtin rounding functions gcc defines
2503 as an extension (lfloor and lceil). As these are gcc extensions we
2504 do not need to worry about setting errno to EDOM.
ad52b9b7 2505 If expanding via optab fails, lower expression to (int)(floor(x)).
2506 EXP is the expression that is a call to the builtin function;
2507 if convenient, the result should be placed in TARGET. SUBTARGET may
2508 be used as the target for computing one of EXP's operands. */
2509
2510static rtx
2511expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget)
2512{
9c42dd28 2513 convert_optab builtin_optab;
ad52b9b7 2514 rtx op0, insns, tmp;
2515 tree fndecl = get_callee_fndecl (exp);
ad52b9b7 2516 enum built_in_function fallback_fn;
2517 tree fallback_fndecl;
2518 enum machine_mode mode;
2519 tree arg, narg;
2520
c2f47e15 2521 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
ad52b9b7 2522 gcc_unreachable ();
2523
c2f47e15 2524 arg = CALL_EXPR_ARG (exp, 0);
ad52b9b7 2525
2526 switch (DECL_FUNCTION_CODE (fndecl))
2527 {
4f35b1fc 2528 CASE_FLT_FN (BUILT_IN_LCEIL):
2529 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 2530 builtin_optab = lceil_optab;
2531 fallback_fn = BUILT_IN_CEIL;
2532 break;
2533
4f35b1fc 2534 CASE_FLT_FN (BUILT_IN_LFLOOR):
2535 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 2536 builtin_optab = lfloor_optab;
2537 fallback_fn = BUILT_IN_FLOOR;
2538 break;
2539
2540 default:
2541 gcc_unreachable ();
2542 }
2543
2544 /* Make a suitable register to place result in. */
2545 mode = TYPE_MODE (TREE_TYPE (exp));
2546
9c42dd28 2547 target = gen_reg_rtx (mode);
ad52b9b7 2548
9c42dd28 2549 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2550 need to expand the argument again. This way, we will not perform
2551 side-effects more the once. */
2552 narg = builtin_save_expr (arg);
2553 if (narg != arg)
2554 {
2555 arg = narg;
c2f47e15 2556 exp = build_call_expr (fndecl, 1, arg);
9c42dd28 2557 }
ad52b9b7 2558
1db6d067 2559 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
ad52b9b7 2560
9c42dd28 2561 start_sequence ();
ad52b9b7 2562
9c42dd28 2563 /* Compute into TARGET. */
2564 if (expand_sfix_optab (target, op0, builtin_optab))
2565 {
2566 /* Output the entire sequence. */
2567 insns = get_insns ();
ad52b9b7 2568 end_sequence ();
9c42dd28 2569 emit_insn (insns);
2570 return target;
ad52b9b7 2571 }
2572
9c42dd28 2573 /* If we were unable to expand via the builtin, stop the sequence
2574 (without outputting the insns). */
2575 end_sequence ();
2576
ad52b9b7 2577 /* Fall back to floating point rounding optab. */
2578 fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
fc0dfa6e 2579
2580 /* For non-C99 targets we may end up without a fallback fndecl here
2581 if the user called __builtin_lfloor directly. In this case emit
2582 a call to the floor/ceil variants nevertheless. This should result
2583 in the best user experience for not full C99 targets. */
2584 if (fallback_fndecl == NULL_TREE)
2585 {
2586 tree fntype;
2587 const char *name = NULL;
2588
2589 switch (DECL_FUNCTION_CODE (fndecl))
2590 {
2591 case BUILT_IN_LCEIL:
2592 case BUILT_IN_LLCEIL:
2593 name = "ceil";
2594 break;
2595 case BUILT_IN_LCEILF:
2596 case BUILT_IN_LLCEILF:
2597 name = "ceilf";
2598 break;
2599 case BUILT_IN_LCEILL:
2600 case BUILT_IN_LLCEILL:
2601 name = "ceill";
2602 break;
2603 case BUILT_IN_LFLOOR:
2604 case BUILT_IN_LLFLOOR:
2605 name = "floor";
2606 break;
2607 case BUILT_IN_LFLOORF:
2608 case BUILT_IN_LLFLOORF:
2609 name = "floorf";
2610 break;
2611 case BUILT_IN_LFLOORL:
2612 case BUILT_IN_LLFLOORL:
2613 name = "floorl";
2614 break;
2615 default:
2616 gcc_unreachable ();
2617 }
2618
2619 fntype = build_function_type_list (TREE_TYPE (arg),
2620 TREE_TYPE (arg), NULL_TREE);
2621 fallback_fndecl = build_fn_decl (name, fntype);
2622 }
2623
c2f47e15 2624 exp = build_call_expr (fallback_fndecl, 1, arg);
ad52b9b7 2625
d4c690af 2626 tmp = expand_normal (exp);
ad52b9b7 2627
2628 /* Truncate the result of floating point optab to integer
2629 via expand_fix (). */
2630 target = gen_reg_rtx (mode);
2631 expand_fix (target, tmp, 0);
2632
2633 return target;
2634}
2635
7d3afc77 2636/* Expand a call to one of the builtin math functions doing integer
2637 conversion (lrint).
2638 Return 0 if a normal call should be emitted rather than expanding the
2639 function in-line. EXP is the expression that is a call to the builtin
2640 function; if convenient, the result should be placed in TARGET.
2641 SUBTARGET may be used as the target for computing one of EXP's operands. */
2642
2643static rtx
2644expand_builtin_int_roundingfn_2 (tree exp, rtx target, rtx subtarget)
2645{
5f51ee59 2646 convert_optab builtin_optab;
7d3afc77 2647 rtx op0, insns;
2648 tree fndecl = get_callee_fndecl (exp);
7d3afc77 2649 tree arg, narg;
c2f47e15 2650 enum machine_mode mode;
7d3afc77 2651
2652 /* There's no easy way to detect the case we need to set EDOM. */
2653 if (flag_errno_math)
2654 return NULL_RTX;
2655
c2f47e15 2656 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2657 gcc_unreachable ();
2658
2659 arg = CALL_EXPR_ARG (exp, 0);
7d3afc77 2660
2661 switch (DECL_FUNCTION_CODE (fndecl))
2662 {
2663 CASE_FLT_FN (BUILT_IN_LRINT):
2664 CASE_FLT_FN (BUILT_IN_LLRINT):
2665 builtin_optab = lrint_optab; break;
ef2f1a10 2666 CASE_FLT_FN (BUILT_IN_LROUND):
2667 CASE_FLT_FN (BUILT_IN_LLROUND):
2668 builtin_optab = lround_optab; break;
7d3afc77 2669 default:
2670 gcc_unreachable ();
2671 }
2672
2673 /* Make a suitable register to place result in. */
2674 mode = TYPE_MODE (TREE_TYPE (exp));
2675
5f51ee59 2676 target = gen_reg_rtx (mode);
7d3afc77 2677
5f51ee59 2678 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2679 need to expand the argument again. This way, we will not perform
2680 side-effects more the once. */
2681 narg = builtin_save_expr (arg);
2682 if (narg != arg)
2683 {
2684 arg = narg;
c2f47e15 2685 exp = build_call_expr (fndecl, 1, arg);
5f51ee59 2686 }
7d3afc77 2687
1db6d067 2688 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
7d3afc77 2689
5f51ee59 2690 start_sequence ();
7d3afc77 2691
5f51ee59 2692 if (expand_sfix_optab (target, op0, builtin_optab))
2693 {
2694 /* Output the entire sequence. */
2695 insns = get_insns ();
7d3afc77 2696 end_sequence ();
5f51ee59 2697 emit_insn (insns);
2698 return target;
7d3afc77 2699 }
2700
5f51ee59 2701 /* If we were unable to expand via the builtin, stop the sequence
2702 (without outputting the insns) and call to the library function
2703 with the stabilized argument list. */
2704 end_sequence ();
2705
7d3afc77 2706 target = expand_call (exp, target, target == const0_rtx);
2707
2708 return target;
2709}
2710
f1b844c6 2711/* To evaluate powi(x,n), the floating point value x raised to the
2712 constant integer exponent n, we use a hybrid algorithm that
2713 combines the "window method" with look-up tables. For an
2714 introduction to exponentiation algorithms and "addition chains",
2715 see section 4.6.3, "Evaluation of Powers" of Donald E. Knuth,
2716 "Seminumerical Algorithms", Vol. 2, "The Art of Computer Programming",
2717 3rd Edition, 1998, and Daniel M. Gordon, "A Survey of Fast Exponentiation
2718 Methods", Journal of Algorithms, Vol. 27, pp. 129-146, 1998. */
2719
2720/* Provide a default value for POWI_MAX_MULTS, the maximum number of
2721 multiplications to inline before calling the system library's pow
2722 function. powi(x,n) requires at worst 2*bits(n)-2 multiplications,
2723 so this default never requires calling pow, powf or powl. */
0862b7e9 2724
f1b844c6 2725#ifndef POWI_MAX_MULTS
2726#define POWI_MAX_MULTS (2*HOST_BITS_PER_WIDE_INT-2)
2727#endif
2728
2729/* The size of the "optimal power tree" lookup table. All
2730 exponents less than this value are simply looked up in the
2731 powi_table below. This threshold is also used to size the
2732 cache of pseudo registers that hold intermediate results. */
2733#define POWI_TABLE_SIZE 256
2734
2735/* The size, in bits of the window, used in the "window method"
2736 exponentiation algorithm. This is equivalent to a radix of
2737 (1<<POWI_WINDOW_SIZE) in the corresponding "m-ary method". */
2738#define POWI_WINDOW_SIZE 3
2739
2740/* The following table is an efficient representation of an
2741 "optimal power tree". For each value, i, the corresponding
2742 value, j, in the table states than an optimal evaluation
2743 sequence for calculating pow(x,i) can be found by evaluating
2744 pow(x,j)*pow(x,i-j). An optimal power tree for the first
2745 100 integers is given in Knuth's "Seminumerical algorithms". */
2746
2747static const unsigned char powi_table[POWI_TABLE_SIZE] =
2748 {
2749 0, 1, 1, 2, 2, 3, 3, 4, /* 0 - 7 */
2750 4, 6, 5, 6, 6, 10, 7, 9, /* 8 - 15 */
2751 8, 16, 9, 16, 10, 12, 11, 13, /* 16 - 23 */
2752 12, 17, 13, 18, 14, 24, 15, 26, /* 24 - 31 */
2753 16, 17, 17, 19, 18, 33, 19, 26, /* 32 - 39 */
2754 20, 25, 21, 40, 22, 27, 23, 44, /* 40 - 47 */
2755 24, 32, 25, 34, 26, 29, 27, 44, /* 48 - 55 */
2756 28, 31, 29, 34, 30, 60, 31, 36, /* 56 - 63 */
2757 32, 64, 33, 34, 34, 46, 35, 37, /* 64 - 71 */
2758 36, 65, 37, 50, 38, 48, 39, 69, /* 72 - 79 */
2759 40, 49, 41, 43, 42, 51, 43, 58, /* 80 - 87 */
2760 44, 64, 45, 47, 46, 59, 47, 76, /* 88 - 95 */
2761 48, 65, 49, 66, 50, 67, 51, 66, /* 96 - 103 */
2762 52, 70, 53, 74, 54, 104, 55, 74, /* 104 - 111 */
2763 56, 64, 57, 69, 58, 78, 59, 68, /* 112 - 119 */
2764 60, 61, 61, 80, 62, 75, 63, 68, /* 120 - 127 */
2765 64, 65, 65, 128, 66, 129, 67, 90, /* 128 - 135 */
2766 68, 73, 69, 131, 70, 94, 71, 88, /* 136 - 143 */
2767 72, 128, 73, 98, 74, 132, 75, 121, /* 144 - 151 */
2768 76, 102, 77, 124, 78, 132, 79, 106, /* 152 - 159 */
2769 80, 97, 81, 160, 82, 99, 83, 134, /* 160 - 167 */
2770 84, 86, 85, 95, 86, 160, 87, 100, /* 168 - 175 */
2771 88, 113, 89, 98, 90, 107, 91, 122, /* 176 - 183 */
2772 92, 111, 93, 102, 94, 126, 95, 150, /* 184 - 191 */
2773 96, 128, 97, 130, 98, 133, 99, 195, /* 192 - 199 */
2774 100, 128, 101, 123, 102, 164, 103, 138, /* 200 - 207 */
2775 104, 145, 105, 146, 106, 109, 107, 149, /* 208 - 215 */
2776 108, 200, 109, 146, 110, 170, 111, 157, /* 216 - 223 */
2777 112, 128, 113, 130, 114, 182, 115, 132, /* 224 - 231 */
2778 116, 200, 117, 132, 118, 158, 119, 206, /* 232 - 239 */
2779 120, 240, 121, 162, 122, 147, 123, 152, /* 240 - 247 */
2780 124, 166, 125, 214, 126, 138, 127, 153, /* 248 - 255 */
2781 };
2782
2783
2784/* Return the number of multiplications required to calculate
2785 powi(x,n) where n is less than POWI_TABLE_SIZE. This is a
2786 subroutine of powi_cost. CACHE is an array indicating
2787 which exponents have already been calculated. */
2788
2789static int
2790powi_lookup_cost (unsigned HOST_WIDE_INT n, bool *cache)
2791{
2792 /* If we've already calculated this exponent, then this evaluation
2793 doesn't require any additional multiplications. */
2794 if (cache[n])
2795 return 0;
2796
2797 cache[n] = true;
2798 return powi_lookup_cost (n - powi_table[n], cache)
2799 + powi_lookup_cost (powi_table[n], cache) + 1;
2800}
2801
2802/* Return the number of multiplications required to calculate
2803 powi(x,n) for an arbitrary x, given the exponent N. This
2804 function needs to be kept in sync with expand_powi below. */
2805
2806static int
2807powi_cost (HOST_WIDE_INT n)
2808{
2809 bool cache[POWI_TABLE_SIZE];
2810 unsigned HOST_WIDE_INT digit;
2811 unsigned HOST_WIDE_INT val;
2812 int result;
2813
2814 if (n == 0)
2815 return 0;
2816
2817 /* Ignore the reciprocal when calculating the cost. */
2818 val = (n < 0) ? -n : n;
2819
2820 /* Initialize the exponent cache. */
2821 memset (cache, 0, POWI_TABLE_SIZE * sizeof (bool));
2822 cache[1] = true;
2823
2824 result = 0;
2825
2826 while (val >= POWI_TABLE_SIZE)
2827 {
2828 if (val & 1)
2829 {
2830 digit = val & ((1 << POWI_WINDOW_SIZE) - 1);
2831 result += powi_lookup_cost (digit, cache)
2832 + POWI_WINDOW_SIZE + 1;
2833 val >>= POWI_WINDOW_SIZE;
2834 }
2835 else
2836 {
2837 val >>= 1;
2838 result++;
2839 }
2840 }
0862b7e9 2841
6881dbab 2842 return result + powi_lookup_cost (val, cache);
f1b844c6 2843}
2844
2845/* Recursive subroutine of expand_powi. This function takes the array,
2846 CACHE, of already calculated exponents and an exponent N and returns
2847 an RTX that corresponds to CACHE[1]**N, as calculated in mode MODE. */
2848
2849static rtx
2850expand_powi_1 (enum machine_mode mode, unsigned HOST_WIDE_INT n, rtx *cache)
2851{
2852 unsigned HOST_WIDE_INT digit;
2853 rtx target, result;
2854 rtx op0, op1;
2855
2856 if (n < POWI_TABLE_SIZE)
2857 {
2858 if (cache[n])
a0c938f0 2859 return cache[n];
f1b844c6 2860
2861 target = gen_reg_rtx (mode);
2862 cache[n] = target;
2863
2864 op0 = expand_powi_1 (mode, n - powi_table[n], cache);
2865 op1 = expand_powi_1 (mode, powi_table[n], cache);
2866 }
2867 else if (n & 1)
2868 {
2869 target = gen_reg_rtx (mode);
2870 digit = n & ((1 << POWI_WINDOW_SIZE) - 1);
2871 op0 = expand_powi_1 (mode, n - digit, cache);
2872 op1 = expand_powi_1 (mode, digit, cache);
2873 }
2874 else
2875 {
2876 target = gen_reg_rtx (mode);
2877 op0 = expand_powi_1 (mode, n >> 1, cache);
2878 op1 = op0;
2879 }
2880
2881 result = expand_mult (mode, op0, op1, target, 0);
2882 if (result != target)
2883 emit_move_insn (target, result);
2884 return target;
2885}
2886
2887/* Expand the RTL to evaluate powi(x,n) in mode MODE. X is the
2888 floating point operand in mode MODE, and N is the exponent. This
2889 function needs to be kept in sync with powi_cost above. */
0862b7e9 2890
f1b844c6 2891static rtx
2892expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n)
2893{
2894 unsigned HOST_WIDE_INT val;
2895 rtx cache[POWI_TABLE_SIZE];
2896 rtx result;
2897
2898 if (n == 0)
2899 return CONST1_RTX (mode);
2900
2901 val = (n < 0) ? -n : n;
2902
19bf118a 2903 memset (cache, 0, sizeof (cache));
f1b844c6 2904 cache[1] = x;
2905
2906 result = expand_powi_1 (mode, (n < 0) ? -n : n, cache);
2907
2908 /* If the original exponent was negative, reciprocate the result. */
2909 if (n < 0)
2910 result = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2911 result, NULL_RTX, 0, OPTAB_LIB_WIDEN);
2912
2913 return result;
2914}
2915
c2f47e15 2916/* Expand a call to the pow built-in mathematical function. Return NULL_RTX if
f1b844c6 2917 a normal call should be emitted rather than expanding the function
2918 in-line. EXP is the expression that is a call to the builtin
2919 function; if convenient, the result should be placed in TARGET. */
2920
2921static rtx
2922expand_builtin_pow (tree exp, rtx target, rtx subtarget)
2923{
c2f47e15 2924 tree arg0, arg1;
2925 tree fn, narg0;
1c4709b4 2926 tree type = TREE_TYPE (exp);
2927 REAL_VALUE_TYPE cint, c, c2;
2928 HOST_WIDE_INT n;
2929 rtx op, op2;
2930 enum machine_mode mode = TYPE_MODE (type);
f1b844c6 2931
c2f47e15 2932 if (! validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2933 return NULL_RTX;
f1b844c6 2934
c2f47e15 2935 arg0 = CALL_EXPR_ARG (exp, 0);
2936 arg1 = CALL_EXPR_ARG (exp, 1);
f1b844c6 2937
1c4709b4 2938 if (TREE_CODE (arg1) != REAL_CST
f96bd2bf 2939 || TREE_OVERFLOW (arg1))
1c4709b4 2940 return expand_builtin_mathfn_2 (exp, target, subtarget);
2941
2942 /* Handle constant exponents. */
2943
2944 /* For integer valued exponents we can expand to an optimal multiplication
2945 sequence using expand_powi. */
2946 c = TREE_REAL_CST (arg1);
2947 n = real_to_integer (&c);
2948 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
2949 if (real_identical (&c, &cint)
2950 && ((n >= -1 && n <= 2)
2951 || (flag_unsafe_math_optimizations
2952 && !optimize_size
2953 && powi_cost (n) <= POWI_MAX_MULTS)))
f1b844c6 2954 {
1db6d067 2955 op = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 2956 if (n != 1)
2957 {
2958 op = force_reg (mode, op);
2959 op = expand_powi (op, mode, n);
2960 }
2961 return op;
2962 }
2963
2964 narg0 = builtin_save_expr (arg0);
f1b844c6 2965
1c4709b4 2966 /* If the exponent is not integer valued, check if it is half of an integer.
2967 In this case we can expand to sqrt (x) * x**(n/2). */
2968 fn = mathfn_built_in (type, BUILT_IN_SQRT);
2969 if (fn != NULL_TREE)
2970 {
2971 real_arithmetic (&c2, MULT_EXPR, &c, &dconst2);
2972 n = real_to_integer (&c2);
f1b844c6 2973 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
1c4709b4 2974 if (real_identical (&c2, &cint)
2975 && ((flag_unsafe_math_optimizations
2976 && !optimize_size
2977 && powi_cost (n/2) <= POWI_MAX_MULTS)
2978 || n == 1))
f1b844c6 2979 {
c2f47e15 2980 tree call_expr = build_call_expr (fn, 1, narg0);
1c4709b4 2981 op = expand_builtin (call_expr, NULL_RTX, subtarget, mode, 0);
2982 if (n != 1)
8c5cac78 2983 {
1db6d067 2984 op2 = expand_expr (narg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 2985 op2 = force_reg (mode, op2);
2986 op2 = expand_powi (op2, mode, abs (n / 2));
2987 op = expand_simple_binop (mode, MULT, op, op2, NULL_RTX,
2988 0, OPTAB_LIB_WIDEN);
2989 /* If the original exponent was negative, reciprocate the
2990 result. */
2991 if (n < 0)
2992 op = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2993 op, NULL_RTX, 0, OPTAB_LIB_WIDEN);
8c5cac78 2994 }
1c4709b4 2995 return op;
f1b844c6 2996 }
2997 }
b613c2a6 2998
1c4709b4 2999 /* Try if the exponent is a third of an integer. In this case
5a84ba55 3000 we can expand to x**(n/3) * cbrt(x)**(n%3). As cbrt (x) is
3001 different from pow (x, 1./3.) due to rounding and behavior
3002 with negative x we need to constrain this transformation to
3003 unsafe math and positive x or finite math. */
1c4709b4 3004 fn = mathfn_built_in (type, BUILT_IN_CBRT);
5a84ba55 3005 if (fn != NULL_TREE
3006 && flag_unsafe_math_optimizations
3007 && (tree_expr_nonnegative_p (arg0)
3008 || !HONOR_NANS (mode)))
1c4709b4 3009 {
3010 real_arithmetic (&c2, MULT_EXPR, &c, &dconst3);
3011 real_round (&c2, mode, &c2);
3012 n = real_to_integer (&c2);
3013 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
3014 real_arithmetic (&c2, RDIV_EXPR, &cint, &dconst3);
3015 real_convert (&c2, mode, &c2);
3016 if (real_identical (&c2, &c)
3017 && ((!optimize_size
1c4709b4 3018 && powi_cost (n/3) <= POWI_MAX_MULTS)
3019 || n == 1))
3020 {
c2f47e15 3021 tree call_expr = build_call_expr (fn, 1,narg0);
1c4709b4 3022 op = expand_builtin (call_expr, NULL_RTX, subtarget, mode, 0);
3023 if (abs (n) % 3 == 2)
3024 op = expand_simple_binop (mode, MULT, op, op, op,
3025 0, OPTAB_LIB_WIDEN);
3026 if (n != 1)
3027 {
1db6d067 3028 op2 = expand_expr (narg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 3029 op2 = force_reg (mode, op2);
3030 op2 = expand_powi (op2, mode, abs (n / 3));
3031 op = expand_simple_binop (mode, MULT, op, op2, NULL_RTX,
3032 0, OPTAB_LIB_WIDEN);
3033 /* If the original exponent was negative, reciprocate the
3034 result. */
3035 if (n < 0)
3036 op = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
3037 op, NULL_RTX, 0, OPTAB_LIB_WIDEN);
3038 }
3039 return op;
3040 }
3041 }
3042
3043 /* Fall back to optab expansion. */
b613c2a6 3044 return expand_builtin_mathfn_2 (exp, target, subtarget);
f1b844c6 3045}
3046
c2f47e15 3047/* Expand a call to the powi built-in mathematical function. Return NULL_RTX if
757c219d 3048 a normal call should be emitted rather than expanding the function
3049 in-line. EXP is the expression that is a call to the builtin
3050 function; if convenient, the result should be placed in TARGET. */
3051
3052static rtx
3053expand_builtin_powi (tree exp, rtx target, rtx subtarget)
3054{
757c219d 3055 tree arg0, arg1;
3056 rtx op0, op1;
3057 enum machine_mode mode;
d0405f40 3058 enum machine_mode mode2;
757c219d 3059
c2f47e15 3060 if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
3061 return NULL_RTX;
757c219d 3062
c2f47e15 3063 arg0 = CALL_EXPR_ARG (exp, 0);
3064 arg1 = CALL_EXPR_ARG (exp, 1);
757c219d 3065 mode = TYPE_MODE (TREE_TYPE (exp));
3066
3067 /* Handle constant power. */
3068
3069 if (TREE_CODE (arg1) == INTEGER_CST
f96bd2bf 3070 && !TREE_OVERFLOW (arg1))
757c219d 3071 {
3072 HOST_WIDE_INT n = TREE_INT_CST_LOW (arg1);
3073
3074 /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
3075 Otherwise, check the number of multiplications required. */
3076 if ((TREE_INT_CST_HIGH (arg1) == 0
3077 || TREE_INT_CST_HIGH (arg1) == -1)
3078 && ((n >= -1 && n <= 2)
3079 || (! optimize_size
3080 && powi_cost (n) <= POWI_MAX_MULTS)))
3081 {
1db6d067 3082 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
757c219d 3083 op0 = force_reg (mode, op0);
3084 return expand_powi (op0, mode, n);
3085 }
3086 }
3087
3088 /* Emit a libcall to libgcc. */
3089
c2f47e15 3090 /* Mode of the 2nd argument must match that of an int. */
d0405f40 3091 mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
3092
757c219d 3093 if (target == NULL_RTX)
3094 target = gen_reg_rtx (mode);
3095
1db6d067 3096 op0 = expand_expr (arg0, subtarget, mode, EXPAND_NORMAL);
757c219d 3097 if (GET_MODE (op0) != mode)
3098 op0 = convert_to_mode (mode, op0, 0);
1db6d067 3099 op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
d0405f40 3100 if (GET_MODE (op1) != mode2)
3101 op1 = convert_to_mode (mode2, op1, 0);
757c219d 3102
99bdde56 3103 target = emit_library_call_value (optab_handler (powi_optab, mode)->libfunc,
757c219d 3104 target, LCT_CONST_MAKE_BLOCK, mode, 2,
d0405f40 3105 op0, mode, op1, mode2);
757c219d 3106
3107 return target;
3108}
3109
c2f47e15 3110/* Expand expression EXP which is a call to the strlen builtin. Return
3111 NULL_RTX if we failed the caller should emit a normal call, otherwise
aed0bd19 3112 try to get the result in TARGET, if convenient. */
f7c44134 3113
53800dbe 3114static rtx
c2f47e15 3115expand_builtin_strlen (tree exp, rtx target,
aecda0d6 3116 enum machine_mode target_mode)
53800dbe 3117{
c2f47e15 3118 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
3119 return NULL_RTX;
53800dbe 3120 else
3121 {
911c0150 3122 rtx pat;
c2f47e15 3123 tree len;
3124 tree src = CALL_EXPR_ARG (exp, 0);
911c0150 3125 rtx result, src_reg, char_rtx, before_strlen;
80cd7a5e 3126 enum machine_mode insn_mode = target_mode, char_mode;
ef2c4a29 3127 enum insn_code icode = CODE_FOR_nothing;
6248e345 3128 int align;
3129
3130 /* If the length can be computed at compile-time, return it. */
681fab1e 3131 len = c_strlen (src, 0);
6248e345 3132 if (len)
80cd7a5e 3133 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
6248e345 3134
681fab1e 3135 /* If the length can be computed at compile-time and is constant
3136 integer, but there are side-effects in src, evaluate
3137 src for side-effects, then return len.
3138 E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
3139 can be optimized into: i++; x = 3; */
3140 len = c_strlen (src, 1);
3141 if (len && TREE_CODE (len) == INTEGER_CST)
3142 {
3143 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
3144 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
3145 }
3146
6248e345 3147 align = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
53800dbe 3148
53800dbe 3149 /* If SRC is not a pointer type, don't do this operation inline. */
3150 if (align == 0)
c2f47e15 3151 return NULL_RTX;
53800dbe 3152
911c0150 3153 /* Bail out if we can't compute strlen in the right mode. */
53800dbe 3154 while (insn_mode != VOIDmode)
3155 {
99bdde56 3156 icode = optab_handler (strlen_optab, insn_mode)->insn_code;
53800dbe 3157 if (icode != CODE_FOR_nothing)
c28ae87f 3158 break;
53800dbe 3159
3160 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
3161 }
3162 if (insn_mode == VOIDmode)
c2f47e15 3163 return NULL_RTX;
53800dbe 3164
3165 /* Make a place to write the result of the instruction. */
3166 result = target;
3167 if (! (result != 0
8ad4c111 3168 && REG_P (result)
53800dbe 3169 && GET_MODE (result) == insn_mode
3170 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3171 result = gen_reg_rtx (insn_mode);
3172
911c0150 3173 /* Make a place to hold the source address. We will not expand
3174 the actual source until we are sure that the expansion will
3175 not fail -- there are trees that cannot be expanded twice. */
3176 src_reg = gen_reg_rtx (Pmode);
53800dbe 3177
911c0150 3178 /* Mark the beginning of the strlen sequence so we can emit the
3179 source operand later. */
f0ce3b1f 3180 before_strlen = get_last_insn ();
53800dbe 3181
53800dbe 3182 char_rtx = const0_rtx;
f7c44134 3183 char_mode = insn_data[(int) icode].operand[2].mode;
3184 if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
3185 char_mode))
53800dbe 3186 char_rtx = copy_to_mode_reg (char_mode, char_rtx);
3187
911c0150 3188 pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
3189 char_rtx, GEN_INT (align));
3190 if (! pat)
c2f47e15 3191 return NULL_RTX;
911c0150 3192 emit_insn (pat);
3193
3194 /* Now that we are assured of success, expand the source. */
3195 start_sequence ();
c5aba89c 3196 pat = expand_expr (src, src_reg, ptr_mode, EXPAND_NORMAL);
911c0150 3197 if (pat != src_reg)
3198 emit_move_insn (src_reg, pat);
31d3e01c 3199 pat = get_insns ();
911c0150 3200 end_sequence ();
bceb0d1f 3201
3202 if (before_strlen)
3203 emit_insn_after (pat, before_strlen);
3204 else
3205 emit_insn_before (pat, get_insns ());
53800dbe 3206
3207 /* Return the value in the proper mode for this function. */
80cd7a5e 3208 if (GET_MODE (result) == target_mode)
911c0150 3209 target = result;
53800dbe 3210 else if (target != 0)
911c0150 3211 convert_move (target, result, 0);
53800dbe 3212 else
80cd7a5e 3213 target = convert_to_mode (target_mode, result, 0);
911c0150 3214
3215 return target;
53800dbe 3216 }
3217}
3218
c2f47e15 3219/* Expand a call to the strstr builtin. Return NULL_RTX if we failed the
17f5ea87 3220 caller should emit a normal call, otherwise try to get the result
3221 in TARGET, if convenient (and in mode MODE if that's convenient). */
3222
3223static rtx
c2f47e15 3224expand_builtin_strstr (tree exp, rtx target, enum machine_mode mode)
17f5ea87 3225{
c2f47e15 3226 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
17f5ea87 3227 {
c2f47e15 3228 tree type = TREE_TYPE (exp);
3229 tree result = fold_builtin_strstr (CALL_EXPR_ARG (exp, 0),
3230 CALL_EXPR_ARG (exp, 1), type);
2c84ee37 3231 if (result)
3232 return expand_expr (result, target, mode, EXPAND_NORMAL);
17f5ea87 3233 }
c2f47e15 3234 return NULL_RTX;
17f5ea87 3235}
3236
c2f47e15 3237/* Expand a call to the strchr builtin. Return NULL_RTX if we failed the
46f3a74a 3238 caller should emit a normal call, otherwise try to get the result
3239 in TARGET, if convenient (and in mode MODE if that's convenient). */
3240
3241static rtx
c2f47e15 3242expand_builtin_strchr (tree exp, rtx target, enum machine_mode mode)
46f3a74a 3243{
c2f47e15 3244 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
46f3a74a 3245 {
c2f47e15 3246 tree type = TREE_TYPE (exp);
3247 tree result = fold_builtin_strchr (CALL_EXPR_ARG (exp, 0),
3248 CALL_EXPR_ARG (exp, 1), type);
2c84ee37 3249 if (result)
3250 return expand_expr (result, target, mode, EXPAND_NORMAL);
83d79705 3251
2c84ee37 3252 /* FIXME: Should use strchrM optab so that ports can optimize this. */
83d79705 3253 }
c2f47e15 3254 return NULL_RTX;
83d79705 3255}
3256
c2f47e15 3257/* Expand a call to the strrchr builtin. Return NULL_RTX if we failed the
83d79705 3258 caller should emit a normal call, otherwise try to get the result
3259 in TARGET, if convenient (and in mode MODE if that's convenient). */
3260
3261static rtx
c2f47e15 3262expand_builtin_strrchr (tree exp, rtx target, enum machine_mode mode)
83d79705 3263{
c2f47e15 3264 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
83d79705 3265 {
c2f47e15 3266 tree type = TREE_TYPE (exp);
3267 tree result = fold_builtin_strrchr (CALL_EXPR_ARG (exp, 0),
3268 CALL_EXPR_ARG (exp, 1), type);
2c84ee37 3269 if (result)
3270 return expand_expr (result, target, mode, EXPAND_NORMAL);
83d79705 3271 }
c2f47e15 3272 return NULL_RTX;
83d79705 3273}
3274
c2f47e15 3275/* Expand a call to the strpbrk builtin. Return NULL_RTX if we failed the
83d79705 3276 caller should emit a normal call, otherwise try to get the result
3277 in TARGET, if convenient (and in mode MODE if that's convenient). */
3278
3279static rtx
c2f47e15 3280expand_builtin_strpbrk (tree exp, rtx target, enum machine_mode mode)
83d79705 3281{
c2f47e15 3282 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
83d79705 3283 {
c2f47e15 3284 tree type = TREE_TYPE (exp);
3285 tree result = fold_builtin_strpbrk (CALL_EXPR_ARG (exp, 0),
3286 CALL_EXPR_ARG (exp, 1), type);
2c84ee37 3287 if (result)
3288 return expand_expr (result, target, mode, EXPAND_NORMAL);
46f3a74a 3289 }
c2f47e15 3290 return NULL_RTX;
46f3a74a 3291}
3292
6840589f 3293/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3294 bytes from constant string DATA + OFFSET and return it as target
3295 constant. */
3296
3297static rtx
aecda0d6 3298builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
3299 enum machine_mode mode)
6840589f 3300{
3301 const char *str = (const char *) data;
3302
64db345d 3303 gcc_assert (offset >= 0
3304 && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
3305 <= strlen (str) + 1));
6840589f 3306
3307 return c_readstr (str + offset, mode);
3308}
3309
c2f47e15 3310/* Expand a call EXP to the memcpy builtin.
3311 Return NULL_RTX if we failed, the caller should emit a normal call,
3b824fa6 3312 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3313 mode MODE if that's convenient). */
c2f47e15 3314
53800dbe 3315static rtx
5a0de151 3316expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode)
53800dbe 3317{
8e76ec06 3318 tree fndecl = get_callee_fndecl (exp);
c2f47e15 3319
3320 if (!validate_arglist (exp,
3321 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3322 return NULL_RTX;
53800dbe 3323 else
3324 {
c2f47e15 3325 tree dest = CALL_EXPR_ARG (exp, 0);
3326 tree src = CALL_EXPR_ARG (exp, 1);
3327 tree len = CALL_EXPR_ARG (exp, 2);
6840589f 3328 const char *src_str;
27d0c333 3329 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3330 unsigned int dest_align
3331 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
53800dbe 3332 rtx dest_mem, src_mem, dest_addr, len_rtx;
c2f47e15 3333 tree result = fold_builtin_memory_op (dest, src, len,
3334 TREE_TYPE (TREE_TYPE (fndecl)),
4f46f2b9 3335 false, /*endp=*/0);
162719b3 3336 HOST_WIDE_INT expected_size = -1;
3337 unsigned int expected_align = 0;
5a0de151 3338
3339 if (result)
4f46f2b9 3340 {
3341 while (TREE_CODE (result) == COMPOUND_EXPR)
3342 {
3343 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3344 EXPAND_NORMAL);
3345 result = TREE_OPERAND (result, 1);
3346 }
3347 return expand_expr (result, target, mode, EXPAND_NORMAL);
3348 }
53800dbe 3349
6f428e8b 3350 /* If DEST is not a pointer type, call the normal function. */
3351 if (dest_align == 0)
c2f47e15 3352 return NULL_RTX;
6f428e8b 3353
6f428e8b 3354 /* If either SRC is not a pointer type, don't do this
a0c938f0 3355 operation in-line. */
6f428e8b 3356 if (src_align == 0)
c2f47e15 3357 return NULL_RTX;
162719b3 3358
3359 stringop_block_profile (exp, &expected_align, &expected_size);
3360 if (expected_align < dest_align)
3361 expected_align = dest_align;
d8ae1baa 3362 dest_mem = get_memory_rtx (dest, len);
2a631e19 3363 set_mem_align (dest_mem, dest_align);
8ec3c5c2 3364 len_rtx = expand_normal (len);
6840589f 3365 src_str = c_getstr (src);
3366
3367 /* If SRC is a string constant and block move would be done
3368 by pieces, we can avoid loading the string from memory
3369 and only stored the computed constants. */
3370 if (src_str
6840589f 3371 && GET_CODE (len_rtx) == CONST_INT
3372 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3373 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
b9a7cc69 3374 (void *) src_str, dest_align))
6840589f 3375 {
9fe0e1b8 3376 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3377 builtin_memcpy_read_str,
b9a7cc69 3378 (void *) src_str, dest_align, 0);
e5716f7e 3379 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3380 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3381 return dest_mem;
6840589f 3382 }
3383
d8ae1baa 3384 src_mem = get_memory_rtx (src, len);
2a631e19 3385 set_mem_align (src_mem, src_align);
53800dbe 3386
53800dbe 3387 /* Copy word part most expediently. */
162719b3 3388 dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
3389 CALL_EXPR_TAILCALL (exp)
3390 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3391 expected_align, expected_size);
53800dbe 3392
3393 if (dest_addr == 0)
e5716f7e 3394 {
3395 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3396 dest_addr = convert_memory_address (ptr_mode, dest_addr);
e5716f7e 3397 }
9fe0e1b8 3398 return dest_addr;
53800dbe 3399 }
3400}
3401
c2f47e15 3402/* Expand a call EXP to the mempcpy builtin.
3403 Return NULL_RTX if we failed; the caller should emit a normal call,
647661c6 3404 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3405 mode MODE if that's convenient). If ENDP is 0 return the
3406 destination pointer, if ENDP is 1 return the end pointer ala
3407 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3408 stpcpy. */
647661c6 3409
3410static rtx
c2f47e15 3411expand_builtin_mempcpy(tree exp, rtx target, enum machine_mode mode)
647661c6 3412{
c2f47e15 3413 if (!validate_arglist (exp,
3414 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3415 return NULL_RTX;
3416 else
3417 {
3418 tree dest = CALL_EXPR_ARG (exp, 0);
3419 tree src = CALL_EXPR_ARG (exp, 1);
3420 tree len = CALL_EXPR_ARG (exp, 2);
3421 return expand_builtin_mempcpy_args (dest, src, len,
3422 TREE_TYPE (exp),
3423 target, mode, /*endp=*/ 1);
3424 }
3425}
3426
3427/* Helper function to do the actual work for expand_builtin_mempcpy. The
3428 arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out
3429 so that this can also be called without constructing an actual CALL_EXPR.
3430 TYPE is the return type of the call. The other arguments and return value
3431 are the same as for expand_builtin_mempcpy. */
3432
3433static rtx
3434expand_builtin_mempcpy_args (tree dest, tree src, tree len, tree type,
3435 rtx target, enum machine_mode mode, int endp)
3436{
3437 /* If return value is ignored, transform mempcpy into memcpy. */
3438 if (target == const0_rtx)
9fe0e1b8 3439 {
3440 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
3441
3442 if (!fn)
c2f47e15 3443 return NULL_RTX;
9fe0e1b8 3444
c2f47e15 3445 return expand_expr (build_call_expr (fn, 3, dest, src, len),
9fe0e1b8 3446 target, mode, EXPAND_NORMAL);
3447 }
647661c6 3448 else
3449 {
9fe0e1b8 3450 const char *src_str;
3451 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3452 unsigned int dest_align
3453 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3454 rtx dest_mem, src_mem, len_rtx;
c2f47e15 3455 tree result = fold_builtin_memory_op (dest, src, len, type, false, endp);
9fe0e1b8 3456
7da1412b 3457 if (result)
4f46f2b9 3458 {
3459 while (TREE_CODE (result) == COMPOUND_EXPR)
3460 {
3461 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3462 EXPAND_NORMAL);
3463 result = TREE_OPERAND (result, 1);
3464 }
3465 return expand_expr (result, target, mode, EXPAND_NORMAL);
3466 }
a0c938f0 3467
7da1412b 3468 /* If either SRC or DEST is not a pointer type, don't do this
a0c938f0 3469 operation in-line. */
7da1412b 3470 if (dest_align == 0 || src_align == 0)
c2f47e15 3471 return NULL_RTX;
9fe0e1b8 3472
6217c238 3473 /* If LEN is not constant, call the normal function. */
3474 if (! host_integerp (len, 1))
c2f47e15 3475 return NULL_RTX;
0862b7e9 3476
8ec3c5c2 3477 len_rtx = expand_normal (len);
9fe0e1b8 3478 src_str = c_getstr (src);
647661c6 3479
9fe0e1b8 3480 /* If SRC is a string constant and block move would be done
3481 by pieces, we can avoid loading the string from memory
3482 and only stored the computed constants. */
3483 if (src_str
3484 && GET_CODE (len_rtx) == CONST_INT
3485 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3486 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
b9a7cc69 3487 (void *) src_str, dest_align))
9fe0e1b8 3488 {
d8ae1baa 3489 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3490 set_mem_align (dest_mem, dest_align);
3491 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3492 builtin_memcpy_read_str,
b9a7cc69 3493 (void *) src_str, dest_align, endp);
9fe0e1b8 3494 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3495 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3496 return dest_mem;
647661c6 3497 }
3498
9fe0e1b8 3499 if (GET_CODE (len_rtx) == CONST_INT
3500 && can_move_by_pieces (INTVAL (len_rtx),
3501 MIN (dest_align, src_align)))
3502 {
d8ae1baa 3503 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3504 set_mem_align (dest_mem, dest_align);
d8ae1baa 3505 src_mem = get_memory_rtx (src, len);
9fe0e1b8 3506 set_mem_align (src_mem, src_align);
3507 dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
3508 MIN (dest_align, src_align), endp);
3509 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3510 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3511 return dest_mem;
3512 }
3513
c2f47e15 3514 return NULL_RTX;
647661c6 3515 }
3516}
3517
c2f47e15 3518/* Expand expression EXP, which is a call to the memmove builtin. Return
3519 NULL_RTX if we failed; the caller should emit a normal call. */
c4950093 3520
3521static rtx
c2f47e15 3522expand_builtin_memmove (tree exp, rtx target, enum machine_mode mode, int ignore)
c4950093 3523{
c2f47e15 3524 if (!validate_arglist (exp,
3525 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3526 return NULL_RTX;
c4950093 3527 else
3528 {
c2f47e15 3529 tree dest = CALL_EXPR_ARG (exp, 0);
3530 tree src = CALL_EXPR_ARG (exp, 1);
3531 tree len = CALL_EXPR_ARG (exp, 2);
3532 return expand_builtin_memmove_args (dest, src, len, TREE_TYPE (exp),
3533 target, mode, ignore);
3534 }
3535}
7e72af53 3536
c2f47e15 3537/* Helper function to do the actual work for expand_builtin_memmove. The
3538 arguments to the builtin_memmove call DEST, SRC, and LEN are broken out
3539 so that this can also be called without constructing an actual CALL_EXPR.
3540 TYPE is the return type of the call. The other arguments and return value
3541 are the same as for expand_builtin_memmove. */
3542
3543static rtx
3544expand_builtin_memmove_args (tree dest, tree src, tree len,
3545 tree type, rtx target, enum machine_mode mode,
3546 int ignore)
3547{
3548 tree result = fold_builtin_memory_op (dest, src, len, type, ignore, /*endp=*/3);
3549
3550 if (result)
3551 {
05be68f3 3552 STRIP_TYPE_NOPS (result);
c2f47e15 3553 while (TREE_CODE (result) == COMPOUND_EXPR)
4f46f2b9 3554 {
c2f47e15 3555 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3556 EXPAND_NORMAL);
3557 result = TREE_OPERAND (result, 1);
4f46f2b9 3558 }
c2f47e15 3559 return expand_expr (result, target, mode, EXPAND_NORMAL);
3560 }
3561
3562 /* Otherwise, call the normal function. */
3563 return NULL_RTX;
c4950093 3564}
3565
c2f47e15 3566/* Expand expression EXP, which is a call to the bcopy builtin. Return
3567 NULL_RTX if we failed the caller should emit a normal call. */
c4950093 3568
3569static rtx
c2f47e15 3570expand_builtin_bcopy (tree exp, int ignore)
c4950093 3571{
0b25db21 3572 tree type = TREE_TYPE (exp);
c2f47e15 3573 tree src, dest, size;
c4950093 3574
c2f47e15 3575 if (!validate_arglist (exp,
3576 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
c4950093 3577 return NULL_RTX;
3578
c2f47e15 3579 src = CALL_EXPR_ARG (exp, 0);
3580 dest = CALL_EXPR_ARG (exp, 1);
3581 size = CALL_EXPR_ARG (exp, 2);
c4950093 3582
c2f47e15 3583 /* Transform bcopy(ptr x, ptr y, int z) to memmove(ptr y, ptr x, size_t z).
3584 This is done this way so that if it isn't expanded inline, we fall
3585 back to calling bcopy instead of memmove. */
3586 return expand_builtin_memmove_args (dest, src,
3587 fold_convert (sizetype, size),
3588 type, const0_rtx, VOIDmode,
3589 ignore);
c4950093 3590}
3591
727c62dd 3592#ifndef HAVE_movstr
3593# define HAVE_movstr 0
3594# define CODE_FOR_movstr CODE_FOR_nothing
3595#endif
3596
c2f47e15 3597/* Expand into a movstr instruction, if one is available. Return NULL_RTX if
727c62dd 3598 we failed, the caller should emit a normal call, otherwise try to
3599 get the result in TARGET, if convenient. If ENDP is 0 return the
3600 destination pointer, if ENDP is 1 return the end pointer ala
3601 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3602 stpcpy. */
3603
3604static rtx
3605expand_movstr (tree dest, tree src, rtx target, int endp)
3606{
3607 rtx end;
3608 rtx dest_mem;
3609 rtx src_mem;
3610 rtx insn;
3611 const struct insn_data * data;
3612
3613 if (!HAVE_movstr)
c2f47e15 3614 return NULL_RTX;
727c62dd 3615
d8ae1baa 3616 dest_mem = get_memory_rtx (dest, NULL);
3617 src_mem = get_memory_rtx (src, NULL);
727c62dd 3618 if (!endp)
3619 {
3620 target = force_reg (Pmode, XEXP (dest_mem, 0));
3621 dest_mem = replace_equiv_address (dest_mem, target);
3622 end = gen_reg_rtx (Pmode);
3623 }
3624 else
3625 {
3626 if (target == 0 || target == const0_rtx)
3627 {
3628 end = gen_reg_rtx (Pmode);
3629 if (target == 0)
3630 target = end;
3631 }
3632 else
3633 end = target;
3634 }
3635
3636 data = insn_data + CODE_FOR_movstr;
3637
3638 if (data->operand[0].mode != VOIDmode)
3639 end = gen_lowpart (data->operand[0].mode, end);
3640
3641 insn = data->genfun (end, dest_mem, src_mem);
3642
64db345d 3643 gcc_assert (insn);
727c62dd 3644
3645 emit_insn (insn);
3646
3647 /* movstr is supposed to set end to the address of the NUL
3648 terminator. If the caller requested a mempcpy-like return value,
3649 adjust it. */
3650 if (endp == 1 && target != const0_rtx)
c5aba89c 3651 {
3652 rtx tem = plus_constant (gen_lowpart (GET_MODE (target), end), 1);
3653 emit_move_insn (target, force_operand (tem, NULL_RTX));
3654 }
727c62dd 3655
3656 return target;
3657}
3658
c2f47e15 3659/* Expand expression EXP, which is a call to the strcpy builtin. Return
3660 NULL_RTX if we failed the caller should emit a normal call, otherwise
3661 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3662 convenient). */
902de8ed 3663
53800dbe 3664static rtx
c2f47e15 3665expand_builtin_strcpy (tree fndecl, tree exp, rtx target, enum machine_mode mode)
53800dbe 3666{
c2f47e15 3667 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3668 {
3669 tree dest = CALL_EXPR_ARG (exp, 0);
3670 tree src = CALL_EXPR_ARG (exp, 1);
3671 return expand_builtin_strcpy_args (fndecl, dest, src, target, mode);
3672 }
3673 return NULL_RTX;
3674}
3675
3676/* Helper function to do the actual work for expand_builtin_strcpy. The
3677 arguments to the builtin_strcpy call DEST and SRC are broken out
3678 so that this can also be called without constructing an actual CALL_EXPR.
3679 The other arguments and return value are the same as for
3680 expand_builtin_strcpy. */
3681
3682static rtx
3683expand_builtin_strcpy_args (tree fndecl, tree dest, tree src,
3684 rtx target, enum machine_mode mode)
3685{
3686 tree result = fold_builtin_strcpy (fndecl, dest, src, 0);
3687 if (result)
3688 return expand_expr (result, target, mode, EXPAND_NORMAL);
3689 return expand_movstr (dest, src, target, /*endp=*/0);
902de8ed 3690
53800dbe 3691}
3692
c2f47e15 3693/* Expand a call EXP to the stpcpy builtin.
3694 Return NULL_RTX if we failed the caller should emit a normal call,
3b824fa6 3695 otherwise try to get the result in TARGET, if convenient (and in
3696 mode MODE if that's convenient). */
3697
3698static rtx
dc369150 3699expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
3b824fa6 3700{
c2f47e15 3701 tree dst, src;
3702
3703 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3704 return NULL_RTX;
3705
3706 dst = CALL_EXPR_ARG (exp, 0);
3707 src = CALL_EXPR_ARG (exp, 1);
3708
727c62dd 3709 /* If return value is ignored, transform stpcpy into strcpy. */
3710 if (target == const0_rtx)
978836e5 3711 {
3712 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
3713 if (!fn)
c2f47e15 3714 return NULL_RTX;
978836e5 3715
c2f47e15 3716 return expand_expr (build_call_expr (fn, 2, dst, src),
3717 target, mode, EXPAND_NORMAL);
978836e5 3718 }
3b824fa6 3719 else
3720 {
c2f47e15 3721 tree len, lenp1;
727c62dd 3722 rtx ret;
647661c6 3723
9fe0e1b8 3724 /* Ensure we get an actual string whose length can be evaluated at
a0c938f0 3725 compile-time, not an expression containing a string. This is
3726 because the latter will potentially produce pessimized code
3727 when used to produce the return value. */
681fab1e 3728 if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
c2f47e15 3729 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3730
7d705727 3731 lenp1 = size_binop (PLUS_EXPR, len, ssize_int (1));
c2f47e15 3732 ret = expand_builtin_mempcpy_args (dst, src, lenp1, TREE_TYPE (exp),
3733 target, mode, /*endp=*/2);
727c62dd 3734
3735 if (ret)
3736 return ret;
3737
3738 if (TREE_CODE (len) == INTEGER_CST)
3739 {
8ec3c5c2 3740 rtx len_rtx = expand_normal (len);
727c62dd 3741
3742 if (GET_CODE (len_rtx) == CONST_INT)
3743 {
c2f47e15 3744 ret = expand_builtin_strcpy_args (get_callee_fndecl (exp),
3745 dst, src, target, mode);
727c62dd 3746
3747 if (ret)
3748 {
3749 if (! target)
7ac87324 3750 {
3751 if (mode != VOIDmode)
3752 target = gen_reg_rtx (mode);
3753 else
3754 target = gen_reg_rtx (GET_MODE (ret));
3755 }
727c62dd 3756 if (GET_MODE (target) != GET_MODE (ret))
3757 ret = gen_lowpart (GET_MODE (target), ret);
3758
c5aba89c 3759 ret = plus_constant (ret, INTVAL (len_rtx));
3760 ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
64db345d 3761 gcc_assert (ret);
727c62dd 3762
3763 return target;
3764 }
3765 }
3766 }
3767
c2f47e15 3768 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3769 }
3770}
3771
6840589f 3772/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3773 bytes from constant string DATA + OFFSET and return it as target
3774 constant. */
3775
3776static rtx
aecda0d6 3777builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
3778 enum machine_mode mode)
6840589f 3779{
3780 const char *str = (const char *) data;
3781
3782 if ((unsigned HOST_WIDE_INT) offset > strlen (str))
3783 return const0_rtx;
3784
3785 return c_readstr (str + offset, mode);
3786}
3787
c2f47e15 3788/* Expand expression EXP, which is a call to the strncpy builtin. Return
3789 NULL_RTX if we failed the caller should emit a normal call. */
ed09096d 3790
3791static rtx
8ff6a5cd 3792expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode)
ed09096d 3793{
ea726109 3794 tree fndecl = get_callee_fndecl (exp);
c2f47e15 3795
3796 if (validate_arglist (exp,
3797 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
ed09096d 3798 {
c2f47e15 3799 tree dest = CALL_EXPR_ARG (exp, 0);
3800 tree src = CALL_EXPR_ARG (exp, 1);
3801 tree len = CALL_EXPR_ARG (exp, 2);
3802 tree slen = c_strlen (src, 1);
3803 tree result = fold_builtin_strncpy (fndecl, dest, src, len, slen);
a0c938f0 3804
8ff6a5cd 3805 if (result)
4f46f2b9 3806 {
3807 while (TREE_CODE (result) == COMPOUND_EXPR)
3808 {
3809 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3810 EXPAND_NORMAL);
3811 result = TREE_OPERAND (result, 1);
3812 }
3813 return expand_expr (result, target, mode, EXPAND_NORMAL);
3814 }
6840589f 3815
8ff6a5cd 3816 /* We must be passed a constant len and src parameter. */
3817 if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
c2f47e15 3818 return NULL_RTX;
ed09096d 3819
3820 slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
3821
3822 /* We're required to pad with trailing zeros if the requested
a0c938f0 3823 len is greater than strlen(s2)+1. In that case try to
6840589f 3824 use store_by_pieces, if it fails, punt. */
ed09096d 3825 if (tree_int_cst_lt (slen, len))
6840589f 3826 {
27d0c333 3827 unsigned int dest_align
3828 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
c2f47e15 3829 const char *p = c_getstr (src);
6840589f 3830 rtx dest_mem;
3831
27d0c333 3832 if (!p || dest_align == 0 || !host_integerp (len, 1)
3833 || !can_store_by_pieces (tree_low_cst (len, 1),
6840589f 3834 builtin_strncpy_read_str,
b9a7cc69 3835 (void *) p, dest_align))
c2f47e15 3836 return NULL_RTX;
6840589f 3837
d8ae1baa 3838 dest_mem = get_memory_rtx (dest, len);
27d0c333 3839 store_by_pieces (dest_mem, tree_low_cst (len, 1),
6840589f 3840 builtin_strncpy_read_str,
b9a7cc69 3841 (void *) p, dest_align, 0);
e5716f7e 3842 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3843 dest_mem = convert_memory_address (ptr_mode, dest_mem);
e5716f7e 3844 return dest_mem;
6840589f 3845 }
ed09096d 3846 }
c2f47e15 3847 return NULL_RTX;
ed09096d 3848}
3849
ecc318ff 3850/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3851 bytes from constant string DATA + OFFSET and return it as target
3852 constant. */
3853
f656b751 3854rtx
aecda0d6 3855builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3856 enum machine_mode mode)
ecc318ff 3857{
3858 const char *c = (const char *) data;
3859 char *p = alloca (GET_MODE_SIZE (mode));
3860
3861 memset (p, *c, GET_MODE_SIZE (mode));
3862
3863 return c_readstr (p, mode);
3864}
3865
a7ec6974 3866/* Callback routine for store_by_pieces. Return the RTL of a register
3867 containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
3868 char value given in the RTL register data. For example, if mode is
3869 4 bytes wide, return the RTL for 0x01010101*data. */
3870
3871static rtx
aecda0d6 3872builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3873 enum machine_mode mode)
a7ec6974 3874{
3875 rtx target, coeff;
3876 size_t size;
3877 char *p;
3878
3879 size = GET_MODE_SIZE (mode);
f0ce3b1f 3880 if (size == 1)
3881 return (rtx) data;
a7ec6974 3882
3883 p = alloca (size);
3884 memset (p, 1, size);
3885 coeff = c_readstr (p, mode);
3886
f0ce3b1f 3887 target = convert_to_mode (mode, (rtx) data, 1);
a7ec6974 3888 target = expand_mult (mode, target, coeff, NULL_RTX, 1);
3889 return force_reg (mode, target);
3890}
3891
c2f47e15 3892/* Expand expression EXP, which is a call to the memset builtin. Return
3893 NULL_RTX if we failed the caller should emit a normal call, otherwise
3894 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3895 convenient). */
902de8ed 3896
53800dbe 3897static rtx
c2f47e15 3898expand_builtin_memset (tree exp, rtx target, enum machine_mode mode)
53800dbe 3899{
c2f47e15 3900 if (!validate_arglist (exp,
3901 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
3902 return NULL_RTX;
53800dbe 3903 else
3904 {
c2f47e15 3905 tree dest = CALL_EXPR_ARG (exp, 0);
3906 tree val = CALL_EXPR_ARG (exp, 1);
3907 tree len = CALL_EXPR_ARG (exp, 2);
3908 return expand_builtin_memset_args (dest, val, len, target, mode, exp);
3909 }
3910}
53800dbe 3911
c2f47e15 3912/* Helper function to do the actual work for expand_builtin_memset. The
3913 arguments to the builtin_memset call DEST, VAL, and LEN are broken out
3914 so that this can also be called without constructing an actual CALL_EXPR.
3915 The other arguments and return value are the same as for
3916 expand_builtin_memset. */
6b961939 3917
c2f47e15 3918static rtx
3919expand_builtin_memset_args (tree dest, tree val, tree len,
3920 rtx target, enum machine_mode mode, tree orig_exp)
3921{
3922 tree fndecl, fn;
3923 enum built_in_function fcode;
3924 char c;
3925 unsigned int dest_align;
3926 rtx dest_mem, dest_addr, len_rtx;
3927 HOST_WIDE_INT expected_size = -1;
3928 unsigned int expected_align = 0;
53800dbe 3929
c2f47e15 3930 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
162719b3 3931
c2f47e15 3932 /* If DEST is not a pointer type, don't do this operation in-line. */
3933 if (dest_align == 0)
3934 return NULL_RTX;
6f428e8b 3935
c2f47e15 3936 stringop_block_profile (orig_exp, &expected_align, &expected_size);
3937 if (expected_align < dest_align)
3938 expected_align = dest_align;
6b961939 3939
c2f47e15 3940 /* If the LEN parameter is zero, return DEST. */
3941 if (integer_zerop (len))
3942 {
3943 /* Evaluate and ignore VAL in case it has side-effects. */
3944 expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
3945 return expand_expr (dest, target, mode, EXPAND_NORMAL);
3946 }
7a3e5564 3947
c2f47e15 3948 /* Stabilize the arguments in case we fail. */
3949 dest = builtin_save_expr (dest);
3950 val = builtin_save_expr (val);
3951 len = builtin_save_expr (len);
a7ec6974 3952
c2f47e15 3953 len_rtx = expand_normal (len);
3954 dest_mem = get_memory_rtx (dest, len);
a7ec6974 3955
c2f47e15 3956 if (TREE_CODE (val) != INTEGER_CST)
3957 {
3958 rtx val_rtx;
a7ec6974 3959
c2f47e15 3960 val_rtx = expand_normal (val);
3961 val_rtx = convert_to_mode (TYPE_MODE (unsigned_char_type_node),
3962 val_rtx, 0);
53800dbe 3963
c2f47e15 3964 /* Assume that we can memset by pieces if we can store
3965 * the coefficients by pieces (in the required modes).
3966 * We can't pass builtin_memset_gen_str as that emits RTL. */
3967 c = 1;
3968 if (host_integerp (len, 1)
3969 && !(optimize_size && tree_low_cst (len, 1) > 1)
3970 && can_store_by_pieces (tree_low_cst (len, 1),
3971 builtin_memset_read_str, &c, dest_align))
3972 {
3973 val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
3974 val_rtx);
3975 store_by_pieces (dest_mem, tree_low_cst (len, 1),
3976 builtin_memset_gen_str, val_rtx, dest_align, 0);
3977 }
3978 else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
3979 dest_align, expected_align,
3980 expected_size))
6b961939 3981 goto do_libcall;
c2f47e15 3982
3983 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3984 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3985 return dest_mem;
3986 }
53800dbe 3987
c2f47e15 3988 if (target_char_cast (val, &c))
3989 goto do_libcall;
ecc318ff 3990
c2f47e15 3991 if (c)
3992 {
3993 if (host_integerp (len, 1)
3994 && !(optimize_size && tree_low_cst (len, 1) > 1)
3995 && can_store_by_pieces (tree_low_cst (len, 1),
3996 builtin_memset_read_str, &c, dest_align))
3997 store_by_pieces (dest_mem, tree_low_cst (len, 1),
3998 builtin_memset_read_str, &c, dest_align, 0);
3999 else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
4000 dest_align, expected_align,
4001 expected_size))
4002 goto do_libcall;
4003
4004 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
4005 dest_mem = convert_memory_address (ptr_mode, dest_mem);
4006 return dest_mem;
4007 }
ecc318ff 4008
c2f47e15 4009 set_mem_align (dest_mem, dest_align);
4010 dest_addr = clear_storage_hints (dest_mem, len_rtx,
4011 CALL_EXPR_TAILCALL (orig_exp)
4012 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
4013 expected_align, expected_size);
53800dbe 4014
c2f47e15 4015 if (dest_addr == 0)
4016 {
4017 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
4018 dest_addr = convert_memory_address (ptr_mode, dest_addr);
4019 }
53800dbe 4020
c2f47e15 4021 return dest_addr;
6b961939 4022
c2f47e15 4023 do_libcall:
4024 fndecl = get_callee_fndecl (orig_exp);
4025 fcode = DECL_FUNCTION_CODE (fndecl);
4026 if (fcode == BUILT_IN_MEMSET)
4027 fn = build_call_expr (fndecl, 3, dest, val, len);
4028 else if (fcode == BUILT_IN_BZERO)
4029 fn = build_call_expr (fndecl, 2, dest, len);
4030 else
4031 gcc_unreachable ();
4032 if (TREE_CODE (fn) == CALL_EXPR)
4033 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
4034 return expand_call (fn, target, target == const0_rtx);
53800dbe 4035}
4036
c2f47e15 4037/* Expand expression EXP, which is a call to the bzero builtin. Return
4038 NULL_RTX if we failed the caller should emit a normal call. */
27d0c333 4039
ffc83088 4040static rtx
0b25db21 4041expand_builtin_bzero (tree exp)
ffc83088 4042{
c2f47e15 4043 tree dest, size;
ffc83088 4044
c2f47e15 4045 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
7369e7ba 4046 return NULL_RTX;
ffc83088 4047
c2f47e15 4048 dest = CALL_EXPR_ARG (exp, 0);
4049 size = CALL_EXPR_ARG (exp, 1);
bf8e3599 4050
7369e7ba 4051 /* New argument list transforming bzero(ptr x, int y) to
6f428e8b 4052 memset(ptr x, int 0, size_t y). This is done this way
4053 so that if it isn't expanded inline, we fallback to
4054 calling bzero instead of memset. */
bf8e3599 4055
c2f47e15 4056 return expand_builtin_memset_args (dest, integer_zero_node,
4057 fold_convert (sizetype, size),
4058 const0_rtx, VOIDmode, exp);
ffc83088 4059}
4060
7959b13b 4061/* Expand a call to the memchr builtin. Return NULL_RTX if we failed the
4062 caller should emit a normal call, otherwise try to get the result
4063 in TARGET, if convenient (and in mode MODE if that's convenient). */
4064
4065static rtx
4066expand_builtin_memchr (tree exp, rtx target, enum machine_mode mode)
4067{
4068 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE,
4069 INTEGER_TYPE, VOID_TYPE))
4070 {
4071 tree type = TREE_TYPE (exp);
4072 tree result = fold_builtin_memchr (CALL_EXPR_ARG (exp, 0),
4073 CALL_EXPR_ARG (exp, 1),
4074 CALL_EXPR_ARG (exp, 2), type);
4075 if (result)
4076 return expand_expr (result, target, mode, EXPAND_NORMAL);
4077 }
4078 return NULL_RTX;
4079}
4080
7a3f89b5 4081/* Expand expression EXP, which is a call to the memcmp built-in function.
c2f47e15 4082 Return NULL_RTX if we failed and the
53800dbe 4083 caller should emit a normal call, otherwise try to get the result in
6f428e8b 4084 TARGET, if convenient (and in mode MODE, if that's convenient). */
27d0c333 4085
53800dbe 4086static rtx
c2f47e15 4087expand_builtin_memcmp (tree exp, rtx target, enum machine_mode mode)
53800dbe 4088{
c2f47e15 4089 if (!validate_arglist (exp,
4090 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4091 return NULL_RTX;
218bc19e 4092 else
6f428e8b 4093 {
c2f47e15 4094 tree result = fold_builtin_memcmp (CALL_EXPR_ARG (exp, 0),
4095 CALL_EXPR_ARG (exp, 1),
4096 CALL_EXPR_ARG (exp, 2));
218bc19e 4097 if (result)
4098 return expand_expr (result, target, mode, EXPAND_NORMAL);
6f428e8b 4099 }
4100
6ac5504b 4101#if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi
53800dbe 4102 {
0cd832f0 4103 rtx arg1_rtx, arg2_rtx, arg3_rtx;
53800dbe 4104 rtx result;
0cd832f0 4105 rtx insn;
c2f47e15 4106 tree arg1 = CALL_EXPR_ARG (exp, 0);
4107 tree arg2 = CALL_EXPR_ARG (exp, 1);
4108 tree len = CALL_EXPR_ARG (exp, 2);
53800dbe 4109
4110 int arg1_align
4111 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4112 int arg2_align
4113 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
b428c0a5 4114 enum machine_mode insn_mode;
4115
4116#ifdef HAVE_cmpmemsi
4117 if (HAVE_cmpmemsi)
4118 insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
4119 else
4120#endif
6ac5504b 4121#ifdef HAVE_cmpstrnsi
4122 if (HAVE_cmpstrnsi)
4123 insn_mode = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
b428c0a5 4124 else
4125#endif
c2f47e15 4126 return NULL_RTX;
53800dbe 4127
4128 /* If we don't have POINTER_TYPE, call the function. */
4129 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4130 return NULL_RTX;
53800dbe 4131
4132 /* Make a place to write the result of the instruction. */
4133 result = target;
4134 if (! (result != 0
8ad4c111 4135 && REG_P (result) && GET_MODE (result) == insn_mode
53800dbe 4136 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4137 result = gen_reg_rtx (insn_mode);
4138
d8ae1baa 4139 arg1_rtx = get_memory_rtx (arg1, len);
4140 arg2_rtx = get_memory_rtx (arg2, len);
8ec3c5c2 4141 arg3_rtx = expand_normal (len);
83f88f8e 4142
4143 /* Set MEM_SIZE as appropriate. */
4144 if (GET_CODE (arg3_rtx) == CONST_INT)
4145 {
4146 set_mem_size (arg1_rtx, arg3_rtx);
4147 set_mem_size (arg2_rtx, arg3_rtx);
4148 }
4149
b428c0a5 4150#ifdef HAVE_cmpmemsi
4151 if (HAVE_cmpmemsi)
4152 insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4153 GEN_INT (MIN (arg1_align, arg2_align)));
0cd832f0 4154 else
b428c0a5 4155#endif
6ac5504b 4156#ifdef HAVE_cmpstrnsi
4157 if (HAVE_cmpstrnsi)
4158 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4159 GEN_INT (MIN (arg1_align, arg2_align)));
b428c0a5 4160 else
4161#endif
64db345d 4162 gcc_unreachable ();
0cd832f0 4163
4164 if (insn)
4165 emit_insn (insn);
4166 else
2c5d421b 4167 emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK,
0cd832f0 4168 TYPE_MODE (integer_type_node), 3,
4169 XEXP (arg1_rtx, 0), Pmode,
4170 XEXP (arg2_rtx, 0), Pmode,
4171 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
78a8ed03 4172 TYPE_UNSIGNED (sizetype)),
0cd832f0 4173 TYPE_MODE (sizetype));
53800dbe 4174
4175 /* Return the value in the proper mode for this function. */
4176 mode = TYPE_MODE (TREE_TYPE (exp));
4177 if (GET_MODE (result) == mode)
4178 return result;
4179 else if (target != 0)
4180 {
4181 convert_move (target, result, 0);
4182 return target;
4183 }
4184 else
4185 return convert_to_mode (mode, result, 0);
4186 }
83d79705 4187#endif
53800dbe 4188
c2f47e15 4189 return NULL_RTX;
6f428e8b 4190}
4191
c2f47e15 4192/* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX
53800dbe 4193 if we failed the caller should emit a normal call, otherwise try to get
4194 the result in TARGET, if convenient. */
902de8ed 4195
53800dbe 4196static rtx
aecda0d6 4197expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
53800dbe 4198{
c2f47e15 4199 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4200 return NULL_RTX;
218bc19e 4201 else
ef6c187e 4202 {
c2f47e15 4203 tree result = fold_builtin_strcmp (CALL_EXPR_ARG (exp, 0),
4204 CALL_EXPR_ARG (exp, 1));
218bc19e 4205 if (result)
4206 return expand_expr (result, target, mode, EXPAND_NORMAL);
ef6c187e 4207 }
bf8e3599 4208
6ac5504b 4209#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
4210 if (cmpstr_optab[SImode] != CODE_FOR_nothing
4211 || cmpstrn_optab[SImode] != CODE_FOR_nothing)
4212 {
4213 rtx arg1_rtx, arg2_rtx;
4214 rtx result, insn = NULL_RTX;
4215 tree fndecl, fn;
c2f47e15 4216 tree arg1 = CALL_EXPR_ARG (exp, 0);
4217 tree arg2 = CALL_EXPR_ARG (exp, 1);
a0c938f0 4218
6ac5504b 4219 int arg1_align
4220 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4221 int arg2_align
4222 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4223
4224 /* If we don't have POINTER_TYPE, call the function. */
4225 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4226 return NULL_RTX;
7a3f89b5 4227
6ac5504b 4228 /* Stabilize the arguments in case gen_cmpstr(n)si fail. */
4229 arg1 = builtin_save_expr (arg1);
4230 arg2 = builtin_save_expr (arg2);
7a3f89b5 4231
d8ae1baa 4232 arg1_rtx = get_memory_rtx (arg1, NULL);
4233 arg2_rtx = get_memory_rtx (arg2, NULL);
53800dbe 4234
6ac5504b 4235#ifdef HAVE_cmpstrsi
4236 /* Try to call cmpstrsi. */
4237 if (HAVE_cmpstrsi)
4238 {
a0c938f0 4239 enum machine_mode insn_mode
6ac5504b 4240 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
4241
4242 /* Make a place to write the result of the instruction. */
4243 result = target;
4244 if (! (result != 0
4245 && REG_P (result) && GET_MODE (result) == insn_mode
4246 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4247 result = gen_reg_rtx (insn_mode);
4248
4249 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
4250 GEN_INT (MIN (arg1_align, arg2_align)));
4251 }
4252#endif
03fd9d2c 4253#ifdef HAVE_cmpstrnsi
6ac5504b 4254 /* Try to determine at least one length and call cmpstrnsi. */
a0c938f0 4255 if (!insn && HAVE_cmpstrnsi)
6ac5504b 4256 {
4257 tree len;
4258 rtx arg3_rtx;
4259
a0c938f0 4260 enum machine_mode insn_mode
6ac5504b 4261 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
4262 tree len1 = c_strlen (arg1, 1);
4263 tree len2 = c_strlen (arg2, 1);
4264
4265 if (len1)
4266 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
4267 if (len2)
4268 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
4269
4270 /* If we don't have a constant length for the first, use the length
4271 of the second, if we know it. We don't require a constant for
4272 this case; some cost analysis could be done if both are available
4273 but neither is constant. For now, assume they're equally cheap,
4274 unless one has side effects. If both strings have constant lengths,
4275 use the smaller. */
4276
4277 if (!len1)
4278 len = len2;
4279 else if (!len2)
4280 len = len1;
4281 else if (TREE_SIDE_EFFECTS (len1))
4282 len = len2;
4283 else if (TREE_SIDE_EFFECTS (len2))
4284 len = len1;
4285 else if (TREE_CODE (len1) != INTEGER_CST)
4286 len = len2;
4287 else if (TREE_CODE (len2) != INTEGER_CST)
4288 len = len1;
4289 else if (tree_int_cst_lt (len1, len2))
4290 len = len1;
4291 else
4292 len = len2;
4293
4294 /* If both arguments have side effects, we cannot optimize. */
4295 if (!len || TREE_SIDE_EFFECTS (len))
6b961939 4296 goto do_libcall;
53800dbe 4297
8ec3c5c2 4298 arg3_rtx = expand_normal (len);
902de8ed 4299
6ac5504b 4300 /* Make a place to write the result of the instruction. */
4301 result = target;
4302 if (! (result != 0
4303 && REG_P (result) && GET_MODE (result) == insn_mode
4304 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4305 result = gen_reg_rtx (insn_mode);
53800dbe 4306
6ac5504b 4307 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4308 GEN_INT (MIN (arg1_align, arg2_align)));
4309 }
4310#endif
3f8aefe2 4311
6ac5504b 4312 if (insn)
4313 {
4314 emit_insn (insn);
3f8aefe2 4315
6ac5504b 4316 /* Return the value in the proper mode for this function. */
4317 mode = TYPE_MODE (TREE_TYPE (exp));
4318 if (GET_MODE (result) == mode)
4319 return result;
4320 if (target == 0)
4321 return convert_to_mode (mode, result, 0);
4322 convert_move (target, result, 0);
4323 return target;
4324 }
902de8ed 4325
6ac5504b 4326 /* Expand the library call ourselves using a stabilized argument
4327 list to avoid re-evaluating the function's arguments twice. */
2694880e 4328#ifdef HAVE_cmpstrnsi
6b961939 4329 do_libcall:
2694880e 4330#endif
6ac5504b 4331 fndecl = get_callee_fndecl (exp);
c2f47e15 4332 fn = build_call_expr (fndecl, 2, arg1, arg2);
6ac5504b 4333 if (TREE_CODE (fn) == CALL_EXPR)
4334 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4335 return expand_call (fn, target, target == const0_rtx);
4336 }
7a3f89b5 4337#endif
c2f47e15 4338 return NULL_RTX;
83d79705 4339}
53800dbe 4340
c2f47e15 4341/* Expand expression EXP, which is a call to the strncmp builtin. Return
4342 NULL_RTX if we failed the caller should emit a normal call, otherwise try to get
ed09096d 4343 the result in TARGET, if convenient. */
27d0c333 4344
ed09096d 4345static rtx
aecda0d6 4346expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
ed09096d 4347{
c2f47e15 4348 if (!validate_arglist (exp,
4349 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4350 return NULL_RTX;
218bc19e 4351 else
ef6c187e 4352 {
c2f47e15 4353 tree result = fold_builtin_strncmp (CALL_EXPR_ARG (exp, 0),
4354 CALL_EXPR_ARG (exp, 1),
4355 CALL_EXPR_ARG (exp, 2));
218bc19e 4356 if (result)
4357 return expand_expr (result, target, mode, EXPAND_NORMAL);
ef6c187e 4358 }
ed09096d 4359
6e34e617 4360 /* If c_strlen can determine an expression for one of the string
6ac5504b 4361 lengths, and it doesn't have side effects, then emit cmpstrnsi
7a3f89b5 4362 using length MIN(strlen(string)+1, arg3). */
6ac5504b 4363#ifdef HAVE_cmpstrnsi
4364 if (HAVE_cmpstrnsi)
7a3f89b5 4365 {
4366 tree len, len1, len2;
4367 rtx arg1_rtx, arg2_rtx, arg3_rtx;
4368 rtx result, insn;
0b25db21 4369 tree fndecl, fn;
c2f47e15 4370 tree arg1 = CALL_EXPR_ARG (exp, 0);
4371 tree arg2 = CALL_EXPR_ARG (exp, 1);
4372 tree arg3 = CALL_EXPR_ARG (exp, 2);
6f428e8b 4373
7a3f89b5 4374 int arg1_align
4375 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4376 int arg2_align
4377 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4378 enum machine_mode insn_mode
6ac5504b 4379 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
bf8e3599 4380
681fab1e 4381 len1 = c_strlen (arg1, 1);
4382 len2 = c_strlen (arg2, 1);
7a3f89b5 4383
4384 if (len1)
4385 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
4386 if (len2)
4387 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
4388
4389 /* If we don't have a constant length for the first, use the length
4390 of the second, if we know it. We don't require a constant for
4391 this case; some cost analysis could be done if both are available
4392 but neither is constant. For now, assume they're equally cheap,
4393 unless one has side effects. If both strings have constant lengths,
4394 use the smaller. */
4395
4396 if (!len1)
4397 len = len2;
4398 else if (!len2)
4399 len = len1;
4400 else if (TREE_SIDE_EFFECTS (len1))
4401 len = len2;
4402 else if (TREE_SIDE_EFFECTS (len2))
4403 len = len1;
4404 else if (TREE_CODE (len1) != INTEGER_CST)
4405 len = len2;
4406 else if (TREE_CODE (len2) != INTEGER_CST)
4407 len = len1;
4408 else if (tree_int_cst_lt (len1, len2))
4409 len = len1;
4410 else
4411 len = len2;
6e34e617 4412
7a3f89b5 4413 /* If both arguments have side effects, we cannot optimize. */
4414 if (!len || TREE_SIDE_EFFECTS (len))
c2f47e15 4415 return NULL_RTX;
bf8e3599 4416
7a3f89b5 4417 /* The actual new length parameter is MIN(len,arg3). */
49d00087 4418 len = fold_build2 (MIN_EXPR, TREE_TYPE (len), len,
4419 fold_convert (TREE_TYPE (len), arg3));
7a3f89b5 4420
4421 /* If we don't have POINTER_TYPE, call the function. */
4422 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4423 return NULL_RTX;
7a3f89b5 4424
4425 /* Make a place to write the result of the instruction. */
4426 result = target;
4427 if (! (result != 0
8ad4c111 4428 && REG_P (result) && GET_MODE (result) == insn_mode
7a3f89b5 4429 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4430 result = gen_reg_rtx (insn_mode);
4431
6ac5504b 4432 /* Stabilize the arguments in case gen_cmpstrnsi fails. */
4ee9c684 4433 arg1 = builtin_save_expr (arg1);
4434 arg2 = builtin_save_expr (arg2);
4435 len = builtin_save_expr (len);
3f8aefe2 4436
d8ae1baa 4437 arg1_rtx = get_memory_rtx (arg1, len);
4438 arg2_rtx = get_memory_rtx (arg2, len);
8ec3c5c2 4439 arg3_rtx = expand_normal (len);
6ac5504b 4440 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4441 GEN_INT (MIN (arg1_align, arg2_align)));
3f8aefe2 4442 if (insn)
4443 {
4444 emit_insn (insn);
4445
4446 /* Return the value in the proper mode for this function. */
4447 mode = TYPE_MODE (TREE_TYPE (exp));
4448 if (GET_MODE (result) == mode)
4449 return result;
4450 if (target == 0)
4451 return convert_to_mode (mode, result, 0);
4452 convert_move (target, result, 0);
4453 return target;
4454 }
7a3f89b5 4455
3f8aefe2 4456 /* Expand the library call ourselves using a stabilized argument
4457 list to avoid re-evaluating the function's arguments twice. */
3f8aefe2 4458 fndecl = get_callee_fndecl (exp);
c2f47e15 4459 fn = build_call_expr (fndecl, 3, arg1, arg2, len);
0b25db21 4460 if (TREE_CODE (fn) == CALL_EXPR)
4461 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4462 return expand_call (fn, target, target == const0_rtx);
7a3f89b5 4463 }
4464#endif
c2f47e15 4465 return NULL_RTX;
ed09096d 4466}
4467
49f0327b 4468/* Expand expression EXP, which is a call to the strcat builtin.
c2f47e15 4469 Return NULL_RTX if we failed the caller should emit a normal call,
49f0327b 4470 otherwise try to get the result in TARGET, if convenient. */
27d0c333 4471
49f0327b 4472static rtx
c2f47e15 4473expand_builtin_strcat (tree fndecl, tree exp, rtx target, enum machine_mode mode)
49f0327b 4474{
c2f47e15 4475 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4476 return NULL_RTX;
49f0327b 4477 else
4478 {
c2f47e15 4479 tree dst = CALL_EXPR_ARG (exp, 0);
4480 tree src = CALL_EXPR_ARG (exp, 1);
49f0327b 4481 const char *p = c_getstr (src);
4482
1d89860b 4483 /* If the string length is zero, return the dst parameter. */
a0c938f0 4484 if (p && *p == '\0')
1d89860b 4485 return expand_expr (dst, target, mode, EXPAND_NORMAL);
a0c938f0 4486
1d89860b 4487 if (!optimize_size)
ca71f89b 4488 {
1d89860b 4489 /* See if we can store by pieces into (dst + strlen(dst)). */
4490 tree newsrc, newdst,
4491 strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
4492 rtx insns;
4493
4494 /* Stabilize the argument list. */
4495 newsrc = builtin_save_expr (src);
1d89860b 4496 dst = builtin_save_expr (dst);
4497
4498 start_sequence ();
4499
4500 /* Create strlen (dst). */
c2f47e15 4501 newdst = build_call_expr (strlen_fn, 1, dst);
0de36bdb 4502 /* Create (dst p+ strlen (dst)). */
1d89860b 4503
0de36bdb 4504 newdst = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
1d89860b 4505 newdst = builtin_save_expr (newdst);
1d89860b 4506
c2f47e15 4507 if (!expand_builtin_strcpy_args (fndecl, newdst, newsrc, target, mode))
ca71f89b 4508 {
1d89860b 4509 end_sequence (); /* Stop sequence. */
c2f47e15 4510 return NULL_RTX;
ca71f89b 4511 }
a0c938f0 4512
1d89860b 4513 /* Output the entire sequence. */
4514 insns = get_insns ();
4515 end_sequence ();
4516 emit_insn (insns);
a0c938f0 4517
1d89860b 4518 return expand_expr (dst, target, mode, EXPAND_NORMAL);
ca71f89b 4519 }
49f0327b 4520
c2f47e15 4521 return NULL_RTX;
49f0327b 4522 }
4523}
4524
4525/* Expand expression EXP, which is a call to the strncat builtin.
c2f47e15 4526 Return NULL_RTX if we failed the caller should emit a normal call,
49f0327b 4527 otherwise try to get the result in TARGET, if convenient. */
27d0c333 4528
49f0327b 4529static rtx
c2f47e15 4530expand_builtin_strncat (tree exp, rtx target, enum machine_mode mode)
49f0327b 4531{
c2f47e15 4532 if (validate_arglist (exp,
4533 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
49f0327b 4534 {
c2f47e15 4535 tree result = fold_builtin_strncat (CALL_EXPR_ARG (exp, 0),
4536 CALL_EXPR_ARG (exp, 1),
4537 CALL_EXPR_ARG (exp, 2));
2c84ee37 4538 if (result)
4539 return expand_expr (result, target, mode, EXPAND_NORMAL);
49f0327b 4540 }
c2f47e15 4541 return NULL_RTX;
49f0327b 4542}
4543
4544/* Expand expression EXP, which is a call to the strspn builtin.
c2f47e15 4545 Return NULL_RTX if we failed the caller should emit a normal call,
49f0327b 4546 otherwise try to get the result in TARGET, if convenient. */
27d0c333 4547
49f0327b 4548static rtx
c2f47e15 4549expand_builtin_strspn (tree exp, rtx target, enum machine_mode mode)
49f0327b 4550{
c2f47e15 4551 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
49f0327b 4552 {
c2f47e15 4553 tree result = fold_builtin_strspn (CALL_EXPR_ARG (exp, 0),
4554 CALL_EXPR_ARG (exp, 1));
2c84ee37 4555 if (result)
4556 return expand_expr (result, target, mode, EXPAND_NORMAL);
49f0327b 4557 }
c2f47e15 4558 return NULL_RTX;
49f0327b 4559}
4560
4561/* Expand expression EXP, which is a call to the strcspn builtin.
c2f47e15 4562 Return NULL_RTX if we failed the caller should emit a normal call,
49f0327b 4563 otherwise try to get the result in TARGET, if convenient. */
27d0c333 4564
49f0327b 4565static rtx
c2f47e15 4566expand_builtin_strcspn (tree exp, rtx target, enum machine_mode mode)
49f0327b 4567{
c2f47e15 4568 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
49f0327b 4569 {
c2f47e15 4570 tree result = fold_builtin_strcspn (CALL_EXPR_ARG (exp, 0),
4571 CALL_EXPR_ARG (exp, 1));
2c84ee37 4572 if (result)
4573 return expand_expr (result, target, mode, EXPAND_NORMAL);
49f0327b 4574 }
c2f47e15 4575 return NULL_RTX;
49f0327b 4576}
4577
a66c9326 4578/* Expand a call to __builtin_saveregs, generating the result in TARGET,
4579 if that's convenient. */
902de8ed 4580
a66c9326 4581rtx
aecda0d6 4582expand_builtin_saveregs (void)
53800dbe 4583{
a66c9326 4584 rtx val, seq;
53800dbe 4585
4586 /* Don't do __builtin_saveregs more than once in a function.
4587 Save the result of the first call and reuse it. */
4588 if (saveregs_value != 0)
4589 return saveregs_value;
53800dbe 4590
a66c9326 4591 /* When this function is called, it means that registers must be
4592 saved on entry to this function. So we migrate the call to the
4593 first insn of this function. */
4594
4595 start_sequence ();
53800dbe 4596
a66c9326 4597 /* Do whatever the machine needs done in this case. */
45550790 4598 val = targetm.calls.expand_builtin_saveregs ();
53800dbe 4599
a66c9326 4600 seq = get_insns ();
4601 end_sequence ();
53800dbe 4602
a66c9326 4603 saveregs_value = val;
53800dbe 4604
31d3e01c 4605 /* Put the insns after the NOTE that starts the function. If this
4606 is inside a start_sequence, make the outer-level insn chain current, so
a66c9326 4607 the code is placed at the start of the function. */
4608 push_topmost_sequence ();
0ec80471 4609 emit_insn_after (seq, entry_of_function ());
a66c9326 4610 pop_topmost_sequence ();
4611
4612 return val;
53800dbe 4613}
4614
4615/* __builtin_args_info (N) returns word N of the arg space info
4616 for the current function. The number and meanings of words
4617 is controlled by the definition of CUMULATIVE_ARGS. */
f7c44134 4618
53800dbe 4619static rtx
c2f47e15 4620expand_builtin_args_info (tree exp)
53800dbe 4621{
53800dbe 4622 int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
4623 int *word_ptr = (int *) &current_function_args_info;
53800dbe 4624
64db345d 4625 gcc_assert (sizeof (CUMULATIVE_ARGS) % sizeof (int) == 0);
53800dbe 4626
c2f47e15 4627 if (call_expr_nargs (exp) != 0)
53800dbe 4628 {
c2f47e15 4629 if (!host_integerp (CALL_EXPR_ARG (exp, 0), 0))
eb586f2c 4630 error ("argument of %<__builtin_args_info%> must be constant");
53800dbe 4631 else
4632 {
c2f47e15 4633 HOST_WIDE_INT wordnum = tree_low_cst (CALL_EXPR_ARG (exp, 0), 0);
53800dbe 4634
27d0c333 4635 if (wordnum < 0 || wordnum >= nwords)
eb586f2c 4636 error ("argument of %<__builtin_args_info%> out of range");
53800dbe 4637 else
4638 return GEN_INT (word_ptr[wordnum]);
4639 }
4640 }
4641 else
eb586f2c 4642 error ("missing argument in %<__builtin_args_info%>");
53800dbe 4643
4644 return const0_rtx;
53800dbe 4645}
4646
79012a9d 4647/* Expand a call to __builtin_next_arg. */
27d0c333 4648
53800dbe 4649static rtx
79012a9d 4650expand_builtin_next_arg (void)
53800dbe 4651{
79012a9d 4652 /* Checking arguments is already done in fold_builtin_next_arg
4653 that must be called before this function. */
940ddc5c 4654 return expand_binop (ptr_mode, add_optab,
53800dbe 4655 current_function_internal_arg_pointer,
4656 current_function_arg_offset_rtx,
4657 NULL_RTX, 0, OPTAB_LIB_WIDEN);
4658}
4659
a66c9326 4660/* Make it easier for the backends by protecting the valist argument
4661 from multiple evaluations. */
4662
4663static tree
aecda0d6 4664stabilize_va_list (tree valist, int needs_lvalue)
a66c9326 4665{
11a61dea 4666 if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
a66c9326 4667 {
2d47cc32 4668 if (TREE_SIDE_EFFECTS (valist))
4669 valist = save_expr (valist);
11a61dea 4670
2d47cc32 4671 /* For this case, the backends will be expecting a pointer to
4672 TREE_TYPE (va_list_type_node), but it's possible we've
4673 actually been given an array (an actual va_list_type_node).
4674 So fix it. */
4675 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
8a15c04a 4676 {
bf8e3599 4677 tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
fcdd3ab3 4678 valist = build_fold_addr_expr_with_type (valist, p1);
8a15c04a 4679 }
a66c9326 4680 }
11a61dea 4681 else
a66c9326 4682 {
2d47cc32 4683 tree pt;
11a61dea 4684
2d47cc32 4685 if (! needs_lvalue)
4686 {
11a61dea 4687 if (! TREE_SIDE_EFFECTS (valist))
4688 return valist;
bf8e3599 4689
11a61dea 4690 pt = build_pointer_type (va_list_type_node);
49d00087 4691 valist = fold_build1 (ADDR_EXPR, pt, valist);
a66c9326 4692 TREE_SIDE_EFFECTS (valist) = 1;
a66c9326 4693 }
2d47cc32 4694
11a61dea 4695 if (TREE_SIDE_EFFECTS (valist))
2d47cc32 4696 valist = save_expr (valist);
fcdd3ab3 4697 valist = build_fold_indirect_ref (valist);
a66c9326 4698 }
4699
4700 return valist;
4701}
4702
2e15d750 4703/* The "standard" definition of va_list is void*. */
4704
4705tree
4706std_build_builtin_va_list (void)
4707{
4708 return ptr_type_node;
4709}
4710
a66c9326 4711/* The "standard" implementation of va_start: just assign `nextarg' to
4712 the variable. */
27d0c333 4713
a66c9326 4714void
aecda0d6 4715std_expand_builtin_va_start (tree valist, rtx nextarg)
a66c9326 4716{
f03c17bc 4717 rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
4718 convert_move (va_r, nextarg, 0);
a66c9326 4719}
4720
c2f47e15 4721/* Expand EXP, a call to __builtin_va_start. */
27d0c333 4722
a66c9326 4723static rtx
c2f47e15 4724expand_builtin_va_start (tree exp)
a66c9326 4725{
4726 rtx nextarg;
c2f47e15 4727 tree valist;
a66c9326 4728
c2f47e15 4729 if (call_expr_nargs (exp) < 2)
cb166087 4730 {
4731 error ("too few arguments to function %<va_start%>");
4732 return const0_rtx;
4733 }
a66c9326 4734
c2f47e15 4735 if (fold_builtin_next_arg (exp, true))
79012a9d 4736 return const0_rtx;
7c2f0500 4737
79012a9d 4738 nextarg = expand_builtin_next_arg ();
c2f47e15 4739 valist = stabilize_va_list (CALL_EXPR_ARG (exp, 0), 1);
a66c9326 4740
4741#ifdef EXPAND_BUILTIN_VA_START
7df226a2 4742 EXPAND_BUILTIN_VA_START (valist, nextarg);
a66c9326 4743#else
7df226a2 4744 std_expand_builtin_va_start (valist, nextarg);
a66c9326 4745#endif
4746
4747 return const0_rtx;
4748}
4749
a66c9326 4750/* The "standard" implementation of va_arg: read the value from the
4751 current (padded) address and increment by the (padded) size. */
f7c44134 4752
e0eca1fa 4753tree
4754std_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
fcdd3ab3 4755{
52cc2eeb 4756 tree addr, t, type_size, rounded_size, valist_tmp;
b8e8e485 4757 unsigned HOST_WIDE_INT align, boundary;
bef380a4 4758 bool indirect;
52cc2eeb 4759
4760#ifdef ARGS_GROW_DOWNWARD
4761 /* All of the alignment and movement below is for args-grow-up machines.
4762 As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
4763 implement their own specialized gimplify_va_arg_expr routines. */
64db345d 4764 gcc_unreachable ();
52cc2eeb 4765#endif
fcdd3ab3 4766
bef380a4 4767 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
4768 if (indirect)
4769 type = build_pointer_type (type);
4770
52cc2eeb 4771 align = PARM_BOUNDARY / BITS_PER_UNIT;
bcff3604 4772 boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type) / BITS_PER_UNIT;
fcdd3ab3 4773
52cc2eeb 4774 /* Hoist the valist value into a temporary for the moment. */
ecdeeb37 4775 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
4776
fcdd3ab3 4777 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
4778 requires greater alignment, we must perform dynamic alignment. */
85c1f587 4779 if (boundary > align
4780 && !integer_zerop (TYPE_SIZE (type)))
fcdd3ab3 4781 {
41076ef6 4782 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
0de36bdb 4783 fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (valist),
4784 valist_tmp, size_int (boundary - 1)));
52cc2eeb 4785 gimplify_and_add (t, pre_p);
4786
0de36bdb 4787 t = fold_convert (sizetype, valist_tmp);
41076ef6 4788 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
0de36bdb 4789 fold_convert (TREE_TYPE (valist),
4790 fold_build2 (BIT_AND_EXPR, sizetype, t,
4791 size_int (-boundary))));
ecdeeb37 4792 gimplify_and_add (t, pre_p);
fcdd3ab3 4793 }
c5dc0c32 4794 else
4795 boundary = align;
4796
4797 /* If the actual alignment is less than the alignment of the type,
4798 adjust the type accordingly so that we don't assume strict alignment
4799 when deferencing the pointer. */
4800 boundary *= BITS_PER_UNIT;
4801 if (boundary < TYPE_ALIGN (type))
4802 {
4803 type = build_variant_type_copy (type);
4804 TYPE_ALIGN (type) = boundary;
4805 }
fcdd3ab3 4806
bcff3604 4807 /* Compute the rounded size of the type. */
52cc2eeb 4808 type_size = size_in_bytes (type);
4809 rounded_size = round_up (type_size, align);
4810
fcdd3ab3 4811 /* Reduce rounded_size so it's sharable with the postqueue. */
4812 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
4813
4814 /* Get AP. */
ecdeeb37 4815 addr = valist_tmp;
52cc2eeb 4816 if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
fcdd3ab3 4817 {
4818 /* Small args are padded downward. */
49d00087 4819 t = fold_build2 (GT_EXPR, sizetype, rounded_size, size_int (align));
4820 t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
4821 size_binop (MINUS_EXPR, rounded_size, type_size));
0de36bdb 4822 addr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (addr), addr, t);
fcdd3ab3 4823 }
4824
fcdd3ab3 4825 /* Compute new value for AP. */
0de36bdb 4826 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (valist), valist_tmp, rounded_size);
41076ef6 4827 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
ecdeeb37 4828 gimplify_and_add (t, pre_p);
e0eca1fa 4829
4830 addr = fold_convert (build_pointer_type (type), addr);
fcdd3ab3 4831
bef380a4 4832 if (indirect)
f2462d6c 4833 addr = build_va_arg_indirect_ref (addr);
4834
4835 return build_va_arg_indirect_ref (addr);
4836}
a0930a69 4837
f2462d6c 4838/* Build an indirect-ref expression over the given TREE, which represents a
4839 piece of a va_arg() expansion. */
4840tree
4841build_va_arg_indirect_ref (tree addr)
4842{
a0930a69 4843 addr = build_fold_indirect_ref (addr);
f2462d6c 4844
a0930a69 4845 if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */
4846 mf_mark (addr);
bef380a4 4847
a0930a69 4848 return addr;
433006a9 4849}
4850
fcdd3ab3 4851/* Return a dummy expression of type TYPE in order to keep going after an
4852 error. */
4853
4854static tree
4855dummy_object (tree type)
4856{
535664e3 4857 tree t = build_int_cst (build_pointer_type (type), 0);
fcdd3ab3 4858 return build1 (INDIRECT_REF, type, t);
4859}
4860
2799a2b7 4861/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
4862 builtin function, but a very special sort of operator. */
fcdd3ab3 4863
4864enum gimplify_status
4865gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p)
4866{
4867 tree promoted_type, want_va_type, have_va_type;
4868 tree valist = TREE_OPERAND (*expr_p, 0);
4869 tree type = TREE_TYPE (*expr_p);
4870 tree t;
4871
4872 /* Verify that valist is of the proper type. */
fcdd3ab3 4873 want_va_type = va_list_type_node;
4874 have_va_type = TREE_TYPE (valist);
f43dda35 4875
4876 if (have_va_type == error_mark_node)
4877 return GS_ERROR;
4878
fcdd3ab3 4879 if (TREE_CODE (want_va_type) == ARRAY_TYPE)
4880 {
4881 /* If va_list is an array type, the argument may have decayed
4882 to a pointer type, e.g. by being passed to another function.
a0c938f0 4883 In that case, unwrap both types so that we can compare the
fcdd3ab3 4884 underlying records. */
4885 if (TREE_CODE (have_va_type) == ARRAY_TYPE
552752f7 4886 || POINTER_TYPE_P (have_va_type))
fcdd3ab3 4887 {
4888 want_va_type = TREE_TYPE (want_va_type);
4889 have_va_type = TREE_TYPE (have_va_type);
4890 }
4891 }
4892
4893 if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
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. */
4901 else if ((promoted_type = lang_hooks.types.type_promotes_to (type))
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;
c3ceba8e 4914 warning (0, "(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. */
e0eca1fa 4933 if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
4934 {
4935 /* For this case, the backends will be expecting a pointer to
4936 TREE_TYPE (va_list_type_node), but it's possible we've
4937 actually been given an array (an actual va_list_type_node).
4938 So fix it. */
4939 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
4940 {
4941 tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
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
4989 if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
4990 {
41076ef6 4991 t = build2 (MODIFY_EXPR, va_list_type_node, dst, src);
a66c9326 4992 TREE_SIDE_EFFECTS (t) = 1;
4993 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4994 }
4995 else
4996 {
11a61dea 4997 rtx dstb, srcb, size;
4998
4999 /* Evaluate to pointers. */
5000 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
5001 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
5002 size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
5003 VOIDmode, EXPAND_NORMAL);
5004
85d654dd 5005 dstb = convert_memory_address (Pmode, dstb);
5006 srcb = convert_memory_address (Pmode, srcb);
726ec87c 5007
11a61dea 5008 /* "Dereference" to BLKmode memories. */
5009 dstb = gen_rtx_MEM (BLKmode, dstb);
ab6ab77e 5010 set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
2a631e19 5011 set_mem_align (dstb, TYPE_ALIGN (va_list_type_node));
11a61dea 5012 srcb = gen_rtx_MEM (BLKmode, srcb);
ab6ab77e 5013 set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
2a631e19 5014 set_mem_align (srcb, TYPE_ALIGN (va_list_type_node));
11a61dea 5015
5016 /* Copy. */
0378dbdc 5017 emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
a66c9326 5018 }
5019
5020 return const0_rtx;
5021}
5022
53800dbe 5023/* Expand a call to one of the builtin functions __builtin_frame_address or
5024 __builtin_return_address. */
27d0c333 5025
53800dbe 5026static rtx
c2f47e15 5027expand_builtin_frame_address (tree fndecl, tree exp)
53800dbe 5028{
53800dbe 5029 /* The argument must be a nonnegative integer constant.
5030 It counts the number of frames to scan up the stack.
5031 The value is the return address saved in that frame. */
c2f47e15 5032 if (call_expr_nargs (exp) == 0)
53800dbe 5033 /* Warning about missing arg was already issued. */
5034 return const0_rtx;
c2f47e15 5035 else if (! host_integerp (CALL_EXPR_ARG (exp, 0), 1))
53800dbe 5036 {
5037 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
07e3a3d2 5038 error ("invalid argument to %<__builtin_frame_address%>");
53800dbe 5039 else
07e3a3d2 5040 error ("invalid argument to %<__builtin_return_address%>");
53800dbe 5041 return const0_rtx;
5042 }
5043 else
5044 {
27d0c333 5045 rtx tem
5046 = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
c2f47e15 5047 tree_low_cst (CALL_EXPR_ARG (exp, 0), 1));
53800dbe 5048
5049 /* Some ports cannot access arbitrary stack frames. */
5050 if (tem == NULL)
5051 {
5052 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
c3ceba8e 5053 warning (0, "unsupported argument to %<__builtin_frame_address%>");
53800dbe 5054 else
c3ceba8e 5055 warning (0, "unsupported argument to %<__builtin_return_address%>");
53800dbe 5056 return const0_rtx;
5057 }
5058
5059 /* For __builtin_frame_address, return what we've got. */
5060 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
5061 return tem;
5062
8ad4c111 5063 if (!REG_P (tem)
53800dbe 5064 && ! CONSTANT_P (tem))
5065 tem = copy_to_mode_reg (Pmode, tem);
5066 return tem;
5067 }
5068}
5069
c2f47e15 5070/* Expand EXP, a call to the alloca builtin. Return NULL_RTX if
53800dbe 5071 we failed and the caller should emit a normal call, otherwise try to get
5072 the result in TARGET, if convenient. */
15c6cf6b 5073
53800dbe 5074static rtx
c2f47e15 5075expand_builtin_alloca (tree exp, rtx target)
53800dbe 5076{
5077 rtx op0;
15c6cf6b 5078 rtx result;
53800dbe 5079
4ee9c684 5080 /* In -fmudflap-instrumented code, alloca() and __builtin_alloca()
5081 should always expand to function calls. These can be intercepted
5082 in libmudflap. */
5083 if (flag_mudflap)
c2f47e15 5084 return NULL_RTX;
4ee9c684 5085
c2f47e15 5086 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
5087 return NULL_RTX;
53800dbe 5088
5089 /* Compute the argument. */
c2f47e15 5090 op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
53800dbe 5091
5092 /* Allocate the desired space. */
15c6cf6b 5093 result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
85d654dd 5094 result = convert_memory_address (ptr_mode, result);
15c6cf6b 5095
5096 return result;
53800dbe 5097}
5098
c2f47e15 5099/* Expand a call to a bswap builtin with argument ARG0. MODE
42791117 5100 is the mode to expand with. */
5101
5102static rtx
c2f47e15 5103expand_builtin_bswap (tree exp, rtx target, rtx subtarget)
42791117 5104{
5105 enum machine_mode mode;
5106 tree arg;
5107 rtx op0;
5108
c2f47e15 5109 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
5110 return NULL_RTX;
42791117 5111
c2f47e15 5112 arg = CALL_EXPR_ARG (exp, 0);
42791117 5113 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 5114 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
42791117 5115
5116 target = expand_unop (mode, bswap_optab, op0, target, 1);
5117
5118 gcc_assert (target);
5119
5120 return convert_to_mode (mode, target, 0);
5121}
5122
c2f47e15 5123/* Expand a call to a unary builtin in EXP.
5124 Return NULL_RTX if a normal call should be emitted rather than expanding the
53800dbe 5125 function in-line. If convenient, the result should be placed in TARGET.
5126 SUBTARGET may be used as the target for computing one of EXP's operands. */
15c6cf6b 5127
53800dbe 5128static rtx
c2f47e15 5129expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target,
aecda0d6 5130 rtx subtarget, optab op_optab)
53800dbe 5131{
5132 rtx op0;
c2f47e15 5133
5134 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
5135 return NULL_RTX;
53800dbe 5136
5137 /* Compute the argument. */
1db6d067 5138 op0 = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
5139 VOIDmode, EXPAND_NORMAL);
6a08d0ab 5140 /* Compute op, into TARGET if possible.
53800dbe 5141 Set TARGET to wherever the result comes back. */
c2f47e15 5142 target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
6a08d0ab 5143 op_optab, op0, target, 1);
64db345d 5144 gcc_assert (target);
7d3f6cc7 5145
efb070c8 5146 return convert_to_mode (target_mode, target, 0);
53800dbe 5147}
89cfe6e5 5148
df94cd3b 5149/* If the string passed to fputs is a constant and is one character
2c0e001b 5150 long, we attempt to transform this call into __builtin_fputc(). */
15c6cf6b 5151
df94cd3b 5152static rtx
c2f47e15 5153expand_builtin_fputs (tree exp, rtx target, bool unlocked)
df94cd3b 5154{
2c0e001b 5155 /* Verify the arguments in the original call. */
c2f47e15 5156 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
ce1b14f4 5157 {
c2f47e15 5158 tree result = fold_builtin_fputs (CALL_EXPR_ARG (exp, 0),
5159 CALL_EXPR_ARG (exp, 1),
5160 (target == const0_rtx),
2c84ee37 5161 unlocked, NULL_TREE);
5162 if (result)
5163 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
ce1b14f4 5164 }
c2f47e15 5165 return NULL_RTX;
3311f67b 5166}
5167
5a74f77e 5168/* Expand a call to __builtin_expect. We just return our argument
5169 as the builtin_expect semantic should've been already executed by
5170 tree branch prediction pass. */
89cfe6e5 5171
5172static rtx
c2f47e15 5173expand_builtin_expect (tree exp, rtx target)
89cfe6e5 5174{
c2f47e15 5175 tree arg, c;
89cfe6e5 5176
c2f47e15 5177 if (call_expr_nargs (exp) < 2)
89cfe6e5 5178 return const0_rtx;
c2f47e15 5179 arg = CALL_EXPR_ARG (exp, 0);
5180 c = CALL_EXPR_ARG (exp, 1);
89cfe6e5 5181
c2f47e15 5182 target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5a74f77e 5183 /* When guessing was done, the hints should be already stripped away. */
07311427 5184 gcc_assert (!flag_guess_branch_prob
5185 || optimize == 0 || errorcount || sorrycount);
89cfe6e5 5186 return target;
5187}
689df48e 5188
c22de3f0 5189void
aecda0d6 5190expand_builtin_trap (void)
a0ef1725 5191{
5192#ifdef HAVE_trap
5193 if (HAVE_trap)
5194 emit_insn (gen_trap ());
5195 else
5196#endif
5197 emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
5198 emit_barrier ();
5199}
78a74442 5200
c2f47e15 5201/* Expand EXP, a call to fabs, fabsf or fabsl.
5202 Return NULL_RTX if a normal call should be emitted rather than expanding
78a74442 5203 the function inline. If convenient, the result should be placed
5204 in TARGET. SUBTARGET may be used as the target for computing
5205 the operand. */
5206
5207static rtx
c2f47e15 5208expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
78a74442 5209{
5210 enum machine_mode mode;
5211 tree arg;
5212 rtx op0;
5213
c2f47e15 5214 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
5215 return NULL_RTX;
78a74442 5216
c2f47e15 5217 arg = CALL_EXPR_ARG (exp, 0);
78a74442 5218 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 5219 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
78a74442 5220 return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
5221}
5222
c2f47e15 5223/* Expand EXP, a call to copysign, copysignf, or copysignl.
270436f3 5224 Return NULL is a normal call should be emitted rather than expanding the
5225 function inline. If convenient, the result should be placed in TARGET.
5226 SUBTARGET may be used as the target for computing the operand. */
5227
5228static rtx
c2f47e15 5229expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
270436f3 5230{
5231 rtx op0, op1;
5232 tree arg;
5233
c2f47e15 5234 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
5235 return NULL_RTX;
270436f3 5236
c2f47e15 5237 arg = CALL_EXPR_ARG (exp, 0);
8ec3c5c2 5238 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
270436f3 5239
c2f47e15 5240 arg = CALL_EXPR_ARG (exp, 1);
8ec3c5c2 5241 op1 = expand_normal (arg);
270436f3 5242
5243 return expand_copysign (op0, op1, target);
5244}
5245
19bf118a 5246/* Create a new constant string literal and return a char* pointer to it.
5247 The STRING_CST value is the LEN characters at STR. */
1e8e9920 5248tree
19bf118a 5249build_string_literal (int len, const char *str)
5250{
5251 tree t, elem, index, type;
5252
5253 t = build_string (len, str);
5254 elem = build_type_variant (char_type_node, 1, 0);
7016c612 5255 index = build_index_type (build_int_cst (NULL_TREE, len - 1));
19bf118a 5256 type = build_array_type (elem, index);
5257 TREE_TYPE (t) = type;
5258 TREE_CONSTANT (t) = 1;
4ee9c684 5259 TREE_INVARIANT (t) = 1;
19bf118a 5260 TREE_READONLY (t) = 1;
5261 TREE_STATIC (t) = 1;
5262
5263 type = build_pointer_type (type);
5264 t = build1 (ADDR_EXPR, type, t);
5265
5266 type = build_pointer_type (elem);
5267 t = build1 (NOP_EXPR, type, t);
5268 return t;
5269}
5270
0b25db21 5271/* Expand EXP, a call to printf or printf_unlocked.
c2f47e15 5272 Return NULL_RTX if a normal call should be emitted rather than transforming
19bf118a 5273 the function inline. If convenient, the result should be placed in
0862b7e9 5274 TARGET with mode MODE. UNLOCKED indicates this is a printf_unlocked
19bf118a 5275 call. */
5276static rtx
0b25db21 5277expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
19bf118a 5278 bool unlocked)
5279{
6d77ed92 5280 /* If we're using an unlocked function, assume the other unlocked
5281 functions exist explicitly. */
5282 tree const fn_putchar = unlocked ? built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
5283 : implicit_built_in_decls[BUILT_IN_PUTCHAR];
5284 tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED]
5285 : implicit_built_in_decls[BUILT_IN_PUTS];
19bf118a 5286 const char *fmt_str;
c2f47e15 5287 tree fn = 0;
5288 tree fmt, arg;
5289 int nargs = call_expr_nargs (exp);
19bf118a 5290
5291 /* If the return value is used, don't do the transformation. */
5292 if (target != const0_rtx)
c2f47e15 5293 return NULL_RTX;
19bf118a 5294
5295 /* Verify the required arguments in the original call. */
c2f47e15 5296 if (nargs == 0)
5297 return NULL_RTX;
5298 fmt = CALL_EXPR_ARG (exp, 0);
552752f7 5299 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
c2f47e15 5300 return NULL_RTX;
19bf118a 5301
5302 /* Check whether the format is a literal string constant. */
5303 fmt_str = c_getstr (fmt);
5304 if (fmt_str == NULL)
c2f47e15 5305 return NULL_RTX;
19bf118a 5306
d4473c84 5307 if (!init_target_chars ())
c2f47e15 5308 return NULL_RTX;
a0c938f0 5309
19bf118a 5310 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
99eabcc1 5311 if (strcmp (fmt_str, target_percent_s_newline) == 0)
19bf118a 5312 {
c2f47e15 5313 if ((nargs != 2)
5314 || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (exp, 1))))
5315 return NULL_RTX;
5316 if (fn_puts)
5317 fn = build_call_expr (fn_puts, 1, CALL_EXPR_ARG (exp, 1));
19bf118a 5318 }
5319 /* If the format specifier was "%c", call __builtin_putchar(arg). */
99eabcc1 5320 else if (strcmp (fmt_str, target_percent_c) == 0)
19bf118a 5321 {
c2f47e15 5322 if ((nargs != 2)
5323 || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1))) != INTEGER_TYPE)
5324 return NULL_RTX;
5325 if (fn_putchar)
5326 fn = build_call_expr (fn_putchar, 1, CALL_EXPR_ARG (exp, 1));
19bf118a 5327 }
5328 else
5329 {
5330 /* We can't handle anything else with % args or %% ... yet. */
99eabcc1 5331 if (strchr (fmt_str, target_percent))
c2f47e15 5332 return NULL_RTX;
19bf118a 5333
c2f47e15 5334 if (nargs > 1)
5335 return NULL_RTX;
19bf118a 5336
5337 /* If the format specifier was "", printf does nothing. */
5338 if (fmt_str[0] == '\0')
5339 return const0_rtx;
5340 /* If the format specifier has length of 1, call putchar. */
5341 if (fmt_str[1] == '\0')
5342 {
5343 /* Given printf("c"), (where c is any one character,)
5344 convert "c"[0] to an int and pass that to the replacement
5345 function. */
7016c612 5346 arg = build_int_cst (NULL_TREE, fmt_str[0]);
c2f47e15 5347 if (fn_putchar)
5348 fn = build_call_expr (fn_putchar, 1, arg);
19bf118a 5349 }
5350 else
5351 {
5352 /* If the format specifier was "string\n", call puts("string"). */
5353 size_t len = strlen (fmt_str);
99eabcc1 5354 if ((unsigned char)fmt_str[len - 1] == target_newline)
19bf118a 5355 {
91c82c20 5356 /* Create a NUL-terminated string that's one char shorter
19bf118a 5357 than the original, stripping off the trailing '\n'. */
4acc30e5 5358 char *newstr = alloca (len);
19bf118a 5359 memcpy (newstr, fmt_str, len - 1);
5360 newstr[len - 1] = 0;
19bf118a 5361 arg = build_string_literal (len, newstr);
c2f47e15 5362 if (fn_puts)
5363 fn = build_call_expr (fn_puts, 1, arg);
19bf118a 5364 }
5365 else
5366 /* We'd like to arrange to call fputs(string,stdout) here,
5367 but we need stdout and don't have a way to get it yet. */
c2f47e15 5368 return NULL_RTX;
19bf118a 5369 }
5370 }
5371
5372 if (!fn)
c2f47e15 5373 return NULL_RTX;
0b25db21 5374 if (TREE_CODE (fn) == CALL_EXPR)
5375 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
5376 return expand_expr (fn, target, mode, EXPAND_NORMAL);
19bf118a 5377}
5378
0b25db21 5379/* Expand EXP, a call to fprintf or fprintf_unlocked.
c2f47e15 5380 Return NULL_RTX if a normal call should be emitted rather than transforming
19bf118a 5381 the function inline. If convenient, the result should be placed in
0862b7e9 5382 TARGET with mode MODE. UNLOCKED indicates this is a fprintf_unlocked
19bf118a 5383 call. */
5384static rtx
0b25db21 5385expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
a0c938f0 5386 bool unlocked)
19bf118a 5387{
6d77ed92 5388 /* If we're using an unlocked function, assume the other unlocked
5389 functions exist explicitly. */
5390 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
5391 : implicit_built_in_decls[BUILT_IN_FPUTC];
5392 tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
5393 : implicit_built_in_decls[BUILT_IN_FPUTS];
19bf118a 5394 const char *fmt_str;
c2f47e15 5395 tree fn = 0;
5396 tree fmt, fp, arg;
5397 int nargs = call_expr_nargs (exp);
19bf118a 5398
5399 /* If the return value is used, don't do the transformation. */
5400 if (target != const0_rtx)
c2f47e15 5401 return NULL_RTX;
19bf118a 5402
5403 /* Verify the required arguments in the original call. */
c2f47e15 5404 if (nargs < 2)
5405 return NULL_RTX;
5406 fp = CALL_EXPR_ARG (exp, 0);
552752f7 5407 if (! POINTER_TYPE_P (TREE_TYPE (fp)))
c2f47e15 5408 return NULL_RTX;
5409 fmt = CALL_EXPR_ARG (exp, 1);
552752f7 5410 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
c2f47e15 5411 return NULL_RTX;
19bf118a 5412
5413 /* Check whether the format is a literal string constant. */
5414 fmt_str = c_getstr (fmt);
5415 if (fmt_str == NULL)
c2f47e15 5416 return NULL_RTX;
19bf118a 5417
d4473c84 5418 if (!init_target_chars ())
c2f47e15 5419 return NULL_RTX;
a0c938f0 5420
19bf118a 5421 /* If the format specifier was "%s", call __builtin_fputs(arg,fp). */
99eabcc1 5422 if (strcmp (fmt_str, target_percent_s) == 0)
19bf118a 5423 {
c2f47e15 5424 if ((nargs != 3)
5425 || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (exp, 2))))
5426 return NULL_RTX;
5427 arg = CALL_EXPR_ARG (exp, 2);
5428 if (fn_fputs)
5429 fn = build_call_expr (fn_fputs, 2, arg, fp);
19bf118a 5430 }
5431 /* If the format specifier was "%c", call __builtin_fputc(arg,fp). */
99eabcc1 5432 else if (strcmp (fmt_str, target_percent_c) == 0)
19bf118a 5433 {
c2f47e15 5434 if ((nargs != 3)
5435 || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2))) != INTEGER_TYPE)
5436 return NULL_RTX;
5437 arg = CALL_EXPR_ARG (exp, 2);
5438 if (fn_fputc)
5439 fn = build_call_expr (fn_fputc, 2, arg, fp);
19bf118a 5440 }
5441 else
5442 {
5443 /* We can't handle anything else with % args or %% ... yet. */
99eabcc1 5444 if (strchr (fmt_str, target_percent))
c2f47e15 5445 return NULL_RTX;
19bf118a 5446
c2f47e15 5447 if (nargs > 2)
5448 return NULL_RTX;
19bf118a 5449
5450 /* If the format specifier was "", fprintf does nothing. */
5451 if (fmt_str[0] == '\0')
5452 {
5453 /* Evaluate and ignore FILE* argument for side-effects. */
5454 expand_expr (fp, const0_rtx, VOIDmode, EXPAND_NORMAL);
5455 return const0_rtx;
5456 }
5457
5458 /* When "string" doesn't contain %, replace all cases of
5459 fprintf(stream,string) with fputs(string,stream). The fputs
5460 builtin will take care of special cases like length == 1. */
c2f47e15 5461 if (fn_fputs)
5462 fn = build_call_expr (fn_fputs, 2, fmt, fp);
19bf118a 5463 }
5464
5465 if (!fn)
c2f47e15 5466 return NULL_RTX;
0b25db21 5467 if (TREE_CODE (fn) == CALL_EXPR)
5468 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
5469 return expand_expr (fn, target, mode, EXPAND_NORMAL);
19bf118a 5470}
5471
c2f47e15 5472/* Expand a call EXP to sprintf. Return NULL_RTX if
6411575e 5473 a normal call should be emitted rather than expanding the function
5474 inline. If convenient, the result should be placed in TARGET with
5475 mode MODE. */
5476
5477static rtx
c2f47e15 5478expand_builtin_sprintf (tree exp, rtx target, enum machine_mode mode)
6411575e 5479{
c2f47e15 5480 tree dest, fmt;
a7a723f0 5481 const char *fmt_str;
c2f47e15 5482 int nargs = call_expr_nargs (exp);
6411575e 5483
5484 /* Verify the required arguments in the original call. */
c2f47e15 5485 if (nargs < 2)
5486 return NULL_RTX;
5487 dest = CALL_EXPR_ARG (exp, 0);
552752f7 5488 if (! POINTER_TYPE_P (TREE_TYPE (dest)))
c2f47e15 5489 return NULL_RTX;
5490 fmt = CALL_EXPR_ARG (exp, 0);
552752f7 5491 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
c2f47e15 5492 return NULL_RTX;
6411575e 5493
5494 /* Check whether the format is a literal string constant. */
a7a723f0 5495 fmt_str = c_getstr (fmt);
5496 if (fmt_str == NULL)
c2f47e15 5497 return NULL_RTX;
6411575e 5498
d4473c84 5499 if (!init_target_chars ())
c2f47e15 5500 return NULL_RTX;
99eabcc1 5501
6411575e 5502 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 5503 if (strchr (fmt_str, target_percent) == 0)
6411575e 5504 {
5505 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
5506 tree exp;
5507
c2f47e15 5508 if ((nargs > 2) || ! fn)
5509 return NULL_RTX;
5510 expand_expr (build_call_expr (fn, 2, dest, fmt),
6411575e 5511 const0_rtx, VOIDmode, EXPAND_NORMAL);
5512 if (target == const0_rtx)
5513 return const0_rtx;
7016c612 5514 exp = build_int_cst (NULL_TREE, strlen (fmt_str));
6411575e 5515 return expand_expr (exp, target, mode, EXPAND_NORMAL);
5516 }
a7a723f0 5517 /* If the format is "%s", use strcpy if the result isn't used. */
99eabcc1 5518 else if (strcmp (fmt_str, target_percent_s) == 0)
6411575e 5519 {
a7a723f0 5520 tree fn, arg, len;
5521 fn = implicit_built_in_decls[BUILT_IN_STRCPY];
6411575e 5522
a7a723f0 5523 if (! fn)
c2f47e15 5524 return NULL_RTX;
5525 if (nargs != 3)
5526 return NULL_RTX;
5527 arg = CALL_EXPR_ARG (exp, 2);
552752f7 5528 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
c2f47e15 5529 return NULL_RTX;
6411575e 5530
5531 if (target != const0_rtx)
5532 {
681fab1e 5533 len = c_strlen (arg, 1);
a7a723f0 5534 if (! len || TREE_CODE (len) != INTEGER_CST)
c2f47e15 5535 return NULL_RTX;
6411575e 5536 }
5537 else
a7a723f0 5538 len = NULL_TREE;
6411575e 5539
c2f47e15 5540 expand_expr (build_call_expr (fn, 2, dest, arg),
6411575e 5541 const0_rtx, VOIDmode, EXPAND_NORMAL);
5542
5543 if (target == const0_rtx)
5544 return const0_rtx;
a7a723f0 5545 return expand_expr (len, target, mode, EXPAND_NORMAL);
6411575e 5546 }
5547
c2f47e15 5548 return NULL_RTX;
6411575e 5549}
27f261ef 5550
4ee9c684 5551/* Expand a call to either the entry or exit function profiler. */
5552
5553static rtx
5554expand_builtin_profile_func (bool exitp)
5555{
5556 rtx this, which;
5557
5558 this = DECL_RTL (current_function_decl);
64db345d 5559 gcc_assert (MEM_P (this));
5560 this = XEXP (this, 0);
4ee9c684 5561
5562 if (exitp)
5563 which = profile_function_exit_libfunc;
5564 else
5565 which = profile_function_entry_libfunc;
5566
5567 emit_library_call (which, LCT_NORMAL, VOIDmode, 2, this, Pmode,
5568 expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
869d0ef0 5569 0),
4ee9c684 5570 Pmode);
5571
5572 return const0_rtx;
5573}
5574
ac8fb6db 5575/* Expand a call to __builtin___clear_cache. */
5576
5577static rtx
5578expand_builtin___clear_cache (tree exp ATTRIBUTE_UNUSED)
5579{
5580#ifndef HAVE_clear_cache
5581#ifdef CLEAR_INSN_CACHE
5582 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
5583 does something. Just do the default expansion to a call to
5584 __clear_cache(). */
5585 return NULL_RTX;
5586#else
5587 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
5588 does nothing. There is no need to call it. Do nothing. */
5589 return const0_rtx;
5590#endif /* CLEAR_INSN_CACHE */
5591#else
5592 /* We have a "clear_cache" insn, and it will handle everything. */
5593 tree begin, end;
5594 rtx begin_rtx, end_rtx;
5595 enum insn_code icode;
5596
5597 /* We must not expand to a library call. If we did, any
5598 fallback library function in libgcc that might contain a call to
5599 __builtin___clear_cache() would recurse infinitely. */
5600 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
5601 {
5602 error ("both arguments to %<__builtin___clear_cache%> must be pointers");
5603 return const0_rtx;
5604 }
5605
5606 if (HAVE_clear_cache)
5607 {
5608 icode = CODE_FOR_clear_cache;
5609
5610 begin = CALL_EXPR_ARG (exp, 0);
5611 begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
5612 begin_rtx = convert_memory_address (Pmode, begin_rtx);
5613 if (!insn_data[icode].operand[0].predicate (begin_rtx, Pmode))
5614 begin_rtx = copy_to_mode_reg (Pmode, begin_rtx);
5615
5616 end = CALL_EXPR_ARG (exp, 1);
5617 end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
5618 end_rtx = convert_memory_address (Pmode, end_rtx);
5619 if (!insn_data[icode].operand[1].predicate (end_rtx, Pmode))
5620 end_rtx = copy_to_mode_reg (Pmode, end_rtx);
5621
5622 emit_insn (gen_clear_cache (begin_rtx, end_rtx));
5623 }
5624 return const0_rtx;
5625#endif /* HAVE_clear_cache */
5626}
5627
4ee9c684 5628/* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
5629
5630static rtx
5631round_trampoline_addr (rtx tramp)
5632{
5633 rtx temp, addend, mask;
5634
5635 /* If we don't need too much alignment, we'll have been guaranteed
5636 proper alignment by get_trampoline_type. */
5637 if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
5638 return tramp;
5639
5640 /* Round address up to desired boundary. */
5641 temp = gen_reg_rtx (Pmode);
5642 addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
5643 mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
5644
5645 temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
5646 temp, 0, OPTAB_LIB_WIDEN);
5647 tramp = expand_simple_binop (Pmode, AND, temp, mask,
5648 temp, 0, OPTAB_LIB_WIDEN);
5649
5650 return tramp;
5651}
5652
5653static rtx
c2f47e15 5654expand_builtin_init_trampoline (tree exp)
4ee9c684 5655{
5656 tree t_tramp, t_func, t_chain;
5657 rtx r_tramp, r_func, r_chain;
5658#ifdef TRAMPOLINE_TEMPLATE
5659 rtx blktramp;
5660#endif
5661
c2f47e15 5662 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
4ee9c684 5663 POINTER_TYPE, VOID_TYPE))
5664 return NULL_RTX;
5665
c2f47e15 5666 t_tramp = CALL_EXPR_ARG (exp, 0);
5667 t_func = CALL_EXPR_ARG (exp, 1);
5668 t_chain = CALL_EXPR_ARG (exp, 2);
4ee9c684 5669
8ec3c5c2 5670 r_tramp = expand_normal (t_tramp);
5671 r_func = expand_normal (t_func);
5672 r_chain = expand_normal (t_chain);
4ee9c684 5673
5674 /* Generate insns to initialize the trampoline. */
5675 r_tramp = round_trampoline_addr (r_tramp);
5676#ifdef TRAMPOLINE_TEMPLATE
5677 blktramp = gen_rtx_MEM (BLKmode, r_tramp);
5678 set_mem_align (blktramp, TRAMPOLINE_ALIGNMENT);
5679 emit_block_move (blktramp, assemble_trampoline_template (),
5680 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
5681#endif
5682 trampolines_created = 1;
5683 INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain);
5684
5685 return const0_rtx;
5686}
5687
5688static rtx
c2f47e15 5689expand_builtin_adjust_trampoline (tree exp)
4ee9c684 5690{
5691 rtx tramp;
5692
c2f47e15 5693 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
4ee9c684 5694 return NULL_RTX;
5695
c2f47e15 5696 tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
4ee9c684 5697 tramp = round_trampoline_addr (tramp);
5698#ifdef TRAMPOLINE_ADJUST_ADDRESS
5699 TRAMPOLINE_ADJUST_ADDRESS (tramp);
5700#endif
5701
5702 return tramp;
5703}
5704
93f564d6 5705/* Expand the call EXP to the built-in signbit, signbitf or signbitl
5706 function. The function first checks whether the back end provides
5707 an insn to implement signbit for the respective mode. If not, it
5708 checks whether the floating point format of the value is such that
5709 the sign bit can be extracted. If that is not the case, the
5710 function returns NULL_RTX to indicate that a normal call should be
5711 emitted rather than expanding the function in-line. EXP is the
5712 expression that is a call to the builtin function; if convenient,
5713 the result should be placed in TARGET. */
27f261ef 5714static rtx
5715expand_builtin_signbit (tree exp, rtx target)
5716{
5717 const struct real_format *fmt;
5718 enum machine_mode fmode, imode, rmode;
5719 HOST_WIDE_INT hi, lo;
c2f47e15 5720 tree arg;
ca4f1f5b 5721 int word, bitpos;
27eda240 5722 enum insn_code icode;
27f261ef 5723 rtx temp;
5724
c2f47e15 5725 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
5726 return NULL_RTX;
27f261ef 5727
c2f47e15 5728 arg = CALL_EXPR_ARG (exp, 0);
27f261ef 5729 fmode = TYPE_MODE (TREE_TYPE (arg));
5730 rmode = TYPE_MODE (TREE_TYPE (exp));
5731 fmt = REAL_MODE_FORMAT (fmode);
5732
93f564d6 5733 arg = builtin_save_expr (arg);
5734
5735 /* Expand the argument yielding a RTX expression. */
5736 temp = expand_normal (arg);
5737
5738 /* Check if the back end provides an insn that handles signbit for the
5739 argument's mode. */
27eda240 5740 icode = signbit_optab->handlers [(int) fmode].insn_code;
5741 if (icode != CODE_FOR_nothing)
93f564d6 5742 {
5743 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
27eda240 5744 emit_unop_insn (icode, target, temp, UNKNOWN);
93f564d6 5745 return target;
5746 }
5747
27f261ef 5748 /* For floating point formats without a sign bit, implement signbit
5749 as "ARG < 0.0". */
8d564692 5750 bitpos = fmt->signbit_ro;
ca4f1f5b 5751 if (bitpos < 0)
27f261ef 5752 {
5753 /* But we can't do this if the format supports signed zero. */
5754 if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
c2f47e15 5755 return NULL_RTX;
27f261ef 5756
49d00087 5757 arg = fold_build2 (LT_EXPR, TREE_TYPE (exp), arg,
5758 build_real (TREE_TYPE (arg), dconst0));
27f261ef 5759 return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5760 }
5761
ca4f1f5b 5762 if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
27f261ef 5763 {
ca4f1f5b 5764 imode = int_mode_for_mode (fmode);
5765 if (imode == BLKmode)
c2f47e15 5766 return NULL_RTX;
ca4f1f5b 5767 temp = gen_lowpart (imode, temp);
24fd4260 5768 }
5769 else
5770 {
ca4f1f5b 5771 imode = word_mode;
5772 /* Handle targets with different FP word orders. */
5773 if (FLOAT_WORDS_BIG_ENDIAN)
a0c938f0 5774 word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
ca4f1f5b 5775 else
a0c938f0 5776 word = bitpos / BITS_PER_WORD;
ca4f1f5b 5777 temp = operand_subword_force (temp, word, fmode);
5778 bitpos = bitpos % BITS_PER_WORD;
5779 }
5780
44b0f1d0 5781 /* Force the intermediate word_mode (or narrower) result into a
5782 register. This avoids attempting to create paradoxical SUBREGs
5783 of floating point modes below. */
5784 temp = force_reg (imode, temp);
5785
ca4f1f5b 5786 /* If the bitpos is within the "result mode" lowpart, the operation
5787 can be implement with a single bitwise AND. Otherwise, we need
5788 a right shift and an AND. */
5789
5790 if (bitpos < GET_MODE_BITSIZE (rmode))
5791 {
24fd4260 5792 if (bitpos < HOST_BITS_PER_WIDE_INT)
27f261ef 5793 {
24fd4260 5794 hi = 0;
5795 lo = (HOST_WIDE_INT) 1 << bitpos;
27f261ef 5796 }
5797 else
24fd4260 5798 {
5799 hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
5800 lo = 0;
5801 }
27f261ef 5802
ca4f1f5b 5803 if (imode != rmode)
5804 temp = gen_lowpart (rmode, temp);
24fd4260 5805 temp = expand_binop (rmode, and_optab, temp,
5806 immed_double_const (lo, hi, rmode),
ca4f1f5b 5807 NULL_RTX, 1, OPTAB_LIB_WIDEN);
27f261ef 5808 }
ca4f1f5b 5809 else
5810 {
5811 /* Perform a logical right shift to place the signbit in the least
a0c938f0 5812 significant bit, then truncate the result to the desired mode
ca4f1f5b 5813 and mask just this bit. */
5814 temp = expand_shift (RSHIFT_EXPR, imode, temp,
5815 build_int_cst (NULL_TREE, bitpos), NULL_RTX, 1);
5816 temp = gen_lowpart (rmode, temp);
5817 temp = expand_binop (rmode, and_optab, temp, const1_rtx,
5818 NULL_RTX, 1, OPTAB_LIB_WIDEN);
5819 }
5820
27f261ef 5821 return temp;
5822}
73673831 5823
5824/* Expand fork or exec calls. TARGET is the desired target of the
c2f47e15 5825 call. EXP is the call. FN is the
73673831 5826 identificator of the actual function. IGNORE is nonzero if the
5827 value is to be ignored. */
5828
5829static rtx
c2f47e15 5830expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
73673831 5831{
5832 tree id, decl;
5833 tree call;
5834
5835 /* If we are not profiling, just call the function. */
5836 if (!profile_arc_flag)
5837 return NULL_RTX;
5838
5839 /* Otherwise call the wrapper. This should be equivalent for the rest of
5840 compiler, so the code does not diverge, and the wrapper may run the
9c9bad97 5841 code necessary for keeping the profiling sane. */
73673831 5842
5843 switch (DECL_FUNCTION_CODE (fn))
5844 {
5845 case BUILT_IN_FORK:
5846 id = get_identifier ("__gcov_fork");
5847 break;
5848
5849 case BUILT_IN_EXECL:
5850 id = get_identifier ("__gcov_execl");
5851 break;
5852
5853 case BUILT_IN_EXECV:
5854 id = get_identifier ("__gcov_execv");
5855 break;
5856
5857 case BUILT_IN_EXECLP:
5858 id = get_identifier ("__gcov_execlp");
5859 break;
5860
5861 case BUILT_IN_EXECLE:
5862 id = get_identifier ("__gcov_execle");
5863 break;
5864
5865 case BUILT_IN_EXECVP:
5866 id = get_identifier ("__gcov_execvp");
5867 break;
5868
5869 case BUILT_IN_EXECVE:
5870 id = get_identifier ("__gcov_execve");
5871 break;
5872
5873 default:
64db345d 5874 gcc_unreachable ();
73673831 5875 }
5876
5877 decl = build_decl (FUNCTION_DECL, id, TREE_TYPE (fn));
5878 DECL_EXTERNAL (decl) = 1;
5879 TREE_PUBLIC (decl) = 1;
5880 DECL_ARTIFICIAL (decl) = 1;
5881 TREE_NOTHROW (decl) = 1;
e82d310b 5882 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
5883 DECL_VISIBILITY_SPECIFIED (decl) = 1;
c2f47e15 5884 call = rewrite_call_expr (exp, 0, decl, 0);
73673831 5885 return expand_call (call, target, ignore);
c2f47e15 5886 }
5887
b6a5fc45 5888
5889\f
3e272de8 5890/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
5891 the pointer in these functions is void*, the tree optimizers may remove
5892 casts. The mode computed in expand_builtin isn't reliable either, due
5893 to __sync_bool_compare_and_swap.
5894
5895 FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
5896 group of builtins. This gives us log2 of the mode size. */
5897
5898static inline enum machine_mode
5899get_builtin_sync_mode (int fcode_diff)
5900{
ad3a13b5 5901 /* The size is not negotiable, so ask not to get BLKmode in return
5902 if the target indicates that a smaller size would be better. */
5903 return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
3e272de8 5904}
5905
041e0215 5906/* Expand the memory expression LOC and return the appropriate memory operand
5907 for the builtin_sync operations. */
5908
5909static rtx
5910get_builtin_sync_mem (tree loc, enum machine_mode mode)
5911{
5912 rtx addr, mem;
5913
1db6d067 5914 addr = expand_expr (loc, NULL_RTX, Pmode, EXPAND_SUM);
041e0215 5915
5916 /* Note that we explicitly do not want any alias information for this
5917 memory, so that we kill all other live memories. Otherwise we don't
5918 satisfy the full barrier semantics of the intrinsic. */
5919 mem = validize_mem (gen_rtx_MEM (mode, addr));
5920
5921 set_mem_align (mem, get_pointer_alignment (loc, BIGGEST_ALIGNMENT));
c94cfd1c 5922 set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
041e0215 5923 MEM_VOLATILE_P (mem) = 1;
5924
5925 return mem;
5926}
5927
b6a5fc45 5928/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
c2f47e15 5929 EXP is the CALL_EXPR. CODE is the rtx code
b6a5fc45 5930 that corresponds to the arithmetic or logical operation from the name;
5931 an exception here is that NOT actually means NAND. TARGET is an optional
5932 place for us to store the results; AFTER is true if this is the
5933 fetch_and_xxx form. IGNORE is true if we don't actually care about
5934 the result of the operation at all. */
5935
5936static rtx
c2f47e15 5937expand_builtin_sync_operation (enum machine_mode mode, tree exp,
3e272de8 5938 enum rtx_code code, bool after,
b6a5fc45 5939 rtx target, bool ignore)
5940{
041e0215 5941 rtx val, mem;
a8bb7059 5942 enum machine_mode old_mode;
b6a5fc45 5943
5944 /* Expand the operands. */
c2f47e15 5945 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5946
1db6d067 5947 val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
a8bb7059 5948 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5949 of CONST_INTs, where we know the old_mode only from the call argument. */
5950 old_mode = GET_MODE (val);
5951 if (old_mode == VOIDmode)
5952 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5953 val = convert_modes (mode, old_mode, val, 1);
b6a5fc45 5954
b6a5fc45 5955 if (ignore)
5956 return expand_sync_operation (mem, val, code);
5957 else
5958 return expand_sync_fetch_operation (mem, val, code, after, target);
5959}
5960
5961/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
c2f47e15 5962 intrinsics. EXP is the CALL_EXPR. IS_BOOL is
b6a5fc45 5963 true if this is the boolean form. TARGET is a place for us to store the
5964 results; this is NOT optional if IS_BOOL is true. */
5965
5966static rtx
c2f47e15 5967expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
3e272de8 5968 bool is_bool, rtx target)
b6a5fc45 5969{
041e0215 5970 rtx old_val, new_val, mem;
a8bb7059 5971 enum machine_mode old_mode;
b6a5fc45 5972
5973 /* Expand the operands. */
c2f47e15 5974 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5975
c2f47e15 5976
1db6d067 5977 old_val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX,
5978 mode, EXPAND_NORMAL);
a8bb7059 5979 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5980 of CONST_INTs, where we know the old_mode only from the call argument. */
5981 old_mode = GET_MODE (old_val);
5982 if (old_mode == VOIDmode)
5983 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5984 old_val = convert_modes (mode, old_mode, old_val, 1);
b6a5fc45 5985
1db6d067 5986 new_val = expand_expr (CALL_EXPR_ARG (exp, 2), NULL_RTX,
5987 mode, EXPAND_NORMAL);
a8bb7059 5988 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5989 of CONST_INTs, where we know the old_mode only from the call argument. */
5990 old_mode = GET_MODE (new_val);
5991 if (old_mode == VOIDmode)
5992 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2)));
5993 new_val = convert_modes (mode, old_mode, new_val, 1);
b6a5fc45 5994
b6a5fc45 5995 if (is_bool)
5996 return expand_bool_compare_and_swap (mem, old_val, new_val, target);
5997 else
5998 return expand_val_compare_and_swap (mem, old_val, new_val, target);
5999}
6000
6001/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
6002 general form is actually an atomic exchange, and some targets only
6003 support a reduced form with the second argument being a constant 1.
c2f47e15 6004 EXP is the CALL_EXPR; TARGET is an optional place for us to store
6005 the results. */
b6a5fc45 6006
6007static rtx
c2f47e15 6008expand_builtin_lock_test_and_set (enum machine_mode mode, tree exp,
3e272de8 6009 rtx target)
b6a5fc45 6010{
041e0215 6011 rtx val, mem;
a8bb7059 6012 enum machine_mode old_mode;
b6a5fc45 6013
6014 /* Expand the operands. */
c2f47e15 6015 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1db6d067 6016 val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
a8bb7059 6017 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
6018 of CONST_INTs, where we know the old_mode only from the call argument. */
6019 old_mode = GET_MODE (val);
6020 if (old_mode == VOIDmode)
6021 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
6022 val = convert_modes (mode, old_mode, val, 1);
b6a5fc45 6023
b6a5fc45 6024 return expand_sync_lock_test_and_set (mem, val, target);
6025}
6026
6027/* Expand the __sync_synchronize intrinsic. */
6028
6029static void
6030expand_builtin_synchronize (void)
6031{
82e58396 6032 tree x;
b6a5fc45 6033
6034#ifdef HAVE_memory_barrier
6035 if (HAVE_memory_barrier)
6036 {
6037 emit_insn (gen_memory_barrier ());
6038 return;
6039 }
6040#endif
6041
82e58396 6042 /* If no explicit memory barrier instruction is available, create an
6043 empty asm stmt with a memory clobber. */
6044 x = build4 (ASM_EXPR, void_type_node, build_string (0, ""), NULL, NULL,
6045 tree_cons (NULL, build_string (6, "memory"), NULL));
6046 ASM_VOLATILE_P (x) = 1;
6047 expand_asm_expr (x);
b6a5fc45 6048}
6049
c2f47e15 6050/* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */
b6a5fc45 6051
6052static void
c2f47e15 6053expand_builtin_lock_release (enum machine_mode mode, tree exp)
b6a5fc45 6054{
b6a5fc45 6055 enum insn_code icode;
041e0215 6056 rtx mem, insn;
3e272de8 6057 rtx val = const0_rtx;
b6a5fc45 6058
6059 /* Expand the operands. */
c2f47e15 6060 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 6061
6062 /* If there is an explicit operation in the md file, use it. */
6063 icode = sync_lock_release[mode];
6064 if (icode != CODE_FOR_nothing)
6065 {
6066 if (!insn_data[icode].operand[1].predicate (val, mode))
6067 val = force_reg (mode, val);
6068
6069 insn = GEN_FCN (icode) (mem, val);
6070 if (insn)
6071 {
6072 emit_insn (insn);
6073 return;
6074 }
6075 }
6076
6077 /* Otherwise we can implement this operation by emitting a barrier
6078 followed by a store of zero. */
6079 expand_builtin_synchronize ();
6080 emit_move_insn (mem, val);
6081}
53800dbe 6082\f
6083/* Expand an expression EXP that calls a built-in function,
6084 with result going to TARGET if that's convenient
6085 (and in mode MODE if that's convenient).
6086 SUBTARGET may be used as the target for computing one of EXP's operands.
6087 IGNORE is nonzero if the value is to be ignored. */
6088
6089rtx
aecda0d6 6090expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
6091 int ignore)
53800dbe 6092{
c6e6ecb1 6093 tree fndecl = get_callee_fndecl (exp);
53800dbe 6094 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
efb070c8 6095 enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
53800dbe 6096
8305149e 6097 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
883b2e73 6098 return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
bf8e3599 6099
53800dbe 6100 /* When not optimizing, generate calls to library functions for a certain
6101 set of builtins. */
cd9ff771 6102 if (!optimize
b6a5fc45 6103 && !called_as_built_in (fndecl)
cd9ff771 6104 && DECL_ASSEMBLER_NAME_SET_P (fndecl)
6105 && fcode != BUILT_IN_ALLOCA)
6106 return expand_call (exp, target, ignore);
53800dbe 6107
8d6d7930 6108 /* The built-in function expanders test for target == const0_rtx
6109 to determine whether the function's result will be ignored. */
6110 if (ignore)
6111 target = const0_rtx;
6112
6113 /* If the result of a pure or const built-in function is ignored, and
6114 none of its arguments are volatile, we can avoid expanding the
6115 built-in call and just evaluate the arguments for side-effects. */
6116 if (target == const0_rtx
6117 && (DECL_IS_PURE (fndecl) || TREE_READONLY (fndecl)))
6118 {
6119 bool volatilep = false;
6120 tree arg;
c2f47e15 6121 call_expr_arg_iterator iter;
8d6d7930 6122
c2f47e15 6123 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
6124 if (TREE_THIS_VOLATILE (arg))
8d6d7930 6125 {
6126 volatilep = true;
6127 break;
6128 }
6129
6130 if (! volatilep)
6131 {
c2f47e15 6132 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
6133 expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
8d6d7930 6134 return const0_rtx;
6135 }
6136 }
6137
53800dbe 6138 switch (fcode)
6139 {
4f35b1fc 6140 CASE_FLT_FN (BUILT_IN_FABS):
c2f47e15 6141 target = expand_builtin_fabs (exp, target, subtarget);
78a74442 6142 if (target)
a0c938f0 6143 return target;
78a74442 6144 break;
6145
4f35b1fc 6146 CASE_FLT_FN (BUILT_IN_COPYSIGN):
c2f47e15 6147 target = expand_builtin_copysign (exp, target, subtarget);
270436f3 6148 if (target)
6149 return target;
6150 break;
6151
7d3f6cc7 6152 /* Just do a normal library call if we were unable to fold
6153 the values. */
4f35b1fc 6154 CASE_FLT_FN (BUILT_IN_CABS):
78a74442 6155 break;
53800dbe 6156
4f35b1fc 6157 CASE_FLT_FN (BUILT_IN_EXP):
6158 CASE_FLT_FN (BUILT_IN_EXP10):
6159 CASE_FLT_FN (BUILT_IN_POW10):
6160 CASE_FLT_FN (BUILT_IN_EXP2):
6161 CASE_FLT_FN (BUILT_IN_EXPM1):
6162 CASE_FLT_FN (BUILT_IN_LOGB):
4f35b1fc 6163 CASE_FLT_FN (BUILT_IN_LOG):
6164 CASE_FLT_FN (BUILT_IN_LOG10):
6165 CASE_FLT_FN (BUILT_IN_LOG2):
6166 CASE_FLT_FN (BUILT_IN_LOG1P):
6167 CASE_FLT_FN (BUILT_IN_TAN):
6168 CASE_FLT_FN (BUILT_IN_ASIN):
6169 CASE_FLT_FN (BUILT_IN_ACOS):
6170 CASE_FLT_FN (BUILT_IN_ATAN):
7f3be425 6171 /* Treat these like sqrt only if unsafe math optimizations are allowed,
6172 because of possible accuracy problems. */
6173 if (! flag_unsafe_math_optimizations)
53800dbe 6174 break;
4f35b1fc 6175 CASE_FLT_FN (BUILT_IN_SQRT):
6176 CASE_FLT_FN (BUILT_IN_FLOOR):
6177 CASE_FLT_FN (BUILT_IN_CEIL):
6178 CASE_FLT_FN (BUILT_IN_TRUNC):
6179 CASE_FLT_FN (BUILT_IN_ROUND):
6180 CASE_FLT_FN (BUILT_IN_NEARBYINT):
6181 CASE_FLT_FN (BUILT_IN_RINT):
53800dbe 6182 target = expand_builtin_mathfn (exp, target, subtarget);
6183 if (target)
6184 return target;
6185 break;
6186
a67a90e5 6187 CASE_FLT_FN (BUILT_IN_ILOGB):
6188 if (! flag_unsafe_math_optimizations)
6189 break;
69b779ea 6190 CASE_FLT_FN (BUILT_IN_ISINF):
cde061c1 6191 CASE_FLT_FN (BUILT_IN_FINITE):
6192 case BUILT_IN_ISFINITE:
8a1a9cb7 6193 case BUILT_IN_ISNORMAL:
a67a90e5 6194 target = expand_builtin_interclass_mathfn (exp, target, subtarget);
6195 if (target)
6196 return target;
6197 break;
6198
4f35b1fc 6199 CASE_FLT_FN (BUILT_IN_LCEIL):
6200 CASE_FLT_FN (BUILT_IN_LLCEIL):
6201 CASE_FLT_FN (BUILT_IN_LFLOOR):
6202 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 6203 target = expand_builtin_int_roundingfn (exp, target, subtarget);
6204 if (target)
6205 return target;
6206 break;
6207
7d3afc77 6208 CASE_FLT_FN (BUILT_IN_LRINT):
6209 CASE_FLT_FN (BUILT_IN_LLRINT):
ef2f1a10 6210 CASE_FLT_FN (BUILT_IN_LROUND):
6211 CASE_FLT_FN (BUILT_IN_LLROUND):
7d3afc77 6212 target = expand_builtin_int_roundingfn_2 (exp, target, subtarget);
6213 if (target)
6214 return target;
6215 break;
6216
4f35b1fc 6217 CASE_FLT_FN (BUILT_IN_POW):
f1b844c6 6218 target = expand_builtin_pow (exp, target, subtarget);
6219 if (target)
6220 return target;
6221 break;
6222
4f35b1fc 6223 CASE_FLT_FN (BUILT_IN_POWI):
757c219d 6224 target = expand_builtin_powi (exp, target, subtarget);
6225 if (target)
6226 return target;
6227 break;
6228
4f35b1fc 6229 CASE_FLT_FN (BUILT_IN_ATAN2):
6230 CASE_FLT_FN (BUILT_IN_LDEXP):
73a954a1 6231 CASE_FLT_FN (BUILT_IN_SCALB):
6232 CASE_FLT_FN (BUILT_IN_SCALBN):
6233 CASE_FLT_FN (BUILT_IN_SCALBLN):
0fd605a5 6234 if (! flag_unsafe_math_optimizations)
6235 break;
ef722005 6236
6237 CASE_FLT_FN (BUILT_IN_FMOD):
6238 CASE_FLT_FN (BUILT_IN_REMAINDER):
6239 CASE_FLT_FN (BUILT_IN_DREM):
0fd605a5 6240 target = expand_builtin_mathfn_2 (exp, target, subtarget);
6241 if (target)
6242 return target;
6243 break;
6244
d735c391 6245 CASE_FLT_FN (BUILT_IN_CEXPI):
6246 target = expand_builtin_cexpi (exp, target, subtarget);
6247 gcc_assert (target);
6248 return target;
6249
4f35b1fc 6250 CASE_FLT_FN (BUILT_IN_SIN):
6251 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 6252 if (! flag_unsafe_math_optimizations)
6253 break;
6254 target = expand_builtin_mathfn_3 (exp, target, subtarget);
6255 if (target)
6256 return target;
6257 break;
6258
c3147c1a 6259 CASE_FLT_FN (BUILT_IN_SINCOS):
6260 if (! flag_unsafe_math_optimizations)
6261 break;
6262 target = expand_builtin_sincos (exp);
6263 if (target)
6264 return target;
6265 break;
6266
53800dbe 6267 case BUILT_IN_APPLY_ARGS:
6268 return expand_builtin_apply_args ();
6269
6270 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
6271 FUNCTION with a copy of the parameters described by
6272 ARGUMENTS, and ARGSIZE. It returns a block of memory
6273 allocated on the stack into which is stored all the registers
6274 that might possibly be used for returning the result of a
6275 function. ARGUMENTS is the value returned by
6276 __builtin_apply_args. ARGSIZE is the number of bytes of
6277 arguments that must be copied. ??? How should this value be
6278 computed? We'll also need a safe worst case value for varargs
6279 functions. */
6280 case BUILT_IN_APPLY:
c2f47e15 6281 if (!validate_arglist (exp, POINTER_TYPE,
0eb671f7 6282 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
c2f47e15 6283 && !validate_arglist (exp, REFERENCE_TYPE,
0eb671f7 6284 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 6285 return const0_rtx;
6286 else
6287 {
53800dbe 6288 rtx ops[3];
6289
c2f47e15 6290 ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
6291 ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
6292 ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
53800dbe 6293
6294 return expand_builtin_apply (ops[0], ops[1], ops[2]);
6295 }
6296
6297 /* __builtin_return (RESULT) causes the function to return the
6298 value described by RESULT. RESULT is address of the block of
6299 memory returned by __builtin_apply. */
6300 case BUILT_IN_RETURN:
c2f47e15 6301 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
6302 expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
53800dbe 6303 return const0_rtx;
6304
6305 case BUILT_IN_SAVEREGS:
a66c9326 6306 return expand_builtin_saveregs ();
53800dbe 6307
6308 case BUILT_IN_ARGS_INFO:
c2f47e15 6309 return expand_builtin_args_info (exp);
53800dbe 6310
6311 /* Return the address of the first anonymous stack arg. */
6312 case BUILT_IN_NEXT_ARG:
c2f47e15 6313 if (fold_builtin_next_arg (exp, false))
a0c938f0 6314 return const0_rtx;
79012a9d 6315 return expand_builtin_next_arg ();
53800dbe 6316
ac8fb6db 6317 case BUILT_IN_CLEAR_CACHE:
6318 target = expand_builtin___clear_cache (exp);
6319 if (target)
6320 return target;
6321 break;
6322
53800dbe 6323 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 6324 return expand_builtin_classify_type (exp);
53800dbe 6325
6326 case BUILT_IN_CONSTANT_P:
4ee9c684 6327 return const0_rtx;
53800dbe 6328
6329 case BUILT_IN_FRAME_ADDRESS:
6330 case BUILT_IN_RETURN_ADDRESS:
c2f47e15 6331 return expand_builtin_frame_address (fndecl, exp);
53800dbe 6332
6333 /* Returns the address of the area where the structure is returned.
6334 0 otherwise. */
6335 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
c2f47e15 6336 if (call_expr_nargs (exp) != 0
9342ee68 6337 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
e16ceb8e 6338 || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
9342ee68 6339 return const0_rtx;
53800dbe 6340 else
9342ee68 6341 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
53800dbe 6342
6343 case BUILT_IN_ALLOCA:
c2f47e15 6344 target = expand_builtin_alloca (exp, target);
53800dbe 6345 if (target)
6346 return target;
6347 break;
6348
4ee9c684 6349 case BUILT_IN_STACK_SAVE:
6350 return expand_stack_save ();
6351
6352 case BUILT_IN_STACK_RESTORE:
c2f47e15 6353 expand_stack_restore (CALL_EXPR_ARG (exp, 0));
4ee9c684 6354 return const0_rtx;
6355
42791117 6356 case BUILT_IN_BSWAP32:
6357 case BUILT_IN_BSWAP64:
c2f47e15 6358 target = expand_builtin_bswap (exp, target, subtarget);
42791117 6359
6360 if (target)
6361 return target;
6362 break;
6363
4f35b1fc 6364 CASE_INT_FN (BUILT_IN_FFS):
5053259b 6365 case BUILT_IN_FFSIMAX:
c2f47e15 6366 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6367 subtarget, ffs_optab);
6a08d0ab 6368 if (target)
6369 return target;
6370 break;
6371
4f35b1fc 6372 CASE_INT_FN (BUILT_IN_CLZ):
5053259b 6373 case BUILT_IN_CLZIMAX:
c2f47e15 6374 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6375 subtarget, clz_optab);
6a08d0ab 6376 if (target)
6377 return target;
6378 break;
6379
4f35b1fc 6380 CASE_INT_FN (BUILT_IN_CTZ):
5053259b 6381 case BUILT_IN_CTZIMAX:
c2f47e15 6382 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6383 subtarget, ctz_optab);
6a08d0ab 6384 if (target)
6385 return target;
6386 break;
6387
4f35b1fc 6388 CASE_INT_FN (BUILT_IN_POPCOUNT):
5053259b 6389 case BUILT_IN_POPCOUNTIMAX:
c2f47e15 6390 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6391 subtarget, popcount_optab);
6a08d0ab 6392 if (target)
6393 return target;
6394 break;
6395
4f35b1fc 6396 CASE_INT_FN (BUILT_IN_PARITY):
5053259b 6397 case BUILT_IN_PARITYIMAX:
c2f47e15 6398 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6399 subtarget, parity_optab);
53800dbe 6400 if (target)
6401 return target;
6402 break;
6403
6404 case BUILT_IN_STRLEN:
c2f47e15 6405 target = expand_builtin_strlen (exp, target, target_mode);
53800dbe 6406 if (target)
6407 return target;
6408 break;
6409
6410 case BUILT_IN_STRCPY:
c2f47e15 6411 target = expand_builtin_strcpy (fndecl, exp, target, mode);
53800dbe 6412 if (target)
6413 return target;
6414 break;
bf8e3599 6415
ed09096d 6416 case BUILT_IN_STRNCPY:
8ff6a5cd 6417 target = expand_builtin_strncpy (exp, target, mode);
ed09096d 6418 if (target)
6419 return target;
6420 break;
bf8e3599 6421
3b824fa6 6422 case BUILT_IN_STPCPY:
dc369150 6423 target = expand_builtin_stpcpy (exp, target, mode);
3b824fa6 6424 if (target)
6425 return target;
6426 break;
6427
49f0327b 6428 case BUILT_IN_STRCAT:
c2f47e15 6429 target = expand_builtin_strcat (fndecl, exp, target, mode);
49f0327b 6430 if (target)
6431 return target;
6432 break;
bf8e3599 6433
49f0327b 6434 case BUILT_IN_STRNCAT:
c2f47e15 6435 target = expand_builtin_strncat (exp, target, mode);
49f0327b 6436 if (target)
6437 return target;
6438 break;
bf8e3599 6439
49f0327b 6440 case BUILT_IN_STRSPN:
c2f47e15 6441 target = expand_builtin_strspn (exp, target, mode);
49f0327b 6442 if (target)
6443 return target;
6444 break;
bf8e3599 6445
49f0327b 6446 case BUILT_IN_STRCSPN:
c2f47e15 6447 target = expand_builtin_strcspn (exp, target, mode);
49f0327b 6448 if (target)
6449 return target;
6450 break;
bf8e3599 6451
17f5ea87 6452 case BUILT_IN_STRSTR:
c2f47e15 6453 target = expand_builtin_strstr (exp, target, mode);
17f5ea87 6454 if (target)
6455 return target;
6456 break;
bf8e3599 6457
46f3a74a 6458 case BUILT_IN_STRPBRK:
c2f47e15 6459 target = expand_builtin_strpbrk (exp, target, mode);
46f3a74a 6460 if (target)
6461 return target;
6462 break;
bf8e3599 6463
398aae36 6464 case BUILT_IN_INDEX:
83d79705 6465 case BUILT_IN_STRCHR:
c2f47e15 6466 target = expand_builtin_strchr (exp, target, mode);
83d79705 6467 if (target)
6468 return target;
6469 break;
6470
398aae36 6471 case BUILT_IN_RINDEX:
83d79705 6472 case BUILT_IN_STRRCHR:
c2f47e15 6473 target = expand_builtin_strrchr (exp, target, mode);
83d79705 6474 if (target)
6475 return target;
6476 break;
6477
53800dbe 6478 case BUILT_IN_MEMCPY:
5a0de151 6479 target = expand_builtin_memcpy (exp, target, mode);
3b824fa6 6480 if (target)
6481 return target;
6482 break;
6483
6484 case BUILT_IN_MEMPCPY:
c2f47e15 6485 target = expand_builtin_mempcpy (exp, target, mode);
53800dbe 6486 if (target)
6487 return target;
6488 break;
6489
c4950093 6490 case BUILT_IN_MEMMOVE:
c2f47e15 6491 target = expand_builtin_memmove (exp, target, mode, ignore);
c4950093 6492 if (target)
6493 return target;
6494 break;
6495
6496 case BUILT_IN_BCOPY:
c2f47e15 6497 target = expand_builtin_bcopy (exp, ignore);
c4950093 6498 if (target)
6499 return target;
6500 break;
6501
53800dbe 6502 case BUILT_IN_MEMSET:
c2f47e15 6503 target = expand_builtin_memset (exp, target, mode);
53800dbe 6504 if (target)
6505 return target;
6506 break;
6507
ffc83088 6508 case BUILT_IN_BZERO:
0b25db21 6509 target = expand_builtin_bzero (exp);
ffc83088 6510 if (target)
6511 return target;
6512 break;
6513
53800dbe 6514 case BUILT_IN_STRCMP:
83d79705 6515 target = expand_builtin_strcmp (exp, target, mode);
53800dbe 6516 if (target)
6517 return target;
6518 break;
6519
ed09096d 6520 case BUILT_IN_STRNCMP:
6521 target = expand_builtin_strncmp (exp, target, mode);
6522 if (target)
6523 return target;
6524 break;
6525
7959b13b 6526 case BUILT_IN_MEMCHR:
6527 target = expand_builtin_memchr (exp, target, mode);
6528 if (target)
6529 return target;
6530 break;
6531
071f1696 6532 case BUILT_IN_BCMP:
53800dbe 6533 case BUILT_IN_MEMCMP:
c2f47e15 6534 target = expand_builtin_memcmp (exp, target, mode);
53800dbe 6535 if (target)
6536 return target;
6537 break;
53800dbe 6538
6539 case BUILT_IN_SETJMP:
2c8a1497 6540 /* This should have been lowered to the builtins below. */
6541 gcc_unreachable ();
6542
6543 case BUILT_IN_SETJMP_SETUP:
6544 /* __builtin_setjmp_setup is passed a pointer to an array of five words
6545 and the receiver label. */
c2f47e15 6546 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2c8a1497 6547 {
c2f47e15 6548 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
2c8a1497 6549 VOIDmode, EXPAND_NORMAL);
c2f47e15 6550 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
2c8a1497 6551 rtx label_r = label_rtx (label);
6552
6553 /* This is copied from the handling of non-local gotos. */
6554 expand_builtin_setjmp_setup (buf_addr, label_r);
6555 nonlocal_goto_handler_labels
6556 = gen_rtx_EXPR_LIST (VOIDmode, label_r,
6557 nonlocal_goto_handler_labels);
6558 /* ??? Do not let expand_label treat us as such since we would
6559 not want to be both on the list of non-local labels and on
6560 the list of forced labels. */
6561 FORCED_LABEL (label) = 0;
6562 return const0_rtx;
6563 }
6564 break;
6565
6566 case BUILT_IN_SETJMP_DISPATCHER:
6567 /* __builtin_setjmp_dispatcher is passed the dispatcher label. */
c2f47e15 6568 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6569 {
c2f47e15 6570 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6571 rtx label_r = label_rtx (label);
6572
6573 /* Remove the dispatcher label from the list of non-local labels
6574 since the receiver labels have been added to it above. */
6575 remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels);
6576 return const0_rtx;
6577 }
6578 break;
6579
6580 case BUILT_IN_SETJMP_RECEIVER:
6581 /* __builtin_setjmp_receiver is passed the receiver label. */
c2f47e15 6582 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6583 {
c2f47e15 6584 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6585 rtx label_r = label_rtx (label);
6586
6587 expand_builtin_setjmp_receiver (label_r);
6588 return const0_rtx;
6589 }
6b7f6858 6590 break;
53800dbe 6591
6592 /* __builtin_longjmp is passed a pointer to an array of five words.
6593 It's similar to the C library longjmp function but works with
6594 __builtin_setjmp above. */
6595 case BUILT_IN_LONGJMP:
c2f47e15 6596 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 6597 {
c2f47e15 6598 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
8ec3c5c2 6599 VOIDmode, EXPAND_NORMAL);
c2f47e15 6600 rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
53800dbe 6601
6602 if (value != const1_rtx)
6603 {
1e5fcbe2 6604 error ("%<__builtin_longjmp%> second argument must be 1");
53800dbe 6605 return const0_rtx;
6606 }
6607
6608 expand_builtin_longjmp (buf_addr, value);
6609 return const0_rtx;
6610 }
2c8a1497 6611 break;
53800dbe 6612
4ee9c684 6613 case BUILT_IN_NONLOCAL_GOTO:
c2f47e15 6614 target = expand_builtin_nonlocal_goto (exp);
4ee9c684 6615 if (target)
6616 return target;
6617 break;
6618
843d08a9 6619 /* This updates the setjmp buffer that is its argument with the value
6620 of the current stack pointer. */
6621 case BUILT_IN_UPDATE_SETJMP_BUF:
c2f47e15 6622 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
843d08a9 6623 {
6624 rtx buf_addr
c2f47e15 6625 = expand_normal (CALL_EXPR_ARG (exp, 0));
843d08a9 6626
6627 expand_builtin_update_setjmp_buf (buf_addr);
6628 return const0_rtx;
6629 }
6630 break;
6631
53800dbe 6632 case BUILT_IN_TRAP:
a0ef1725 6633 expand_builtin_trap ();
53800dbe 6634 return const0_rtx;
6635
19bf118a 6636 case BUILT_IN_PRINTF:
0b25db21 6637 target = expand_builtin_printf (exp, target, mode, false);
19bf118a 6638 if (target)
6639 return target;
6640 break;
6641
6642 case BUILT_IN_PRINTF_UNLOCKED:
0b25db21 6643 target = expand_builtin_printf (exp, target, mode, true);
19bf118a 6644 if (target)
6645 return target;
6646 break;
6647
df94cd3b 6648 case BUILT_IN_FPUTS:
c2f47e15 6649 target = expand_builtin_fputs (exp, target, false);
c013a46e 6650 if (target)
6651 return target;
6652 break;
6653 case BUILT_IN_FPUTS_UNLOCKED:
c2f47e15 6654 target = expand_builtin_fputs (exp, target, true);
19bf118a 6655 if (target)
6656 return target;
6657 break;
6658
6659 case BUILT_IN_FPRINTF:
0b25db21 6660 target = expand_builtin_fprintf (exp, target, mode, false);
19bf118a 6661 if (target)
6662 return target;
6663 break;
6664
6665 case BUILT_IN_FPRINTF_UNLOCKED:
0b25db21 6666 target = expand_builtin_fprintf (exp, target, mode, true);
df94cd3b 6667 if (target)
6668 return target;
6669 break;
bf8e3599 6670
6411575e 6671 case BUILT_IN_SPRINTF:
c2f47e15 6672 target = expand_builtin_sprintf (exp, target, mode);
6411575e 6673 if (target)
6674 return target;
6675 break;
6676
4f35b1fc 6677 CASE_FLT_FN (BUILT_IN_SIGNBIT):
004e23c4 6678 case BUILT_IN_SIGNBITD32:
6679 case BUILT_IN_SIGNBITD64:
6680 case BUILT_IN_SIGNBITD128:
27f261ef 6681 target = expand_builtin_signbit (exp, target);
6682 if (target)
6683 return target;
6684 break;
6685
53800dbe 6686 /* Various hooks for the DWARF 2 __throw routine. */
6687 case BUILT_IN_UNWIND_INIT:
6688 expand_builtin_unwind_init ();
6689 return const0_rtx;
6690 case BUILT_IN_DWARF_CFA:
6691 return virtual_cfa_rtx;
6692#ifdef DWARF2_UNWIND_INFO
f8f023a5 6693 case BUILT_IN_DWARF_SP_COLUMN:
6694 return expand_builtin_dwarf_sp_column ();
695e919b 6695 case BUILT_IN_INIT_DWARF_REG_SIZES:
c2f47e15 6696 expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
695e919b 6697 return const0_rtx;
53800dbe 6698#endif
6699 case BUILT_IN_FROB_RETURN_ADDR:
c2f47e15 6700 return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6701 case BUILT_IN_EXTRACT_RETURN_ADDR:
c2f47e15 6702 return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6703 case BUILT_IN_EH_RETURN:
c2f47e15 6704 expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
6705 CALL_EXPR_ARG (exp, 1));
53800dbe 6706 return const0_rtx;
df4b504c 6707#ifdef EH_RETURN_DATA_REGNO
6708 case BUILT_IN_EH_RETURN_DATA_REGNO:
c2f47e15 6709 return expand_builtin_eh_return_data_regno (exp);
df4b504c 6710#endif
26093bf4 6711 case BUILT_IN_EXTEND_POINTER:
c2f47e15 6712 return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
26093bf4 6713
7ccc713a 6714 case BUILT_IN_VA_START:
a66c9326 6715 case BUILT_IN_STDARG_START:
c2f47e15 6716 return expand_builtin_va_start (exp);
a66c9326 6717 case BUILT_IN_VA_END:
c2f47e15 6718 return expand_builtin_va_end (exp);
a66c9326 6719 case BUILT_IN_VA_COPY:
c2f47e15 6720 return expand_builtin_va_copy (exp);
89cfe6e5 6721 case BUILT_IN_EXPECT:
c2f47e15 6722 return expand_builtin_expect (exp, target);
5e3608d8 6723 case BUILT_IN_PREFETCH:
c2f47e15 6724 expand_builtin_prefetch (exp);
5e3608d8 6725 return const0_rtx;
6726
4ee9c684 6727 case BUILT_IN_PROFILE_FUNC_ENTER:
6728 return expand_builtin_profile_func (false);
6729 case BUILT_IN_PROFILE_FUNC_EXIT:
6730 return expand_builtin_profile_func (true);
6731
6732 case BUILT_IN_INIT_TRAMPOLINE:
c2f47e15 6733 return expand_builtin_init_trampoline (exp);
4ee9c684 6734 case BUILT_IN_ADJUST_TRAMPOLINE:
c2f47e15 6735 return expand_builtin_adjust_trampoline (exp);
4ee9c684 6736
73673831 6737 case BUILT_IN_FORK:
6738 case BUILT_IN_EXECL:
6739 case BUILT_IN_EXECV:
6740 case BUILT_IN_EXECLP:
6741 case BUILT_IN_EXECLE:
6742 case BUILT_IN_EXECVP:
6743 case BUILT_IN_EXECVE:
c2f47e15 6744 target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
73673831 6745 if (target)
6746 return target;
6747 break;
53800dbe 6748
b6a5fc45 6749 case BUILT_IN_FETCH_AND_ADD_1:
6750 case BUILT_IN_FETCH_AND_ADD_2:
6751 case BUILT_IN_FETCH_AND_ADD_4:
6752 case BUILT_IN_FETCH_AND_ADD_8:
27213ba3 6753 case BUILT_IN_FETCH_AND_ADD_16:
3e272de8 6754 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_ADD_1);
c2f47e15 6755 target = expand_builtin_sync_operation (mode, exp, PLUS,
b6a5fc45 6756 false, target, ignore);
6757 if (target)
6758 return target;
6759 break;
6760
6761 case BUILT_IN_FETCH_AND_SUB_1:
6762 case BUILT_IN_FETCH_AND_SUB_2:
6763 case BUILT_IN_FETCH_AND_SUB_4:
6764 case BUILT_IN_FETCH_AND_SUB_8:
27213ba3 6765 case BUILT_IN_FETCH_AND_SUB_16:
3e272de8 6766 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_SUB_1);
c2f47e15 6767 target = expand_builtin_sync_operation (mode, exp, MINUS,
b6a5fc45 6768 false, target, ignore);
6769 if (target)
6770 return target;
6771 break;
6772
6773 case BUILT_IN_FETCH_AND_OR_1:
6774 case BUILT_IN_FETCH_AND_OR_2:
6775 case BUILT_IN_FETCH_AND_OR_4:
6776 case BUILT_IN_FETCH_AND_OR_8:
27213ba3 6777 case BUILT_IN_FETCH_AND_OR_16:
3e272de8 6778 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_OR_1);
c2f47e15 6779 target = expand_builtin_sync_operation (mode, exp, IOR,
b6a5fc45 6780 false, target, ignore);
6781 if (target)
6782 return target;
6783 break;
6784
6785 case BUILT_IN_FETCH_AND_AND_1:
6786 case BUILT_IN_FETCH_AND_AND_2:
6787 case BUILT_IN_FETCH_AND_AND_4:
6788 case BUILT_IN_FETCH_AND_AND_8:
27213ba3 6789 case BUILT_IN_FETCH_AND_AND_16:
3e272de8 6790 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_AND_1);
c2f47e15 6791 target = expand_builtin_sync_operation (mode, exp, AND,
b6a5fc45 6792 false, target, ignore);
6793 if (target)
6794 return target;
6795 break;
6796
6797 case BUILT_IN_FETCH_AND_XOR_1:
6798 case BUILT_IN_FETCH_AND_XOR_2:
6799 case BUILT_IN_FETCH_AND_XOR_4:
6800 case BUILT_IN_FETCH_AND_XOR_8:
27213ba3 6801 case BUILT_IN_FETCH_AND_XOR_16:
3e272de8 6802 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_XOR_1);
c2f47e15 6803 target = expand_builtin_sync_operation (mode, exp, XOR,
b6a5fc45 6804 false, target, ignore);
6805 if (target)
6806 return target;
6807 break;
6808
6809 case BUILT_IN_FETCH_AND_NAND_1:
6810 case BUILT_IN_FETCH_AND_NAND_2:
6811 case BUILT_IN_FETCH_AND_NAND_4:
6812 case BUILT_IN_FETCH_AND_NAND_8:
27213ba3 6813 case BUILT_IN_FETCH_AND_NAND_16:
3e272de8 6814 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_NAND_1);
c2f47e15 6815 target = expand_builtin_sync_operation (mode, exp, NOT,
b6a5fc45 6816 false, target, ignore);
6817 if (target)
6818 return target;
6819 break;
6820
6821 case BUILT_IN_ADD_AND_FETCH_1:
6822 case BUILT_IN_ADD_AND_FETCH_2:
6823 case BUILT_IN_ADD_AND_FETCH_4:
6824 case BUILT_IN_ADD_AND_FETCH_8:
27213ba3 6825 case BUILT_IN_ADD_AND_FETCH_16:
3e272de8 6826 mode = get_builtin_sync_mode (fcode - BUILT_IN_ADD_AND_FETCH_1);
c2f47e15 6827 target = expand_builtin_sync_operation (mode, exp, PLUS,
b6a5fc45 6828 true, target, ignore);
6829 if (target)
6830 return target;
6831 break;
6832
6833 case BUILT_IN_SUB_AND_FETCH_1:
6834 case BUILT_IN_SUB_AND_FETCH_2:
6835 case BUILT_IN_SUB_AND_FETCH_4:
6836 case BUILT_IN_SUB_AND_FETCH_8:
27213ba3 6837 case BUILT_IN_SUB_AND_FETCH_16:
3e272de8 6838 mode = get_builtin_sync_mode (fcode - BUILT_IN_SUB_AND_FETCH_1);
c2f47e15 6839 target = expand_builtin_sync_operation (mode, exp, MINUS,
b6a5fc45 6840 true, target, ignore);
6841 if (target)
6842 return target;
6843 break;
6844
6845 case BUILT_IN_OR_AND_FETCH_1:
6846 case BUILT_IN_OR_AND_FETCH_2:
6847 case BUILT_IN_OR_AND_FETCH_4:
6848 case BUILT_IN_OR_AND_FETCH_8:
27213ba3 6849 case BUILT_IN_OR_AND_FETCH_16:
3e272de8 6850 mode = get_builtin_sync_mode (fcode - BUILT_IN_OR_AND_FETCH_1);
c2f47e15 6851 target = expand_builtin_sync_operation (mode, exp, IOR,
b6a5fc45 6852 true, target, ignore);
6853 if (target)
6854 return target;
6855 break;
6856
6857 case BUILT_IN_AND_AND_FETCH_1:
6858 case BUILT_IN_AND_AND_FETCH_2:
6859 case BUILT_IN_AND_AND_FETCH_4:
6860 case BUILT_IN_AND_AND_FETCH_8:
27213ba3 6861 case BUILT_IN_AND_AND_FETCH_16:
3e272de8 6862 mode = get_builtin_sync_mode (fcode - BUILT_IN_AND_AND_FETCH_1);
c2f47e15 6863 target = expand_builtin_sync_operation (mode, exp, AND,
b6a5fc45 6864 true, target, ignore);
6865 if (target)
6866 return target;
6867 break;
6868
6869 case BUILT_IN_XOR_AND_FETCH_1:
6870 case BUILT_IN_XOR_AND_FETCH_2:
6871 case BUILT_IN_XOR_AND_FETCH_4:
6872 case BUILT_IN_XOR_AND_FETCH_8:
27213ba3 6873 case BUILT_IN_XOR_AND_FETCH_16:
3e272de8 6874 mode = get_builtin_sync_mode (fcode - BUILT_IN_XOR_AND_FETCH_1);
c2f47e15 6875 target = expand_builtin_sync_operation (mode, exp, XOR,
b6a5fc45 6876 true, target, ignore);
6877 if (target)
6878 return target;
6879 break;
6880
6881 case BUILT_IN_NAND_AND_FETCH_1:
6882 case BUILT_IN_NAND_AND_FETCH_2:
6883 case BUILT_IN_NAND_AND_FETCH_4:
6884 case BUILT_IN_NAND_AND_FETCH_8:
27213ba3 6885 case BUILT_IN_NAND_AND_FETCH_16:
3e272de8 6886 mode = get_builtin_sync_mode (fcode - BUILT_IN_NAND_AND_FETCH_1);
c2f47e15 6887 target = expand_builtin_sync_operation (mode, exp, NOT,
b6a5fc45 6888 true, target, ignore);
6889 if (target)
6890 return target;
6891 break;
6892
6893 case BUILT_IN_BOOL_COMPARE_AND_SWAP_1:
6894 case BUILT_IN_BOOL_COMPARE_AND_SWAP_2:
6895 case BUILT_IN_BOOL_COMPARE_AND_SWAP_4:
6896 case BUILT_IN_BOOL_COMPARE_AND_SWAP_8:
27213ba3 6897 case BUILT_IN_BOOL_COMPARE_AND_SWAP_16:
a601d32a 6898 if (mode == VOIDmode)
6899 mode = TYPE_MODE (boolean_type_node);
b6a5fc45 6900 if (!target || !register_operand (target, mode))
6901 target = gen_reg_rtx (mode);
3e272de8 6902
6903 mode = get_builtin_sync_mode (fcode - BUILT_IN_BOOL_COMPARE_AND_SWAP_1);
c2f47e15 6904 target = expand_builtin_compare_and_swap (mode, exp, true, target);
b6a5fc45 6905 if (target)
6906 return target;
6907 break;
6908
6909 case BUILT_IN_VAL_COMPARE_AND_SWAP_1:
6910 case BUILT_IN_VAL_COMPARE_AND_SWAP_2:
6911 case BUILT_IN_VAL_COMPARE_AND_SWAP_4:
6912 case BUILT_IN_VAL_COMPARE_AND_SWAP_8:
27213ba3 6913 case BUILT_IN_VAL_COMPARE_AND_SWAP_16:
3e272de8 6914 mode = get_builtin_sync_mode (fcode - BUILT_IN_VAL_COMPARE_AND_SWAP_1);
c2f47e15 6915 target = expand_builtin_compare_and_swap (mode, exp, false, target);
b6a5fc45 6916 if (target)
6917 return target;
6918 break;
6919
6920 case BUILT_IN_LOCK_TEST_AND_SET_1:
6921 case BUILT_IN_LOCK_TEST_AND_SET_2:
6922 case BUILT_IN_LOCK_TEST_AND_SET_4:
6923 case BUILT_IN_LOCK_TEST_AND_SET_8:
27213ba3 6924 case BUILT_IN_LOCK_TEST_AND_SET_16:
3e272de8 6925 mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_TEST_AND_SET_1);
c2f47e15 6926 target = expand_builtin_lock_test_and_set (mode, exp, target);
b6a5fc45 6927 if (target)
6928 return target;
6929 break;
6930
6931 case BUILT_IN_LOCK_RELEASE_1:
6932 case BUILT_IN_LOCK_RELEASE_2:
6933 case BUILT_IN_LOCK_RELEASE_4:
6934 case BUILT_IN_LOCK_RELEASE_8:
27213ba3 6935 case BUILT_IN_LOCK_RELEASE_16:
3e272de8 6936 mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_RELEASE_1);
c2f47e15 6937 expand_builtin_lock_release (mode, exp);
b6a5fc45 6938 return const0_rtx;
6939
6940 case BUILT_IN_SYNCHRONIZE:
6941 expand_builtin_synchronize ();
6942 return const0_rtx;
6943
0a39fd54 6944 case BUILT_IN_OBJECT_SIZE:
6945 return expand_builtin_object_size (exp);
6946
6947 case BUILT_IN_MEMCPY_CHK:
6948 case BUILT_IN_MEMPCPY_CHK:
6949 case BUILT_IN_MEMMOVE_CHK:
6950 case BUILT_IN_MEMSET_CHK:
6951 target = expand_builtin_memory_chk (exp, target, mode, fcode);
6952 if (target)
6953 return target;
6954 break;
6955
6956 case BUILT_IN_STRCPY_CHK:
6957 case BUILT_IN_STPCPY_CHK:
6958 case BUILT_IN_STRNCPY_CHK:
6959 case BUILT_IN_STRCAT_CHK:
b356dfef 6960 case BUILT_IN_STRNCAT_CHK:
0a39fd54 6961 case BUILT_IN_SNPRINTF_CHK:
6962 case BUILT_IN_VSNPRINTF_CHK:
6963 maybe_emit_chk_warning (exp, fcode);
6964 break;
6965
6966 case BUILT_IN_SPRINTF_CHK:
6967 case BUILT_IN_VSPRINTF_CHK:
6968 maybe_emit_sprintf_chk_warning (exp, fcode);
6969 break;
6970
92482ee0 6971 default: /* just do library call, if unknown builtin */
146c1b4f 6972 break;
53800dbe 6973 }
6974
6975 /* The switch statement above can drop through to cause the function
6976 to be called normally. */
6977 return expand_call (exp, target, ignore);
6978}
650e4c94 6979
805e22b2 6980/* Determine whether a tree node represents a call to a built-in
52203a9d 6981 function. If the tree T is a call to a built-in function with
6982 the right number of arguments of the appropriate types, return
6983 the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
6984 Otherwise the return value is END_BUILTINS. */
aecda0d6 6985
805e22b2 6986enum built_in_function
b7bf20db 6987builtin_mathfn_code (const_tree t)
805e22b2 6988{
b7bf20db 6989 const_tree fndecl, arg, parmlist;
6990 const_tree argtype, parmtype;
6991 const_call_expr_arg_iterator iter;
805e22b2 6992
6993 if (TREE_CODE (t) != CALL_EXPR
c2f47e15 6994 || TREE_CODE (CALL_EXPR_FN (t)) != ADDR_EXPR)
805e22b2 6995 return END_BUILTINS;
6996
c6e6ecb1 6997 fndecl = get_callee_fndecl (t);
6998 if (fndecl == NULL_TREE
52203a9d 6999 || TREE_CODE (fndecl) != FUNCTION_DECL
805e22b2 7000 || ! DECL_BUILT_IN (fndecl)
7001 || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
7002 return END_BUILTINS;
7003
52203a9d 7004 parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
b7bf20db 7005 init_const_call_expr_arg_iterator (t, &iter);
52203a9d 7006 for (; parmlist; parmlist = TREE_CHAIN (parmlist))
e9f80ff5 7007 {
52203a9d 7008 /* If a function doesn't take a variable number of arguments,
7009 the last element in the list will have type `void'. */
7010 parmtype = TREE_VALUE (parmlist);
7011 if (VOID_TYPE_P (parmtype))
7012 {
b7bf20db 7013 if (more_const_call_expr_args_p (&iter))
52203a9d 7014 return END_BUILTINS;
7015 return DECL_FUNCTION_CODE (fndecl);
7016 }
7017
b7bf20db 7018 if (! more_const_call_expr_args_p (&iter))
e9f80ff5 7019 return END_BUILTINS;
c2f47e15 7020
b7bf20db 7021 arg = next_const_call_expr_arg (&iter);
c2f47e15 7022 argtype = TREE_TYPE (arg);
52203a9d 7023
7024 if (SCALAR_FLOAT_TYPE_P (parmtype))
7025 {
7026 if (! SCALAR_FLOAT_TYPE_P (argtype))
7027 return END_BUILTINS;
7028 }
7029 else if (COMPLEX_FLOAT_TYPE_P (parmtype))
7030 {
7031 if (! COMPLEX_FLOAT_TYPE_P (argtype))
7032 return END_BUILTINS;
7033 }
7034 else if (POINTER_TYPE_P (parmtype))
7035 {
7036 if (! POINTER_TYPE_P (argtype))
7037 return END_BUILTINS;
7038 }
7039 else if (INTEGRAL_TYPE_P (parmtype))
7040 {
7041 if (! INTEGRAL_TYPE_P (argtype))
7042 return END_BUILTINS;
7043 }
7044 else
e9f80ff5 7045 return END_BUILTINS;
e9f80ff5 7046 }
7047
52203a9d 7048 /* Variable-length argument list. */
805e22b2 7049 return DECL_FUNCTION_CODE (fndecl);
7050}
7051
c2f47e15 7052/* Fold a call to __builtin_constant_p, if we know its argument ARG will
7053 evaluate to a constant. */
650e4c94 7054
7055static tree
c2f47e15 7056fold_builtin_constant_p (tree arg)
650e4c94 7057{
650e4c94 7058 /* We return 1 for a numeric type that's known to be a constant
7059 value at compile-time or for an aggregate type that's a
7060 literal constant. */
c2f47e15 7061 STRIP_NOPS (arg);
650e4c94 7062
7063 /* If we know this is a constant, emit the constant of one. */
c2f47e15 7064 if (CONSTANT_CLASS_P (arg)
7065 || (TREE_CODE (arg) == CONSTRUCTOR
7066 && TREE_CONSTANT (arg)))
650e4c94 7067 return integer_one_node;
c2f47e15 7068 if (TREE_CODE (arg) == ADDR_EXPR)
adcfa3a3 7069 {
c2f47e15 7070 tree op = TREE_OPERAND (arg, 0);
adcfa3a3 7071 if (TREE_CODE (op) == STRING_CST
7072 || (TREE_CODE (op) == ARRAY_REF
7073 && integer_zerop (TREE_OPERAND (op, 1))
7074 && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
7075 return integer_one_node;
7076 }
650e4c94 7077
1fb4300c 7078 /* If this expression has side effects, show we don't know it to be a
7079 constant. Likewise if it's a pointer or aggregate type since in
7080 those case we only want literals, since those are only optimized
f97c71a1 7081 when generating RTL, not later.
7082 And finally, if we are compiling an initializer, not code, we
7083 need to return a definite result now; there's not going to be any
7084 more optimization done. */
c2f47e15 7085 if (TREE_SIDE_EFFECTS (arg)
7086 || AGGREGATE_TYPE_P (TREE_TYPE (arg))
7087 || POINTER_TYPE_P (TREE_TYPE (arg))
47be647d 7088 || cfun == 0
7089 || folding_initializer)
650e4c94 7090 return integer_zero_node;
7091
c2f47e15 7092 return NULL_TREE;
650e4c94 7093}
7094
c2f47e15 7095/* Fold a call to __builtin_expect with argument ARG, if we expect that a
7096 comparison against the argument will fold to a constant. In practice,
7097 this means a true constant or the address of a non-weak symbol. */
4ee9c684 7098
7099static tree
c2f47e15 7100fold_builtin_expect (tree arg)
4ee9c684 7101{
c2f47e15 7102 tree inner;
4ee9c684 7103
7104 /* If the argument isn't invariant, then there's nothing we can do. */
7105 if (!TREE_INVARIANT (arg))
c2f47e15 7106 return NULL_TREE;
4ee9c684 7107
7108 /* If we're looking at an address of a weak decl, then do not fold. */
7109 inner = arg;
7110 STRIP_NOPS (inner);
7111 if (TREE_CODE (inner) == ADDR_EXPR)
7112 {
7113 do
7114 {
7115 inner = TREE_OPERAND (inner, 0);
7116 }
7117 while (TREE_CODE (inner) == COMPONENT_REF
7118 || TREE_CODE (inner) == ARRAY_REF);
7119 if (DECL_P (inner) && DECL_WEAK (inner))
c2f47e15 7120 return NULL_TREE;
4ee9c684 7121 }
7122
7123 /* Otherwise, ARG already has the proper type for the return value. */
7124 return arg;
7125}
7126
c2f47e15 7127/* Fold a call to __builtin_classify_type with argument ARG. */
27d0c333 7128
539a3a92 7129static tree
c2f47e15 7130fold_builtin_classify_type (tree arg)
539a3a92 7131{
c2f47e15 7132 if (arg == 0)
7016c612 7133 return build_int_cst (NULL_TREE, no_type_class);
539a3a92 7134
c2f47e15 7135 return build_int_cst (NULL_TREE, type_to_class (TREE_TYPE (arg)));
539a3a92 7136}
7137
c2f47e15 7138/* Fold a call to __builtin_strlen with argument ARG. */
e6e27594 7139
7140static tree
c2f47e15 7141fold_builtin_strlen (tree arg)
e6e27594 7142{
c2f47e15 7143 if (!validate_arg (arg, POINTER_TYPE))
e6e27594 7144 return NULL_TREE;
7145 else
7146 {
c2f47e15 7147 tree len = c_strlen (arg, 0);
e6e27594 7148
7149 if (len)
7150 {
7151 /* Convert from the internal "sizetype" type to "size_t". */
7152 if (size_type_node)
7153 len = fold_convert (size_type_node, len);
7154 return len;
7155 }
7156
7157 return NULL_TREE;
7158 }
7159}
7160
92c43e3c 7161/* Fold a call to __builtin_inf or __builtin_huge_val. */
7162
7163static tree
aecda0d6 7164fold_builtin_inf (tree type, int warn)
92c43e3c 7165{
aa870c1b 7166 REAL_VALUE_TYPE real;
7167
40f4dbd5 7168 /* __builtin_inff is intended to be usable to define INFINITY on all
7169 targets. If an infinity is not available, INFINITY expands "to a
7170 positive constant of type float that overflows at translation
7171 time", footnote "In this case, using INFINITY will violate the
7172 constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
7173 Thus we pedwarn to ensure this constraint violation is
7174 diagnosed. */
92c43e3c 7175 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
40f4dbd5 7176 pedwarn ("target format does not support infinity");
92c43e3c 7177
aa870c1b 7178 real_inf (&real);
7179 return build_real (type, real);
92c43e3c 7180}
7181
c2f47e15 7182/* Fold a call to __builtin_nan or __builtin_nans with argument ARG. */
b0db7939 7183
7184static tree
c2f47e15 7185fold_builtin_nan (tree arg, tree type, int quiet)
b0db7939 7186{
7187 REAL_VALUE_TYPE real;
7188 const char *str;
7189
c2f47e15 7190 if (!validate_arg (arg, POINTER_TYPE))
7191 return NULL_TREE;
7192 str = c_getstr (arg);
b0db7939 7193 if (!str)
c2f47e15 7194 return NULL_TREE;
b0db7939 7195
7196 if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
c2f47e15 7197 return NULL_TREE;
b0db7939 7198
7199 return build_real (type, real);
7200}
7201
277f8dd2 7202/* Return true if the floating point expression T has an integer value.
7203 We also allow +Inf, -Inf and NaN to be considered integer values. */
7204
7205static bool
7206integer_valued_real_p (tree t)
7207{
7208 switch (TREE_CODE (t))
7209 {
7210 case FLOAT_EXPR:
7211 return true;
7212
7213 case ABS_EXPR:
7214 case SAVE_EXPR:
7215 case NON_LVALUE_EXPR:
7216 return integer_valued_real_p (TREE_OPERAND (t, 0));
7217
7218 case COMPOUND_EXPR:
41076ef6 7219 case MODIFY_EXPR:
277f8dd2 7220 case BIND_EXPR:
35cc02b5 7221 return integer_valued_real_p (GENERIC_TREE_OPERAND (t, 1));
277f8dd2 7222
7223 case PLUS_EXPR:
7224 case MINUS_EXPR:
7225 case MULT_EXPR:
7226 case MIN_EXPR:
7227 case MAX_EXPR:
7228 return integer_valued_real_p (TREE_OPERAND (t, 0))
7229 && integer_valued_real_p (TREE_OPERAND (t, 1));
7230
7231 case COND_EXPR:
7232 return integer_valued_real_p (TREE_OPERAND (t, 1))
7233 && integer_valued_real_p (TREE_OPERAND (t, 2));
7234
7235 case REAL_CST:
0570334c 7236 return real_isinteger (TREE_REAL_CST_PTR (t), TYPE_MODE (TREE_TYPE (t)));
277f8dd2 7237
7238 case NOP_EXPR:
7239 {
7240 tree type = TREE_TYPE (TREE_OPERAND (t, 0));
7241 if (TREE_CODE (type) == INTEGER_TYPE)
7242 return true;
7243 if (TREE_CODE (type) == REAL_TYPE)
7244 return integer_valued_real_p (TREE_OPERAND (t, 0));
7245 break;
7246 }
7247
7248 case CALL_EXPR:
7249 switch (builtin_mathfn_code (t))
7250 {
4f35b1fc 7251 CASE_FLT_FN (BUILT_IN_CEIL):
7252 CASE_FLT_FN (BUILT_IN_FLOOR):
7253 CASE_FLT_FN (BUILT_IN_NEARBYINT):
7254 CASE_FLT_FN (BUILT_IN_RINT):
7255 CASE_FLT_FN (BUILT_IN_ROUND):
7256 CASE_FLT_FN (BUILT_IN_TRUNC):
277f8dd2 7257 return true;
7258
d4a43a03 7259 CASE_FLT_FN (BUILT_IN_FMIN):
7260 CASE_FLT_FN (BUILT_IN_FMAX):
c2f47e15 7261 return integer_valued_real_p (CALL_EXPR_ARG (t, 0))
7262 && integer_valued_real_p (CALL_EXPR_ARG (t, 1));
d4a43a03 7263
277f8dd2 7264 default:
7265 break;
7266 }
7267 break;
7268
7269 default:
7270 break;
7271 }
7272 return false;
7273}
7274
c2f47e15 7275/* FNDECL is assumed to be a builtin where truncation can be propagated
6528f4f4 7276 across (for instance floor((double)f) == (double)floorf (f).
c2f47e15 7277 Do the transformation for a call with argument ARG. */
277f8dd2 7278
6528f4f4 7279static tree
c2f47e15 7280fold_trunc_transparent_mathfn (tree fndecl, tree arg)
6528f4f4 7281{
6528f4f4 7282 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
277f8dd2 7283
c2f47e15 7284 if (!validate_arg (arg, REAL_TYPE))
7285 return NULL_TREE;
6528f4f4 7286
277f8dd2 7287 /* Integer rounding functions are idempotent. */
7288 if (fcode == builtin_mathfn_code (arg))
7289 return arg;
7290
7291 /* If argument is already integer valued, and we don't need to worry
7292 about setting errno, there's no need to perform rounding. */
7293 if (! flag_errno_math && integer_valued_real_p (arg))
7294 return arg;
7295
7296 if (optimize)
6528f4f4 7297 {
277f8dd2 7298 tree arg0 = strip_float_extensions (arg);
2426241c 7299 tree ftype = TREE_TYPE (TREE_TYPE (fndecl));
6528f4f4 7300 tree newtype = TREE_TYPE (arg0);
7301 tree decl;
7302
7303 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7304 && (decl = mathfn_built_in (newtype, fcode)))
c2f47e15 7305 return fold_convert (ftype,
7306 build_call_expr (decl, 1,
7307 fold_convert (newtype, arg0)));
6528f4f4 7308 }
c2f47e15 7309 return NULL_TREE;
6528f4f4 7310}
7311
c2f47e15 7312/* FNDECL is assumed to be builtin which can narrow the FP type of
7313 the argument, for instance lround((double)f) -> lroundf (f).
7314 Do the transformation for a call with argument ARG. */
9ed65c7f 7315
7316static tree
c2f47e15 7317fold_fixed_mathfn (tree fndecl, tree arg)
9ed65c7f 7318{
9ed65c7f 7319 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9ed65c7f 7320
c2f47e15 7321 if (!validate_arg (arg, REAL_TYPE))
7322 return NULL_TREE;
9ed65c7f 7323
7324 /* If argument is already integer valued, and we don't need to worry
7325 about setting errno, there's no need to perform rounding. */
7326 if (! flag_errno_math && integer_valued_real_p (arg))
49d00087 7327 return fold_build1 (FIX_TRUNC_EXPR, TREE_TYPE (TREE_TYPE (fndecl)), arg);
9ed65c7f 7328
7329 if (optimize)
7330 {
7331 tree ftype = TREE_TYPE (arg);
7332 tree arg0 = strip_float_extensions (arg);
7333 tree newtype = TREE_TYPE (arg0);
7334 tree decl;
7335
7336 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7337 && (decl = mathfn_built_in (newtype, fcode)))
c2f47e15 7338 return build_call_expr (decl, 1, fold_convert (newtype, arg0));
9ed65c7f 7339 }
73a0da56 7340
7341 /* Canonicalize llround (x) to lround (x) on LP64 targets where
7342 sizeof (long long) == sizeof (long). */
7343 if (TYPE_PRECISION (long_long_integer_type_node)
7344 == TYPE_PRECISION (long_integer_type_node))
7345 {
7346 tree newfn = NULL_TREE;
7347 switch (fcode)
7348 {
7349 CASE_FLT_FN (BUILT_IN_LLCEIL):
7350 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
7351 break;
7352
7353 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7354 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
7355 break;
7356
7357 CASE_FLT_FN (BUILT_IN_LLROUND):
7358 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
7359 break;
7360
7361 CASE_FLT_FN (BUILT_IN_LLRINT):
7362 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
7363 break;
7364
7365 default:
7366 break;
7367 }
7368
7369 if (newfn)
7370 {
c2f47e15 7371 tree newcall = build_call_expr(newfn, 1, arg);
73a0da56 7372 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), newcall);
7373 }
7374 }
7375
c2f47e15 7376 return NULL_TREE;
9ed65c7f 7377}
7378
c2f47e15 7379/* Fold call to builtin cabs, cabsf or cabsl with argument ARG. TYPE is the
7380 return type. Return NULL_TREE if no simplification can be made. */
c63f4ad3 7381
7382static tree
c2f47e15 7383fold_builtin_cabs (tree arg, tree type, tree fndecl)
c63f4ad3 7384{
c2f47e15 7385 tree res;
c63f4ad3 7386
c63f4ad3 7387 if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
7388 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
7389 return NULL_TREE;
7390
b4725390 7391 /* Calculate the result when the argument is a constant. */
7392 if (TREE_CODE (arg) == COMPLEX_CST
7393 && (res = do_mpfr_arg2 (TREE_REALPART (arg), TREE_IMAGPART (arg),
7394 type, mpfr_hypot)))
7395 return res;
7396
1af0d139 7397 if (TREE_CODE (arg) == COMPLEX_EXPR)
7398 {
7399 tree real = TREE_OPERAND (arg, 0);
7400 tree imag = TREE_OPERAND (arg, 1);
7401
7402 /* If either part is zero, cabs is fabs of the other. */
7403 if (real_zerop (real))
7404 return fold_build1 (ABS_EXPR, type, imag);
7405 if (real_zerop (imag))
7406 return fold_build1 (ABS_EXPR, type, real);
7407
7408 /* cabs(x+xi) -> fabs(x)*sqrt(2). */
7409 if (flag_unsafe_math_optimizations
7410 && operand_equal_p (real, imag, OEP_PURE_SAME))
7411 {
2e7ca27b 7412 const REAL_VALUE_TYPE sqrt2_trunc
7413 = real_value_truncate (TYPE_MODE (type), dconstsqrt2);
1af0d139 7414 STRIP_NOPS (real);
7415 return fold_build2 (MULT_EXPR, type,
7416 fold_build1 (ABS_EXPR, type, real),
2e7ca27b 7417 build_real (type, sqrt2_trunc));
1af0d139 7418 }
7419 }
c63f4ad3 7420
749891b2 7421 /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */
7422 if (TREE_CODE (arg) == NEGATE_EXPR
7423 || TREE_CODE (arg) == CONJ_EXPR)
c2f47e15 7424 return build_call_expr (fndecl, 1, TREE_OPERAND (arg, 0));
749891b2 7425
7d3f6cc7 7426 /* Don't do this when optimizing for size. */
7427 if (flag_unsafe_math_optimizations
7428 && optimize && !optimize_size)
c63f4ad3 7429 {
0da0dbfa 7430 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
c63f4ad3 7431
7432 if (sqrtfn != NULL_TREE)
7433 {
c2f47e15 7434 tree rpart, ipart, result;
c63f4ad3 7435
4ee9c684 7436 arg = builtin_save_expr (arg);
29a6518e 7437
49d00087 7438 rpart = fold_build1 (REALPART_EXPR, type, arg);
7439 ipart = fold_build1 (IMAGPART_EXPR, type, arg);
c63f4ad3 7440
4ee9c684 7441 rpart = builtin_save_expr (rpart);
7442 ipart = builtin_save_expr (ipart);
c63f4ad3 7443
49d00087 7444 result = fold_build2 (PLUS_EXPR, type,
7445 fold_build2 (MULT_EXPR, type,
7446 rpart, rpart),
7447 fold_build2 (MULT_EXPR, type,
7448 ipart, ipart));
c63f4ad3 7449
c2f47e15 7450 return build_call_expr (sqrtfn, 1, result);
c63f4ad3 7451 }
7452 }
7453
7454 return NULL_TREE;
7455}
7456
c2f47e15 7457/* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG.
7458 Return NULL_TREE if no simplification can be made. */
e6e27594 7459
7460static tree
c2f47e15 7461fold_builtin_sqrt (tree arg, tree type)
e6e27594 7462{
7463
7464 enum built_in_function fcode;
b4e8ab0c 7465 tree res;
c2f47e15 7466
7467 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7468 return NULL_TREE;
7469
b4e8ab0c 7470 /* Calculate the result when the argument is a constant. */
7471 if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
7472 return res;
7473
e6e27594 7474 /* Optimize sqrt(expN(x)) = expN(x*0.5). */
7475 fcode = builtin_mathfn_code (arg);
7476 if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
7477 {
c2f47e15 7478 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
49d00087 7479 arg = fold_build2 (MULT_EXPR, type,
c2f47e15 7480 CALL_EXPR_ARG (arg, 0),
49d00087 7481 build_real (type, dconsthalf));
c2f47e15 7482 return build_call_expr (expfn, 1, arg);
e6e27594 7483 }
7484
7485 /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */
7486 if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
7487 {
7488 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7489
7490 if (powfn)
7491 {
c2f47e15 7492 tree arg0 = CALL_EXPR_ARG (arg, 0);
e6e27594 7493 tree tree_root;
7494 /* The inner root was either sqrt or cbrt. */
7495 REAL_VALUE_TYPE dconstroot =
7496 BUILTIN_SQRT_P (fcode) ? dconsthalf : dconstthird;
7497
7498 /* Adjust for the outer root. */
7499 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7500 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7501 tree_root = build_real (type, dconstroot);
c2f47e15 7502 return build_call_expr (powfn, 2, arg0, tree_root);
e6e27594 7503 }
7504 }
7505
bc33117f 7506 /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
e6e27594 7507 if (flag_unsafe_math_optimizations
7508 && (fcode == BUILT_IN_POW
7509 || fcode == BUILT_IN_POWF
7510 || fcode == BUILT_IN_POWL))
7511 {
c2f47e15 7512 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
7513 tree arg0 = CALL_EXPR_ARG (arg, 0);
7514 tree arg1 = CALL_EXPR_ARG (arg, 1);
bc33117f 7515 tree narg1;
7516 if (!tree_expr_nonnegative_p (arg0))
7517 arg0 = build1 (ABS_EXPR, type, arg0);
49d00087 7518 narg1 = fold_build2 (MULT_EXPR, type, arg1,
7519 build_real (type, dconsthalf));
c2f47e15 7520 return build_call_expr (powfn, 2, arg0, narg1);
e6e27594 7521 }
7522
7523 return NULL_TREE;
7524}
7525
c2f47e15 7526/* Fold a builtin function call to cbrt, cbrtf, or cbrtl with argument ARG.
7527 Return NULL_TREE if no simplification can be made. */
7528
e6e27594 7529static tree
c2f47e15 7530fold_builtin_cbrt (tree arg, tree type)
e6e27594 7531{
e6e27594 7532 const enum built_in_function fcode = builtin_mathfn_code (arg);
29f4cd78 7533 tree res;
e6e27594 7534
c2f47e15 7535 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7536 return NULL_TREE;
7537
29f4cd78 7538 /* Calculate the result when the argument is a constant. */
7539 if ((res = do_mpfr_arg1 (arg, type, mpfr_cbrt, NULL, NULL, 0)))
7540 return res;
e6e27594 7541
cdfeb715 7542 if (flag_unsafe_math_optimizations)
e6e27594 7543 {
cdfeb715 7544 /* Optimize cbrt(expN(x)) -> expN(x/3). */
7545 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 7546 {
c2f47e15 7547 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7548 const REAL_VALUE_TYPE third_trunc =
7549 real_value_truncate (TYPE_MODE (type), dconstthird);
49d00087 7550 arg = fold_build2 (MULT_EXPR, type,
c2f47e15 7551 CALL_EXPR_ARG (arg, 0),
49d00087 7552 build_real (type, third_trunc));
c2f47e15 7553 return build_call_expr (expfn, 1, arg);
cdfeb715 7554 }
e6e27594 7555
cdfeb715 7556 /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */
7557 if (BUILTIN_SQRT_P (fcode))
a0c938f0 7558 {
cdfeb715 7559 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
e6e27594 7560
cdfeb715 7561 if (powfn)
7562 {
c2f47e15 7563 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7564 tree tree_root;
7565 REAL_VALUE_TYPE dconstroot = dconstthird;
7566
7567 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7568 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7569 tree_root = build_real (type, dconstroot);
c2f47e15 7570 return build_call_expr (powfn, 2, arg0, tree_root);
cdfeb715 7571 }
e6e27594 7572 }
7573
cdfeb715 7574 /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */
7575 if (BUILTIN_CBRT_P (fcode))
a0c938f0 7576 {
c2f47e15 7577 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7578 if (tree_expr_nonnegative_p (arg0))
7579 {
7580 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7581
7582 if (powfn)
a0c938f0 7583 {
cdfeb715 7584 tree tree_root;
7585 REAL_VALUE_TYPE dconstroot;
a0c938f0 7586
cdfeb715 7587 real_arithmetic (&dconstroot, MULT_EXPR, &dconstthird, &dconstthird);
7588 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7589 tree_root = build_real (type, dconstroot);
c2f47e15 7590 return build_call_expr (powfn, 2, arg0, tree_root);
cdfeb715 7591 }
7592 }
7593 }
a0c938f0 7594
cdfeb715 7595 /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */
c2f47e15 7596 if (fcode == BUILT_IN_POW
7597 || fcode == BUILT_IN_POWF
cdfeb715 7598 || fcode == BUILT_IN_POWL)
a0c938f0 7599 {
c2f47e15 7600 tree arg00 = CALL_EXPR_ARG (arg, 0);
7601 tree arg01 = CALL_EXPR_ARG (arg, 1);
cdfeb715 7602 if (tree_expr_nonnegative_p (arg00))
7603 {
c2f47e15 7604 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7605 const REAL_VALUE_TYPE dconstroot
7606 = real_value_truncate (TYPE_MODE (type), dconstthird);
49d00087 7607 tree narg01 = fold_build2 (MULT_EXPR, type, arg01,
7608 build_real (type, dconstroot));
c2f47e15 7609 return build_call_expr (powfn, 2, arg00, narg01);
cdfeb715 7610 }
7611 }
e6e27594 7612 }
7613 return NULL_TREE;
7614}
7615
c2f47e15 7616/* Fold function call to builtin cos, cosf, or cosl with argument ARG.
7617 TYPE is the type of the return value. Return NULL_TREE if no
7618 simplification can be made. */
7619
e6e27594 7620static tree
c2f47e15 7621fold_builtin_cos (tree arg, tree type, tree fndecl)
e6e27594 7622{
e6ab33d8 7623 tree res, narg;
e6e27594 7624
c2f47e15 7625 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7626 return NULL_TREE;
7627
bffb7645 7628 /* Calculate the result when the argument is a constant. */
728bac60 7629 if ((res = do_mpfr_arg1 (arg, type, mpfr_cos, NULL, NULL, 0)))
bffb7645 7630 return res;
7631
e6e27594 7632 /* Optimize cos(-x) into cos (x). */
e6ab33d8 7633 if ((narg = fold_strip_sign_ops (arg)))
c2f47e15 7634 return build_call_expr (fndecl, 1, narg);
e6e27594 7635
7636 return NULL_TREE;
7637}
7638
c2f47e15 7639/* Fold function call to builtin cosh, coshf, or coshl with argument ARG.
7640 Return NULL_TREE if no simplification can be made. */
7641
cacdc1af 7642static tree
c2f47e15 7643fold_builtin_cosh (tree arg, tree type, tree fndecl)
cacdc1af 7644{
c2f47e15 7645 if (validate_arg (arg, REAL_TYPE))
cacdc1af 7646 {
cacdc1af 7647 tree res, narg;
7648
7649 /* Calculate the result when the argument is a constant. */
7650 if ((res = do_mpfr_arg1 (arg, type, mpfr_cosh, NULL, NULL, 0)))
7651 return res;
7652
7653 /* Optimize cosh(-x) into cosh (x). */
7654 if ((narg = fold_strip_sign_ops (arg)))
c2f47e15 7655 return build_call_expr (fndecl, 1, narg);
cacdc1af 7656 }
7657
7658 return NULL_TREE;
7659}
7660
c2f47e15 7661/* Fold function call to builtin tan, tanf, or tanl with argument ARG.
7662 Return NULL_TREE if no simplification can be made. */
7663
e6e27594 7664static tree
c2f47e15 7665fold_builtin_tan (tree arg, tree type)
e6e27594 7666{
7667 enum built_in_function fcode;
29f4cd78 7668 tree res;
e6e27594 7669
c2f47e15 7670 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7671 return NULL_TREE;
7672
bffb7645 7673 /* Calculate the result when the argument is a constant. */
728bac60 7674 if ((res = do_mpfr_arg1 (arg, type, mpfr_tan, NULL, NULL, 0)))
bffb7645 7675 return res;
7676
e6e27594 7677 /* Optimize tan(atan(x)) = x. */
7678 fcode = builtin_mathfn_code (arg);
7679 if (flag_unsafe_math_optimizations
7680 && (fcode == BUILT_IN_ATAN
7681 || fcode == BUILT_IN_ATANF
7682 || fcode == BUILT_IN_ATANL))
c2f47e15 7683 return CALL_EXPR_ARG (arg, 0);
e6e27594 7684
7685 return NULL_TREE;
7686}
7687
d735c391 7688/* Fold function call to builtin sincos, sincosf, or sincosl. Return
7689 NULL_TREE if no simplification can be made. */
7690
7691static tree
c2f47e15 7692fold_builtin_sincos (tree arg0, tree arg1, tree arg2)
d735c391 7693{
c2f47e15 7694 tree type;
d735c391 7695 tree res, fn, call;
7696
c2f47e15 7697 if (!validate_arg (arg0, REAL_TYPE)
7698 || !validate_arg (arg1, POINTER_TYPE)
7699 || !validate_arg (arg2, POINTER_TYPE))
d735c391 7700 return NULL_TREE;
7701
d735c391 7702 type = TREE_TYPE (arg0);
d735c391 7703
7704 /* Calculate the result when the argument is a constant. */
7705 if ((res = do_mpfr_sincos (arg0, arg1, arg2)))
7706 return res;
7707
7708 /* Canonicalize sincos to cexpi. */
2a6b4c77 7709 if (!TARGET_C99_FUNCTIONS)
7710 return NULL_TREE;
d735c391 7711 fn = mathfn_built_in (type, BUILT_IN_CEXPI);
7712 if (!fn)
7713 return NULL_TREE;
7714
c2f47e15 7715 call = build_call_expr (fn, 1, arg0);
d735c391 7716 call = builtin_save_expr (call);
7717
7718 return build2 (COMPOUND_EXPR, type,
7719 build2 (MODIFY_EXPR, void_type_node,
7720 build_fold_indirect_ref (arg1),
7721 build1 (IMAGPART_EXPR, type, call)),
7722 build2 (MODIFY_EXPR, void_type_node,
7723 build_fold_indirect_ref (arg2),
7724 build1 (REALPART_EXPR, type, call)));
7725}
7726
c5bb2c4b 7727/* Fold function call to builtin cexp, cexpf, or cexpl. Return
7728 NULL_TREE if no simplification can be made. */
7729
7730static tree
c2f47e15 7731fold_builtin_cexp (tree arg0, tree type)
c5bb2c4b 7732{
c2f47e15 7733 tree rtype;
c5bb2c4b 7734 tree realp, imagp, ifn;
7735
c2f47e15 7736 if (!validate_arg (arg0, COMPLEX_TYPE))
c5bb2c4b 7737 return NULL_TREE;
7738
c5bb2c4b 7739 rtype = TREE_TYPE (TREE_TYPE (arg0));
7740
7741 /* In case we can figure out the real part of arg0 and it is constant zero
7742 fold to cexpi. */
2a6b4c77 7743 if (!TARGET_C99_FUNCTIONS)
7744 return NULL_TREE;
c5bb2c4b 7745 ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI);
7746 if (!ifn)
7747 return NULL_TREE;
7748
7749 if ((realp = fold_unary (REALPART_EXPR, rtype, arg0))
7750 && real_zerop (realp))
7751 {
7752 tree narg = fold_build1 (IMAGPART_EXPR, rtype, arg0);
c2f47e15 7753 return build_call_expr (ifn, 1, narg);
c5bb2c4b 7754 }
7755
7756 /* In case we can easily decompose real and imaginary parts split cexp
7757 to exp (r) * cexpi (i). */
7758 if (flag_unsafe_math_optimizations
7759 && realp)
7760 {
7761 tree rfn, rcall, icall;
7762
7763 rfn = mathfn_built_in (rtype, BUILT_IN_EXP);
7764 if (!rfn)
7765 return NULL_TREE;
7766
7767 imagp = fold_unary (IMAGPART_EXPR, rtype, arg0);
7768 if (!imagp)
7769 return NULL_TREE;
7770
c2f47e15 7771 icall = build_call_expr (ifn, 1, imagp);
c5bb2c4b 7772 icall = builtin_save_expr (icall);
c2f47e15 7773 rcall = build_call_expr (rfn, 1, realp);
c5bb2c4b 7774 rcall = builtin_save_expr (rcall);
7775 return build2 (COMPLEX_EXPR, type,
7776 build2 (MULT_EXPR, rtype,
7777 rcall,
7778 build1 (REALPART_EXPR, rtype, icall)),
7779 build2 (MULT_EXPR, rtype,
7780 rcall,
7781 build1 (IMAGPART_EXPR, rtype, icall)));
7782 }
7783
7784 return NULL_TREE;
7785}
7786
c2f47e15 7787/* Fold function call to builtin trunc, truncf or truncl with argument ARG.
7788 Return NULL_TREE if no simplification can be made. */
277f8dd2 7789
7790static tree
c2f47e15 7791fold_builtin_trunc (tree fndecl, tree arg)
277f8dd2 7792{
c2f47e15 7793 if (!validate_arg (arg, REAL_TYPE))
7794 return NULL_TREE;
277f8dd2 7795
7796 /* Optimize trunc of constant value. */
f96bd2bf 7797 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7798 {
7799 REAL_VALUE_TYPE r, x;
2426241c 7800 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7801
7802 x = TREE_REAL_CST (arg);
7803 real_trunc (&r, TYPE_MODE (type), &x);
7804 return build_real (type, r);
7805 }
7806
c2f47e15 7807 return fold_trunc_transparent_mathfn (fndecl, arg);
277f8dd2 7808}
7809
c2f47e15 7810/* Fold function call to builtin floor, floorf or floorl with argument ARG.
7811 Return NULL_TREE if no simplification can be made. */
277f8dd2 7812
7813static tree
c2f47e15 7814fold_builtin_floor (tree fndecl, tree arg)
277f8dd2 7815{
c2f47e15 7816 if (!validate_arg (arg, REAL_TYPE))
7817 return NULL_TREE;
277f8dd2 7818
7819 /* Optimize floor of constant value. */
f96bd2bf 7820 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7821 {
7822 REAL_VALUE_TYPE x;
7823
7824 x = TREE_REAL_CST (arg);
7825 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7826 {
2426241c 7827 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7828 REAL_VALUE_TYPE r;
7829
7830 real_floor (&r, TYPE_MODE (type), &x);
7831 return build_real (type, r);
7832 }
7833 }
7834
acc2b92e 7835 /* Fold floor (x) where x is nonnegative to trunc (x). */
7836 if (tree_expr_nonnegative_p (arg))
30fe8286 7837 {
7838 tree truncfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_TRUNC);
7839 if (truncfn)
c2f47e15 7840 return build_call_expr (truncfn, 1, arg);
30fe8286 7841 }
acc2b92e 7842
c2f47e15 7843 return fold_trunc_transparent_mathfn (fndecl, arg);
277f8dd2 7844}
7845
c2f47e15 7846/* Fold function call to builtin ceil, ceilf or ceill with argument ARG.
7847 Return NULL_TREE if no simplification can be made. */
277f8dd2 7848
7849static tree
c2f47e15 7850fold_builtin_ceil (tree fndecl, tree arg)
277f8dd2 7851{
c2f47e15 7852 if (!validate_arg (arg, REAL_TYPE))
7853 return NULL_TREE;
277f8dd2 7854
7855 /* Optimize ceil of constant value. */
f96bd2bf 7856 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7857 {
7858 REAL_VALUE_TYPE x;
7859
7860 x = TREE_REAL_CST (arg);
7861 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7862 {
2426241c 7863 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7864 REAL_VALUE_TYPE r;
7865
7866 real_ceil (&r, TYPE_MODE (type), &x);
7867 return build_real (type, r);
7868 }
7869 }
7870
c2f47e15 7871 return fold_trunc_transparent_mathfn (fndecl, arg);
277f8dd2 7872}
7873
c2f47e15 7874/* Fold function call to builtin round, roundf or roundl with argument ARG.
7875 Return NULL_TREE if no simplification can be made. */
89ab3887 7876
7877static tree
c2f47e15 7878fold_builtin_round (tree fndecl, tree arg)
89ab3887 7879{
c2f47e15 7880 if (!validate_arg (arg, REAL_TYPE))
7881 return NULL_TREE;
89ab3887 7882
34f17811 7883 /* Optimize round of constant value. */
f96bd2bf 7884 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
89ab3887 7885 {
7886 REAL_VALUE_TYPE x;
7887
7888 x = TREE_REAL_CST (arg);
7889 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7890 {
2426241c 7891 tree type = TREE_TYPE (TREE_TYPE (fndecl));
89ab3887 7892 REAL_VALUE_TYPE r;
7893
7894 real_round (&r, TYPE_MODE (type), &x);
7895 return build_real (type, r);
7896 }
7897 }
7898
c2f47e15 7899 return fold_trunc_transparent_mathfn (fndecl, arg);
89ab3887 7900}
7901
34f17811 7902/* Fold function call to builtin lround, lroundf or lroundl (or the
c2f47e15 7903 corresponding long long versions) and other rounding functions. ARG
7904 is the argument to the call. Return NULL_TREE if no simplification
7905 can be made. */
34f17811 7906
7907static tree
c2f47e15 7908fold_builtin_int_roundingfn (tree fndecl, tree arg)
34f17811 7909{
c2f47e15 7910 if (!validate_arg (arg, REAL_TYPE))
7911 return NULL_TREE;
34f17811 7912
7913 /* Optimize lround of constant value. */
f96bd2bf 7914 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
34f17811 7915 {
7916 const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
7917
776a7bab 7918 if (real_isfinite (&x))
34f17811 7919 {
2426241c 7920 tree itype = TREE_TYPE (TREE_TYPE (fndecl));
ca9b061d 7921 tree ftype = TREE_TYPE (arg);
7922 unsigned HOST_WIDE_INT lo2;
34f17811 7923 HOST_WIDE_INT hi, lo;
7924 REAL_VALUE_TYPE r;
7925
ad52b9b7 7926 switch (DECL_FUNCTION_CODE (fndecl))
7927 {
4f35b1fc 7928 CASE_FLT_FN (BUILT_IN_LFLOOR):
7929 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 7930 real_floor (&r, TYPE_MODE (ftype), &x);
7931 break;
7932
4f35b1fc 7933 CASE_FLT_FN (BUILT_IN_LCEIL):
7934 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 7935 real_ceil (&r, TYPE_MODE (ftype), &x);
7936 break;
7937
4f35b1fc 7938 CASE_FLT_FN (BUILT_IN_LROUND):
7939 CASE_FLT_FN (BUILT_IN_LLROUND):
ad52b9b7 7940 real_round (&r, TYPE_MODE (ftype), &x);
7941 break;
7942
7943 default:
7944 gcc_unreachable ();
7945 }
7946
34f17811 7947 REAL_VALUE_TO_INT (&lo, &hi, r);
ca9b061d 7948 if (!fit_double_type (lo, hi, &lo2, &hi, itype))
7949 return build_int_cst_wide (itype, lo2, hi);
34f17811 7950 }
7951 }
7952
acc2b92e 7953 switch (DECL_FUNCTION_CODE (fndecl))
7954 {
7955 CASE_FLT_FN (BUILT_IN_LFLOOR):
7956 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7957 /* Fold lfloor (x) where x is nonnegative to FIX_TRUNC (x). */
7958 if (tree_expr_nonnegative_p (arg))
7959 return fold_build1 (FIX_TRUNC_EXPR, TREE_TYPE (TREE_TYPE (fndecl)),
7960 arg);
7961 break;
7962 default:;
7963 }
7964
c2f47e15 7965 return fold_fixed_mathfn (fndecl, arg);
34f17811 7966}
7967
70fb4c07 7968/* Fold function call to builtin ffs, clz, ctz, popcount and parity
c2f47e15 7969 and their long and long long variants (i.e. ffsl and ffsll). ARG is
7970 the argument to the call. Return NULL_TREE if no simplification can
7971 be made. */
70fb4c07 7972
7973static tree
c2f47e15 7974fold_builtin_bitop (tree fndecl, tree arg)
70fb4c07 7975{
c2f47e15 7976 if (!validate_arg (arg, INTEGER_TYPE))
70fb4c07 7977 return NULL_TREE;
7978
7979 /* Optimize for constant argument. */
f96bd2bf 7980 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
70fb4c07 7981 {
7982 HOST_WIDE_INT hi, width, result;
7983 unsigned HOST_WIDE_INT lo;
7c446c95 7984 tree type;
70fb4c07 7985
7986 type = TREE_TYPE (arg);
7987 width = TYPE_PRECISION (type);
7988 lo = TREE_INT_CST_LOW (arg);
7989
7990 /* Clear all the bits that are beyond the type's precision. */
7991 if (width > HOST_BITS_PER_WIDE_INT)
7992 {
7993 hi = TREE_INT_CST_HIGH (arg);
7994 if (width < 2 * HOST_BITS_PER_WIDE_INT)
7995 hi &= ~((HOST_WIDE_INT) (-1) >> (width - HOST_BITS_PER_WIDE_INT));
7996 }
7997 else
7998 {
7999 hi = 0;
8000 if (width < HOST_BITS_PER_WIDE_INT)
8001 lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
8002 }
8003
8004 switch (DECL_FUNCTION_CODE (fndecl))
8005 {
4f35b1fc 8006 CASE_INT_FN (BUILT_IN_FFS):
70fb4c07 8007 if (lo != 0)
8008 result = exact_log2 (lo & -lo) + 1;
8009 else if (hi != 0)
8010 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi) + 1;
8011 else
8012 result = 0;
8013 break;
8014
4f35b1fc 8015 CASE_INT_FN (BUILT_IN_CLZ):
70fb4c07 8016 if (hi != 0)
8017 result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
8018 else if (lo != 0)
8019 result = width - floor_log2 (lo) - 1;
8020 else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
8021 result = width;
8022 break;
8023
4f35b1fc 8024 CASE_INT_FN (BUILT_IN_CTZ):
70fb4c07 8025 if (lo != 0)
8026 result = exact_log2 (lo & -lo);
8027 else if (hi != 0)
8028 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi);
8029 else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
8030 result = width;
8031 break;
8032
4f35b1fc 8033 CASE_INT_FN (BUILT_IN_POPCOUNT):
70fb4c07 8034 result = 0;
8035 while (lo)
8036 result++, lo &= lo - 1;
8037 while (hi)
8038 result++, hi &= hi - 1;
8039 break;
8040
4f35b1fc 8041 CASE_INT_FN (BUILT_IN_PARITY):
70fb4c07 8042 result = 0;
8043 while (lo)
8044 result++, lo &= lo - 1;
8045 while (hi)
8046 result++, hi &= hi - 1;
8047 result &= 1;
8048 break;
8049
8050 default:
64db345d 8051 gcc_unreachable ();
70fb4c07 8052 }
8053
2426241c 8054 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
70fb4c07 8055 }
8056
8057 return NULL_TREE;
8058}
8059
42791117 8060/* Fold function call to builtin_bswap and the long and long long
8061 variants. Return NULL_TREE if no simplification can be made. */
8062static tree
c2f47e15 8063fold_builtin_bswap (tree fndecl, tree arg)
42791117 8064{
c2f47e15 8065 if (! validate_arg (arg, INTEGER_TYPE))
8066 return NULL_TREE;
42791117 8067
8068 /* Optimize constant value. */
f96bd2bf 8069 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
42791117 8070 {
8071 HOST_WIDE_INT hi, width, r_hi = 0;
8072 unsigned HOST_WIDE_INT lo, r_lo = 0;
8073 tree type;
8074
8075 type = TREE_TYPE (arg);
8076 width = TYPE_PRECISION (type);
8077 lo = TREE_INT_CST_LOW (arg);
8078 hi = TREE_INT_CST_HIGH (arg);
8079
8080 switch (DECL_FUNCTION_CODE (fndecl))
8081 {
8082 case BUILT_IN_BSWAP32:
8083 case BUILT_IN_BSWAP64:
8084 {
8085 int s;
8086
8087 for (s = 0; s < width; s += 8)
8088 {
8089 int d = width - s - 8;
8090 unsigned HOST_WIDE_INT byte;
8091
8092 if (s < HOST_BITS_PER_WIDE_INT)
8093 byte = (lo >> s) & 0xff;
8094 else
8095 byte = (hi >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff;
8096
8097 if (d < HOST_BITS_PER_WIDE_INT)
8098 r_lo |= byte << d;
8099 else
8100 r_hi |= byte << (d - HOST_BITS_PER_WIDE_INT);
8101 }
8102 }
8103
8104 break;
8105
8106 default:
8107 gcc_unreachable ();
8108 }
8109
8110 if (width < HOST_BITS_PER_WIDE_INT)
8111 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), r_lo);
8112 else
8113 return build_int_cst_wide (TREE_TYPE (TREE_TYPE (fndecl)), r_lo, r_hi);
8114 }
8115
8116 return NULL_TREE;
8117}
c2f47e15 8118
8918c507 8119/* Return true if EXPR is the real constant contained in VALUE. */
8120
8121static bool
8122real_dconstp (tree expr, const REAL_VALUE_TYPE *value)
8123{
8124 STRIP_NOPS (expr);
8125
8126 return ((TREE_CODE (expr) == REAL_CST
f96bd2bf 8127 && !TREE_OVERFLOW (expr)
a0c938f0 8128 && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), *value))
8129 || (TREE_CODE (expr) == COMPLEX_CST
8130 && real_dconstp (TREE_REALPART (expr), value)
8131 && real_zerop (TREE_IMAGPART (expr))));
8918c507 8132}
8133
8134/* A subroutine of fold_builtin to fold the various logarithmic
29f4cd78 8135 functions. Return NULL_TREE if no simplification can me made.
8136 FUNC is the corresponding MPFR logarithm function. */
8918c507 8137
8138static tree
c2f47e15 8139fold_builtin_logarithm (tree fndecl, tree arg,
29f4cd78 8140 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8141{
c2f47e15 8142 if (validate_arg (arg, REAL_TYPE))
8918c507 8143 {
8918c507 8144 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8145 tree res;
8918c507 8146 const enum built_in_function fcode = builtin_mathfn_code (arg);
0862b7e9 8147
29f4cd78 8148 /* Optimize log(e) = 1.0. We're never passed an exact 'e',
8149 instead we'll look for 'e' truncated to MODE. So only do
8150 this if flag_unsafe_math_optimizations is set. */
8151 if (flag_unsafe_math_optimizations && func == mpfr_log)
8152 {
8153 const REAL_VALUE_TYPE e_truncated =
8154 real_value_truncate (TYPE_MODE (type), dconste);
8155 if (real_dconstp (arg, &e_truncated))
1f5cb383 8156 return build_real (type, dconst1);
8157 }
0862b7e9 8158
29f4cd78 8159 /* Calculate the result when the argument is a constant. */
8160 if ((res = do_mpfr_arg1 (arg, type, func, &dconst0, NULL, false)))
8161 return res;
8162
8918c507 8163 /* Special case, optimize logN(expN(x)) = x. */
8164 if (flag_unsafe_math_optimizations
29f4cd78 8165 && ((func == mpfr_log
8918c507 8166 && (fcode == BUILT_IN_EXP
8167 || fcode == BUILT_IN_EXPF
8168 || fcode == BUILT_IN_EXPL))
29f4cd78 8169 || (func == mpfr_log2
8918c507 8170 && (fcode == BUILT_IN_EXP2
8171 || fcode == BUILT_IN_EXP2F
8172 || fcode == BUILT_IN_EXP2L))
29f4cd78 8173 || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode)))))
c2f47e15 8174 return fold_convert (type, CALL_EXPR_ARG (arg, 0));
8918c507 8175
ca273d4a 8176 /* Optimize logN(func()) for various exponential functions. We
a0c938f0 8177 want to determine the value "x" and the power "exponent" in
8178 order to transform logN(x**exponent) into exponent*logN(x). */
8918c507 8179 if (flag_unsafe_math_optimizations)
a0c938f0 8180 {
8918c507 8181 tree exponent = 0, x = 0;
0862b7e9 8182
8918c507 8183 switch (fcode)
8184 {
4f35b1fc 8185 CASE_FLT_FN (BUILT_IN_EXP):
8918c507 8186 /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
8918c507 8187 x = build_real (type,
8188 real_value_truncate (TYPE_MODE (type), dconste));
c2f47e15 8189 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8190 break;
4f35b1fc 8191 CASE_FLT_FN (BUILT_IN_EXP2):
8918c507 8192 /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */
8193 x = build_real (type, dconst2);
c2f47e15 8194 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8195 break;
4f35b1fc 8196 CASE_FLT_FN (BUILT_IN_EXP10):
8197 CASE_FLT_FN (BUILT_IN_POW10):
8918c507 8198 /* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */
8199 x = build_real (type, dconst10);
c2f47e15 8200 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8201 break;
4f35b1fc 8202 CASE_FLT_FN (BUILT_IN_SQRT):
8918c507 8203 /* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */
c2f47e15 8204 x = CALL_EXPR_ARG (arg, 0);
8918c507 8205 exponent = build_real (type, dconsthalf);
8206 break;
4f35b1fc 8207 CASE_FLT_FN (BUILT_IN_CBRT):
8918c507 8208 /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */
c2f47e15 8209 x = CALL_EXPR_ARG (arg, 0);
8918c507 8210 exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
8211 dconstthird));
8212 break;
4f35b1fc 8213 CASE_FLT_FN (BUILT_IN_POW):
8918c507 8214 /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x). */
c2f47e15 8215 x = CALL_EXPR_ARG (arg, 0);
8216 exponent = CALL_EXPR_ARG (arg, 1);
8918c507 8217 break;
8218 default:
8219 break;
8220 }
8221
8222 /* Now perform the optimization. */
8223 if (x && exponent)
8224 {
c2f47e15 8225 tree logfn = build_call_expr (fndecl, 1, x);
49d00087 8226 return fold_build2 (MULT_EXPR, type, exponent, logfn);
8918c507 8227 }
8228 }
8229 }
8230
c2f47e15 8231 return NULL_TREE;
8918c507 8232}
0862b7e9 8233
f0c477f2 8234/* Fold a builtin function call to hypot, hypotf, or hypotl. Return
8235 NULL_TREE if no simplification can be made. */
8236
8237static tree
c2f47e15 8238fold_builtin_hypot (tree fndecl, tree arg0, tree arg1, tree type)
f0c477f2 8239{
e6ab33d8 8240 tree res, narg0, narg1;
f0c477f2 8241
c2f47e15 8242 if (!validate_arg (arg0, REAL_TYPE)
8243 || !validate_arg (arg1, REAL_TYPE))
f0c477f2 8244 return NULL_TREE;
8245
8246 /* Calculate the result when the argument is a constant. */
8247 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot)))
8248 return res;
8249
6c95f21c 8250 /* If either argument to hypot has a negate or abs, strip that off.
8251 E.g. hypot(-x,fabs(y)) -> hypot(x,y). */
e6ab33d8 8252 narg0 = fold_strip_sign_ops (arg0);
8253 narg1 = fold_strip_sign_ops (arg1);
8254 if (narg0 || narg1)
8255 {
c2f47e15 8256 return build_call_expr (fndecl, 2, narg0 ? narg0 : arg0,
8257 narg1 ? narg1 : arg1);
6c95f21c 8258 }
8259
f0c477f2 8260 /* If either argument is zero, hypot is fabs of the other. */
8261 if (real_zerop (arg0))
8262 return fold_build1 (ABS_EXPR, type, arg1);
8263 else if (real_zerop (arg1))
8264 return fold_build1 (ABS_EXPR, type, arg0);
8265
6c95f21c 8266 /* hypot(x,x) -> fabs(x)*sqrt(2). */
8267 if (flag_unsafe_math_optimizations
8268 && operand_equal_p (arg0, arg1, OEP_PURE_SAME))
f0c477f2 8269 {
2e7ca27b 8270 const REAL_VALUE_TYPE sqrt2_trunc
8271 = real_value_truncate (TYPE_MODE (type), dconstsqrt2);
6c95f21c 8272 return fold_build2 (MULT_EXPR, type,
8273 fold_build1 (ABS_EXPR, type, arg0),
2e7ca27b 8274 build_real (type, sqrt2_trunc));
f0c477f2 8275 }
8276
f0c477f2 8277 return NULL_TREE;
8278}
8279
8280
e6e27594 8281/* Fold a builtin function call to pow, powf, or powl. Return
8282 NULL_TREE if no simplification can be made. */
8283static tree
c2f47e15 8284fold_builtin_pow (tree fndecl, tree arg0, tree arg1, tree type)
e6e27594 8285{
f0c477f2 8286 tree res;
e6e27594 8287
c2f47e15 8288 if (!validate_arg (arg0, REAL_TYPE)
8289 || !validate_arg (arg1, REAL_TYPE))
e6e27594 8290 return NULL_TREE;
8291
f0c477f2 8292 /* Calculate the result when the argument is a constant. */
8293 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_pow)))
8294 return res;
8295
e6e27594 8296 /* Optimize pow(1.0,y) = 1.0. */
8297 if (real_onep (arg0))
8298 return omit_one_operand (type, build_real (type, dconst1), arg1);
8299
8300 if (TREE_CODE (arg1) == REAL_CST
f96bd2bf 8301 && !TREE_OVERFLOW (arg1))
e6e27594 8302 {
198d9bbe 8303 REAL_VALUE_TYPE cint;
e6e27594 8304 REAL_VALUE_TYPE c;
198d9bbe 8305 HOST_WIDE_INT n;
8306
e6e27594 8307 c = TREE_REAL_CST (arg1);
8308
8309 /* Optimize pow(x,0.0) = 1.0. */
8310 if (REAL_VALUES_EQUAL (c, dconst0))
8311 return omit_one_operand (type, build_real (type, dconst1),
8312 arg0);
8313
8314 /* Optimize pow(x,1.0) = x. */
8315 if (REAL_VALUES_EQUAL (c, dconst1))
8316 return arg0;
8317
8318 /* Optimize pow(x,-1.0) = 1.0/x. */
8319 if (REAL_VALUES_EQUAL (c, dconstm1))
49d00087 8320 return fold_build2 (RDIV_EXPR, type,
8321 build_real (type, dconst1), arg0);
e6e27594 8322
8323 /* Optimize pow(x,0.5) = sqrt(x). */
8324 if (flag_unsafe_math_optimizations
8325 && REAL_VALUES_EQUAL (c, dconsthalf))
8326 {
8327 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
8328
8329 if (sqrtfn != NULL_TREE)
c2f47e15 8330 return build_call_expr (sqrtfn, 1, arg0);
e6e27594 8331 }
8332
feb5b3eb 8333 /* Optimize pow(x,1.0/3.0) = cbrt(x). */
8334 if (flag_unsafe_math_optimizations)
8335 {
8336 const REAL_VALUE_TYPE dconstroot
8337 = real_value_truncate (TYPE_MODE (type), dconstthird);
8338
8339 if (REAL_VALUES_EQUAL (c, dconstroot))
8340 {
8341 tree cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT);
8342 if (cbrtfn != NULL_TREE)
c2f47e15 8343 return build_call_expr (cbrtfn, 1, arg0);
feb5b3eb 8344 }
8345 }
8346
198d9bbe 8347 /* Check for an integer exponent. */
8348 n = real_to_integer (&c);
8349 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
8350 if (real_identical (&c, &cint))
e6e27594 8351 {
198d9bbe 8352 /* Attempt to evaluate pow at compile-time. */
8353 if (TREE_CODE (arg0) == REAL_CST
f96bd2bf 8354 && !TREE_OVERFLOW (arg0))
e6e27594 8355 {
8356 REAL_VALUE_TYPE x;
8357 bool inexact;
8358
8359 x = TREE_REAL_CST (arg0);
8360 inexact = real_powi (&x, TYPE_MODE (type), &x, n);
8361 if (flag_unsafe_math_optimizations || !inexact)
8362 return build_real (type, x);
8363 }
198d9bbe 8364
8365 /* Strip sign ops from even integer powers. */
8366 if ((n & 1) == 0 && flag_unsafe_math_optimizations)
8367 {
8368 tree narg0 = fold_strip_sign_ops (arg0);
8369 if (narg0)
c2f47e15 8370 return build_call_expr (fndecl, 2, narg0, arg1);
198d9bbe 8371 }
e6e27594 8372 }
8373 }
8374
cdfeb715 8375 if (flag_unsafe_math_optimizations)
e6e27594 8376 {
cdfeb715 8377 const enum built_in_function fcode = builtin_mathfn_code (arg0);
e6e27594 8378
cdfeb715 8379 /* Optimize pow(expN(x),y) = expN(x*y). */
8380 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 8381 {
c2f47e15 8382 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
8383 tree arg = CALL_EXPR_ARG (arg0, 0);
49d00087 8384 arg = fold_build2 (MULT_EXPR, type, arg, arg1);
c2f47e15 8385 return build_call_expr (expfn, 1, arg);
cdfeb715 8386 }
e6e27594 8387
cdfeb715 8388 /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
8389 if (BUILTIN_SQRT_P (fcode))
a0c938f0 8390 {
c2f47e15 8391 tree narg0 = CALL_EXPR_ARG (arg0, 0);
49d00087 8392 tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
8393 build_real (type, dconsthalf));
c2f47e15 8394 return build_call_expr (fndecl, 2, narg0, narg1);
cdfeb715 8395 }
8396
8397 /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */
8398 if (BUILTIN_CBRT_P (fcode))
a0c938f0 8399 {
c2f47e15 8400 tree arg = CALL_EXPR_ARG (arg0, 0);
cdfeb715 8401 if (tree_expr_nonnegative_p (arg))
8402 {
8403 const REAL_VALUE_TYPE dconstroot
8404 = real_value_truncate (TYPE_MODE (type), dconstthird);
49d00087 8405 tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
8406 build_real (type, dconstroot));
c2f47e15 8407 return build_call_expr (fndecl, 2, arg, narg1);
cdfeb715 8408 }
8409 }
a0c938f0 8410
cdfeb715 8411 /* Optimize pow(pow(x,y),z) = pow(x,y*z). */
c2f47e15 8412 if (fcode == BUILT_IN_POW
8413 || fcode == BUILT_IN_POWF
8414 || fcode == BUILT_IN_POWL)
a0c938f0 8415 {
c2f47e15 8416 tree arg00 = CALL_EXPR_ARG (arg0, 0);
8417 tree arg01 = CALL_EXPR_ARG (arg0, 1);
49d00087 8418 tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1);
c2f47e15 8419 return build_call_expr (fndecl, 2, arg00, narg1);
cdfeb715 8420 }
e6e27594 8421 }
cdfeb715 8422
e6e27594 8423 return NULL_TREE;
8424}
8425
c2f47e15 8426/* Fold a builtin function call to powi, powif, or powil with argument ARG.
8427 Return NULL_TREE if no simplification can be made. */
b4d0c20c 8428static tree
c2f47e15 8429fold_builtin_powi (tree fndecl ATTRIBUTE_UNUSED,
8430 tree arg0, tree arg1, tree type)
b4d0c20c 8431{
c2f47e15 8432 if (!validate_arg (arg0, REAL_TYPE)
8433 || !validate_arg (arg1, INTEGER_TYPE))
b4d0c20c 8434 return NULL_TREE;
8435
8436 /* Optimize pow(1.0,y) = 1.0. */
8437 if (real_onep (arg0))
8438 return omit_one_operand (type, build_real (type, dconst1), arg1);
8439
8440 if (host_integerp (arg1, 0))
8441 {
8442 HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
8443
8444 /* Evaluate powi at compile-time. */
8445 if (TREE_CODE (arg0) == REAL_CST
f96bd2bf 8446 && !TREE_OVERFLOW (arg0))
b4d0c20c 8447 {
8448 REAL_VALUE_TYPE x;
8449 x = TREE_REAL_CST (arg0);
8450 real_powi (&x, TYPE_MODE (type), &x, c);
8451 return build_real (type, x);
8452 }
8453
8454 /* Optimize pow(x,0) = 1.0. */
8455 if (c == 0)
8456 return omit_one_operand (type, build_real (type, dconst1),
8457 arg0);
8458
8459 /* Optimize pow(x,1) = x. */
8460 if (c == 1)
8461 return arg0;
8462
8463 /* Optimize pow(x,-1) = 1.0/x. */
8464 if (c == -1)
49d00087 8465 return fold_build2 (RDIV_EXPR, type,
8466 build_real (type, dconst1), arg0);
b4d0c20c 8467 }
8468
8469 return NULL_TREE;
8470}
8471
8918c507 8472/* A subroutine of fold_builtin to fold the various exponent
c2f47e15 8473 functions. Return NULL_TREE if no simplification can be made.
debf9994 8474 FUNC is the corresponding MPFR exponent function. */
8918c507 8475
8476static tree
c2f47e15 8477fold_builtin_exponent (tree fndecl, tree arg,
debf9994 8478 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8479{
c2f47e15 8480 if (validate_arg (arg, REAL_TYPE))
8918c507 8481 {
8918c507 8482 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8483 tree res;
debf9994 8484
8485 /* Calculate the result when the argument is a constant. */
728bac60 8486 if ((res = do_mpfr_arg1 (arg, type, func, NULL, NULL, 0)))
debf9994 8487 return res;
8918c507 8488
8489 /* Optimize expN(logN(x)) = x. */
8490 if (flag_unsafe_math_optimizations)
a0c938f0 8491 {
8918c507 8492 const enum built_in_function fcode = builtin_mathfn_code (arg);
8493
debf9994 8494 if ((func == mpfr_exp
8918c507 8495 && (fcode == BUILT_IN_LOG
8496 || fcode == BUILT_IN_LOGF
8497 || fcode == BUILT_IN_LOGL))
debf9994 8498 || (func == mpfr_exp2
8918c507 8499 && (fcode == BUILT_IN_LOG2
8500 || fcode == BUILT_IN_LOG2F
8501 || fcode == BUILT_IN_LOG2L))
debf9994 8502 || (func == mpfr_exp10
8918c507 8503 && (fcode == BUILT_IN_LOG10
8504 || fcode == BUILT_IN_LOG10F
8505 || fcode == BUILT_IN_LOG10L)))
c2f47e15 8506 return fold_convert (type, CALL_EXPR_ARG (arg, 0));
8918c507 8507 }
8508 }
8509
c2f47e15 8510 return NULL_TREE;
8918c507 8511}
8512
e973ffcc 8513/* Return true if VAR is a VAR_DECL or a component thereof. */
8514
8515static bool
8516var_decl_component_p (tree var)
8517{
8518 tree inner = var;
8519 while (handled_component_p (inner))
8520 inner = TREE_OPERAND (inner, 0);
8521 return SSA_VAR_P (inner);
8522}
8523
4f46f2b9 8524/* Fold function call to builtin memset. Return
9c8a1629 8525 NULL_TREE if no simplification can be made. */
8526
8527static tree
c2f47e15 8528fold_builtin_memset (tree dest, tree c, tree len, tree type, bool ignore)
9c8a1629 8529{
c2f47e15 8530 tree var, ret;
4f46f2b9 8531 unsigned HOST_WIDE_INT length, cval;
9c8a1629 8532
c2f47e15 8533 if (! validate_arg (dest, POINTER_TYPE)
8534 || ! validate_arg (c, INTEGER_TYPE)
8535 || ! validate_arg (len, INTEGER_TYPE))
8536 return NULL_TREE;
9c8a1629 8537
4f46f2b9 8538 if (! host_integerp (len, 1))
c2f47e15 8539 return NULL_TREE;
4f46f2b9 8540
9c8a1629 8541 /* If the LEN parameter is zero, return DEST. */
8542 if (integer_zerop (len))
4f46f2b9 8543 return omit_one_operand (type, dest, c);
9c8a1629 8544
4f46f2b9 8545 if (! host_integerp (c, 1) || TREE_SIDE_EFFECTS (dest))
c2f47e15 8546 return NULL_TREE;
9c8a1629 8547
4f46f2b9 8548 var = dest;
8549 STRIP_NOPS (var);
8550 if (TREE_CODE (var) != ADDR_EXPR)
c2f47e15 8551 return NULL_TREE;
4f46f2b9 8552
8553 var = TREE_OPERAND (var, 0);
8554 if (TREE_THIS_VOLATILE (var))
c2f47e15 8555 return NULL_TREE;
4f46f2b9 8556
8557 if (!INTEGRAL_TYPE_P (TREE_TYPE (var))
8558 && !POINTER_TYPE_P (TREE_TYPE (var)))
c2f47e15 8559 return NULL_TREE;
4f46f2b9 8560
e973ffcc 8561 if (! var_decl_component_p (var))
c2f47e15 8562 return NULL_TREE;
e973ffcc 8563
4f46f2b9 8564 length = tree_low_cst (len, 1);
8565 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (var))) != length
8566 || get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
8567 < (int) length)
c2f47e15 8568 return NULL_TREE;
4f46f2b9 8569
8570 if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT)
c2f47e15 8571 return NULL_TREE;
4f46f2b9 8572
8573 if (integer_zerop (c))
8574 cval = 0;
8575 else
8576 {
8577 if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64)
c2f47e15 8578 return NULL_TREE;
4f46f2b9 8579
8580 cval = tree_low_cst (c, 1);
8581 cval &= 0xff;
8582 cval |= cval << 8;
8583 cval |= cval << 16;
8584 cval |= (cval << 31) << 1;
8585 }
8586
8587 ret = build_int_cst_type (TREE_TYPE (var), cval);
41076ef6 8588 ret = build2 (MODIFY_EXPR, TREE_TYPE (var), var, ret);
4f46f2b9 8589 if (ignore)
8590 return ret;
8591
8592 return omit_one_operand (type, dest, ret);
9c8a1629 8593}
8594
4f46f2b9 8595/* Fold function call to builtin memset. Return
9c8a1629 8596 NULL_TREE if no simplification can be made. */
8597
8598static tree
c2f47e15 8599fold_builtin_bzero (tree dest, tree size, bool ignore)
9c8a1629 8600{
c2f47e15 8601 if (! validate_arg (dest, POINTER_TYPE)
8602 || ! validate_arg (size, INTEGER_TYPE))
8603 return NULL_TREE;
9c8a1629 8604
4f46f2b9 8605 if (!ignore)
c2f47e15 8606 return NULL_TREE;
a0c938f0 8607
4f46f2b9 8608 /* New argument list transforming bzero(ptr x, int y) to
8609 memset(ptr x, int 0, size_t y). This is done this way
8610 so that if it isn't expanded inline, we fallback to
8611 calling bzero instead of memset. */
8612
c2f47e15 8613 return fold_builtin_memset (dest, integer_zero_node,
8614 fold_convert (sizetype, size),
8615 void_type_node, ignore);
9c8a1629 8616}
8617
4f46f2b9 8618/* Fold function call to builtin mem{{,p}cpy,move}. Return
8619 NULL_TREE if no simplification can be made.
8620 If ENDP is 0, return DEST (like memcpy).
8621 If ENDP is 1, return DEST+LEN (like mempcpy).
8622 If ENDP is 2, return DEST+LEN-1 (like stpcpy).
8623 If ENDP is 3, return DEST, additionally *SRC and *DEST may overlap
8624 (memmove). */
9c8a1629 8625
8626static tree
c2f47e15 8627fold_builtin_memory_op (tree dest, tree src, tree len, tree type, bool ignore, int endp)
9c8a1629 8628{
c2f47e15 8629 tree destvar, srcvar, expr;
9c8a1629 8630
c2f47e15 8631 if (! validate_arg (dest, POINTER_TYPE)
8632 || ! validate_arg (src, POINTER_TYPE)
8633 || ! validate_arg (len, INTEGER_TYPE))
8634 return NULL_TREE;
9c8a1629 8635
8636 /* If the LEN parameter is zero, return DEST. */
8637 if (integer_zerop (len))
7e72af53 8638 return omit_one_operand (type, dest, src);
9c8a1629 8639
4f46f2b9 8640 /* If SRC and DEST are the same (and not volatile), return
8641 DEST{,+LEN,+LEN-1}. */
9c8a1629 8642 if (operand_equal_p (src, dest, 0))
4f46f2b9 8643 expr = len;
8644 else
8645 {
5a84fdd6 8646 tree srctype, desttype;
3b1757a2 8647 if (endp == 3)
8648 {
5a84fdd6 8649 int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
8650 int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
8651
3b1757a2 8652 /* Both DEST and SRC must be pointer types.
8653 ??? This is what old code did. Is the testing for pointer types
8654 really mandatory?
8655
8656 If either SRC is readonly or length is 1, we can use memcpy. */
8657 if (dest_align && src_align
8658 && (readonly_data_expr (src)
5a84fdd6 8659 || (host_integerp (len, 1)
b4fc673b 8660 && (MIN (src_align, dest_align) / BITS_PER_UNIT >=
5a84fdd6 8661 tree_low_cst (len, 1)))))
3b1757a2 8662 {
8663 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8664 if (!fn)
c2f47e15 8665 return NULL_TREE;
8666 return build_call_expr (fn, 3, dest, src, len);
3b1757a2 8667 }
c2f47e15 8668 return NULL_TREE;
3b1757a2 8669 }
4f46f2b9 8670
5a84fdd6 8671 if (!host_integerp (len, 0))
c2f47e15 8672 return NULL_TREE;
5a84fdd6 8673 /* FIXME:
8674 This logic lose for arguments like (type *)malloc (sizeof (type)),
8675 since we strip the casts of up to VOID return value from malloc.
8676 Perhaps we ought to inherit type from non-VOID argument here? */
8677 STRIP_NOPS (src);
8678 STRIP_NOPS (dest);
8679 srctype = TREE_TYPE (TREE_TYPE (src));
8680 desttype = TREE_TYPE (TREE_TYPE (dest));
8681 if (!srctype || !desttype
8682 || !TYPE_SIZE_UNIT (srctype)
8683 || !TYPE_SIZE_UNIT (desttype)
8684 || TREE_CODE (TYPE_SIZE_UNIT (srctype)) != INTEGER_CST
8685 || TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST
92552a26 8686 || !tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len)
8687 || !tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
c2f47e15 8688 return NULL_TREE;
4f46f2b9 8689
5a84fdd6 8690 if (get_pointer_alignment (dest, BIGGEST_ALIGNMENT)
8691 < (int) TYPE_ALIGN (desttype)
8692 || (get_pointer_alignment (src, BIGGEST_ALIGNMENT)
8693 < (int) TYPE_ALIGN (srctype)))
c2f47e15 8694 return NULL_TREE;
e973ffcc 8695
5a84fdd6 8696 if (!ignore)
8697 dest = builtin_save_expr (dest);
4f46f2b9 8698
5a84fdd6 8699 srcvar = build_fold_indirect_ref (src);
4f46f2b9 8700 if (TREE_THIS_VOLATILE (srcvar))
c2f47e15 8701 return NULL_TREE;
92552a26 8702 if (!tree_int_cst_equal (lang_hooks.expr_size (srcvar), len))
c2f47e15 8703 return NULL_TREE;
5a84fdd6 8704 /* With memcpy, it is possible to bypass aliasing rules, so without
8705 this check i. e. execute/20060930-2.c would be misoptimized, because
8706 it use conflicting alias set to hold argument for the memcpy call.
8707 This check is probably unnecesary with -fno-strict-aliasing.
8708 Similarly for destvar. See also PR29286. */
8709 if (!var_decl_component_p (srcvar)
8710 /* Accept: memcpy (*char_var, "test", 1); that simplify
8711 to char_var='t'; */
8712 || is_gimple_min_invariant (srcvar)
8713 || readonly_data_expr (src))
c2f47e15 8714 return NULL_TREE;
4f46f2b9 8715
5a84fdd6 8716 destvar = build_fold_indirect_ref (dest);
8717 if (TREE_THIS_VOLATILE (destvar))
c2f47e15 8718 return NULL_TREE;
92552a26 8719 if (!tree_int_cst_equal (lang_hooks.expr_size (destvar), len))
c2f47e15 8720 return NULL_TREE;
5a84fdd6 8721 if (!var_decl_component_p (destvar))
c2f47e15 8722 return NULL_TREE;
4f46f2b9 8723
5a84fdd6 8724 if (srctype == desttype
2d04fd8d 8725 || (gimple_in_ssa_p (cfun)
548044d8 8726 && useless_type_conversion_p (desttype, srctype)))
5a84fdd6 8727 expr = srcvar;
8728 else if ((INTEGRAL_TYPE_P (TREE_TYPE (srcvar))
4f46f2b9 8729 || POINTER_TYPE_P (TREE_TYPE (srcvar)))
8730 && (INTEGRAL_TYPE_P (TREE_TYPE (destvar))
8731 || POINTER_TYPE_P (TREE_TYPE (destvar))))
8732 expr = fold_convert (TREE_TYPE (destvar), srcvar);
8733 else
8734 expr = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (destvar), srcvar);
41076ef6 8735 expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, expr);
4f46f2b9 8736 }
8737
8738 if (ignore)
8739 return expr;
8740
8741 if (endp == 0 || endp == 3)
8742 return omit_one_operand (type, dest, expr);
8743
8744 if (expr == len)
c2f47e15 8745 expr = NULL_TREE;
4f46f2b9 8746
8747 if (endp == 2)
8748 len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len,
8749 ssize_int (1));
8750
0de36bdb 8751 dest = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
4f46f2b9 8752 dest = fold_convert (type, dest);
8753 if (expr)
8754 dest = omit_one_operand (type, dest, expr);
8755 return dest;
8756}
8757
c2f47e15 8758/* Fold function call to builtin strcpy with arguments DEST and SRC.
8759 If LEN is not NULL, it represents the length of the string to be
8760 copied. Return NULL_TREE if no simplification can be made. */
9c8a1629 8761
f0613857 8762tree
c2f47e15 8763fold_builtin_strcpy (tree fndecl, tree dest, tree src, tree len)
9c8a1629 8764{
c2f47e15 8765 tree fn;
9c8a1629 8766
c2f47e15 8767 if (!validate_arg (dest, POINTER_TYPE)
8768 || !validate_arg (src, POINTER_TYPE))
8769 return NULL_TREE;
9c8a1629 8770
8771 /* If SRC and DEST are the same (and not volatile), return DEST. */
8772 if (operand_equal_p (src, dest, 0))
2426241c 8773 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
9c8a1629 8774
f0613857 8775 if (optimize_size)
c2f47e15 8776 return NULL_TREE;
f0613857 8777
8778 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8779 if (!fn)
c2f47e15 8780 return NULL_TREE;
f0613857 8781
8782 if (!len)
8783 {
8784 len = c_strlen (src, 1);
8785 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 8786 return NULL_TREE;
f0613857 8787 }
8788
8789 len = size_binop (PLUS_EXPR, len, ssize_int (1));
2426241c 8790 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
c2f47e15 8791 build_call_expr (fn, 3, dest, src, len));
9c8a1629 8792}
8793
c2f47e15 8794/* Fold function call to builtin strncpy with arguments DEST, SRC, and LEN.
8795 If SLEN is not NULL, it represents the length of the source string.
8796 Return NULL_TREE if no simplification can be made. */
9c8a1629 8797
f0613857 8798tree
c2f47e15 8799fold_builtin_strncpy (tree fndecl, tree dest, tree src, tree len, tree slen)
9c8a1629 8800{
c2f47e15 8801 tree fn;
9c8a1629 8802
c2f47e15 8803 if (!validate_arg (dest, POINTER_TYPE)
8804 || !validate_arg (src, POINTER_TYPE)
8805 || !validate_arg (len, INTEGER_TYPE))
8806 return NULL_TREE;
9c8a1629 8807
8808 /* If the LEN parameter is zero, return DEST. */
8809 if (integer_zerop (len))
2426241c 8810 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
9c8a1629 8811
19226313 8812 /* We can't compare slen with len as constants below if len is not a
8813 constant. */
8814 if (len == 0 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 8815 return NULL_TREE;
19226313 8816
f0613857 8817 if (!slen)
8818 slen = c_strlen (src, 1);
8819
8820 /* Now, we must be passed a constant src ptr parameter. */
8821 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
c2f47e15 8822 return NULL_TREE;
f0613857 8823
8824 slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
8825
8826 /* We do not support simplification of this case, though we do
8827 support it when expanding trees into RTL. */
8828 /* FIXME: generate a call to __builtin_memset. */
8829 if (tree_int_cst_lt (slen, len))
c2f47e15 8830 return NULL_TREE;
f0613857 8831
8832 /* OK transform into builtin memcpy. */
8833 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8834 if (!fn)
c2f47e15 8835 return NULL_TREE;
2426241c 8836 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
c2f47e15 8837 build_call_expr (fn, 3, dest, src, len));
9c8a1629 8838}
8839
7959b13b 8840/* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the
8841 arguments to the call, and TYPE is its return type.
8842 Return NULL_TREE if no simplification can be made. */
8843
8844static tree
8845fold_builtin_memchr (tree arg1, tree arg2, tree len, tree type)
8846{
8847 if (!validate_arg (arg1, POINTER_TYPE)
8848 || !validate_arg (arg2, INTEGER_TYPE)
8849 || !validate_arg (len, INTEGER_TYPE))
8850 return NULL_TREE;
8851 else
8852 {
8853 const char *p1;
8854
8855 if (TREE_CODE (arg2) != INTEGER_CST
8856 || !host_integerp (len, 1))
8857 return NULL_TREE;
8858
8859 p1 = c_getstr (arg1);
8860 if (p1 && compare_tree_int (len, strlen (p1) + 1) <= 0)
8861 {
8862 char c;
8863 const char *r;
8864 tree tem;
8865
8866 if (target_char_cast (arg2, &c))
8867 return NULL_TREE;
8868
8869 r = memchr (p1, c, tree_low_cst (len, 1));
8870
8871 if (r == NULL)
8872 return build_int_cst (TREE_TYPE (arg1), 0);
8873
0de36bdb 8874 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (arg1), arg1,
8875 size_int (r - p1));
7959b13b 8876 return fold_convert (type, tem);
8877 }
8878 return NULL_TREE;
8879 }
8880}
8881
c2f47e15 8882/* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
8883 Return NULL_TREE if no simplification can be made. */
9c8a1629 8884
8885static tree
c2f47e15 8886fold_builtin_memcmp (tree arg1, tree arg2, tree len)
9c8a1629 8887{
c4fef134 8888 const char *p1, *p2;
9c8a1629 8889
c2f47e15 8890 if (!validate_arg (arg1, POINTER_TYPE)
8891 || !validate_arg (arg2, POINTER_TYPE)
8892 || !validate_arg (len, INTEGER_TYPE))
8893 return NULL_TREE;
9c8a1629 8894
8895 /* If the LEN parameter is zero, return zero. */
8896 if (integer_zerop (len))
c4fef134 8897 return omit_two_operands (integer_type_node, integer_zero_node,
8898 arg1, arg2);
9c8a1629 8899
8900 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8901 if (operand_equal_p (arg1, arg2, 0))
c4fef134 8902 return omit_one_operand (integer_type_node, integer_zero_node, len);
8903
8904 p1 = c_getstr (arg1);
8905 p2 = c_getstr (arg2);
8906
8907 /* If all arguments are constant, and the value of len is not greater
8908 than the lengths of arg1 and arg2, evaluate at compile-time. */
8909 if (host_integerp (len, 1) && p1 && p2
8910 && compare_tree_int (len, strlen (p1) + 1) <= 0
8911 && compare_tree_int (len, strlen (p2) + 1) <= 0)
8912 {
8913 const int r = memcmp (p1, p2, tree_low_cst (len, 1));
8914
8915 if (r > 0)
8916 return integer_one_node;
8917 else if (r < 0)
8918 return integer_minus_one_node;
8919 else
8920 return integer_zero_node;
8921 }
8922
8923 /* If len parameter is one, return an expression corresponding to
8924 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
8925 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
8926 {
8927 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8928 tree cst_uchar_ptr_node
8929 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8930
c4fef134 8931 tree ind1 = fold_convert (integer_type_node,
8932 build1 (INDIRECT_REF, cst_uchar_node,
8933 fold_convert (cst_uchar_ptr_node,
8934 arg1)));
8935 tree ind2 = fold_convert (integer_type_node,
8936 build1 (INDIRECT_REF, cst_uchar_node,
8937 fold_convert (cst_uchar_ptr_node,
8938 arg2)));
49d00087 8939 return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
c4fef134 8940 }
9c8a1629 8941
c2f47e15 8942 return NULL_TREE;
9c8a1629 8943}
8944
c2f47e15 8945/* Fold function call to builtin strcmp with arguments ARG1 and ARG2.
8946 Return NULL_TREE if no simplification can be made. */
9c8a1629 8947
8948static tree
c2f47e15 8949fold_builtin_strcmp (tree arg1, tree arg2)
9c8a1629 8950{
9c8a1629 8951 const char *p1, *p2;
8952
c2f47e15 8953 if (!validate_arg (arg1, POINTER_TYPE)
8954 || !validate_arg (arg2, POINTER_TYPE))
8955 return NULL_TREE;
9c8a1629 8956
8957 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8958 if (operand_equal_p (arg1, arg2, 0))
c4fef134 8959 return integer_zero_node;
9c8a1629 8960
8961 p1 = c_getstr (arg1);
8962 p2 = c_getstr (arg2);
8963
8964 if (p1 && p2)
8965 {
9c8a1629 8966 const int i = strcmp (p1, p2);
8967 if (i < 0)
c4fef134 8968 return integer_minus_one_node;
9c8a1629 8969 else if (i > 0)
c4fef134 8970 return integer_one_node;
9c8a1629 8971 else
c4fef134 8972 return integer_zero_node;
8973 }
8974
8975 /* If the second arg is "", return *(const unsigned char*)arg1. */
8976 if (p2 && *p2 == '\0')
8977 {
8978 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8979 tree cst_uchar_ptr_node
8980 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8981
c4fef134 8982 return fold_convert (integer_type_node,
8983 build1 (INDIRECT_REF, cst_uchar_node,
8984 fold_convert (cst_uchar_ptr_node,
8985 arg1)));
8986 }
8987
8988 /* If the first arg is "", return -*(const unsigned char*)arg2. */
8989 if (p1 && *p1 == '\0')
8990 {
8991 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8992 tree cst_uchar_ptr_node
8993 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8994
c4fef134 8995 tree temp = fold_convert (integer_type_node,
8996 build1 (INDIRECT_REF, cst_uchar_node,
8997 fold_convert (cst_uchar_ptr_node,
8998 arg2)));
49d00087 8999 return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
9c8a1629 9000 }
9001
c2f47e15 9002 return NULL_TREE;
9c8a1629 9003}
9004
c2f47e15 9005/* Fold function call to builtin strncmp with arguments ARG1, ARG2, and LEN.
9006 Return NULL_TREE if no simplification can be made. */
9c8a1629 9007
9008static tree
c2f47e15 9009fold_builtin_strncmp (tree arg1, tree arg2, tree len)
9c8a1629 9010{
9c8a1629 9011 const char *p1, *p2;
9012
c2f47e15 9013 if (!validate_arg (arg1, POINTER_TYPE)
9014 || !validate_arg (arg2, POINTER_TYPE)
9015 || !validate_arg (len, INTEGER_TYPE))
9016 return NULL_TREE;
9c8a1629 9017
9018 /* If the LEN parameter is zero, return zero. */
9019 if (integer_zerop (len))
c4fef134 9020 return omit_two_operands (integer_type_node, integer_zero_node,
9021 arg1, arg2);
9c8a1629 9022
9023 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9024 if (operand_equal_p (arg1, arg2, 0))
c4fef134 9025 return omit_one_operand (integer_type_node, integer_zero_node, len);
9c8a1629 9026
9027 p1 = c_getstr (arg1);
9028 p2 = c_getstr (arg2);
9029
9030 if (host_integerp (len, 1) && p1 && p2)
9031 {
9c8a1629 9032 const int i = strncmp (p1, p2, tree_low_cst (len, 1));
c4fef134 9033 if (i > 0)
9034 return integer_one_node;
9035 else if (i < 0)
9036 return integer_minus_one_node;
9c8a1629 9037 else
c4fef134 9038 return integer_zero_node;
9039 }
9040
9041 /* If the second arg is "", and the length is greater than zero,
9042 return *(const unsigned char*)arg1. */
9043 if (p2 && *p2 == '\0'
9044 && TREE_CODE (len) == INTEGER_CST
9045 && tree_int_cst_sgn (len) == 1)
9046 {
9047 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9048 tree cst_uchar_ptr_node
9049 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9050
c4fef134 9051 return fold_convert (integer_type_node,
9052 build1 (INDIRECT_REF, cst_uchar_node,
9053 fold_convert (cst_uchar_ptr_node,
9054 arg1)));
9055 }
9056
9057 /* If the first arg is "", and the length is greater than zero,
9058 return -*(const unsigned char*)arg2. */
9059 if (p1 && *p1 == '\0'
9060 && TREE_CODE (len) == INTEGER_CST
9061 && tree_int_cst_sgn (len) == 1)
9062 {
9063 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9064 tree cst_uchar_ptr_node
9065 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9066
c4fef134 9067 tree temp = fold_convert (integer_type_node,
9068 build1 (INDIRECT_REF, cst_uchar_node,
9069 fold_convert (cst_uchar_ptr_node,
9070 arg2)));
49d00087 9071 return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
c4fef134 9072 }
9073
9074 /* If len parameter is one, return an expression corresponding to
9075 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
9076 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
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 ind1 = fold_convert (integer_type_node,
9083 build1 (INDIRECT_REF, cst_uchar_node,
9084 fold_convert (cst_uchar_ptr_node,
9085 arg1)));
9086 tree ind2 = fold_convert (integer_type_node,
9087 build1 (INDIRECT_REF, cst_uchar_node,
9088 fold_convert (cst_uchar_ptr_node,
9089 arg2)));
49d00087 9090 return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
9c8a1629 9091 }
9092
c2f47e15 9093 return NULL_TREE;
9c8a1629 9094}
9095
c2f47e15 9096/* Fold function call to builtin signbit, signbitf or signbitl with argument
9097 ARG. Return NULL_TREE if no simplification can be made. */
27f261ef 9098
9099static tree
c2f47e15 9100fold_builtin_signbit (tree arg, tree type)
27f261ef 9101{
c2f47e15 9102 tree temp;
27f261ef 9103
c2f47e15 9104 if (!validate_arg (arg, REAL_TYPE))
27f261ef 9105 return NULL_TREE;
9106
27f261ef 9107 /* If ARG is a compile-time constant, determine the result. */
9108 if (TREE_CODE (arg) == REAL_CST
f96bd2bf 9109 && !TREE_OVERFLOW (arg))
27f261ef 9110 {
9111 REAL_VALUE_TYPE c;
9112
9113 c = TREE_REAL_CST (arg);
9114 temp = REAL_VALUE_NEGATIVE (c) ? integer_one_node : integer_zero_node;
2426241c 9115 return fold_convert (type, temp);
27f261ef 9116 }
9117
9118 /* If ARG is non-negative, the result is always zero. */
9119 if (tree_expr_nonnegative_p (arg))
2426241c 9120 return omit_one_operand (type, integer_zero_node, arg);
27f261ef 9121
9122 /* If ARG's format doesn't have signed zeros, return "arg < 0.0". */
9123 if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
49d00087 9124 return fold_build2 (LT_EXPR, type, arg,
9125 build_real (TREE_TYPE (arg), dconst0));
27f261ef 9126
9127 return NULL_TREE;
9128}
9129
c2f47e15 9130/* Fold function call to builtin copysign, copysignf or copysignl with
9131 arguments ARG1 and ARG2. Return NULL_TREE if no simplification can
9132 be made. */
467214fd 9133
9134static tree
c2f47e15 9135fold_builtin_copysign (tree fndecl, tree arg1, tree arg2, tree type)
467214fd 9136{
c2f47e15 9137 tree tem;
467214fd 9138
c2f47e15 9139 if (!validate_arg (arg1, REAL_TYPE)
9140 || !validate_arg (arg2, REAL_TYPE))
467214fd 9141 return NULL_TREE;
9142
467214fd 9143 /* copysign(X,X) is X. */
9144 if (operand_equal_p (arg1, arg2, 0))
9145 return fold_convert (type, arg1);
9146
9147 /* If ARG1 and ARG2 are compile-time constants, determine the result. */
9148 if (TREE_CODE (arg1) == REAL_CST
9149 && TREE_CODE (arg2) == REAL_CST
f96bd2bf 9150 && !TREE_OVERFLOW (arg1)
9151 && !TREE_OVERFLOW (arg2))
467214fd 9152 {
9153 REAL_VALUE_TYPE c1, c2;
9154
9155 c1 = TREE_REAL_CST (arg1);
9156 c2 = TREE_REAL_CST (arg2);
749680e2 9157 /* c1.sign := c2.sign. */
467214fd 9158 real_copysign (&c1, &c2);
9159 return build_real (type, c1);
467214fd 9160 }
9161
9162 /* copysign(X, Y) is fabs(X) when Y is always non-negative.
9163 Remember to evaluate Y for side-effects. */
9164 if (tree_expr_nonnegative_p (arg2))
9165 return omit_one_operand (type,
49d00087 9166 fold_build1 (ABS_EXPR, type, arg1),
467214fd 9167 arg2);
9168
198d9bbe 9169 /* Strip sign changing operations for the first argument. */
9170 tem = fold_strip_sign_ops (arg1);
9171 if (tem)
c2f47e15 9172 return build_call_expr (fndecl, 2, tem, arg2);
198d9bbe 9173
467214fd 9174 return NULL_TREE;
9175}
9176
c2f47e15 9177/* Fold a call to builtin isascii with argument ARG. */
d49367d4 9178
9179static tree
c2f47e15 9180fold_builtin_isascii (tree arg)
d49367d4 9181{
c2f47e15 9182 if (!validate_arg (arg, INTEGER_TYPE))
9183 return NULL_TREE;
d49367d4 9184 else
9185 {
9186 /* Transform isascii(c) -> ((c & ~0x7f) == 0). */
7c446c95 9187 arg = build2 (BIT_AND_EXPR, integer_type_node, arg,
9188 build_int_cst (NULL_TREE,
7016c612 9189 ~ (unsigned HOST_WIDE_INT) 0x7f));
f2532264 9190 return fold_build2 (EQ_EXPR, integer_type_node,
9191 arg, integer_zero_node);
d49367d4 9192 }
9193}
9194
c2f47e15 9195/* Fold a call to builtin toascii with argument ARG. */
d49367d4 9196
9197static tree
c2f47e15 9198fold_builtin_toascii (tree arg)
d49367d4 9199{
c2f47e15 9200 if (!validate_arg (arg, INTEGER_TYPE))
9201 return NULL_TREE;
9202
9203 /* Transform toascii(c) -> (c & 0x7f). */
9204 return fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
9205 build_int_cst (NULL_TREE, 0x7f));
d49367d4 9206}
9207
c2f47e15 9208/* Fold a call to builtin isdigit with argument ARG. */
df1cf42e 9209
9210static tree
c2f47e15 9211fold_builtin_isdigit (tree arg)
df1cf42e 9212{
c2f47e15 9213 if (!validate_arg (arg, INTEGER_TYPE))
9214 return NULL_TREE;
df1cf42e 9215 else
9216 {
9217 /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */
624d37a6 9218 /* According to the C standard, isdigit is unaffected by locale.
9219 However, it definitely is affected by the target character set. */
624d37a6 9220 unsigned HOST_WIDE_INT target_digit0
9221 = lang_hooks.to_target_charset ('0');
9222
9223 if (target_digit0 == 0)
9224 return NULL_TREE;
9225
c2f47e15 9226 arg = fold_convert (unsigned_type_node, arg);
05abc81b 9227 arg = build2 (MINUS_EXPR, unsigned_type_node, arg,
624d37a6 9228 build_int_cst (unsigned_type_node, target_digit0));
f2532264 9229 return fold_build2 (LE_EXPR, integer_type_node, arg,
9230 build_int_cst (unsigned_type_node, 9));
df1cf42e 9231 }
9232}
27f261ef 9233
c2f47e15 9234/* Fold a call to fabs, fabsf or fabsl with argument ARG. */
d1aade50 9235
9236static tree
c2f47e15 9237fold_builtin_fabs (tree arg, tree type)
d1aade50 9238{
c2f47e15 9239 if (!validate_arg (arg, REAL_TYPE))
9240 return NULL_TREE;
d1aade50 9241
9829e110 9242 arg = fold_convert (type, arg);
d1aade50 9243 if (TREE_CODE (arg) == REAL_CST)
9244 return fold_abs_const (arg, type);
49d00087 9245 return fold_build1 (ABS_EXPR, type, arg);
d1aade50 9246}
9247
c2f47e15 9248/* Fold a call to abs, labs, llabs or imaxabs with argument ARG. */
d1aade50 9249
9250static tree
c2f47e15 9251fold_builtin_abs (tree arg, tree type)
d1aade50 9252{
c2f47e15 9253 if (!validate_arg (arg, INTEGER_TYPE))
9254 return NULL_TREE;
d1aade50 9255
9829e110 9256 arg = fold_convert (type, arg);
d1aade50 9257 if (TREE_CODE (arg) == INTEGER_CST)
9258 return fold_abs_const (arg, type);
49d00087 9259 return fold_build1 (ABS_EXPR, type, arg);
d1aade50 9260}
9261
d4a43a03 9262/* Fold a call to builtin fmin or fmax. */
9263
9264static tree
c2f47e15 9265fold_builtin_fmin_fmax (tree arg0, tree arg1, tree type, bool max)
d4a43a03 9266{
c2f47e15 9267 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, REAL_TYPE))
d4a43a03 9268 {
d4a43a03 9269 /* Calculate the result when the argument is a constant. */
9270 tree res = do_mpfr_arg2 (arg0, arg1, type, (max ? mpfr_max : mpfr_min));
9271
9272 if (res)
9273 return res;
9274
61fe3555 9275 /* If either argument is NaN, return the other one. Avoid the
9276 transformation if we get (and honor) a signalling NaN. Using
9277 omit_one_operand() ensures we create a non-lvalue. */
9278 if (TREE_CODE (arg0) == REAL_CST
9279 && real_isnan (&TREE_REAL_CST (arg0))
9280 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
9281 || ! TREE_REAL_CST (arg0).signalling))
9282 return omit_one_operand (type, arg1, arg0);
9283 if (TREE_CODE (arg1) == REAL_CST
9284 && real_isnan (&TREE_REAL_CST (arg1))
9285 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
9286 || ! TREE_REAL_CST (arg1).signalling))
9287 return omit_one_operand (type, arg0, arg1);
9288
d4a43a03 9289 /* Transform fmin/fmax(x,x) -> x. */
9290 if (operand_equal_p (arg0, arg1, OEP_PURE_SAME))
9291 return omit_one_operand (type, arg0, arg1);
9292
9293 /* Convert fmin/fmax to MIN_EXPR/MAX_EXPR. C99 requires these
9294 functions to return the numeric arg if the other one is NaN.
9295 These tree codes don't honor that, so only transform if
9296 -ffinite-math-only is set. C99 doesn't require -0.0 to be
9297 handled, so we don't have to worry about it either. */
9298 if (flag_finite_math_only)
9299 return fold_build2 ((max ? MAX_EXPR : MIN_EXPR), type,
9300 fold_convert (type, arg0),
9301 fold_convert (type, arg1));
9302 }
9303 return NULL_TREE;
9304}
9305
abe4dcf6 9306/* Fold a call to builtin carg(a+bi) -> atan2(b,a). */
9307
9308static tree
c2f47e15 9309fold_builtin_carg (tree arg, tree type)
abe4dcf6 9310{
c2f47e15 9311 if (validate_arg (arg, COMPLEX_TYPE))
abe4dcf6 9312 {
9313 tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
9314
9315 if (atan2_fn)
9316 {
c2f47e15 9317 tree new_arg = builtin_save_expr (arg);
9318 tree r_arg = fold_build1 (REALPART_EXPR, type, new_arg);
9319 tree i_arg = fold_build1 (IMAGPART_EXPR, type, new_arg);
9320 return build_call_expr (atan2_fn, 2, i_arg, r_arg);
abe4dcf6 9321 }
9322 }
9323
9324 return NULL_TREE;
9325}
9326
cb2b9385 9327/* Fold a call to builtin logb/ilogb. */
9328
9329static tree
9330fold_builtin_logb (tree arg, tree rettype)
9331{
9332 if (! validate_arg (arg, REAL_TYPE))
9333 return NULL_TREE;
9334
9335 STRIP_NOPS (arg);
9336
9337 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9338 {
9339 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
9340
9341 switch (value->cl)
9342 {
9343 case rvc_nan:
9344 case rvc_inf:
9345 /* If arg is Inf or NaN and we're logb, return it. */
9346 if (TREE_CODE (rettype) == REAL_TYPE)
9347 return fold_convert (rettype, arg);
9348 /* Fall through... */
9349 case rvc_zero:
9350 /* Zero may set errno and/or raise an exception for logb, also
9351 for ilogb we don't know FP_ILOGB0. */
9352 return NULL_TREE;
9353 case rvc_normal:
9354 /* For normal numbers, proceed iff radix == 2. In GCC,
9355 normalized significands are in the range [0.5, 1.0). We
9356 want the exponent as if they were [1.0, 2.0) so get the
9357 exponent and subtract 1. */
9358 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
9359 return fold_convert (rettype, build_int_cst (NULL_TREE,
9360 REAL_EXP (value)-1));
9361 break;
9362 }
9363 }
9364
9365 return NULL_TREE;
9366}
9367
9368/* Fold a call to builtin significand, if radix == 2. */
9369
9370static tree
9371fold_builtin_significand (tree arg, tree rettype)
9372{
9373 if (! validate_arg (arg, REAL_TYPE))
9374 return NULL_TREE;
9375
9376 STRIP_NOPS (arg);
9377
9378 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9379 {
9380 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
9381
9382 switch (value->cl)
9383 {
9384 case rvc_zero:
9385 case rvc_nan:
9386 case rvc_inf:
9387 /* If arg is +-0, +-Inf or +-NaN, then return it. */
9388 return fold_convert (rettype, arg);
9389 case rvc_normal:
9390 /* For normal numbers, proceed iff radix == 2. */
9391 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
9392 {
9393 REAL_VALUE_TYPE result = *value;
9394 /* In GCC, normalized significands are in the range [0.5,
9395 1.0). We want them to be [1.0, 2.0) so set the
9396 exponent to 1. */
9397 SET_REAL_EXP (&result, 1);
9398 return build_real (rettype, result);
9399 }
9400 break;
9401 }
9402 }
9403
9404 return NULL_TREE;
9405}
9406
3838b9ae 9407/* Fold a call to builtin frexp, we can assume the base is 2. */
9408
9409static tree
9410fold_builtin_frexp (tree arg0, tree arg1, tree rettype)
9411{
9412 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9413 return NULL_TREE;
9414
9415 STRIP_NOPS (arg0);
9416
9417 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9418 return NULL_TREE;
9419
9420 arg1 = build_fold_indirect_ref (arg1);
9421
9422 /* Proceed if a valid pointer type was passed in. */
9423 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
9424 {
9425 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9426 tree frac, exp;
9427
9428 switch (value->cl)
9429 {
9430 case rvc_zero:
9431 /* For +-0, return (*exp = 0, +-0). */
9432 exp = integer_zero_node;
9433 frac = arg0;
9434 break;
9435 case rvc_nan:
9436 case rvc_inf:
9437 /* For +-NaN or +-Inf, *exp is unspecified, return arg0. */
9438 return omit_one_operand (rettype, arg0, arg1);
9439 case rvc_normal:
9440 {
9441 /* Since the frexp function always expects base 2, and in
9442 GCC normalized significands are already in the range
9443 [0.5, 1.0), we have exactly what frexp wants. */
9444 REAL_VALUE_TYPE frac_rvt = *value;
9445 SET_REAL_EXP (&frac_rvt, 0);
9446 frac = build_real (rettype, frac_rvt);
9447 exp = build_int_cst (NULL_TREE, REAL_EXP (value));
9448 }
9449 break;
9450 default:
9451 gcc_unreachable ();
9452 }
9453
9454 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
9455 arg1 = fold_build2 (MODIFY_EXPR, rettype, arg1, exp);
9456 TREE_SIDE_EFFECTS (arg1) = 1;
9457 return fold_build2 (COMPOUND_EXPR, rettype, arg1, frac);
9458 }
9459
9460 return NULL_TREE;
9461}
9462
7587301b 9463/* Fold a call to builtin ldexp or scalbn/scalbln. If LDEXP is true
9464 then we can assume the base is two. If it's false, then we have to
9465 check the mode of the TYPE parameter in certain cases. */
9466
9467static tree
9468fold_builtin_load_exponent (tree arg0, tree arg1, tree type, bool ldexp)
9469{
9470 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, INTEGER_TYPE))
9471 {
9472 STRIP_NOPS (arg0);
9473 STRIP_NOPS (arg1);
9474
9475 /* If arg0 is 0, Inf or NaN, or if arg1 is 0, then return arg0. */
9476 if (real_zerop (arg0) || integer_zerop (arg1)
9477 || (TREE_CODE (arg0) == REAL_CST
776a7bab 9478 && !real_isfinite (&TREE_REAL_CST (arg0))))
7587301b 9479 return omit_one_operand (type, arg0, arg1);
9480
9481 /* If both arguments are constant, then try to evaluate it. */
9482 if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2)
9483 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
9484 && host_integerp (arg1, 0))
9485 {
9486 /* Bound the maximum adjustment to twice the range of the
9487 mode's valid exponents. Use abs to ensure the range is
9488 positive as a sanity check. */
9489 const long max_exp_adj = 2 *
9490 labs (REAL_MODE_FORMAT (TYPE_MODE (type))->emax
9491 - REAL_MODE_FORMAT (TYPE_MODE (type))->emin);
9492
9493 /* Get the user-requested adjustment. */
9494 const HOST_WIDE_INT req_exp_adj = tree_low_cst (arg1, 0);
9495
9496 /* The requested adjustment must be inside this range. This
9497 is a preliminary cap to avoid things like overflow, we
9498 may still fail to compute the result for other reasons. */
9499 if (-max_exp_adj < req_exp_adj && req_exp_adj < max_exp_adj)
9500 {
9501 REAL_VALUE_TYPE initial_result;
9502
9503 real_ldexp (&initial_result, &TREE_REAL_CST (arg0), req_exp_adj);
9504
9505 /* Ensure we didn't overflow. */
9506 if (! real_isinf (&initial_result))
9507 {
9508 const REAL_VALUE_TYPE trunc_result
9509 = real_value_truncate (TYPE_MODE (type), initial_result);
9510
9511 /* Only proceed if the target mode can hold the
9512 resulting value. */
9513 if (REAL_VALUES_EQUAL (initial_result, trunc_result))
9514 return build_real (type, trunc_result);
9515 }
9516 }
9517 }
9518 }
9519
9520 return NULL_TREE;
9521}
9522
ebf8b4f5 9523/* Fold a call to builtin modf. */
9524
9525static tree
9526fold_builtin_modf (tree arg0, tree arg1, tree rettype)
9527{
9528 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9529 return NULL_TREE;
9530
9531 STRIP_NOPS (arg0);
9532
9533 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9534 return NULL_TREE;
9535
9536 arg1 = build_fold_indirect_ref (arg1);
9537
9538 /* Proceed if a valid pointer type was passed in. */
9539 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
9540 {
9541 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9542 REAL_VALUE_TYPE trunc, frac;
9543
9544 switch (value->cl)
9545 {
9546 case rvc_nan:
9547 case rvc_zero:
9548 /* For +-NaN or +-0, return (*arg1 = arg0, arg0). */
9549 trunc = frac = *value;
9550 break;
9551 case rvc_inf:
9552 /* For +-Inf, return (*arg1 = arg0, +-0). */
9553 frac = dconst0;
9554 frac.sign = value->sign;
9555 trunc = *value;
9556 break;
9557 case rvc_normal:
9558 /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)). */
9559 real_trunc (&trunc, VOIDmode, value);
9560 real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
9561 /* If the original number was negative and already
9562 integral, then the fractional part is -0.0. */
9563 if (value->sign && frac.cl == rvc_zero)
9564 frac.sign = value->sign;
9565 break;
9566 }
9567
9568 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
9569 arg1 = fold_build2 (MODIFY_EXPR, rettype, arg1,
9570 build_real (rettype, trunc));
9571 TREE_SIDE_EFFECTS (arg1) = 1;
9572 return fold_build2 (COMPOUND_EXPR, rettype, arg1,
9573 build_real (rettype, frac));
9574 }
9575
9576 return NULL_TREE;
9577}
9578
726069ba 9579/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
c2f47e15 9580 ARG is the argument for the call. */
726069ba 9581
9582static tree
c2f47e15 9583fold_builtin_classify (tree fndecl, tree arg, int builtin_index)
726069ba 9584{
726069ba 9585 tree type = TREE_TYPE (TREE_TYPE (fndecl));
726069ba 9586 REAL_VALUE_TYPE r;
9587
c2f47e15 9588 if (!validate_arg (arg, REAL_TYPE))
726069ba 9589 {
c2f47e15 9590 error ("non-floating-point argument to function %qs",
9591 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
9592 return error_mark_node;
726069ba 9593 }
9594
726069ba 9595 switch (builtin_index)
9596 {
9597 case BUILT_IN_ISINF:
b70bfd00 9598 if (!HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
a0c938f0 9599 return omit_one_operand (type, integer_zero_node, arg);
726069ba 9600
9601 if (TREE_CODE (arg) == REAL_CST)
9602 {
9603 r = TREE_REAL_CST (arg);
9604 if (real_isinf (&r))
9605 return real_compare (GT_EXPR, &r, &dconst0)
9606 ? integer_one_node : integer_minus_one_node;
9607 else
9608 return integer_zero_node;
9609 }
9610
9611 return NULL_TREE;
9612
cde061c1 9613 case BUILT_IN_ISFINITE:
b70bfd00 9614 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
9615 && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
34709e02 9616 return omit_one_operand (type, integer_one_node, arg);
726069ba 9617
9618 if (TREE_CODE (arg) == REAL_CST)
9619 {
9620 r = TREE_REAL_CST (arg);
776a7bab 9621 return real_isfinite (&r) ? integer_one_node : integer_zero_node;
726069ba 9622 }
9623
9624 return NULL_TREE;
9625
9626 case BUILT_IN_ISNAN:
b70bfd00 9627 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))))
a0c938f0 9628 return omit_one_operand (type, integer_zero_node, arg);
726069ba 9629
9630 if (TREE_CODE (arg) == REAL_CST)
9631 {
9632 r = TREE_REAL_CST (arg);
9633 return real_isnan (&r) ? integer_one_node : integer_zero_node;
9634 }
9635
9636 arg = builtin_save_expr (arg);
49d00087 9637 return fold_build2 (UNORDERED_EXPR, type, arg, arg);
726069ba 9638
9639 default:
64db345d 9640 gcc_unreachable ();
726069ba 9641 }
9642}
9643
9bc9f15f 9644/* Fold a call to an unordered comparison function such as
d5019fe8 9645 __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function
c2f47e15 9646 being called and ARG0 and ARG1 are the arguments for the call.
726069ba 9647 UNORDERED_CODE and ORDERED_CODE are comparison codes that give
9648 the opposite of the desired result. UNORDERED_CODE is used
9649 for modes that can hold NaNs and ORDERED_CODE is used for
9650 the rest. */
9bc9f15f 9651
9652static tree
c2f47e15 9653fold_builtin_unordered_cmp (tree fndecl, tree arg0, tree arg1,
9bc9f15f 9654 enum tree_code unordered_code,
9655 enum tree_code ordered_code)
9656{
859f903a 9657 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9bc9f15f 9658 enum tree_code code;
6978db0d 9659 tree type0, type1;
9660 enum tree_code code0, code1;
9661 tree cmp_type = NULL_TREE;
9bc9f15f 9662
6978db0d 9663 type0 = TREE_TYPE (arg0);
9664 type1 = TREE_TYPE (arg1);
a0c938f0 9665
6978db0d 9666 code0 = TREE_CODE (type0);
9667 code1 = TREE_CODE (type1);
a0c938f0 9668
6978db0d 9669 if (code0 == REAL_TYPE && code1 == REAL_TYPE)
9670 /* Choose the wider of two real types. */
9671 cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
9672 ? type0 : type1;
9673 else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
9674 cmp_type = type0;
9675 else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
9676 cmp_type = type1;
859f903a 9677 else
9678 {
6978db0d 9679 error ("non-floating-point argument to function %qs",
9680 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
9681 return error_mark_node;
859f903a 9682 }
a0c938f0 9683
6978db0d 9684 arg0 = fold_convert (cmp_type, arg0);
9685 arg1 = fold_convert (cmp_type, arg1);
859f903a 9686
9687 if (unordered_code == UNORDERED_EXPR)
9688 {
b70bfd00 9689 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
859f903a 9690 return omit_two_operands (type, integer_zero_node, arg0, arg1);
49d00087 9691 return fold_build2 (UNORDERED_EXPR, type, arg0, arg1);
859f903a 9692 }
9bc9f15f 9693
b70bfd00 9694 code = HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
9695 : ordered_code;
49d00087 9696 return fold_build1 (TRUTH_NOT_EXPR, type,
9697 fold_build2 (code, type, arg0, arg1));
9bc9f15f 9698}
9699
c2f47e15 9700/* Fold a call to built-in function FNDECL with 0 arguments.
9701 IGNORE is true if the result of the function call is ignored. This
9702 function returns NULL_TREE if no simplification was possible. */
650e4c94 9703
4ee9c684 9704static tree
c2f47e15 9705fold_builtin_0 (tree fndecl, bool ignore ATTRIBUTE_UNUSED)
650e4c94 9706{
e9f80ff5 9707 tree type = TREE_TYPE (TREE_TYPE (fndecl));
c2f47e15 9708 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
189b3398 9709 switch (fcode)
650e4c94 9710 {
c2f47e15 9711 CASE_FLT_FN (BUILT_IN_INF):
9712 case BUILT_IN_INFD32:
9713 case BUILT_IN_INFD64:
9714 case BUILT_IN_INFD128:
9715 return fold_builtin_inf (type, true);
7c2f0500 9716
c2f47e15 9717 CASE_FLT_FN (BUILT_IN_HUGE_VAL):
9718 return fold_builtin_inf (type, false);
7c2f0500 9719
c2f47e15 9720 case BUILT_IN_CLASSIFY_TYPE:
9721 return fold_builtin_classify_type (NULL_TREE);
7c2f0500 9722
c2f47e15 9723 default:
9724 break;
9725 }
9726 return NULL_TREE;
9727}
7c2f0500 9728
c2f47e15 9729/* Fold a call to built-in function FNDECL with 1 argument, ARG0.
9730 IGNORE is true if the result of the function call is ignored. This
9731 function returns NULL_TREE if no simplification was possible. */
7c2f0500 9732
c2f47e15 9733static tree
9734fold_builtin_1 (tree fndecl, tree arg0, bool ignore)
9735{
9736 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9737 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9738 switch (fcode)
9739 {
7c2f0500 9740
650e4c94 9741 case BUILT_IN_CONSTANT_P:
7c2f0500 9742 {
c2f47e15 9743 tree val = fold_builtin_constant_p (arg0);
7c2f0500 9744
7c2f0500 9745 /* Gimplification will pull the CALL_EXPR for the builtin out of
9746 an if condition. When not optimizing, we'll not CSE it back.
9747 To avoid link error types of regressions, return false now. */
9748 if (!val && !optimize)
9749 val = integer_zero_node;
9750
9751 return val;
9752 }
650e4c94 9753
539a3a92 9754 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 9755 return fold_builtin_classify_type (arg0);
539a3a92 9756
650e4c94 9757 case BUILT_IN_STRLEN:
c2f47e15 9758 return fold_builtin_strlen (arg0);
650e4c94 9759
4f35b1fc 9760 CASE_FLT_FN (BUILT_IN_FABS):
c2f47e15 9761 return fold_builtin_fabs (arg0, type);
d1aade50 9762
9763 case BUILT_IN_ABS:
9764 case BUILT_IN_LABS:
9765 case BUILT_IN_LLABS:
9766 case BUILT_IN_IMAXABS:
c2f47e15 9767 return fold_builtin_abs (arg0, type);
c63f4ad3 9768
4f35b1fc 9769 CASE_FLT_FN (BUILT_IN_CONJ):
c2f47e15 9770 if (validate_arg (arg0, COMPLEX_TYPE))
9771 return fold_build1 (CONJ_EXPR, type, arg0);
9772 break;
36d3581d 9773
4f35b1fc 9774 CASE_FLT_FN (BUILT_IN_CREAL):
c2f47e15 9775 if (validate_arg (arg0, COMPLEX_TYPE))
9776 return non_lvalue (fold_build1 (REALPART_EXPR, type, arg0));;
9777 break;
36d3581d 9778
4f35b1fc 9779 CASE_FLT_FN (BUILT_IN_CIMAG):
c2f47e15 9780 if (validate_arg (arg0, COMPLEX_TYPE))
9781 return non_lvalue (fold_build1 (IMAGPART_EXPR, type, arg0));
9782 break;
36d3581d 9783
503733d5 9784 CASE_FLT_FN (BUILT_IN_CCOS):
9785 CASE_FLT_FN (BUILT_IN_CCOSH):
9786 /* These functions are "even", i.e. f(x) == f(-x). */
c2f47e15 9787 if (validate_arg (arg0, COMPLEX_TYPE))
9788 {
9789 tree narg = fold_strip_sign_ops (arg0);
503733d5 9790 if (narg)
c2f47e15 9791 return build_call_expr (fndecl, 1, narg);
503733d5 9792 }
c2f47e15 9793 break;
503733d5 9794
4f35b1fc 9795 CASE_FLT_FN (BUILT_IN_CABS):
c2f47e15 9796 return fold_builtin_cabs (arg0, type, fndecl);
c63f4ad3 9797
abe4dcf6 9798 CASE_FLT_FN (BUILT_IN_CARG):
c2f47e15 9799 return fold_builtin_carg (arg0, type);
abe4dcf6 9800
4f35b1fc 9801 CASE_FLT_FN (BUILT_IN_SQRT):
c2f47e15 9802 return fold_builtin_sqrt (arg0, type);
805e22b2 9803
4f35b1fc 9804 CASE_FLT_FN (BUILT_IN_CBRT):
c2f47e15 9805 return fold_builtin_cbrt (arg0, type);
3bc5c41b 9806
728bac60 9807 CASE_FLT_FN (BUILT_IN_ASIN):
c2f47e15 9808 if (validate_arg (arg0, REAL_TYPE))
9809 return do_mpfr_arg1 (arg0, type, mpfr_asin,
728bac60 9810 &dconstm1, &dconst1, true);
9811 break;
9812
9813 CASE_FLT_FN (BUILT_IN_ACOS):
c2f47e15 9814 if (validate_arg (arg0, REAL_TYPE))
9815 return do_mpfr_arg1 (arg0, type, mpfr_acos,
728bac60 9816 &dconstm1, &dconst1, true);
9817 break;
9818
9819 CASE_FLT_FN (BUILT_IN_ATAN):
c2f47e15 9820 if (validate_arg (arg0, REAL_TYPE))
9821 return do_mpfr_arg1 (arg0, type, mpfr_atan, NULL, NULL, 0);
728bac60 9822 break;
9823
9824 CASE_FLT_FN (BUILT_IN_ASINH):
c2f47e15 9825 if (validate_arg (arg0, REAL_TYPE))
9826 return do_mpfr_arg1 (arg0, type, mpfr_asinh, NULL, NULL, 0);
728bac60 9827 break;
9828
9829 CASE_FLT_FN (BUILT_IN_ACOSH):
c2f47e15 9830 if (validate_arg (arg0, REAL_TYPE))
9831 return do_mpfr_arg1 (arg0, type, mpfr_acosh,
728bac60 9832 &dconst1, NULL, true);
9833 break;
9834
9835 CASE_FLT_FN (BUILT_IN_ATANH):
c2f47e15 9836 if (validate_arg (arg0, REAL_TYPE))
9837 return do_mpfr_arg1 (arg0, type, mpfr_atanh,
728bac60 9838 &dconstm1, &dconst1, false);
9839 break;
9840
4f35b1fc 9841 CASE_FLT_FN (BUILT_IN_SIN):
c2f47e15 9842 if (validate_arg (arg0, REAL_TYPE))
9843 return do_mpfr_arg1 (arg0, type, mpfr_sin, NULL, NULL, 0);
728bac60 9844 break;
77e89269 9845
4f35b1fc 9846 CASE_FLT_FN (BUILT_IN_COS):
c2f47e15 9847 return fold_builtin_cos (arg0, type, fndecl);
9848 break;
77e89269 9849
728bac60 9850 CASE_FLT_FN (BUILT_IN_TAN):
c2f47e15 9851 return fold_builtin_tan (arg0, type);
d735c391 9852
c5bb2c4b 9853 CASE_FLT_FN (BUILT_IN_CEXP):
c2f47e15 9854 return fold_builtin_cexp (arg0, type);
c5bb2c4b 9855
d735c391 9856 CASE_FLT_FN (BUILT_IN_CEXPI):
c2f47e15 9857 if (validate_arg (arg0, REAL_TYPE))
9858 return do_mpfr_sincos (arg0, NULL_TREE, NULL_TREE);
9859 break;
d92f994c 9860
728bac60 9861 CASE_FLT_FN (BUILT_IN_SINH):
c2f47e15 9862 if (validate_arg (arg0, REAL_TYPE))
9863 return do_mpfr_arg1 (arg0, type, mpfr_sinh, NULL, NULL, 0);
728bac60 9864 break;
9865
9866 CASE_FLT_FN (BUILT_IN_COSH):
c2f47e15 9867 return fold_builtin_cosh (arg0, type, fndecl);
728bac60 9868
9869 CASE_FLT_FN (BUILT_IN_TANH):
c2f47e15 9870 if (validate_arg (arg0, REAL_TYPE))
9871 return do_mpfr_arg1 (arg0, type, mpfr_tanh, NULL, NULL, 0);
728bac60 9872 break;
9873
29f4cd78 9874 CASE_FLT_FN (BUILT_IN_ERF):
c2f47e15 9875 if (validate_arg (arg0, REAL_TYPE))
9876 return do_mpfr_arg1 (arg0, type, mpfr_erf, NULL, NULL, 0);
29f4cd78 9877 break;
9878
9879 CASE_FLT_FN (BUILT_IN_ERFC):
c2f47e15 9880 if (validate_arg (arg0, REAL_TYPE))
9881 return do_mpfr_arg1 (arg0, type, mpfr_erfc, NULL, NULL, 0);
29f4cd78 9882 break;
9883
32dba52b 9884 CASE_FLT_FN (BUILT_IN_TGAMMA):
c2f47e15 9885 if (validate_arg (arg0, REAL_TYPE))
9886 return do_mpfr_arg1 (arg0, type, mpfr_gamma, NULL, NULL, 0);
32dba52b 9887 break;
9888
4f35b1fc 9889 CASE_FLT_FN (BUILT_IN_EXP):
c2f47e15 9890 return fold_builtin_exponent (fndecl, arg0, mpfr_exp);
467214fd 9891
4f35b1fc 9892 CASE_FLT_FN (BUILT_IN_EXP2):
c2f47e15 9893 return fold_builtin_exponent (fndecl, arg0, mpfr_exp2);
467214fd 9894
4f35b1fc 9895 CASE_FLT_FN (BUILT_IN_EXP10):
9896 CASE_FLT_FN (BUILT_IN_POW10):
c2f47e15 9897 return fold_builtin_exponent (fndecl, arg0, mpfr_exp10);
467214fd 9898
29f4cd78 9899 CASE_FLT_FN (BUILT_IN_EXPM1):
c2f47e15 9900 if (validate_arg (arg0, REAL_TYPE))
9901 return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0);
29f4cd78 9902 break;
9903
4f35b1fc 9904 CASE_FLT_FN (BUILT_IN_LOG):
c2f47e15 9905 return fold_builtin_logarithm (fndecl, arg0, mpfr_log);
467214fd 9906
4f35b1fc 9907 CASE_FLT_FN (BUILT_IN_LOG2):
c2f47e15 9908 return fold_builtin_logarithm (fndecl, arg0, mpfr_log2);
467214fd 9909
4f35b1fc 9910 CASE_FLT_FN (BUILT_IN_LOG10):
c2f47e15 9911 return fold_builtin_logarithm (fndecl, arg0, mpfr_log10);
29f4cd78 9912
9913 CASE_FLT_FN (BUILT_IN_LOG1P):
c2f47e15 9914 if (validate_arg (arg0, REAL_TYPE))
9915 return do_mpfr_arg1 (arg0, type, mpfr_log1p,
29f4cd78 9916 &dconstm1, NULL, false);
9917 break;
805e22b2 9918
65dd1378 9919#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
9920 CASE_FLT_FN (BUILT_IN_J0):
9921 if (validate_arg (arg0, REAL_TYPE))
9922 return do_mpfr_arg1 (arg0, type, mpfr_j0,
9923 NULL, NULL, 0);
9924 break;
9925
9926 CASE_FLT_FN (BUILT_IN_J1):
9927 if (validate_arg (arg0, REAL_TYPE))
9928 return do_mpfr_arg1 (arg0, type, mpfr_j1,
9929 NULL, NULL, 0);
9930 break;
6ff9eeff 9931
9932 CASE_FLT_FN (BUILT_IN_Y0):
9933 if (validate_arg (arg0, REAL_TYPE))
9934 return do_mpfr_arg1 (arg0, type, mpfr_y0,
9935 &dconst0, NULL, false);
9936 break;
9937
9938 CASE_FLT_FN (BUILT_IN_Y1):
9939 if (validate_arg (arg0, REAL_TYPE))
9940 return do_mpfr_arg1 (arg0, type, mpfr_y1,
9941 &dconst0, NULL, false);
9942 break;
65dd1378 9943#endif
9944
4f35b1fc 9945 CASE_FLT_FN (BUILT_IN_NAN):
c4503c0a 9946 case BUILT_IN_NAND32:
9947 case BUILT_IN_NAND64:
9948 case BUILT_IN_NAND128:
c2f47e15 9949 return fold_builtin_nan (arg0, type, true);
b0db7939 9950
4f35b1fc 9951 CASE_FLT_FN (BUILT_IN_NANS):
c2f47e15 9952 return fold_builtin_nan (arg0, type, false);
b0db7939 9953
4f35b1fc 9954 CASE_FLT_FN (BUILT_IN_FLOOR):
c2f47e15 9955 return fold_builtin_floor (fndecl, arg0);
277f8dd2 9956
4f35b1fc 9957 CASE_FLT_FN (BUILT_IN_CEIL):
c2f47e15 9958 return fold_builtin_ceil (fndecl, arg0);
277f8dd2 9959
4f35b1fc 9960 CASE_FLT_FN (BUILT_IN_TRUNC):
c2f47e15 9961 return fold_builtin_trunc (fndecl, arg0);
277f8dd2 9962
4f35b1fc 9963 CASE_FLT_FN (BUILT_IN_ROUND):
c2f47e15 9964 return fold_builtin_round (fndecl, arg0);
89ab3887 9965
4f35b1fc 9966 CASE_FLT_FN (BUILT_IN_NEARBYINT):
9967 CASE_FLT_FN (BUILT_IN_RINT):
c2f47e15 9968 return fold_trunc_transparent_mathfn (fndecl, arg0);
6528f4f4 9969
4f35b1fc 9970 CASE_FLT_FN (BUILT_IN_LCEIL):
9971 CASE_FLT_FN (BUILT_IN_LLCEIL):
9972 CASE_FLT_FN (BUILT_IN_LFLOOR):
9973 CASE_FLT_FN (BUILT_IN_LLFLOOR):
a0c938f0 9974 CASE_FLT_FN (BUILT_IN_LROUND):
4f35b1fc 9975 CASE_FLT_FN (BUILT_IN_LLROUND):
c2f47e15 9976 return fold_builtin_int_roundingfn (fndecl, arg0);
34f17811 9977
4f35b1fc 9978 CASE_FLT_FN (BUILT_IN_LRINT):
9979 CASE_FLT_FN (BUILT_IN_LLRINT):
c2f47e15 9980 return fold_fixed_mathfn (fndecl, arg0);
9ed65c7f 9981
42791117 9982 case BUILT_IN_BSWAP32:
9983 case BUILT_IN_BSWAP64:
c2f47e15 9984 return fold_builtin_bswap (fndecl, arg0);
42791117 9985
4f35b1fc 9986 CASE_INT_FN (BUILT_IN_FFS):
9987 CASE_INT_FN (BUILT_IN_CLZ):
9988 CASE_INT_FN (BUILT_IN_CTZ):
9989 CASE_INT_FN (BUILT_IN_POPCOUNT):
9990 CASE_INT_FN (BUILT_IN_PARITY):
c2f47e15 9991 return fold_builtin_bitop (fndecl, arg0);
9c8a1629 9992
4f35b1fc 9993 CASE_FLT_FN (BUILT_IN_SIGNBIT):
c2f47e15 9994 return fold_builtin_signbit (arg0, type);
27f261ef 9995
cb2b9385 9996 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
9997 return fold_builtin_significand (arg0, type);
9998
9999 CASE_FLT_FN (BUILT_IN_ILOGB):
10000 CASE_FLT_FN (BUILT_IN_LOGB):
10001 return fold_builtin_logb (arg0, type);
10002
d49367d4 10003 case BUILT_IN_ISASCII:
c2f47e15 10004 return fold_builtin_isascii (arg0);
d49367d4 10005
10006 case BUILT_IN_TOASCII:
c2f47e15 10007 return fold_builtin_toascii (arg0);
d49367d4 10008
df1cf42e 10009 case BUILT_IN_ISDIGIT:
c2f47e15 10010 return fold_builtin_isdigit (arg0);
467214fd 10011
4f35b1fc 10012 CASE_FLT_FN (BUILT_IN_FINITE):
c4503c0a 10013 case BUILT_IN_FINITED32:
10014 case BUILT_IN_FINITED64:
10015 case BUILT_IN_FINITED128:
cde061c1 10016 case BUILT_IN_ISFINITE:
10017 return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISFINITE);
726069ba 10018
4f35b1fc 10019 CASE_FLT_FN (BUILT_IN_ISINF):
c4503c0a 10020 case BUILT_IN_ISINFD32:
10021 case BUILT_IN_ISINFD64:
10022 case BUILT_IN_ISINFD128:
c2f47e15 10023 return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISINF);
726069ba 10024
4f35b1fc 10025 CASE_FLT_FN (BUILT_IN_ISNAN):
c4503c0a 10026 case BUILT_IN_ISNAND32:
10027 case BUILT_IN_ISNAND64:
10028 case BUILT_IN_ISNAND128:
c2f47e15 10029 return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISNAN);
10030
10031 case BUILT_IN_PRINTF:
10032 case BUILT_IN_PRINTF_UNLOCKED:
10033 case BUILT_IN_VPRINTF:
10034 return fold_builtin_printf (fndecl, arg0, NULL_TREE, ignore, fcode);
10035
10036 default:
10037 break;
10038 }
10039
10040 return NULL_TREE;
10041
10042}
10043
10044/* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1.
10045 IGNORE is true if the result of the function call is ignored. This
10046 function returns NULL_TREE if no simplification was possible. */
10047
10048static tree
10049fold_builtin_2 (tree fndecl, tree arg0, tree arg1, bool ignore)
10050{
10051 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10052 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10053
10054 switch (fcode)
10055 {
65dd1378 10056#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
10057 CASE_FLT_FN (BUILT_IN_JN):
10058 if (validate_arg (arg0, INTEGER_TYPE)
10059 && validate_arg (arg1, REAL_TYPE))
10060 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_jn, NULL, 0);
10061 break;
6ff9eeff 10062
10063 CASE_FLT_FN (BUILT_IN_YN):
10064 if (validate_arg (arg0, INTEGER_TYPE)
10065 && validate_arg (arg1, REAL_TYPE))
10066 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_yn,
10067 &dconst0, false);
10068 break;
e5407ca6 10069
10070 CASE_FLT_FN (BUILT_IN_DREM):
10071 CASE_FLT_FN (BUILT_IN_REMAINDER):
10072 if (validate_arg (arg0, REAL_TYPE)
10073 && validate_arg(arg1, REAL_TYPE))
10074 return do_mpfr_arg2 (arg0, arg1, type, mpfr_remainder);
10075 break;
e84da7c1 10076
10077 CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
10078 CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
10079 if (validate_arg (arg0, REAL_TYPE)
10080 && validate_arg(arg1, POINTER_TYPE))
10081 return do_mpfr_lgamma_r (arg0, arg1, type);
10082 break;
65dd1378 10083#endif
c2f47e15 10084
10085 CASE_FLT_FN (BUILT_IN_ATAN2):
10086 if (validate_arg (arg0, REAL_TYPE)
10087 && validate_arg(arg1, REAL_TYPE))
10088 return do_mpfr_arg2 (arg0, arg1, type, mpfr_atan2);
10089 break;
10090
10091 CASE_FLT_FN (BUILT_IN_FDIM):
10092 if (validate_arg (arg0, REAL_TYPE)
10093 && validate_arg(arg1, REAL_TYPE))
10094 return do_mpfr_arg2 (arg0, arg1, type, mpfr_dim);
10095 break;
10096
10097 CASE_FLT_FN (BUILT_IN_HYPOT):
10098 return fold_builtin_hypot (fndecl, arg0, arg1, type);
10099
7587301b 10100 CASE_FLT_FN (BUILT_IN_LDEXP):
10101 return fold_builtin_load_exponent (arg0, arg1, type, /*ldexp=*/true);
10102 CASE_FLT_FN (BUILT_IN_SCALBN):
10103 CASE_FLT_FN (BUILT_IN_SCALBLN):
10104 return fold_builtin_load_exponent (arg0, arg1, type, /*ldexp=*/false);
10105
3838b9ae 10106 CASE_FLT_FN (BUILT_IN_FREXP):
10107 return fold_builtin_frexp (arg0, arg1, type);
10108
ebf8b4f5 10109 CASE_FLT_FN (BUILT_IN_MODF):
10110 return fold_builtin_modf (arg0, arg1, type);
10111
c2f47e15 10112 case BUILT_IN_BZERO:
10113 return fold_builtin_bzero (arg0, arg1, ignore);
10114
10115 case BUILT_IN_FPUTS:
10116 return fold_builtin_fputs (arg0, arg1, ignore, false, NULL_TREE);
10117
10118 case BUILT_IN_FPUTS_UNLOCKED:
10119 return fold_builtin_fputs (arg0, arg1, ignore, true, NULL_TREE);
10120
10121 case BUILT_IN_STRSTR:
10122 return fold_builtin_strstr (arg0, arg1, type);
10123
10124 case BUILT_IN_STRCAT:
10125 return fold_builtin_strcat (arg0, arg1);
10126
10127 case BUILT_IN_STRSPN:
10128 return fold_builtin_strspn (arg0, arg1);
10129
10130 case BUILT_IN_STRCSPN:
10131 return fold_builtin_strcspn (arg0, arg1);
10132
10133 case BUILT_IN_STRCHR:
10134 case BUILT_IN_INDEX:
10135 return fold_builtin_strchr (arg0, arg1, type);
10136
10137 case BUILT_IN_STRRCHR:
10138 case BUILT_IN_RINDEX:
10139 return fold_builtin_strrchr (arg0, arg1, type);
10140
10141 case BUILT_IN_STRCPY:
10142 return fold_builtin_strcpy (fndecl, arg0, arg1, NULL_TREE);
10143
10144 case BUILT_IN_STRCMP:
10145 return fold_builtin_strcmp (arg0, arg1);
10146
10147 case BUILT_IN_STRPBRK:
10148 return fold_builtin_strpbrk (arg0, arg1, type);
10149
10150 case BUILT_IN_EXPECT:
10151 return fold_builtin_expect (arg0);
10152
10153 CASE_FLT_FN (BUILT_IN_POW):
10154 return fold_builtin_pow (fndecl, arg0, arg1, type);
10155
10156 CASE_FLT_FN (BUILT_IN_POWI):
10157 return fold_builtin_powi (fndecl, arg0, arg1, type);
10158
10159 CASE_FLT_FN (BUILT_IN_COPYSIGN):
10160 return fold_builtin_copysign (fndecl, arg0, arg1, type);
10161
10162 CASE_FLT_FN (BUILT_IN_FMIN):
10163 return fold_builtin_fmin_fmax (arg0, arg1, type, /*max=*/false);
10164
10165 CASE_FLT_FN (BUILT_IN_FMAX):
10166 return fold_builtin_fmin_fmax (arg0, arg1, type, /*max=*/true);
726069ba 10167
9bc9f15f 10168 case BUILT_IN_ISGREATER:
c2f47e15 10169 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNLE_EXPR, LE_EXPR);
9bc9f15f 10170 case BUILT_IN_ISGREATEREQUAL:
c2f47e15 10171 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNLT_EXPR, LT_EXPR);
9bc9f15f 10172 case BUILT_IN_ISLESS:
c2f47e15 10173 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNGE_EXPR, GE_EXPR);
9bc9f15f 10174 case BUILT_IN_ISLESSEQUAL:
c2f47e15 10175 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNGT_EXPR, GT_EXPR);
9bc9f15f 10176 case BUILT_IN_ISLESSGREATER:
c2f47e15 10177 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNEQ_EXPR, EQ_EXPR);
9bc9f15f 10178 case BUILT_IN_ISUNORDERED:
c2f47e15 10179 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNORDERED_EXPR,
d5019fe8 10180 NOP_EXPR);
9bc9f15f 10181
7c2f0500 10182 /* We do the folding for va_start in the expander. */
10183 case BUILT_IN_VA_START:
10184 break;
f0613857 10185
c2f47e15 10186 case BUILT_IN_SPRINTF:
10187 return fold_builtin_sprintf (arg0, arg1, NULL_TREE, ignore);
10188
0a39fd54 10189 case BUILT_IN_OBJECT_SIZE:
c2f47e15 10190 return fold_builtin_object_size (arg0, arg1);
0a39fd54 10191
10192 case BUILT_IN_PRINTF:
10193 case BUILT_IN_PRINTF_UNLOCKED:
10194 case BUILT_IN_VPRINTF:
c2f47e15 10195 return fold_builtin_printf (fndecl, arg0, arg1, ignore, fcode);
10196
0a39fd54 10197 case BUILT_IN_PRINTF_CHK:
10198 case BUILT_IN_VPRINTF_CHK:
c2f47e15 10199 if (!validate_arg (arg0, INTEGER_TYPE)
10200 || TREE_SIDE_EFFECTS (arg0))
10201 return NULL_TREE;
10202 else
10203 return fold_builtin_printf (fndecl, arg1, NULL_TREE, ignore, fcode);
10204 break;
0a39fd54 10205
10206 case BUILT_IN_FPRINTF:
10207 case BUILT_IN_FPRINTF_UNLOCKED:
10208 case BUILT_IN_VFPRINTF:
c2f47e15 10209 return fold_builtin_fprintf (fndecl, arg0, arg1, NULL_TREE,
10210 ignore, fcode);
10211
10212 default:
10213 break;
10214 }
10215 return NULL_TREE;
10216}
10217
10218/* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
10219 and ARG2. IGNORE is true if the result of the function call is ignored.
10220 This function returns NULL_TREE if no simplification was possible. */
10221
10222static tree
10223fold_builtin_3 (tree fndecl, tree arg0, tree arg1, tree arg2, bool ignore)
10224{
10225 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10226 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10227 switch (fcode)
10228 {
10229
10230 CASE_FLT_FN (BUILT_IN_SINCOS):
10231 return fold_builtin_sincos (arg0, arg1, arg2);
10232
10233 CASE_FLT_FN (BUILT_IN_FMA):
10234 if (validate_arg (arg0, REAL_TYPE)
10235 && validate_arg(arg1, REAL_TYPE)
10236 && validate_arg(arg2, REAL_TYPE))
10237 return do_mpfr_arg3 (arg0, arg1, arg2, type, mpfr_fma);
10238 break;
10239
e5407ca6 10240#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
10241 CASE_FLT_FN (BUILT_IN_REMQUO):
10242 if (validate_arg (arg0, REAL_TYPE)
10243 && validate_arg(arg1, REAL_TYPE)
10244 && validate_arg(arg2, POINTER_TYPE))
10245 return do_mpfr_remquo (arg0, arg1, arg2);
10246 break;
10247#endif
10248
c2f47e15 10249 case BUILT_IN_MEMSET:
10250 return fold_builtin_memset (arg0, arg1, arg2, type, ignore);
10251
10252 case BUILT_IN_BCOPY:
10253 return fold_builtin_memory_op (arg1, arg0, arg2, void_type_node, true, /*endp=*/3);
10254
10255 case BUILT_IN_MEMCPY:
10256 return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/0);
10257
10258 case BUILT_IN_MEMPCPY:
10259 return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/1);
10260
10261 case BUILT_IN_MEMMOVE:
10262 return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/3);
10263
10264 case BUILT_IN_STRNCAT:
10265 return fold_builtin_strncat (arg0, arg1, arg2);
10266
10267 case BUILT_IN_STRNCPY:
10268 return fold_builtin_strncpy (fndecl, arg0, arg1, arg2, NULL_TREE);
10269
10270 case BUILT_IN_STRNCMP:
10271 return fold_builtin_strncmp (arg0, arg1, arg2);
10272
7959b13b 10273 case BUILT_IN_MEMCHR:
10274 return fold_builtin_memchr (arg0, arg1, arg2, type);
10275
c2f47e15 10276 case BUILT_IN_BCMP:
10277 case BUILT_IN_MEMCMP:
10278 return fold_builtin_memcmp (arg0, arg1, arg2);;
10279
10280 case BUILT_IN_SPRINTF:
10281 return fold_builtin_sprintf (arg0, arg1, arg2, ignore);
10282
10283 case BUILT_IN_STRCPY_CHK:
10284 case BUILT_IN_STPCPY_CHK:
10285 return fold_builtin_stxcpy_chk (fndecl, arg0, arg1, arg2, NULL_TREE,
10286 ignore, fcode);
10287
10288 case BUILT_IN_STRCAT_CHK:
10289 return fold_builtin_strcat_chk (fndecl, arg0, arg1, arg2);
10290
10291 case BUILT_IN_PRINTF_CHK:
10292 case BUILT_IN_VPRINTF_CHK:
10293 if (!validate_arg (arg0, INTEGER_TYPE)
10294 || TREE_SIDE_EFFECTS (arg0))
10295 return NULL_TREE;
10296 else
10297 return fold_builtin_printf (fndecl, arg1, arg2, ignore, fcode);
10298 break;
10299
10300 case BUILT_IN_FPRINTF:
10301 case BUILT_IN_FPRINTF_UNLOCKED:
10302 case BUILT_IN_VFPRINTF:
10303 return fold_builtin_fprintf (fndecl, arg0, arg1, arg2, ignore, fcode);
10304
0a39fd54 10305 case BUILT_IN_FPRINTF_CHK:
10306 case BUILT_IN_VFPRINTF_CHK:
c2f47e15 10307 if (!validate_arg (arg1, INTEGER_TYPE)
10308 || TREE_SIDE_EFFECTS (arg1))
10309 return NULL_TREE;
10310 else
10311 return fold_builtin_fprintf (fndecl, arg0, arg2, NULL_TREE,
10312 ignore, fcode);
0a39fd54 10313
650e4c94 10314 default:
10315 break;
10316 }
c2f47e15 10317 return NULL_TREE;
10318}
650e4c94 10319
c2f47e15 10320/* Fold a call to built-in function FNDECL with 4 arguments, ARG0, ARG1,
10321 ARG2, and ARG3. IGNORE is true if the result of the function call is
10322 ignored. This function returns NULL_TREE if no simplification was
10323 possible. */
10324
10325static tree
10326fold_builtin_4 (tree fndecl, tree arg0, tree arg1, tree arg2, tree arg3,
10327 bool ignore)
10328{
10329 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10330
10331 switch (fcode)
10332 {
10333 case BUILT_IN_MEMCPY_CHK:
10334 case BUILT_IN_MEMPCPY_CHK:
10335 case BUILT_IN_MEMMOVE_CHK:
10336 case BUILT_IN_MEMSET_CHK:
10337 return fold_builtin_memory_chk (fndecl, arg0, arg1, arg2, arg3,
10338 NULL_TREE, ignore,
10339 DECL_FUNCTION_CODE (fndecl));
10340
10341 case BUILT_IN_STRNCPY_CHK:
10342 return fold_builtin_strncpy_chk (arg0, arg1, arg2, arg3, NULL_TREE);
10343
10344 case BUILT_IN_STRNCAT_CHK:
10345 return fold_builtin_strncat_chk (fndecl, arg0, arg1, arg2, arg3);
10346
10347 case BUILT_IN_FPRINTF_CHK:
10348 case BUILT_IN_VFPRINTF_CHK:
10349 if (!validate_arg (arg1, INTEGER_TYPE)
10350 || TREE_SIDE_EFFECTS (arg1))
10351 return NULL_TREE;
10352 else
10353 return fold_builtin_fprintf (fndecl, arg0, arg2, arg3,
10354 ignore, fcode);
10355 break;
10356
10357 default:
10358 break;
10359 }
10360 return NULL_TREE;
10361}
10362
10363/* Fold a call to built-in function FNDECL. ARGS is an array of NARGS
10364 arguments, where NARGS <= 4. IGNORE is true if the result of the
10365 function call is ignored. This function returns NULL_TREE if no
10366 simplification was possible. Note that this only folds builtins with
10367 fixed argument patterns. Foldings that do varargs-to-varargs
10368 transformations, or that match calls with more than 4 arguments,
10369 need to be handled with fold_builtin_varargs instead. */
10370
10371#define MAX_ARGS_TO_FOLD_BUILTIN 4
10372
10373static tree
10374fold_builtin_n (tree fndecl, tree *args, int nargs, bool ignore)
10375{
10376 tree ret = NULL_TREE;
10377 switch (nargs)
10378 {
10379 case 0:
10380 ret = fold_builtin_0 (fndecl, ignore);
10381 break;
10382 case 1:
10383 ret = fold_builtin_1 (fndecl, args[0], ignore);
10384 break;
10385 case 2:
10386 ret = fold_builtin_2 (fndecl, args[0], args[1], ignore);
10387 break;
10388 case 3:
10389 ret = fold_builtin_3 (fndecl, args[0], args[1], args[2], ignore);
10390 break;
10391 case 4:
10392 ret = fold_builtin_4 (fndecl, args[0], args[1], args[2], args[3],
10393 ignore);
10394 break;
10395 default:
10396 break;
10397 }
10398 if (ret)
10399 {
10400 ret = build1 (NOP_EXPR, GENERIC_TREE_TYPE (ret), ret);
10401 TREE_NO_WARNING (ret) = 1;
10402 return ret;
10403 }
10404 return NULL_TREE;
10405}
10406
10407/* Builtins with folding operations that operate on "..." arguments
10408 need special handling; we need to store the arguments in a convenient
10409 data structure before attempting any folding. Fortunately there are
10410 only a few builtins that fall into this category. FNDECL is the
10411 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
10412 result of the function call is ignored. */
10413
10414static tree
10415fold_builtin_varargs (tree fndecl, tree exp, bool ignore ATTRIBUTE_UNUSED)
10416{
10417 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10418 tree ret = NULL_TREE;
10419
10420 switch (fcode)
10421 {
10422 case BUILT_IN_SPRINTF_CHK:
10423 case BUILT_IN_VSPRINTF_CHK:
10424 ret = fold_builtin_sprintf_chk (exp, fcode);
10425 break;
10426
10427 case BUILT_IN_SNPRINTF_CHK:
10428 case BUILT_IN_VSNPRINTF_CHK:
10429 ret = fold_builtin_snprintf_chk (exp, NULL_TREE, fcode);
10430
10431 default:
10432 break;
10433 }
10434 if (ret)
10435 {
10436 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
10437 TREE_NO_WARNING (ret) = 1;
10438 return ret;
10439 }
10440 return NULL_TREE;
650e4c94 10441}
7e15618b 10442
4ee9c684 10443/* A wrapper function for builtin folding that prevents warnings for
491e04ef 10444 "statement without effect" and the like, caused by removing the
4ee9c684 10445 call node earlier than the warning is generated. */
10446
10447tree
c2f47e15 10448fold_call_expr (tree exp, bool ignore)
4ee9c684 10449{
c2f47e15 10450 tree ret = NULL_TREE;
10451 tree fndecl = get_callee_fndecl (exp);
10452 if (fndecl
10453 && TREE_CODE (fndecl) == FUNCTION_DECL
10454 && DECL_BUILT_IN (fndecl))
4ee9c684 10455 {
c2f47e15 10456 /* FIXME: Don't use a list in this interface. */
10457 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
10458 return targetm.fold_builtin (fndecl, CALL_EXPR_ARGS (exp), ignore);
10459 else
10460 {
10461 int nargs = call_expr_nargs (exp);
10462 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
10463 {
10464 tree *args = CALL_EXPR_ARGP (exp);
10465 ret = fold_builtin_n (fndecl, args, nargs, ignore);
10466 }
10467 if (!ret)
10468 ret = fold_builtin_varargs (fndecl, exp, ignore);
10469 if (ret)
10470 {
10471 /* Propagate location information from original call to
10472 expansion of builtin. Otherwise things like
10473 maybe_emit_chk_warning, that operate on the expansion
10474 of a builtin, will use the wrong location information. */
10475 if (CAN_HAVE_LOCATION_P (exp) && EXPR_HAS_LOCATION (exp))
10476 {
10477 tree realret = ret;
10478 if (TREE_CODE (ret) == NOP_EXPR)
10479 realret = TREE_OPERAND (ret, 0);
10480 if (CAN_HAVE_LOCATION_P (realret)
10481 && !EXPR_HAS_LOCATION (realret))
10482 SET_EXPR_LOCATION (realret, EXPR_LOCATION (exp));
10483 }
10484 return ret;
10485 }
10486 }
4ee9c684 10487 }
c2f47e15 10488 return NULL_TREE;
10489}
10490
10491/* Conveniently construct a function call expression. FNDECL names the
10492 function to be called and ARGLIST is a TREE_LIST of arguments. */
10493
10494tree
10495build_function_call_expr (tree fndecl, tree arglist)
10496{
10497 tree fntype = TREE_TYPE (fndecl);
10498 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
d01f58f9 10499 int n = list_length (arglist);
10500 tree *argarray = (tree *) alloca (n * sizeof (tree));
10501 int i;
10502
10503 for (i = 0; i < n; i++, arglist = TREE_CHAIN (arglist))
10504 argarray[i] = TREE_VALUE (arglist);
10505 return fold_builtin_call_array (TREE_TYPE (fntype), fn, n, argarray);
c2f47e15 10506}
10507
10508/* Conveniently construct a function call expression. FNDECL names the
10509 function to be called, N is the number of arguments, and the "..."
10510 parameters are the argument expressions. */
10511
10512tree
10513build_call_expr (tree fndecl, int n, ...)
10514{
10515 va_list ap;
c2f47e15 10516 tree fntype = TREE_TYPE (fndecl);
10517 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
d01f58f9 10518 tree *argarray = (tree *) alloca (n * sizeof (tree));
10519 int i;
c2f47e15 10520
10521 va_start (ap, n);
d01f58f9 10522 for (i = 0; i < n; i++)
10523 argarray[i] = va_arg (ap, tree);
c2f47e15 10524 va_end (ap);
d01f58f9 10525 return fold_builtin_call_array (TREE_TYPE (fntype), fn, n, argarray);
4ee9c684 10526}
10527
c2f47e15 10528/* Construct a CALL_EXPR with type TYPE with FN as the function expression.
d01f58f9 10529 N arguments are passed in the array ARGARRAY. */
805e22b2 10530
10531tree
d01f58f9 10532fold_builtin_call_array (tree type,
10533 tree fn,
10534 int n,
10535 tree *argarray)
7e15618b 10536{
c2f47e15 10537 tree ret = NULL_TREE;
10538 int i;
10539 tree exp;
10540
10541 if (TREE_CODE (fn) == ADDR_EXPR)
10542 {
10543 tree fndecl = TREE_OPERAND (fn, 0);
10544 if (TREE_CODE (fndecl) == FUNCTION_DECL
10545 && DECL_BUILT_IN (fndecl))
10546 {
10547 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
10548 {
10549 tree arglist = NULL_TREE;
d01f58f9 10550 for (i = n - 1; i >= 0; i--)
10551 arglist = tree_cons (NULL_TREE, argarray[i], arglist);
c2f47e15 10552 ret = targetm.fold_builtin (fndecl, arglist, false);
10553 if (ret)
10554 return ret;
10555 }
10556 else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
10557 {
10558 /* First try the transformations that don't require consing up
10559 an exp. */
d01f58f9 10560 ret = fold_builtin_n (fndecl, argarray, n, false);
c2f47e15 10561 if (ret)
10562 return ret;
10563 }
10564
10565 /* If we got this far, we need to build an exp. */
d01f58f9 10566 exp = build_call_array (type, fn, n, argarray);
c2f47e15 10567 ret = fold_builtin_varargs (fndecl, exp, false);
10568 return ret ? ret : exp;
10569 }
10570 }
10571
d01f58f9 10572 return build_call_array (type, fn, n, argarray);
c2f47e15 10573}
10574
10575/* Construct a new CALL_EXPR using the tail of the argument list of EXP
10576 along with N new arguments specified as the "..." parameters. SKIP
10577 is the number of arguments in EXP to be omitted. This function is used
10578 to do varargs-to-varargs transformations. */
10579
10580static tree
10581rewrite_call_expr (tree exp, int skip, tree fndecl, int n, ...)
10582{
10583 int oldnargs = call_expr_nargs (exp);
10584 int nargs = oldnargs - skip + n;
10585 tree fntype = TREE_TYPE (fndecl);
10586 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
10587 tree *buffer;
10588
10589 if (n > 0)
10590 {
10591 int i, j;
10592 va_list ap;
7e15618b 10593
c2f47e15 10594 buffer = alloca (nargs * sizeof (tree));
10595 va_start (ap, n);
10596 for (i = 0; i < n; i++)
10597 buffer[i] = va_arg (ap, tree);
10598 va_end (ap);
10599 for (j = skip; j < oldnargs; j++, i++)
10600 buffer[i] = CALL_EXPR_ARG (exp, j);
10601 }
10602 else
10603 buffer = CALL_EXPR_ARGP (exp) + skip;
10604
10605 return fold (build_call_array (TREE_TYPE (exp), fn, nargs, buffer));
10606}
10607
10608/* Validate a single argument ARG against a tree code CODE representing
10609 a type. */
10610
10611static bool
b7bf20db 10612validate_arg (const_tree arg, enum tree_code code)
c2f47e15 10613{
10614 if (!arg)
10615 return false;
10616 else if (code == POINTER_TYPE)
10617 return POINTER_TYPE_P (TREE_TYPE (arg));
10618 return code == TREE_CODE (TREE_TYPE (arg));
7e15618b 10619}
0eb671f7 10620
10621/* This function validates the types of a function call argument list
c2f47e15 10622 against a specified list of tree_codes. If the last specifier is a 0,
10623 that represents an ellipses, otherwise the last specifier must be a
10624 VOID_TYPE. */
27d0c333 10625
c2f47e15 10626bool
b7bf20db 10627validate_arglist (const_tree callexpr, ...)
0eb671f7 10628{
0eb671f7 10629 enum tree_code code;
c2f47e15 10630 bool res = 0;
ee582a61 10631 va_list ap;
b7bf20db 10632 const_call_expr_arg_iterator iter;
10633 const_tree arg;
aecda0d6 10634
c2f47e15 10635 va_start (ap, callexpr);
b7bf20db 10636 init_const_call_expr_arg_iterator (callexpr, &iter);
0eb671f7 10637
f0ce3b1f 10638 do
0eb671f7 10639 {
f0ce3b1f 10640 code = va_arg (ap, enum tree_code);
10641 switch (code)
10642 {
10643 case 0:
10644 /* This signifies an ellipses, any further arguments are all ok. */
c2f47e15 10645 res = true;
f0ce3b1f 10646 goto end;
10647 case VOID_TYPE:
10648 /* This signifies an endlink, if no arguments remain, return
10649 true, otherwise return false. */
b7bf20db 10650 res = !more_const_call_expr_args_p (&iter);
f0ce3b1f 10651 goto end;
10652 default:
10653 /* If no parameters remain or the parameter's code does not
10654 match the specified code, return false. Otherwise continue
10655 checking any remaining arguments. */
b7bf20db 10656 arg = next_const_call_expr_arg (&iter);
c2f47e15 10657 if (!validate_arg (arg, code))
f0ce3b1f 10658 goto end;
10659 break;
10660 }
0eb671f7 10661 }
f0ce3b1f 10662 while (1);
0903457a 10663
10664 /* We need gotos here since we can only have one VA_CLOSE in a
10665 function. */
10666 end: ;
ee582a61 10667 va_end (ap);
0903457a 10668
10669 return res;
0eb671f7 10670}
fc2a2dcb 10671
fc2a2dcb 10672/* Default target-specific builtin expander that does nothing. */
10673
10674rtx
aecda0d6 10675default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
10676 rtx target ATTRIBUTE_UNUSED,
10677 rtx subtarget ATTRIBUTE_UNUSED,
10678 enum machine_mode mode ATTRIBUTE_UNUSED,
10679 int ignore ATTRIBUTE_UNUSED)
fc2a2dcb 10680{
10681 return NULL_RTX;
10682}
c7926a82 10683
01537105 10684/* Returns true is EXP represents data that would potentially reside
10685 in a readonly section. */
10686
10687static bool
10688readonly_data_expr (tree exp)
10689{
10690 STRIP_NOPS (exp);
10691
9ff0637e 10692 if (TREE_CODE (exp) != ADDR_EXPR)
10693 return false;
10694
10695 exp = get_base_address (TREE_OPERAND (exp, 0));
10696 if (!exp)
10697 return false;
10698
10699 /* Make sure we call decl_readonly_section only for trees it
10700 can handle (since it returns true for everything it doesn't
10701 understand). */
491e04ef 10702 if (TREE_CODE (exp) == STRING_CST
9ff0637e 10703 || TREE_CODE (exp) == CONSTRUCTOR
10704 || (TREE_CODE (exp) == VAR_DECL && TREE_STATIC (exp)))
10705 return decl_readonly_section (exp, 0);
01537105 10706 else
10707 return false;
10708}
4ee9c684 10709
c2f47e15 10710/* Simplify a call to the strstr builtin. S1 and S2 are the arguments
10711 to the call, and TYPE is its return type.
4ee9c684 10712
c2f47e15 10713 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10714 simplified form of the call as a tree.
10715
10716 The simplified form may be a constant or other expression which
10717 computes the same value, but in a more efficient manner (including
10718 calls to other builtin functions).
10719
10720 The call may contain arguments which need to be evaluated, but
10721 which are not useful to determine the result of the call. In
10722 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10723 COMPOUND_EXPR will be an argument which must be evaluated.
10724 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10725 COMPOUND_EXPR in the chain will contain the tree for the simplified
10726 form of the builtin function call. */
10727
10728static tree
c2f47e15 10729fold_builtin_strstr (tree s1, tree s2, tree type)
4ee9c684 10730{
c2f47e15 10731 if (!validate_arg (s1, POINTER_TYPE)
10732 || !validate_arg (s2, POINTER_TYPE))
10733 return NULL_TREE;
4ee9c684 10734 else
10735 {
4ee9c684 10736 tree fn;
10737 const char *p1, *p2;
10738
10739 p2 = c_getstr (s2);
10740 if (p2 == NULL)
c2f47e15 10741 return NULL_TREE;
4ee9c684 10742
10743 p1 = c_getstr (s1);
10744 if (p1 != NULL)
10745 {
10746 const char *r = strstr (p1, p2);
daa1d5f5 10747 tree tem;
4ee9c684 10748
4ee9c684 10749 if (r == NULL)
779b4c41 10750 return build_int_cst (TREE_TYPE (s1), 0);
c0c67e38 10751
10752 /* Return an offset into the constant string argument. */
0de36bdb 10753 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
10754 s1, size_int (r - p1));
daa1d5f5 10755 return fold_convert (type, tem);
4ee9c684 10756 }
10757
7efa231c 10758 /* The argument is const char *, and the result is char *, so we need
10759 a type conversion here to avoid a warning. */
4ee9c684 10760 if (p2[0] == '\0')
7efa231c 10761 return fold_convert (type, s1);
4ee9c684 10762
10763 if (p2[1] != '\0')
c2f47e15 10764 return NULL_TREE;
4ee9c684 10765
10766 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
10767 if (!fn)
c2f47e15 10768 return NULL_TREE;
4ee9c684 10769
10770 /* New argument list transforming strstr(s1, s2) to
10771 strchr(s1, s2[0]). */
c2f47e15 10772 return build_call_expr (fn, 2, s1, build_int_cst (NULL_TREE, p2[0]));
4ee9c684 10773 }
10774}
10775
c2f47e15 10776/* Simplify a call to the strchr builtin. S1 and S2 are the arguments to
10777 the call, and TYPE is its return type.
4ee9c684 10778
c2f47e15 10779 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10780 simplified form of the call as a tree.
10781
10782 The simplified form may be a constant or other expression which
10783 computes the same value, but in a more efficient manner (including
10784 calls to other builtin functions).
10785
10786 The call may contain arguments which need to be evaluated, but
10787 which are not useful to determine the result of the call. In
10788 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10789 COMPOUND_EXPR will be an argument which must be evaluated.
10790 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10791 COMPOUND_EXPR in the chain will contain the tree for the simplified
10792 form of the builtin function call. */
10793
10794static tree
c2f47e15 10795fold_builtin_strchr (tree s1, tree s2, tree type)
4ee9c684 10796{
c2f47e15 10797 if (!validate_arg (s1, POINTER_TYPE)
10798 || !validate_arg (s2, INTEGER_TYPE))
10799 return NULL_TREE;
4ee9c684 10800 else
10801 {
4ee9c684 10802 const char *p1;
10803
10804 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 10805 return NULL_TREE;
4ee9c684 10806
10807 p1 = c_getstr (s1);
10808 if (p1 != NULL)
10809 {
10810 char c;
10811 const char *r;
daa1d5f5 10812 tree tem;
4ee9c684 10813
10814 if (target_char_cast (s2, &c))
c2f47e15 10815 return NULL_TREE;
4ee9c684 10816
10817 r = strchr (p1, c);
10818
10819 if (r == NULL)
779b4c41 10820 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 10821
10822 /* Return an offset into the constant string argument. */
0de36bdb 10823 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
10824 s1, size_int (r - p1));
daa1d5f5 10825 return fold_convert (type, tem);
4ee9c684 10826 }
c2f47e15 10827 return NULL_TREE;
4ee9c684 10828 }
10829}
10830
c2f47e15 10831/* Simplify a call to the strrchr builtin. S1 and S2 are the arguments to
10832 the call, and TYPE is its return type.
4ee9c684 10833
c2f47e15 10834 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10835 simplified form of the call as a tree.
10836
10837 The simplified form may be a constant or other expression which
10838 computes the same value, but in a more efficient manner (including
10839 calls to other builtin functions).
10840
10841 The call may contain arguments which need to be evaluated, but
10842 which are not useful to determine the result of the call. In
10843 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10844 COMPOUND_EXPR will be an argument which must be evaluated.
10845 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10846 COMPOUND_EXPR in the chain will contain the tree for the simplified
10847 form of the builtin function call. */
10848
10849static tree
c2f47e15 10850fold_builtin_strrchr (tree s1, tree s2, tree type)
4ee9c684 10851{
c2f47e15 10852 if (!validate_arg (s1, POINTER_TYPE)
10853 || !validate_arg (s2, INTEGER_TYPE))
10854 return NULL_TREE;
4ee9c684 10855 else
10856 {
4ee9c684 10857 tree fn;
10858 const char *p1;
10859
10860 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 10861 return NULL_TREE;
4ee9c684 10862
10863 p1 = c_getstr (s1);
10864 if (p1 != NULL)
10865 {
10866 char c;
10867 const char *r;
daa1d5f5 10868 tree tem;
4ee9c684 10869
10870 if (target_char_cast (s2, &c))
c2f47e15 10871 return NULL_TREE;
4ee9c684 10872
10873 r = strrchr (p1, c);
10874
10875 if (r == NULL)
779b4c41 10876 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 10877
10878 /* Return an offset into the constant string argument. */
0de36bdb 10879 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
10880 s1, size_int (r - p1));
daa1d5f5 10881 return fold_convert (type, tem);
4ee9c684 10882 }
10883
10884 if (! integer_zerop (s2))
c2f47e15 10885 return NULL_TREE;
4ee9c684 10886
10887 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
10888 if (!fn)
c2f47e15 10889 return NULL_TREE;
4ee9c684 10890
10891 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
c2f47e15 10892 return build_call_expr (fn, 2, s1, s2);
4ee9c684 10893 }
10894}
10895
c2f47e15 10896/* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments
10897 to the call, and TYPE is its return type.
4ee9c684 10898
c2f47e15 10899 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10900 simplified form of the call as a tree.
10901
10902 The simplified form may be a constant or other expression which
10903 computes the same value, but in a more efficient manner (including
10904 calls to other builtin functions).
10905
10906 The call may contain arguments which need to be evaluated, but
10907 which are not useful to determine the result of the call. In
10908 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10909 COMPOUND_EXPR will be an argument which must be evaluated.
10910 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10911 COMPOUND_EXPR in the chain will contain the tree for the simplified
10912 form of the builtin function call. */
10913
10914static tree
c2f47e15 10915fold_builtin_strpbrk (tree s1, tree s2, tree type)
4ee9c684 10916{
c2f47e15 10917 if (!validate_arg (s1, POINTER_TYPE)
10918 || !validate_arg (s2, POINTER_TYPE))
10919 return NULL_TREE;
4ee9c684 10920 else
10921 {
4ee9c684 10922 tree fn;
10923 const char *p1, *p2;
10924
10925 p2 = c_getstr (s2);
10926 if (p2 == NULL)
c2f47e15 10927 return NULL_TREE;
4ee9c684 10928
10929 p1 = c_getstr (s1);
10930 if (p1 != NULL)
10931 {
10932 const char *r = strpbrk (p1, p2);
daa1d5f5 10933 tree tem;
4ee9c684 10934
10935 if (r == NULL)
779b4c41 10936 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 10937
10938 /* Return an offset into the constant string argument. */
0de36bdb 10939 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1),
10940 s1, size_int (r - p1));
daa1d5f5 10941 return fold_convert (type, tem);
4ee9c684 10942 }
10943
10944 if (p2[0] == '\0')
05abc81b 10945 /* strpbrk(x, "") == NULL.
10946 Evaluate and ignore s1 in case it had side-effects. */
10947 return omit_one_operand (TREE_TYPE (s1), integer_zero_node, s1);
4ee9c684 10948
10949 if (p2[1] != '\0')
c2f47e15 10950 return NULL_TREE; /* Really call strpbrk. */
4ee9c684 10951
10952 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
10953 if (!fn)
c2f47e15 10954 return NULL_TREE;
4ee9c684 10955
10956 /* New argument list transforming strpbrk(s1, s2) to
10957 strchr(s1, s2[0]). */
c2f47e15 10958 return build_call_expr (fn, 2, s1, build_int_cst (NULL_TREE, p2[0]));
4ee9c684 10959 }
10960}
10961
c2f47e15 10962/* Simplify a call to the strcat builtin. DST and SRC are the arguments
10963 to the call.
4ee9c684 10964
c2f47e15 10965 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10966 simplified form of the call as a tree.
10967
10968 The simplified form may be a constant or other expression which
10969 computes the same value, but in a more efficient manner (including
10970 calls to other builtin functions).
10971
10972 The call may contain arguments which need to be evaluated, but
10973 which are not useful to determine the result of the call. In
10974 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10975 COMPOUND_EXPR will be an argument which must be evaluated.
10976 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10977 COMPOUND_EXPR in the chain will contain the tree for the simplified
10978 form of the builtin function call. */
10979
10980static tree
c2f47e15 10981fold_builtin_strcat (tree dst, tree src)
4ee9c684 10982{
c2f47e15 10983 if (!validate_arg (dst, POINTER_TYPE)
10984 || !validate_arg (src, POINTER_TYPE))
10985 return NULL_TREE;
4ee9c684 10986 else
10987 {
4ee9c684 10988 const char *p = c_getstr (src);
10989
10990 /* If the string length is zero, return the dst parameter. */
10991 if (p && *p == '\0')
10992 return dst;
10993
c2f47e15 10994 return NULL_TREE;
4ee9c684 10995 }
10996}
10997
c2f47e15 10998/* Simplify a call to the strncat builtin. DST, SRC, and LEN are the
10999 arguments to the call.
4ee9c684 11000
c2f47e15 11001 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11002 simplified form of the call as a tree.
11003
11004 The simplified form may be a constant or other expression which
11005 computes the same value, but in a more efficient manner (including
11006 calls to other builtin functions).
11007
11008 The call may contain arguments which need to be evaluated, but
11009 which are not useful to determine the result of the call. In
11010 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11011 COMPOUND_EXPR will be an argument which must be evaluated.
11012 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11013 COMPOUND_EXPR in the chain will contain the tree for the simplified
11014 form of the builtin function call. */
11015
11016static tree
c2f47e15 11017fold_builtin_strncat (tree dst, tree src, tree len)
4ee9c684 11018{
c2f47e15 11019 if (!validate_arg (dst, POINTER_TYPE)
11020 || !validate_arg (src, POINTER_TYPE)
11021 || !validate_arg (len, INTEGER_TYPE))
11022 return NULL_TREE;
4ee9c684 11023 else
11024 {
4ee9c684 11025 const char *p = c_getstr (src);
11026
11027 /* If the requested length is zero, or the src parameter string
0a39fd54 11028 length is zero, return the dst parameter. */
4ee9c684 11029 if (integer_zerop (len) || (p && *p == '\0'))
a0c938f0 11030 return omit_two_operands (TREE_TYPE (dst), dst, src, len);
4ee9c684 11031
11032 /* If the requested len is greater than or equal to the string
a0c938f0 11033 length, call strcat. */
4ee9c684 11034 if (TREE_CODE (len) == INTEGER_CST && p
11035 && compare_tree_int (len, strlen (p)) >= 0)
11036 {
4ee9c684 11037 tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
11038
11039 /* If the replacement _DECL isn't initialized, don't do the
11040 transformation. */
11041 if (!fn)
c2f47e15 11042 return NULL_TREE;
4ee9c684 11043
c2f47e15 11044 return build_call_expr (fn, 2, dst, src);
4ee9c684 11045 }
c2f47e15 11046 return NULL_TREE;
4ee9c684 11047 }
11048}
11049
c2f47e15 11050/* Simplify a call to the strspn builtin. S1 and S2 are the arguments
11051 to the call.
4ee9c684 11052
c2f47e15 11053 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11054 simplified form of the call as a tree.
11055
11056 The simplified form may be a constant or other expression which
11057 computes the same value, but in a more efficient manner (including
11058 calls to other builtin functions).
11059
11060 The call may contain arguments which need to be evaluated, but
11061 which are not useful to determine the result of the call. In
11062 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11063 COMPOUND_EXPR will be an argument which must be evaluated.
11064 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11065 COMPOUND_EXPR in the chain will contain the tree for the simplified
11066 form of the builtin function call. */
11067
11068static tree
c2f47e15 11069fold_builtin_strspn (tree s1, tree s2)
4ee9c684 11070{
c2f47e15 11071 if (!validate_arg (s1, POINTER_TYPE)
11072 || !validate_arg (s2, POINTER_TYPE))
11073 return NULL_TREE;
4ee9c684 11074 else
11075 {
4ee9c684 11076 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11077
11078 /* If both arguments are constants, evaluate at compile-time. */
11079 if (p1 && p2)
11080 {
11081 const size_t r = strspn (p1, p2);
11082 return size_int (r);
11083 }
11084
c2f47e15 11085 /* If either argument is "", return NULL_TREE. */
4ee9c684 11086 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9bc9f15f 11087 /* Evaluate and ignore both arguments in case either one has
11088 side-effects. */
11089 return omit_two_operands (integer_type_node, integer_zero_node,
11090 s1, s2);
c2f47e15 11091 return NULL_TREE;
4ee9c684 11092 }
11093}
11094
c2f47e15 11095/* Simplify a call to the strcspn builtin. S1 and S2 are the arguments
11096 to the call.
4ee9c684 11097
c2f47e15 11098 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11099 simplified form of the call as a tree.
11100
11101 The simplified form may be a constant or other expression which
11102 computes the same value, but in a more efficient manner (including
11103 calls to other builtin functions).
11104
11105 The call may contain arguments which need to be evaluated, but
11106 which are not useful to determine the result of the call. In
11107 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11108 COMPOUND_EXPR will be an argument which must be evaluated.
11109 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11110 COMPOUND_EXPR in the chain will contain the tree for the simplified
11111 form of the builtin function call. */
11112
11113static tree
c2f47e15 11114fold_builtin_strcspn (tree s1, tree s2)
4ee9c684 11115{
c2f47e15 11116 if (!validate_arg (s1, POINTER_TYPE)
11117 || !validate_arg (s2, POINTER_TYPE))
11118 return NULL_TREE;
4ee9c684 11119 else
11120 {
4ee9c684 11121 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11122
11123 /* If both arguments are constants, evaluate at compile-time. */
11124 if (p1 && p2)
11125 {
11126 const size_t r = strcspn (p1, p2);
11127 return size_int (r);
11128 }
11129
c2f47e15 11130 /* If the first argument is "", return NULL_TREE. */
4ee9c684 11131 if (p1 && *p1 == '\0')
11132 {
11133 /* Evaluate and ignore argument s2 in case it has
11134 side-effects. */
05abc81b 11135 return omit_one_operand (integer_type_node,
11136 integer_zero_node, s2);
4ee9c684 11137 }
11138
11139 /* If the second argument is "", return __builtin_strlen(s1). */
11140 if (p2 && *p2 == '\0')
11141 {
c2f47e15 11142 tree fn = implicit_built_in_decls[BUILT_IN_STRLEN];
4ee9c684 11143
11144 /* If the replacement _DECL isn't initialized, don't do the
11145 transformation. */
11146 if (!fn)
c2f47e15 11147 return NULL_TREE;
4ee9c684 11148
c2f47e15 11149 return build_call_expr (fn, 1, s1);
4ee9c684 11150 }
c2f47e15 11151 return NULL_TREE;
4ee9c684 11152 }
11153}
11154
c2f47e15 11155/* Fold a call to the fputs builtin. ARG0 and ARG1 are the arguments
11156 to the call. IGNORE is true if the value returned
f0613857 11157 by the builtin will be ignored. UNLOCKED is true is true if this
11158 actually a call to fputs_unlocked. If LEN in non-NULL, it represents
11159 the known length of the string. Return NULL_TREE if no simplification
11160 was possible. */
4ee9c684 11161
11162tree
c2f47e15 11163fold_builtin_fputs (tree arg0, tree arg1, bool ignore, bool unlocked, tree len)
4ee9c684 11164{
6d77ed92 11165 /* If we're using an unlocked function, assume the other unlocked
11166 functions exist explicitly. */
11167 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
4ee9c684 11168 : implicit_built_in_decls[BUILT_IN_FPUTC];
6d77ed92 11169 tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
4ee9c684 11170 : implicit_built_in_decls[BUILT_IN_FWRITE];
11171
c403edd4 11172 /* If the return value is used, don't do the transformation. */
11173 if (!ignore)
c2f47e15 11174 return NULL_TREE;
4ee9c684 11175
11176 /* Verify the arguments in the original call. */
c2f47e15 11177 if (!validate_arg (arg0, POINTER_TYPE)
11178 || !validate_arg (arg1, POINTER_TYPE))
11179 return NULL_TREE;
4ee9c684 11180
f0613857 11181 if (! len)
c2f47e15 11182 len = c_strlen (arg0, 0);
4ee9c684 11183
11184 /* Get the length of the string passed to fputs. If the length
11185 can't be determined, punt. */
11186 if (!len
11187 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 11188 return NULL_TREE;
4ee9c684 11189
11190 switch (compare_tree_int (len, 1))
11191 {
11192 case -1: /* length is 0, delete the call entirely . */
c2f47e15 11193 return omit_one_operand (integer_type_node, integer_zero_node, arg1);;
05abc81b 11194
4ee9c684 11195 case 0: /* length is 1, call fputc. */
11196 {
c2f47e15 11197 const char *p = c_getstr (arg0);
4ee9c684 11198
11199 if (p != NULL)
11200 {
c2f47e15 11201 if (fn_fputc)
11202 return build_call_expr (fn_fputc, 2,
11203 build_int_cst (NULL_TREE, p[0]), arg1);
11204 else
11205 return NULL_TREE;
4ee9c684 11206 }
11207 }
11208 /* FALLTHROUGH */
11209 case 1: /* length is greater than 1, call fwrite. */
11210 {
0bed3869 11211 /* If optimizing for size keep fputs. */
4ee9c684 11212 if (optimize_size)
c2f47e15 11213 return NULL_TREE;
4ee9c684 11214 /* New argument list transforming fputs(string, stream) to
11215 fwrite(string, 1, len, stream). */
c2f47e15 11216 if (fn_fwrite)
11217 return build_call_expr (fn_fwrite, 4, arg0, size_one_node, len, arg1);
11218 else
11219 return NULL_TREE;
4ee9c684 11220 }
11221 default:
64db345d 11222 gcc_unreachable ();
4ee9c684 11223 }
c2f47e15 11224 return NULL_TREE;
4ee9c684 11225}
11226
c2f47e15 11227/* Fold the next_arg or va_start call EXP. Returns true if there was an error
743b0c6a 11228 produced. False otherwise. This is done so that we don't output the error
11229 or warning twice or three times. */
11230bool
c2f47e15 11231fold_builtin_next_arg (tree exp, bool va_start_p)
4ee9c684 11232{
11233 tree fntype = TREE_TYPE (current_function_decl);
c2f47e15 11234 int nargs = call_expr_nargs (exp);
11235 tree arg;
4ee9c684 11236
11237 if (TYPE_ARG_TYPES (fntype) == 0
11238 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
11239 == void_type_node))
743b0c6a 11240 {
11241 error ("%<va_start%> used in function with fixed args");
11242 return true;
11243 }
c2f47e15 11244
11245 if (va_start_p)
79012a9d 11246 {
c2f47e15 11247 if (va_start_p && (nargs != 2))
11248 {
11249 error ("wrong number of arguments to function %<va_start%>");
11250 return true;
11251 }
11252 arg = CALL_EXPR_ARG (exp, 1);
79012a9d 11253 }
11254 /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
11255 when we checked the arguments and if needed issued a warning. */
c2f47e15 11256 else
4ee9c684 11257 {
c2f47e15 11258 if (nargs == 0)
11259 {
11260 /* Evidently an out of date version of <stdarg.h>; can't validate
11261 va_start's second argument, but can still work as intended. */
11262 warning (0, "%<__builtin_next_arg%> called without an argument");
11263 return true;
11264 }
11265 else if (nargs > 1)
a0c938f0 11266 {
c2f47e15 11267 error ("wrong number of arguments to function %<__builtin_next_arg%>");
a0c938f0 11268 return true;
11269 }
c2f47e15 11270 arg = CALL_EXPR_ARG (exp, 0);
11271 }
11272
11273 /* We destructively modify the call to be __builtin_va_start (ap, 0)
11274 or __builtin_next_arg (0) the first time we see it, after checking
11275 the arguments and if needed issuing a warning. */
11276 if (!integer_zerop (arg))
11277 {
11278 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
79012a9d 11279
4ee9c684 11280 /* Strip off all nops for the sake of the comparison. This
11281 is not quite the same as STRIP_NOPS. It does more.
11282 We must also strip off INDIRECT_EXPR for C++ reference
11283 parameters. */
11284 while (TREE_CODE (arg) == NOP_EXPR
11285 || TREE_CODE (arg) == CONVERT_EXPR
11286 || TREE_CODE (arg) == NON_LVALUE_EXPR
11287 || TREE_CODE (arg) == INDIRECT_REF)
11288 arg = TREE_OPERAND (arg, 0);
11289 if (arg != last_parm)
a0c938f0 11290 {
b08cf617 11291 /* FIXME: Sometimes with the tree optimizers we can get the
11292 not the last argument even though the user used the last
11293 argument. We just warn and set the arg to be the last
11294 argument so that we will get wrong-code because of
11295 it. */
c3ceba8e 11296 warning (0, "second parameter of %<va_start%> not last named argument");
743b0c6a 11297 }
79012a9d 11298 /* We want to verify the second parameter just once before the tree
a0c938f0 11299 optimizers are run and then avoid keeping it in the tree,
11300 as otherwise we could warn even for correct code like:
11301 void foo (int i, ...)
11302 { va_list ap; i++; va_start (ap, i); va_end (ap); } */
c2f47e15 11303 if (va_start_p)
11304 CALL_EXPR_ARG (exp, 1) = integer_zero_node;
11305 else
11306 CALL_EXPR_ARG (exp, 0) = integer_zero_node;
743b0c6a 11307 }
11308 return false;
4ee9c684 11309}
11310
11311
c2f47e15 11312/* Simplify a call to the sprintf builtin with arguments DEST, FMT, and ORIG.
11313 ORIG may be null if this is a 2-argument call. We don't attempt to
11314 simplify calls with more than 3 arguments.
4ee9c684 11315
c2f47e15 11316 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11317 simplified form of the call as a tree. If IGNORED is true, it means that
11318 the caller does not use the returned value of the function. */
11319
11320static tree
c2f47e15 11321fold_builtin_sprintf (tree dest, tree fmt, tree orig, int ignored)
4ee9c684 11322{
c2f47e15 11323 tree call, retval;
4ee9c684 11324 const char *fmt_str = NULL;
11325
11326 /* Verify the required arguments in the original call. We deal with two
11327 types of sprintf() calls: 'sprintf (str, fmt)' and
11328 'sprintf (dest, "%s", orig)'. */
c2f47e15 11329 if (!validate_arg (dest, POINTER_TYPE)
11330 || !validate_arg (fmt, POINTER_TYPE))
11331 return NULL_TREE;
11332 if (orig && !validate_arg (orig, POINTER_TYPE))
4ee9c684 11333 return NULL_TREE;
4ee9c684 11334
11335 /* Check whether the format is a literal string constant. */
11336 fmt_str = c_getstr (fmt);
11337 if (fmt_str == NULL)
11338 return NULL_TREE;
11339
11340 call = NULL_TREE;
11341 retval = NULL_TREE;
11342
d4473c84 11343 if (!init_target_chars ())
c2f47e15 11344 return NULL_TREE;
99eabcc1 11345
4ee9c684 11346 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 11347 if (strchr (fmt_str, target_percent) == NULL)
4ee9c684 11348 {
11349 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11350
11351 if (!fn)
11352 return NULL_TREE;
11353
72dfb3f2 11354 /* Don't optimize sprintf (buf, "abc", ptr++). */
c2f47e15 11355 if (orig)
72dfb3f2 11356 return NULL_TREE;
11357
4ee9c684 11358 /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
11359 'format' is known to contain no % formats. */
c2f47e15 11360 call = build_call_expr (fn, 2, dest, fmt);
4ee9c684 11361 if (!ignored)
7016c612 11362 retval = build_int_cst (NULL_TREE, strlen (fmt_str));
4ee9c684 11363 }
11364
11365 /* If the format is "%s", use strcpy if the result isn't used. */
99eabcc1 11366 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
4ee9c684 11367 {
c2f47e15 11368 tree fn;
4ee9c684 11369 fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11370
11371 if (!fn)
11372 return NULL_TREE;
11373
72dfb3f2 11374 /* Don't crash on sprintf (str1, "%s"). */
c2f47e15 11375 if (!orig)
72dfb3f2 11376 return NULL_TREE;
11377
4ee9c684 11378 /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2). */
4ee9c684 11379 if (!ignored)
11380 {
11381 retval = c_strlen (orig, 1);
11382 if (!retval || TREE_CODE (retval) != INTEGER_CST)
11383 return NULL_TREE;
11384 }
c2f47e15 11385 call = build_call_expr (fn, 2, dest, orig);
4ee9c684 11386 }
11387
11388 if (call && retval)
11389 {
e3b560a6 11390 retval = fold_convert
4ee9c684 11391 (TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])),
11392 retval);
05abc81b 11393 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
4ee9c684 11394 }
11395 else
11396 return call;
11397}
0a39fd54 11398
c2f47e15 11399/* Expand a call EXP to __builtin_object_size. */
0a39fd54 11400
11401rtx
11402expand_builtin_object_size (tree exp)
11403{
11404 tree ost;
11405 int object_size_type;
11406 tree fndecl = get_callee_fndecl (exp);
0a39fd54 11407 location_t locus = EXPR_LOCATION (exp);
11408
c2f47e15 11409 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
0a39fd54 11410 {
11411 error ("%Hfirst argument of %D must be a pointer, second integer constant",
11412 &locus, fndecl);
11413 expand_builtin_trap ();
11414 return const0_rtx;
11415 }
11416
c2f47e15 11417 ost = CALL_EXPR_ARG (exp, 1);
0a39fd54 11418 STRIP_NOPS (ost);
11419
11420 if (TREE_CODE (ost) != INTEGER_CST
11421 || tree_int_cst_sgn (ost) < 0
11422 || compare_tree_int (ost, 3) > 0)
11423 {
11424 error ("%Hlast argument of %D is not integer constant between 0 and 3",
11425 &locus, fndecl);
11426 expand_builtin_trap ();
11427 return const0_rtx;
11428 }
11429
11430 object_size_type = tree_low_cst (ost, 0);
11431
11432 return object_size_type < 2 ? constm1_rtx : const0_rtx;
11433}
11434
11435/* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
11436 FCODE is the BUILT_IN_* to use.
c2f47e15 11437 Return NULL_RTX if we failed; the caller should emit a normal call,
0a39fd54 11438 otherwise try to get the result in TARGET, if convenient (and in
11439 mode MODE if that's convenient). */
11440
11441static rtx
11442expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
11443 enum built_in_function fcode)
11444{
0a39fd54 11445 tree dest, src, len, size;
11446
c2f47e15 11447 if (!validate_arglist (exp,
0a39fd54 11448 POINTER_TYPE,
11449 fcode == BUILT_IN_MEMSET_CHK
11450 ? INTEGER_TYPE : POINTER_TYPE,
11451 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
c2f47e15 11452 return NULL_RTX;
0a39fd54 11453
c2f47e15 11454 dest = CALL_EXPR_ARG (exp, 0);
11455 src = CALL_EXPR_ARG (exp, 1);
11456 len = CALL_EXPR_ARG (exp, 2);
11457 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11458
11459 if (! host_integerp (size, 1))
c2f47e15 11460 return NULL_RTX;
0a39fd54 11461
11462 if (host_integerp (len, 1) || integer_all_onesp (size))
11463 {
11464 tree fn;
11465
11466 if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
11467 {
11468 location_t locus = EXPR_LOCATION (exp);
11469 warning (0, "%Hcall to %D will always overflow destination buffer",
11470 &locus, get_callee_fndecl (exp));
c2f47e15 11471 return NULL_RTX;
0a39fd54 11472 }
11473
0a39fd54 11474 fn = NULL_TREE;
11475 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
11476 mem{cpy,pcpy,move,set} is available. */
11477 switch (fcode)
11478 {
11479 case BUILT_IN_MEMCPY_CHK:
11480 fn = built_in_decls[BUILT_IN_MEMCPY];
11481 break;
11482 case BUILT_IN_MEMPCPY_CHK:
11483 fn = built_in_decls[BUILT_IN_MEMPCPY];
11484 break;
11485 case BUILT_IN_MEMMOVE_CHK:
11486 fn = built_in_decls[BUILT_IN_MEMMOVE];
11487 break;
11488 case BUILT_IN_MEMSET_CHK:
11489 fn = built_in_decls[BUILT_IN_MEMSET];
11490 break;
11491 default:
11492 break;
11493 }
11494
11495 if (! fn)
c2f47e15 11496 return NULL_RTX;
0a39fd54 11497
c2f47e15 11498 fn = build_call_expr (fn, 3, dest, src, len);
0a39fd54 11499 if (TREE_CODE (fn) == CALL_EXPR)
11500 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
11501 return expand_expr (fn, target, mode, EXPAND_NORMAL);
11502 }
11503 else if (fcode == BUILT_IN_MEMSET_CHK)
c2f47e15 11504 return NULL_RTX;
0a39fd54 11505 else
11506 {
11507 unsigned int dest_align
11508 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
11509
11510 /* If DEST is not a pointer type, call the normal function. */
11511 if (dest_align == 0)
c2f47e15 11512 return NULL_RTX;
0a39fd54 11513
11514 /* If SRC and DEST are the same (and not volatile), do nothing. */
11515 if (operand_equal_p (src, dest, 0))
11516 {
11517 tree expr;
11518
11519 if (fcode != BUILT_IN_MEMPCPY_CHK)
11520 {
11521 /* Evaluate and ignore LEN in case it has side-effects. */
11522 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
11523 return expand_expr (dest, target, mode, EXPAND_NORMAL);
11524 }
11525
0de36bdb 11526 expr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
0a39fd54 11527 return expand_expr (expr, target, mode, EXPAND_NORMAL);
11528 }
11529
11530 /* __memmove_chk special case. */
11531 if (fcode == BUILT_IN_MEMMOVE_CHK)
11532 {
11533 unsigned int src_align
11534 = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
11535
11536 if (src_align == 0)
c2f47e15 11537 return NULL_RTX;
0a39fd54 11538
11539 /* If src is categorized for a readonly section we can use
11540 normal __memcpy_chk. */
11541 if (readonly_data_expr (src))
11542 {
11543 tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
11544 if (!fn)
c2f47e15 11545 return NULL_RTX;
11546 fn = build_call_expr (fn, 4, dest, src, len, size);
0a39fd54 11547 if (TREE_CODE (fn) == CALL_EXPR)
11548 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
11549 return expand_expr (fn, target, mode, EXPAND_NORMAL);
11550 }
11551 }
c2f47e15 11552 return NULL_RTX;
0a39fd54 11553 }
11554}
11555
11556/* Emit warning if a buffer overflow is detected at compile time. */
11557
11558static void
11559maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
11560{
c2f47e15 11561 int is_strlen = 0;
0a39fd54 11562 tree len, size;
11563 location_t locus;
11564
11565 switch (fcode)
11566 {
11567 case BUILT_IN_STRCPY_CHK:
11568 case BUILT_IN_STPCPY_CHK:
11569 /* For __strcat_chk the warning will be emitted only if overflowing
11570 by at least strlen (dest) + 1 bytes. */
11571 case BUILT_IN_STRCAT_CHK:
c2f47e15 11572 len = CALL_EXPR_ARG (exp, 1);
11573 size = CALL_EXPR_ARG (exp, 2);
0a39fd54 11574 is_strlen = 1;
11575 break;
b356dfef 11576 case BUILT_IN_STRNCAT_CHK:
0a39fd54 11577 case BUILT_IN_STRNCPY_CHK:
c2f47e15 11578 len = CALL_EXPR_ARG (exp, 2);
11579 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11580 break;
11581 case BUILT_IN_SNPRINTF_CHK:
11582 case BUILT_IN_VSNPRINTF_CHK:
c2f47e15 11583 len = CALL_EXPR_ARG (exp, 1);
11584 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11585 break;
11586 default:
11587 gcc_unreachable ();
11588 }
11589
0a39fd54 11590 if (!len || !size)
11591 return;
11592
0a39fd54 11593 if (! host_integerp (size, 1) || integer_all_onesp (size))
11594 return;
11595
11596 if (is_strlen)
11597 {
11598 len = c_strlen (len, 1);
11599 if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
11600 return;
11601 }
b356dfef 11602 else if (fcode == BUILT_IN_STRNCAT_CHK)
11603 {
c2f47e15 11604 tree src = CALL_EXPR_ARG (exp, 1);
b356dfef 11605 if (! src || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
11606 return;
11607 src = c_strlen (src, 1);
11608 if (! src || ! host_integerp (src, 1))
11609 {
11610 locus = EXPR_LOCATION (exp);
11611 warning (0, "%Hcall to %D might overflow destination buffer",
11612 &locus, get_callee_fndecl (exp));
11613 return;
11614 }
11615 else if (tree_int_cst_lt (src, size))
11616 return;
11617 }
0a39fd54 11618 else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
11619 return;
11620
11621 locus = EXPR_LOCATION (exp);
11622 warning (0, "%Hcall to %D will always overflow destination buffer",
11623 &locus, get_callee_fndecl (exp));
11624}
11625
11626/* Emit warning if a buffer overflow is detected at compile time
11627 in __sprintf_chk/__vsprintf_chk calls. */
11628
11629static void
11630maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
11631{
0a39fd54 11632 tree dest, size, len, fmt, flag;
11633 const char *fmt_str;
c2f47e15 11634 int nargs = call_expr_nargs (exp);
0a39fd54 11635
11636 /* Verify the required arguments in the original call. */
c2f47e15 11637
11638 if (nargs < 4)
0a39fd54 11639 return;
c2f47e15 11640 dest = CALL_EXPR_ARG (exp, 0);
11641 flag = CALL_EXPR_ARG (exp, 1);
11642 size = CALL_EXPR_ARG (exp, 2);
11643 fmt = CALL_EXPR_ARG (exp, 3);
0a39fd54 11644
11645 if (! host_integerp (size, 1) || integer_all_onesp (size))
11646 return;
11647
11648 /* Check whether the format is a literal string constant. */
11649 fmt_str = c_getstr (fmt);
11650 if (fmt_str == NULL)
11651 return;
11652
d4473c84 11653 if (!init_target_chars ())
99eabcc1 11654 return;
11655
0a39fd54 11656 /* If the format doesn't contain % args or %%, we know its size. */
99eabcc1 11657 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 11658 len = build_int_cstu (size_type_node, strlen (fmt_str));
11659 /* If the format is "%s" and first ... argument is a string literal,
11660 we know it too. */
c2f47e15 11661 else if (fcode == BUILT_IN_SPRINTF_CHK
11662 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 11663 {
11664 tree arg;
11665
c2f47e15 11666 if (nargs < 5)
0a39fd54 11667 return;
c2f47e15 11668 arg = CALL_EXPR_ARG (exp, 4);
0a39fd54 11669 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
11670 return;
11671
11672 len = c_strlen (arg, 1);
11673 if (!len || ! host_integerp (len, 1))
11674 return;
11675 }
11676 else
11677 return;
11678
11679 if (! tree_int_cst_lt (len, size))
11680 {
11681 location_t locus = EXPR_LOCATION (exp);
11682 warning (0, "%Hcall to %D will always overflow destination buffer",
11683 &locus, get_callee_fndecl (exp));
11684 }
11685}
11686
c2f47e15 11687/* Fold a call to __builtin_object_size with arguments PTR and OST,
11688 if possible. */
0a39fd54 11689
11690tree
c2f47e15 11691fold_builtin_object_size (tree ptr, tree ost)
0a39fd54 11692{
c2f47e15 11693 tree ret = NULL_TREE;
0a39fd54 11694 int object_size_type;
11695
c2f47e15 11696 if (!validate_arg (ptr, POINTER_TYPE)
11697 || !validate_arg (ost, INTEGER_TYPE))
11698 return NULL_TREE;
0a39fd54 11699
0a39fd54 11700 STRIP_NOPS (ost);
11701
11702 if (TREE_CODE (ost) != INTEGER_CST
11703 || tree_int_cst_sgn (ost) < 0
11704 || compare_tree_int (ost, 3) > 0)
c2f47e15 11705 return NULL_TREE;
0a39fd54 11706
11707 object_size_type = tree_low_cst (ost, 0);
11708
11709 /* __builtin_object_size doesn't evaluate side-effects in its arguments;
11710 if there are any side-effects, it returns (size_t) -1 for types 0 and 1
11711 and (size_t) 0 for types 2 and 3. */
11712 if (TREE_SIDE_EFFECTS (ptr))
697bbc3f 11713 return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
0a39fd54 11714
11715 if (TREE_CODE (ptr) == ADDR_EXPR)
11716 ret = build_int_cstu (size_type_node,
697bbc3f 11717 compute_builtin_object_size (ptr, object_size_type));
0a39fd54 11718
11719 else if (TREE_CODE (ptr) == SSA_NAME)
11720 {
11721 unsigned HOST_WIDE_INT bytes;
11722
11723 /* If object size is not known yet, delay folding until
11724 later. Maybe subsequent passes will help determining
11725 it. */
11726 bytes = compute_builtin_object_size (ptr, object_size_type);
11727 if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2
11728 ? -1 : 0))
11729 ret = build_int_cstu (size_type_node, bytes);
11730 }
11731
11732 if (ret)
11733 {
697bbc3f 11734 unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (ret);
11735 HOST_WIDE_INT high = TREE_INT_CST_HIGH (ret);
11736 if (fit_double_type (low, high, &low, &high, TREE_TYPE (ret)))
11737 ret = NULL_TREE;
0a39fd54 11738 }
11739
11740 return ret;
11741}
11742
11743/* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
c2f47e15 11744 DEST, SRC, LEN, and SIZE are the arguments to the call.
0a39fd54 11745 IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_*
11746 code of the builtin. If MAXLEN is not NULL, it is maximum length
11747 passed as third argument. */
11748
11749tree
c2f47e15 11750fold_builtin_memory_chk (tree fndecl,
11751 tree dest, tree src, tree len, tree size,
11752 tree maxlen, bool ignore,
0a39fd54 11753 enum built_in_function fcode)
11754{
c2f47e15 11755 tree fn;
0a39fd54 11756
c2f47e15 11757 if (!validate_arg (dest, POINTER_TYPE)
11758 || !validate_arg (src,
11759 (fcode == BUILT_IN_MEMSET_CHK
11760 ? INTEGER_TYPE : POINTER_TYPE))
11761 || !validate_arg (len, INTEGER_TYPE)
11762 || !validate_arg (size, INTEGER_TYPE))
11763 return NULL_TREE;
0a39fd54 11764
11765 /* If SRC and DEST are the same (and not volatile), return DEST
11766 (resp. DEST+LEN for __mempcpy_chk). */
11767 if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
11768 {
11769 if (fcode != BUILT_IN_MEMPCPY_CHK)
11770 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
11771 else
11772 {
0de36bdb 11773 tree temp = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
0a39fd54 11774 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), temp);
11775 }
11776 }
11777
11778 if (! host_integerp (size, 1))
c2f47e15 11779 return NULL_TREE;
0a39fd54 11780
11781 if (! integer_all_onesp (size))
11782 {
11783 if (! host_integerp (len, 1))
11784 {
11785 /* If LEN is not constant, try MAXLEN too.
11786 For MAXLEN only allow optimizing into non-_ocs function
11787 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
11788 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
11789 {
11790 if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
11791 {
11792 /* (void) __mempcpy_chk () can be optimized into
11793 (void) __memcpy_chk (). */
11794 fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
11795 if (!fn)
c2f47e15 11796 return NULL_TREE;
0a39fd54 11797
c2f47e15 11798 return build_call_expr (fn, 4, dest, src, len, size);
0a39fd54 11799 }
c2f47e15 11800 return NULL_TREE;
0a39fd54 11801 }
0a39fd54 11802 }
ad89623c 11803 else
11804 maxlen = len;
0a39fd54 11805
ad89623c 11806 if (tree_int_cst_lt (size, maxlen))
c2f47e15 11807 return NULL_TREE;
0a39fd54 11808 }
11809
0a39fd54 11810 fn = NULL_TREE;
11811 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
11812 mem{cpy,pcpy,move,set} is available. */
11813 switch (fcode)
11814 {
11815 case BUILT_IN_MEMCPY_CHK:
11816 fn = built_in_decls[BUILT_IN_MEMCPY];
11817 break;
11818 case BUILT_IN_MEMPCPY_CHK:
11819 fn = built_in_decls[BUILT_IN_MEMPCPY];
11820 break;
11821 case BUILT_IN_MEMMOVE_CHK:
11822 fn = built_in_decls[BUILT_IN_MEMMOVE];
11823 break;
11824 case BUILT_IN_MEMSET_CHK:
11825 fn = built_in_decls[BUILT_IN_MEMSET];
11826 break;
11827 default:
11828 break;
11829 }
11830
11831 if (!fn)
c2f47e15 11832 return NULL_TREE;
0a39fd54 11833
c2f47e15 11834 return build_call_expr (fn, 3, dest, src, len);
0a39fd54 11835}
11836
11837/* Fold a call to the __st[rp]cpy_chk builtin.
c2f47e15 11838 DEST, SRC, and SIZE are the arguments to the call.
11839 IGNORE is true if return value can be ignored. FCODE is the BUILT_IN_*
0a39fd54 11840 code of the builtin. If MAXLEN is not NULL, it is maximum length of
11841 strings passed as second argument. */
11842
11843tree
c2f47e15 11844fold_builtin_stxcpy_chk (tree fndecl, tree dest, tree src, tree size,
11845 tree maxlen, bool ignore,
0a39fd54 11846 enum built_in_function fcode)
11847{
c2f47e15 11848 tree len, fn;
0a39fd54 11849
c2f47e15 11850 if (!validate_arg (dest, POINTER_TYPE)
11851 || !validate_arg (src, POINTER_TYPE)
11852 || !validate_arg (size, INTEGER_TYPE))
11853 return NULL_TREE;
0a39fd54 11854
11855 /* If SRC and DEST are the same (and not volatile), return DEST. */
11856 if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
11857 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
a0c938f0 11858
0a39fd54 11859 if (! host_integerp (size, 1))
c2f47e15 11860 return NULL_TREE;
0a39fd54 11861
11862 if (! integer_all_onesp (size))
11863 {
11864 len = c_strlen (src, 1);
11865 if (! len || ! host_integerp (len, 1))
11866 {
11867 /* If LEN is not constant, try MAXLEN too.
11868 For MAXLEN only allow optimizing into non-_ocs function
11869 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
11870 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
11871 {
11872 if (fcode == BUILT_IN_STPCPY_CHK)
11873 {
11874 if (! ignore)
c2f47e15 11875 return NULL_TREE;
0a39fd54 11876
11877 /* If return value of __stpcpy_chk is ignored,
11878 optimize into __strcpy_chk. */
11879 fn = built_in_decls[BUILT_IN_STRCPY_CHK];
11880 if (!fn)
c2f47e15 11881 return NULL_TREE;
0a39fd54 11882
c2f47e15 11883 return build_call_expr (fn, 3, dest, src, size);
0a39fd54 11884 }
11885
11886 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 11887 return NULL_TREE;
0a39fd54 11888
11889 /* If c_strlen returned something, but not a constant,
11890 transform __strcpy_chk into __memcpy_chk. */
11891 fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
11892 if (!fn)
c2f47e15 11893 return NULL_TREE;
0a39fd54 11894
11895 len = size_binop (PLUS_EXPR, len, ssize_int (1));
0a39fd54 11896 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
c2f47e15 11897 build_call_expr (fn, 4,
11898 dest, src, len, size));
0a39fd54 11899 }
0a39fd54 11900 }
ad89623c 11901 else
11902 maxlen = len;
11903
11904 if (! tree_int_cst_lt (maxlen, size))
c2f47e15 11905 return NULL_TREE;
0a39fd54 11906 }
11907
0a39fd54 11908 /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available. */
11909 fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK
11910 ? BUILT_IN_STPCPY : BUILT_IN_STRCPY];
11911 if (!fn)
c2f47e15 11912 return NULL_TREE;
0a39fd54 11913
c2f47e15 11914 return build_call_expr (fn, 2, dest, src);
0a39fd54 11915}
11916
c2f47e15 11917/* Fold a call to the __strncpy_chk builtin. DEST, SRC, LEN, and SIZE
11918 are the arguments to the call. If MAXLEN is not NULL, it is maximum
11919 length passed as third argument. */
0a39fd54 11920
11921tree
c2f47e15 11922fold_builtin_strncpy_chk (tree dest, tree src, tree len, tree size,
11923 tree maxlen)
0a39fd54 11924{
c2f47e15 11925 tree fn;
0a39fd54 11926
c2f47e15 11927 if (!validate_arg (dest, POINTER_TYPE)
11928 || !validate_arg (src, POINTER_TYPE)
11929 || !validate_arg (len, INTEGER_TYPE)
11930 || !validate_arg (size, INTEGER_TYPE))
11931 return NULL_TREE;
0a39fd54 11932
11933 if (! host_integerp (size, 1))
c2f47e15 11934 return NULL_TREE;
0a39fd54 11935
11936 if (! integer_all_onesp (size))
11937 {
11938 if (! host_integerp (len, 1))
11939 {
11940 /* If LEN is not constant, try MAXLEN too.
11941 For MAXLEN only allow optimizing into non-_ocs function
11942 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
11943 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 11944 return NULL_TREE;
0a39fd54 11945 }
ad89623c 11946 else
11947 maxlen = len;
0a39fd54 11948
ad89623c 11949 if (tree_int_cst_lt (size, maxlen))
c2f47e15 11950 return NULL_TREE;
0a39fd54 11951 }
11952
0a39fd54 11953 /* If __builtin_strncpy_chk is used, assume strncpy is available. */
11954 fn = built_in_decls[BUILT_IN_STRNCPY];
11955 if (!fn)
c2f47e15 11956 return NULL_TREE;
0a39fd54 11957
c2f47e15 11958 return build_call_expr (fn, 3, dest, src, len);
0a39fd54 11959}
11960
c2f47e15 11961/* Fold a call to the __strcat_chk builtin FNDECL. DEST, SRC, and SIZE
11962 are the arguments to the call. */
0a39fd54 11963
11964static tree
c2f47e15 11965fold_builtin_strcat_chk (tree fndecl, tree dest, tree src, tree size)
0a39fd54 11966{
c2f47e15 11967 tree fn;
0a39fd54 11968 const char *p;
11969
c2f47e15 11970 if (!validate_arg (dest, POINTER_TYPE)
11971 || !validate_arg (src, POINTER_TYPE)
11972 || !validate_arg (size, INTEGER_TYPE))
11973 return NULL_TREE;
0a39fd54 11974
11975 p = c_getstr (src);
11976 /* If the SRC parameter is "", return DEST. */
11977 if (p && *p == '\0')
11978 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
11979
11980 if (! host_integerp (size, 1) || ! integer_all_onesp (size))
c2f47e15 11981 return NULL_TREE;
0a39fd54 11982
11983 /* If __builtin_strcat_chk is used, assume strcat is available. */
11984 fn = built_in_decls[BUILT_IN_STRCAT];
11985 if (!fn)
c2f47e15 11986 return NULL_TREE;
0a39fd54 11987
c2f47e15 11988 return build_call_expr (fn, 2, dest, src);
0a39fd54 11989}
11990
c2f47e15 11991/* Fold a call to the __strncat_chk builtin with arguments DEST, SRC,
11992 LEN, and SIZE. */
0a39fd54 11993
11994static tree
c2f47e15 11995fold_builtin_strncat_chk (tree fndecl,
11996 tree dest, tree src, tree len, tree size)
0a39fd54 11997{
c2f47e15 11998 tree fn;
0a39fd54 11999 const char *p;
12000
c2f47e15 12001 if (!validate_arg (dest, POINTER_TYPE)
12002 || !validate_arg (src, POINTER_TYPE)
12003 || !validate_arg (size, INTEGER_TYPE)
12004 || !validate_arg (size, INTEGER_TYPE))
12005 return NULL_TREE;
0a39fd54 12006
12007 p = c_getstr (src);
12008 /* If the SRC parameter is "" or if LEN is 0, return DEST. */
12009 if (p && *p == '\0')
12010 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
12011 else if (integer_zerop (len))
12012 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
12013
12014 if (! host_integerp (size, 1))
c2f47e15 12015 return NULL_TREE;
0a39fd54 12016
12017 if (! integer_all_onesp (size))
12018 {
12019 tree src_len = c_strlen (src, 1);
12020 if (src_len
12021 && host_integerp (src_len, 1)
12022 && host_integerp (len, 1)
12023 && ! tree_int_cst_lt (len, src_len))
12024 {
12025 /* If LEN >= strlen (SRC), optimize into __strcat_chk. */
12026 fn = built_in_decls[BUILT_IN_STRCAT_CHK];
12027 if (!fn)
c2f47e15 12028 return NULL_TREE;
0a39fd54 12029
c2f47e15 12030 return build_call_expr (fn, 3, dest, src, size);
0a39fd54 12031 }
c2f47e15 12032 return NULL_TREE;
0a39fd54 12033 }
12034
0a39fd54 12035 /* If __builtin_strncat_chk is used, assume strncat is available. */
12036 fn = built_in_decls[BUILT_IN_STRNCAT];
12037 if (!fn)
c2f47e15 12038 return NULL_TREE;
0a39fd54 12039
c2f47e15 12040 return build_call_expr (fn, 3, dest, src, len);
0a39fd54 12041}
12042
c2f47e15 12043/* Fold a call EXP to __{,v}sprintf_chk. Return NULL_TREE if
0a39fd54 12044 a normal call should be emitted rather than expanding the function
12045 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
12046
12047static tree
c2f47e15 12048fold_builtin_sprintf_chk (tree exp, enum built_in_function fcode)
0a39fd54 12049{
12050 tree dest, size, len, fn, fmt, flag;
12051 const char *fmt_str;
c2f47e15 12052 int nargs = call_expr_nargs (exp);
0a39fd54 12053
12054 /* Verify the required arguments in the original call. */
c2f47e15 12055 if (nargs < 4)
12056 return NULL_TREE;
12057 dest = CALL_EXPR_ARG (exp, 0);
12058 if (!validate_arg (dest, POINTER_TYPE))
12059 return NULL_TREE;
12060 flag = CALL_EXPR_ARG (exp, 1);
12061 if (!validate_arg (flag, INTEGER_TYPE))
12062 return NULL_TREE;
12063 size = CALL_EXPR_ARG (exp, 2);
12064 if (!validate_arg (size, INTEGER_TYPE))
12065 return NULL_TREE;
12066 fmt = CALL_EXPR_ARG (exp, 3);
12067 if (!validate_arg (fmt, POINTER_TYPE))
12068 return NULL_TREE;
0a39fd54 12069
12070 if (! host_integerp (size, 1))
c2f47e15 12071 return NULL_TREE;
0a39fd54 12072
12073 len = NULL_TREE;
12074
d4473c84 12075 if (!init_target_chars ())
c2f47e15 12076 return NULL_TREE;
99eabcc1 12077
0a39fd54 12078 /* Check whether the format is a literal string constant. */
12079 fmt_str = c_getstr (fmt);
12080 if (fmt_str != NULL)
12081 {
12082 /* If the format doesn't contain % args or %%, we know the size. */
99eabcc1 12083 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 12084 {
c2f47e15 12085 if (fcode != BUILT_IN_SPRINTF_CHK || nargs == 4)
0a39fd54 12086 len = build_int_cstu (size_type_node, strlen (fmt_str));
12087 }
12088 /* If the format is "%s" and first ... argument is a string literal,
12089 we know the size too. */
c2f47e15 12090 else if (fcode == BUILT_IN_SPRINTF_CHK
12091 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12092 {
12093 tree arg;
12094
c2f47e15 12095 if (nargs == 5)
0a39fd54 12096 {
c2f47e15 12097 arg = CALL_EXPR_ARG (exp, 4);
12098 if (validate_arg (arg, POINTER_TYPE))
0a39fd54 12099 {
12100 len = c_strlen (arg, 1);
12101 if (! len || ! host_integerp (len, 1))
12102 len = NULL_TREE;
12103 }
12104 }
12105 }
12106 }
12107
12108 if (! integer_all_onesp (size))
12109 {
12110 if (! len || ! tree_int_cst_lt (len, size))
c2f47e15 12111 return NULL_TREE;
0a39fd54 12112 }
12113
12114 /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
12115 or if format doesn't contain % chars or is "%s". */
12116 if (! integer_zerop (flag))
12117 {
12118 if (fmt_str == NULL)
c2f47e15 12119 return NULL_TREE;
12120 if (strchr (fmt_str, target_percent) != NULL
12121 && strcmp (fmt_str, target_percent_s))
12122 return NULL_TREE;
0a39fd54 12123 }
12124
0a39fd54 12125 /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
12126 fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
12127 ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
12128 if (!fn)
c2f47e15 12129 return NULL_TREE;
0a39fd54 12130
c2f47e15 12131 return rewrite_call_expr (exp, 4, fn, 2, dest, fmt);
0a39fd54 12132}
12133
c2f47e15 12134/* Fold a call EXP to {,v}snprintf. Return NULL_TREE if
0a39fd54 12135 a normal call should be emitted rather than expanding the function
12136 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
12137 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
12138 passed as second argument. */
12139
12140tree
c2f47e15 12141fold_builtin_snprintf_chk (tree exp, tree maxlen,
0a39fd54 12142 enum built_in_function fcode)
12143{
12144 tree dest, size, len, fn, fmt, flag;
12145 const char *fmt_str;
12146
12147 /* Verify the required arguments in the original call. */
c2f47e15 12148 if (call_expr_nargs (exp) < 5)
12149 return NULL_TREE;
12150 dest = CALL_EXPR_ARG (exp, 0);
12151 if (!validate_arg (dest, POINTER_TYPE))
12152 return NULL_TREE;
12153 len = CALL_EXPR_ARG (exp, 1);
12154 if (!validate_arg (len, INTEGER_TYPE))
12155 return NULL_TREE;
12156 flag = CALL_EXPR_ARG (exp, 2);
12157 if (!validate_arg (flag, INTEGER_TYPE))
12158 return NULL_TREE;
12159 size = CALL_EXPR_ARG (exp, 3);
12160 if (!validate_arg (size, INTEGER_TYPE))
12161 return NULL_TREE;
12162 fmt = CALL_EXPR_ARG (exp, 4);
12163 if (!validate_arg (fmt, POINTER_TYPE))
12164 return NULL_TREE;
0a39fd54 12165
12166 if (! host_integerp (size, 1))
c2f47e15 12167 return NULL_TREE;
0a39fd54 12168
12169 if (! integer_all_onesp (size))
12170 {
12171 if (! host_integerp (len, 1))
12172 {
12173 /* If LEN is not constant, try MAXLEN too.
12174 For MAXLEN only allow optimizing into non-_ocs function
12175 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12176 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 12177 return NULL_TREE;
0a39fd54 12178 }
ad89623c 12179 else
12180 maxlen = len;
0a39fd54 12181
ad89623c 12182 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12183 return NULL_TREE;
0a39fd54 12184 }
12185
d4473c84 12186 if (!init_target_chars ())
c2f47e15 12187 return NULL_TREE;
99eabcc1 12188
0a39fd54 12189 /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
12190 or if format doesn't contain % chars or is "%s". */
12191 if (! integer_zerop (flag))
12192 {
12193 fmt_str = c_getstr (fmt);
12194 if (fmt_str == NULL)
c2f47e15 12195 return NULL_TREE;
12196 if (strchr (fmt_str, target_percent) != NULL
12197 && strcmp (fmt_str, target_percent_s))
12198 return NULL_TREE;
0a39fd54 12199 }
12200
0a39fd54 12201 /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
12202 available. */
12203 fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
12204 ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
12205 if (!fn)
c2f47e15 12206 return NULL_TREE;
0a39fd54 12207
c2f47e15 12208 return rewrite_call_expr (exp, 5, fn, 3, dest, len, fmt);
0a39fd54 12209}
12210
12211/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 12212 FMT and ARG are the arguments to the call; we don't fold cases with
12213 more than 2 arguments, and ARG may be null if this is a 1-argument case.
0a39fd54 12214
c2f47e15 12215 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 12216 simplified form of the call as a tree. FCODE is the BUILT_IN_*
12217 code of the function to be simplified. */
12218
12219static tree
c2f47e15 12220fold_builtin_printf (tree fndecl, tree fmt, tree arg, bool ignore,
0a39fd54 12221 enum built_in_function fcode)
12222{
c2f47e15 12223 tree fn_putchar, fn_puts, newarg, call = NULL_TREE;
0a39fd54 12224 const char *fmt_str = NULL;
12225
12226 /* If the return value is used, don't do the transformation. */
12227 if (! ignore)
c2f47e15 12228 return NULL_TREE;
0a39fd54 12229
12230 /* Verify the required arguments in the original call. */
c2f47e15 12231 if (!validate_arg (fmt, POINTER_TYPE))
12232 return NULL_TREE;
0a39fd54 12233
12234 /* Check whether the format is a literal string constant. */
12235 fmt_str = c_getstr (fmt);
12236 if (fmt_str == NULL)
12237 return NULL_TREE;
12238
12239 if (fcode == BUILT_IN_PRINTF_UNLOCKED)
12240 {
6d77ed92 12241 /* If we're using an unlocked function, assume the other
12242 unlocked functions exist explicitly. */
12243 fn_putchar = built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED];
12244 fn_puts = built_in_decls[BUILT_IN_PUTS_UNLOCKED];
0a39fd54 12245 }
12246 else
12247 {
12248 fn_putchar = implicit_built_in_decls[BUILT_IN_PUTCHAR];
12249 fn_puts = implicit_built_in_decls[BUILT_IN_PUTS];
12250 }
12251
d4473c84 12252 if (!init_target_chars ())
c2f47e15 12253 return NULL_TREE;
a0c938f0 12254
c2f47e15 12255 if (strcmp (fmt_str, target_percent_s) == 0
12256 || strchr (fmt_str, target_percent) == NULL)
0a39fd54 12257 {
12258 const char *str;
12259
99eabcc1 12260 if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12261 {
12262 if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 12263 return NULL_TREE;
0a39fd54 12264
c2f47e15 12265 if (!arg || !validate_arg (arg, POINTER_TYPE))
12266 return NULL_TREE;
0a39fd54 12267
c2f47e15 12268 str = c_getstr (arg);
0a39fd54 12269 if (str == NULL)
c2f47e15 12270 return NULL_TREE;
0a39fd54 12271 }
12272 else
12273 {
12274 /* The format specifier doesn't contain any '%' characters. */
12275 if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
c2f47e15 12276 && arg)
12277 return NULL_TREE;
0a39fd54 12278 str = fmt_str;
12279 }
12280
12281 /* If the string was "", printf does nothing. */
12282 if (str[0] == '\0')
12283 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
12284
12285 /* If the string has length of 1, call putchar. */
12286 if (str[1] == '\0')
12287 {
12288 /* Given printf("c"), (where c is any one character,)
12289 convert "c"[0] to an int and pass that to the replacement
12290 function. */
c2f47e15 12291 newarg = build_int_cst (NULL_TREE, str[0]);
12292 if (fn_putchar)
12293 call = build_call_expr (fn_putchar, 1, newarg);
0a39fd54 12294 }
12295 else
12296 {
12297 /* If the string was "string\n", call puts("string"). */
12298 size_t len = strlen (str);
99eabcc1 12299 if ((unsigned char)str[len - 1] == target_newline)
0a39fd54 12300 {
12301 /* Create a NUL-terminated string that's one char shorter
12302 than the original, stripping off the trailing '\n'. */
12303 char *newstr = alloca (len);
12304 memcpy (newstr, str, len - 1);
12305 newstr[len - 1] = 0;
12306
c2f47e15 12307 newarg = build_string_literal (len, newstr);
12308 if (fn_puts)
12309 call = build_call_expr (fn_puts, 1, newarg);
0a39fd54 12310 }
12311 else
12312 /* We'd like to arrange to call fputs(string,stdout) here,
12313 but we need stdout and don't have a way to get it yet. */
c2f47e15 12314 return NULL_TREE;
0a39fd54 12315 }
12316 }
12317
12318 /* The other optimizations can be done only on the non-va_list variants. */
12319 else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 12320 return NULL_TREE;
0a39fd54 12321
12322 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
99eabcc1 12323 else if (strcmp (fmt_str, target_percent_s_newline) == 0)
0a39fd54 12324 {
c2f47e15 12325 if (!arg || !validate_arg (arg, POINTER_TYPE))
12326 return NULL_TREE;
12327 if (fn_puts)
12328 call = build_call_expr (fn_puts, 1, arg);
0a39fd54 12329 }
12330
12331 /* If the format specifier was "%c", call __builtin_putchar(arg). */
99eabcc1 12332 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 12333 {
c2f47e15 12334 if (!arg || !validate_arg (arg, INTEGER_TYPE))
12335 return NULL_TREE;
12336 if (fn_putchar)
12337 call = build_call_expr (fn_putchar, 1, arg);
0a39fd54 12338 }
12339
c2f47e15 12340 if (!call)
12341 return NULL_TREE;
0a39fd54 12342
0a39fd54 12343 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
12344}
12345
12346/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 12347 FP, FMT, and ARG are the arguments to the call. We don't fold calls with
12348 more than 3 arguments, and ARG may be null in the 2-argument case.
0a39fd54 12349
c2f47e15 12350 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 12351 simplified form of the call as a tree. FCODE is the BUILT_IN_*
12352 code of the function to be simplified. */
12353
12354static tree
c2f47e15 12355fold_builtin_fprintf (tree fndecl, tree fp, tree fmt, tree arg, bool ignore,
0a39fd54 12356 enum built_in_function fcode)
12357{
c2f47e15 12358 tree fn_fputc, fn_fputs, call = NULL_TREE;
0a39fd54 12359 const char *fmt_str = NULL;
12360
12361 /* If the return value is used, don't do the transformation. */
12362 if (! ignore)
c2f47e15 12363 return NULL_TREE;
0a39fd54 12364
12365 /* Verify the required arguments in the original call. */
c2f47e15 12366 if (!validate_arg (fp, POINTER_TYPE))
12367 return NULL_TREE;
12368 if (!validate_arg (fmt, POINTER_TYPE))
12369 return NULL_TREE;
0a39fd54 12370
12371 /* Check whether the format is a literal string constant. */
12372 fmt_str = c_getstr (fmt);
12373 if (fmt_str == NULL)
12374 return NULL_TREE;
12375
12376 if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
12377 {
6d77ed92 12378 /* If we're using an unlocked function, assume the other
12379 unlocked functions exist explicitly. */
12380 fn_fputc = built_in_decls[BUILT_IN_FPUTC_UNLOCKED];
12381 fn_fputs = built_in_decls[BUILT_IN_FPUTS_UNLOCKED];
0a39fd54 12382 }
12383 else
12384 {
12385 fn_fputc = implicit_built_in_decls[BUILT_IN_FPUTC];
12386 fn_fputs = implicit_built_in_decls[BUILT_IN_FPUTS];
12387 }
12388
d4473c84 12389 if (!init_target_chars ())
c2f47e15 12390 return NULL_TREE;
a0c938f0 12391
0a39fd54 12392 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 12393 if (strchr (fmt_str, target_percent) == NULL)
0a39fd54 12394 {
12395 if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
c2f47e15 12396 && arg)
12397 return NULL_TREE;
0a39fd54 12398
12399 /* If the format specifier was "", fprintf does nothing. */
12400 if (fmt_str[0] == '\0')
12401 {
12402 /* If FP has side-effects, just wait until gimplification is
12403 done. */
12404 if (TREE_SIDE_EFFECTS (fp))
c2f47e15 12405 return NULL_TREE;
0a39fd54 12406
12407 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
12408 }
12409
12410 /* When "string" doesn't contain %, replace all cases of
12411 fprintf (fp, string) with fputs (string, fp). The fputs
12412 builtin will take care of special cases like length == 1. */
c2f47e15 12413 if (fn_fputs)
12414 call = build_call_expr (fn_fputs, 2, fmt, fp);
0a39fd54 12415 }
12416
12417 /* The other optimizations can be done only on the non-va_list variants. */
12418 else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
c2f47e15 12419 return NULL_TREE;
0a39fd54 12420
12421 /* If the format specifier was "%s", call __builtin_fputs (arg, fp). */
99eabcc1 12422 else if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12423 {
c2f47e15 12424 if (!arg || !validate_arg (arg, POINTER_TYPE))
12425 return NULL_TREE;
12426 if (fn_fputs)
12427 call = build_call_expr (fn_fputs, 2, arg, fp);
0a39fd54 12428 }
12429
12430 /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */
99eabcc1 12431 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 12432 {
c2f47e15 12433 if (!arg || !validate_arg (arg, INTEGER_TYPE))
12434 return NULL_TREE;
12435 if (fn_fputc)
12436 call = build_call_expr (fn_fputc, 2, arg, fp);
0a39fd54 12437 }
12438
c2f47e15 12439 if (!call)
12440 return NULL_TREE;
0a39fd54 12441 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
12442}
99eabcc1 12443
12444/* Initialize format string characters in the target charset. */
12445
12446static bool
12447init_target_chars (void)
12448{
12449 static bool init;
12450 if (!init)
12451 {
12452 target_newline = lang_hooks.to_target_charset ('\n');
12453 target_percent = lang_hooks.to_target_charset ('%');
12454 target_c = lang_hooks.to_target_charset ('c');
12455 target_s = lang_hooks.to_target_charset ('s');
12456 if (target_newline == 0 || target_percent == 0 || target_c == 0
12457 || target_s == 0)
12458 return false;
12459
12460 target_percent_c[0] = target_percent;
12461 target_percent_c[1] = target_c;
12462 target_percent_c[2] = '\0';
12463
12464 target_percent_s[0] = target_percent;
12465 target_percent_s[1] = target_s;
12466 target_percent_s[2] = '\0';
12467
12468 target_percent_s_newline[0] = target_percent;
12469 target_percent_s_newline[1] = target_s;
12470 target_percent_s_newline[2] = target_newline;
12471 target_percent_s_newline[3] = '\0';
a0c938f0 12472
99eabcc1 12473 init = true;
12474 }
12475 return true;
12476}
bffb7645 12477
f0c477f2 12478/* Helper function for do_mpfr_arg*(). Ensure M is a normal number
12479 and no overflow/underflow occurred. INEXACT is true if M was not
fa7637bd 12480 exactly calculated. TYPE is the tree type for the result. This
f0c477f2 12481 function assumes that you cleared the MPFR flags and then
12482 calculated M to see if anything subsequently set a flag prior to
12483 entering this function. Return NULL_TREE if any checks fail. */
12484
12485static tree
d4473c84 12486do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
f0c477f2 12487{
12488 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
12489 overflow/underflow occurred. If -frounding-math, proceed iff the
12490 result of calling FUNC was exact. */
d4473c84 12491 if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
f0c477f2 12492 && (!flag_rounding_math || !inexact))
12493 {
12494 REAL_VALUE_TYPE rr;
12495
66fa16e6 12496 real_from_mpfr (&rr, m, type, GMP_RNDN);
f0c477f2 12497 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
12498 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
12499 but the mpft_t is not, then we underflowed in the
12500 conversion. */
776a7bab 12501 if (real_isfinite (&rr)
f0c477f2 12502 && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
12503 {
12504 REAL_VALUE_TYPE rmode;
12505
12506 real_convert (&rmode, TYPE_MODE (type), &rr);
12507 /* Proceed iff the specified mode can hold the value. */
12508 if (real_identical (&rmode, &rr))
12509 return build_real (type, rmode);
12510 }
12511 }
12512 return NULL_TREE;
12513}
12514
bffb7645 12515/* If argument ARG is a REAL_CST, call the one-argument mpfr function
12516 FUNC on it and return the resulting value as a tree with type TYPE.
728bac60 12517 If MIN and/or MAX are not NULL, then the supplied ARG must be
12518 within those bounds. If INCLUSIVE is true, then MIN/MAX are
12519 acceptable values, otherwise they are not. The mpfr precision is
12520 set to the precision of TYPE. We assume that function FUNC returns
12521 zero if the result could be calculated exactly within the requested
12522 precision. */
bffb7645 12523
12524static tree
728bac60 12525do_mpfr_arg1 (tree arg, tree type, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
12526 const REAL_VALUE_TYPE *min, const REAL_VALUE_TYPE *max,
12527 bool inclusive)
bffb7645 12528{
12529 tree result = NULL_TREE;
12530
12531 STRIP_NOPS (arg);
12532
bd7d6fa4 12533 /* To proceed, MPFR must exactly represent the target floating point
12534 format, which only happens when the target base equals two. */
12535 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12536 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
bffb7645 12537 {
f0c477f2 12538 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
bffb7645 12539
776a7bab 12540 if (real_isfinite (ra)
f0c477f2 12541 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min))
12542 && (!max || real_compare (inclusive ? LE_EXPR: LT_EXPR , ra, max)))
bffb7645 12543 {
f0c477f2 12544 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
debf9994 12545 int inexact;
bffb7645 12546 mpfr_t m;
12547
12548 mpfr_init2 (m, prec);
66fa16e6 12549 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 12550 mpfr_clear_flags ();
debf9994 12551 inexact = func (m, m, GMP_RNDN);
f0c477f2 12552 result = do_mpfr_ckconv (m, type, inexact);
bffb7645 12553 mpfr_clear (m);
12554 }
12555 }
12556
12557 return result;
12558}
f0c477f2 12559
12560/* If argument ARG is a REAL_CST, call the two-argument mpfr function
12561 FUNC on it and return the resulting value as a tree with type TYPE.
12562 The mpfr precision is set to the precision of TYPE. We assume that
12563 function FUNC returns zero if the result could be calculated
12564 exactly within the requested precision. */
12565
12566static tree
12567do_mpfr_arg2 (tree arg1, tree arg2, tree type,
12568 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
12569{
12570 tree result = NULL_TREE;
12571
12572 STRIP_NOPS (arg1);
12573 STRIP_NOPS (arg2);
12574
bd7d6fa4 12575 /* To proceed, MPFR must exactly represent the target floating point
12576 format, which only happens when the target base equals two. */
12577 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12578 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
12579 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
f0c477f2 12580 {
12581 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
12582 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
12583
776a7bab 12584 if (real_isfinite (ra1) && real_isfinite (ra2))
f0c477f2 12585 {
12586 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12587 int inexact;
12588 mpfr_t m1, m2;
12589
12590 mpfr_inits2 (prec, m1, m2, NULL);
66fa16e6 12591 mpfr_from_real (m1, ra1, GMP_RNDN);
12592 mpfr_from_real (m2, ra2, GMP_RNDN);
d4473c84 12593 mpfr_clear_flags ();
f0c477f2 12594 inexact = func (m1, m1, m2, GMP_RNDN);
12595 result = do_mpfr_ckconv (m1, type, inexact);
12596 mpfr_clears (m1, m2, NULL);
12597 }
12598 }
12599
12600 return result;
12601}
d92f994c 12602
9917422b 12603/* If argument ARG is a REAL_CST, call the three-argument mpfr function
12604 FUNC on it and return the resulting value as a tree with type TYPE.
12605 The mpfr precision is set to the precision of TYPE. We assume that
12606 function FUNC returns zero if the result could be calculated
12607 exactly within the requested precision. */
12608
12609static tree
12610do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type,
12611 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
12612{
12613 tree result = NULL_TREE;
12614
12615 STRIP_NOPS (arg1);
12616 STRIP_NOPS (arg2);
12617 STRIP_NOPS (arg3);
12618
bd7d6fa4 12619 /* To proceed, MPFR must exactly represent the target floating point
12620 format, which only happens when the target base equals two. */
12621 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12622 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
12623 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2)
12624 && TREE_CODE (arg3) == REAL_CST && !TREE_OVERFLOW (arg3))
9917422b 12625 {
12626 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
12627 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
12628 const REAL_VALUE_TYPE *const ra3 = &TREE_REAL_CST (arg3);
12629
776a7bab 12630 if (real_isfinite (ra1) && real_isfinite (ra2) && real_isfinite (ra3))
9917422b 12631 {
12632 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12633 int inexact;
12634 mpfr_t m1, m2, m3;
12635
12636 mpfr_inits2 (prec, m1, m2, m3, NULL);
66fa16e6 12637 mpfr_from_real (m1, ra1, GMP_RNDN);
12638 mpfr_from_real (m2, ra2, GMP_RNDN);
12639 mpfr_from_real (m3, ra3, GMP_RNDN);
d4473c84 12640 mpfr_clear_flags ();
9917422b 12641 inexact = func (m1, m1, m2, m3, GMP_RNDN);
12642 result = do_mpfr_ckconv (m1, type, inexact);
12643 mpfr_clears (m1, m2, m3, NULL);
12644 }
12645 }
12646
12647 return result;
12648}
12649
d92f994c 12650/* If argument ARG is a REAL_CST, call mpfr_sin_cos() on it and set
12651 the pointers *(ARG_SINP) and *(ARG_COSP) to the resulting values.
d735c391 12652 If ARG_SINP and ARG_COSP are NULL then the result is returned
12653 as a complex value.
d92f994c 12654 The type is taken from the type of ARG and is used for setting the
12655 precision of the calculation and results. */
12656
12657static tree
12658do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp)
12659{
bd7d6fa4 12660 tree const type = TREE_TYPE (arg);
d92f994c 12661 tree result = NULL_TREE;
12662
12663 STRIP_NOPS (arg);
12664
bd7d6fa4 12665 /* To proceed, MPFR must exactly represent the target floating point
12666 format, which only happens when the target base equals two. */
12667 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12668 && TREE_CODE (arg) == REAL_CST
12669 && !TREE_OVERFLOW (arg))
d92f994c 12670 {
12671 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
12672
776a7bab 12673 if (real_isfinite (ra))
d92f994c 12674 {
d92f994c 12675 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12676 tree result_s, result_c;
12677 int inexact;
12678 mpfr_t m, ms, mc;
12679
12680 mpfr_inits2 (prec, m, ms, mc, NULL);
66fa16e6 12681 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 12682 mpfr_clear_flags ();
d92f994c 12683 inexact = mpfr_sin_cos (ms, mc, m, GMP_RNDN);
12684 result_s = do_mpfr_ckconv (ms, type, inexact);
12685 result_c = do_mpfr_ckconv (mc, type, inexact);
12686 mpfr_clears (m, ms, mc, NULL);
12687 if (result_s && result_c)
12688 {
d735c391 12689 /* If we are to return in a complex value do so. */
12690 if (!arg_sinp && !arg_cosp)
12691 return build_complex (build_complex_type (type),
12692 result_c, result_s);
12693
d92f994c 12694 /* Dereference the sin/cos pointer arguments. */
12695 arg_sinp = build_fold_indirect_ref (arg_sinp);
12696 arg_cosp = build_fold_indirect_ref (arg_cosp);
12697 /* Proceed if valid pointer type were passed in. */
12698 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_sinp)) == TYPE_MAIN_VARIANT (type)
12699 && TYPE_MAIN_VARIANT (TREE_TYPE (arg_cosp)) == TYPE_MAIN_VARIANT (type))
12700 {
12701 /* Set the values. */
41076ef6 12702 result_s = fold_build2 (MODIFY_EXPR, type, arg_sinp,
35cc02b5 12703 result_s);
d92f994c 12704 TREE_SIDE_EFFECTS (result_s) = 1;
41076ef6 12705 result_c = fold_build2 (MODIFY_EXPR, type, arg_cosp,
35cc02b5 12706 result_c);
d92f994c 12707 TREE_SIDE_EFFECTS (result_c) = 1;
12708 /* Combine the assignments into a compound expr. */
12709 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
12710 result_s, result_c));
12711 }
12712 }
12713 }
12714 }
12715 return result;
12716}
65dd1378 12717
12718#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
12719/* If argument ARG1 is an INTEGER_CST and ARG2 is a REAL_CST, call the
12720 two-argument mpfr order N Bessel function FUNC on them and return
12721 the resulting value as a tree with type TYPE. The mpfr precision
12722 is set to the precision of TYPE. We assume that function FUNC
12723 returns zero if the result could be calculated exactly within the
12724 requested precision. */
12725static tree
12726do_mpfr_bessel_n (tree arg1, tree arg2, tree type,
12727 int (*func)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
12728 const REAL_VALUE_TYPE *min, bool inclusive)
12729{
12730 tree result = NULL_TREE;
12731
12732 STRIP_NOPS (arg1);
12733 STRIP_NOPS (arg2);
12734
12735 /* To proceed, MPFR must exactly represent the target floating point
12736 format, which only happens when the target base equals two. */
12737 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
12738 && host_integerp (arg1, 0)
12739 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
12740 {
12741 const HOST_WIDE_INT n = tree_low_cst(arg1, 0);
12742 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg2);
12743
12744 if (n == (long)n
776a7bab 12745 && real_isfinite (ra)
65dd1378 12746 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min)))
12747 {
12748 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12749 int inexact;
12750 mpfr_t m;
12751
12752 mpfr_init2 (m, prec);
12753 mpfr_from_real (m, ra, GMP_RNDN);
12754 mpfr_clear_flags ();
12755 inexact = func (m, n, m, GMP_RNDN);
12756 result = do_mpfr_ckconv (m, type, inexact);
12757 mpfr_clear (m);
12758 }
12759 }
12760
12761 return result;
12762}
e5407ca6 12763
12764/* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
12765 the pointer *(ARG_QUO) and return the result. The type is taken
12766 from the type of ARG0 and is used for setting the precision of the
12767 calculation and results. */
12768
12769static tree
12770do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
12771{
12772 tree const type = TREE_TYPE (arg0);
12773 tree result = NULL_TREE;
12774
12775 STRIP_NOPS (arg0);
12776 STRIP_NOPS (arg1);
12777
12778 /* To proceed, MPFR must exactly represent the target floating point
12779 format, which only happens when the target base equals two. */
12780 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
12781 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
12782 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
12783 {
12784 const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
12785 const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
12786
776a7bab 12787 if (real_isfinite (ra0) && real_isfinite (ra1))
e5407ca6 12788 {
12789 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12790 tree result_rem;
12791 long integer_quo;
12792 mpfr_t m0, m1;
12793
12794 mpfr_inits2 (prec, m0, m1, NULL);
12795 mpfr_from_real (m0, ra0, GMP_RNDN);
12796 mpfr_from_real (m1, ra1, GMP_RNDN);
12797 mpfr_clear_flags ();
12798 mpfr_remquo (m0, &integer_quo, m0, m1, GMP_RNDN);
12799 /* Remquo is independent of the rounding mode, so pass
12800 inexact=0 to do_mpfr_ckconv(). */
12801 result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
12802 mpfr_clears (m0, m1, NULL);
12803 if (result_rem)
12804 {
12805 /* MPFR calculates quo in the host's long so it may
12806 return more bits in quo than the target int can hold
12807 if sizeof(host long) > sizeof(target int). This can
12808 happen even for native compilers in LP64 mode. In
12809 these cases, modulo the quo value with the largest
12810 number that the target int can hold while leaving one
12811 bit for the sign. */
12812 if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
12813 integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
12814
12815 /* Dereference the quo pointer argument. */
12816 arg_quo = build_fold_indirect_ref (arg_quo);
12817 /* Proceed iff a valid pointer type was passed in. */
12818 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
12819 {
12820 /* Set the value. */
12821 tree result_quo = fold_build2 (MODIFY_EXPR,
12822 TREE_TYPE (arg_quo), arg_quo,
12823 build_int_cst (NULL, integer_quo));
12824 TREE_SIDE_EFFECTS (result_quo) = 1;
12825 /* Combine the quo assignment with the rem. */
12826 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
12827 result_quo, result_rem));
12828 }
12829 }
12830 }
12831 }
12832 return result;
12833}
e84da7c1 12834
12835/* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
12836 resulting value as a tree with type TYPE. The mpfr precision is
12837 set to the precision of TYPE. We assume that this mpfr function
12838 returns zero if the result could be calculated exactly within the
12839 requested precision. In addition, the integer pointer represented
12840 by ARG_SG will be dereferenced and set to the appropriate signgam
12841 (-1,1) value. */
12842
12843static tree
12844do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
12845{
12846 tree result = NULL_TREE;
12847
12848 STRIP_NOPS (arg);
12849
12850 /* To proceed, MPFR must exactly represent the target floating point
12851 format, which only happens when the target base equals two. Also
12852 verify ARG is a constant and that ARG_SG is an int pointer. */
12853 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
12854 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
12855 && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
12856 && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
12857 {
12858 const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
12859
12860 /* In addition to NaN and Inf, the argument cannot be zero or a
12861 negative integer. */
776a7bab 12862 if (real_isfinite (ra)
e84da7c1 12863 && ra->cl != rvc_zero
12864 && !(real_isneg(ra) && real_isinteger(ra, TYPE_MODE (type))))
12865 {
12866 const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
12867 int inexact, sg;
12868 mpfr_t m;
12869 tree result_lg;
12870
12871 mpfr_init2 (m, prec);
12872 mpfr_from_real (m, ra, GMP_RNDN);
12873 mpfr_clear_flags ();
12874 inexact = mpfr_lgamma (m, &sg, m, GMP_RNDN);
12875 result_lg = do_mpfr_ckconv (m, type, inexact);
12876 mpfr_clear (m);
12877 if (result_lg)
12878 {
12879 tree result_sg;
12880
12881 /* Dereference the arg_sg pointer argument. */
12882 arg_sg = build_fold_indirect_ref (arg_sg);
12883 /* Assign the signgam value into *arg_sg. */
12884 result_sg = fold_build2 (MODIFY_EXPR,
12885 TREE_TYPE (arg_sg), arg_sg,
12886 build_int_cst (NULL, sg));
12887 TREE_SIDE_EFFECTS (result_sg) = 1;
12888 /* Combine the signgam assignment with the lgamma result. */
12889 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
12890 result_sg, result_lg));
12891 }
12892 }
12893 }
12894
12895 return result;
12896}
65dd1378 12897#endif