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