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