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