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