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