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