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