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