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