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