]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/builtins.c
PR optimization/12260
[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,
3 2000, 2001, 2002, 2003 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"
53800dbe 30#include "flags.h"
31#include "regs.h"
32#include "hard-reg-set.h"
33#include "except.h"
34#include "function.h"
53800dbe 35#include "insn-config.h"
36#include "expr.h"
d8fc4d0b 37#include "optabs.h"
38#include "libfuncs.h"
53800dbe 39#include "recog.h"
40#include "output.h"
41#include "typeclass.h"
53800dbe 42#include "toplev.h"
689df48e 43#include "predict.h"
1dd6c958 44#include "tm_p.h"
fc2a2dcb 45#include "target.h"
63c62881 46#include "langhooks.h"
53800dbe 47
48#define CALLED_AS_BUILT_IN(NODE) \
49 (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10))
50
53800dbe 51/* Register mappings for target machines without register windows. */
52#ifndef INCOMING_REGNO
53#define INCOMING_REGNO(OUT) (OUT)
54#endif
55#ifndef OUTGOING_REGNO
56#define OUTGOING_REGNO(IN) (IN)
57#endif
58
726e2588 59#ifndef PAD_VARARGS_DOWN
60#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
61#endif
62
ab7943b9 63/* Define the names of the builtin function types and codes. */
8934cb0c 64const char *const built_in_class_names[4]
ab7943b9 65 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
66
18e43155 67#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM) #X,
8934cb0c 68const char *const built_in_names[(int) END_BUILTINS] =
4e9d90c7 69{
70#include "builtins.def"
71};
72#undef DEF_BUILTIN
ab7943b9 73
df94cd3b 74/* Setup an array of _DECL trees, make sure each element is
75 initialized to NULL_TREE. */
d2d4bdde 76tree built_in_decls[(int) END_BUILTINS];
0a68165a 77/* Declarations used when constructing the builtin implicitly in the compiler.
78 It may be NULL_TREE when this is invalid (for instance runtime is not
79 required to implement the function call in all cases. */
80tree implicit_built_in_decls[(int) END_BUILTINS];
df94cd3b 81
aecda0d6 82static int get_pointer_alignment (tree, unsigned int);
681fab1e 83static tree c_strlen (tree, int);
aecda0d6 84static const char *c_getstr (tree);
85static rtx c_readstr (const char *, enum machine_mode);
86static int target_char_cast (tree, char *);
87static rtx get_memory_rtx (tree);
19bf118a 88static tree build_string_literal (int, const char *);
aecda0d6 89static int apply_args_size (void);
90static int apply_result_size (void);
d8c9779c 91#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
aecda0d6 92static rtx result_vector (int, rtx);
d8c9779c 93#endif
aecda0d6 94static rtx expand_builtin_setjmp (tree, rtx);
95static void expand_builtin_prefetch (tree);
96static rtx expand_builtin_apply_args (void);
97static rtx expand_builtin_apply_args_1 (void);
98static rtx expand_builtin_apply (rtx, rtx, rtx);
99static void expand_builtin_return (rtx);
100static enum type_class type_to_class (tree);
101static rtx expand_builtin_classify_type (tree);
102static void expand_errno_check (tree, rtx);
103static rtx expand_builtin_mathfn (tree, rtx, rtx);
104static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
105static rtx expand_builtin_constant_p (tree, enum machine_mode);
106static rtx expand_builtin_args_info (tree);
107static rtx expand_builtin_next_arg (tree);
108static rtx expand_builtin_va_start (tree);
109static rtx expand_builtin_va_end (tree);
110static rtx expand_builtin_va_copy (tree);
111static rtx expand_builtin_memcmp (tree, tree, rtx, enum machine_mode);
112static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
113static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
114static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
115static rtx expand_builtin_strcat (tree, rtx, enum machine_mode);
116static rtx expand_builtin_strncat (tree, rtx, enum machine_mode);
117static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
118static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
119static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
120static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode, int);
121static rtx expand_builtin_memmove (tree, rtx, enum machine_mode);
122static rtx expand_builtin_bcopy (tree);
123static rtx expand_builtin_strcpy (tree, rtx, enum machine_mode);
124static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
125static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
126static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
127static rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
128static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
129static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
130static rtx expand_builtin_bzero (tree);
131static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
132static rtx expand_builtin_strstr (tree, rtx, enum machine_mode);
133static rtx expand_builtin_strpbrk (tree, rtx, enum machine_mode);
134static rtx expand_builtin_strchr (tree, rtx, enum machine_mode);
135static rtx expand_builtin_strrchr (tree, rtx, enum machine_mode);
136static rtx expand_builtin_alloca (tree, rtx);
137static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
138static rtx expand_builtin_frame_address (tree, tree);
19bf118a 139static rtx expand_builtin_fputs (tree, rtx, bool);
140static rtx expand_builtin_printf (tree, rtx, enum machine_mode, bool);
141static rtx expand_builtin_fprintf (tree, rtx, enum machine_mode, bool);
6411575e 142static rtx expand_builtin_sprintf (tree, rtx, enum machine_mode);
aecda0d6 143static tree stabilize_va_list (tree, int);
144static rtx expand_builtin_expect (tree, rtx);
145static tree fold_builtin_constant_p (tree);
146static tree fold_builtin_classify_type (tree);
147static tree fold_builtin_inf (tree, int);
148static tree fold_builtin_nan (tree, tree, int);
149static int validate_arglist (tree, ...);
277f8dd2 150static bool integer_valued_real_p (tree);
aecda0d6 151static tree fold_trunc_transparent_mathfn (tree);
152static bool readonly_data_expr (tree);
153static rtx expand_builtin_fabs (tree, rtx, rtx);
154static rtx expand_builtin_cabs (tree, rtx);
aecda0d6 155static tree fold_builtin_cabs (tree, tree, tree);
277f8dd2 156static tree fold_builtin_trunc (tree);
157static tree fold_builtin_floor (tree);
158static tree fold_builtin_ceil (tree);
70fb4c07 159static tree fold_builtin_bitop (tree);
98b40778 160
53800dbe 161/* Return the alignment in bits of EXP, a pointer valued expression.
162 But don't return more than MAX_ALIGN no matter what.
163 The alignment returned is, by default, the alignment of the thing that
27d0c333 164 EXP points to. If it is not a POINTER_TYPE, 0 is returned.
53800dbe 165
166 Otherwise, look at the expression to see if we can do better, i.e., if the
167 expression is actually pointing at an object whose alignment is tighter. */
168
169static int
aecda0d6 170get_pointer_alignment (tree exp, unsigned int max_align)
53800dbe 171{
27d0c333 172 unsigned int align, inner;
53800dbe 173
174 if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
175 return 0;
176
177 align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
178 align = MIN (align, max_align);
179
180 while (1)
181 {
182 switch (TREE_CODE (exp))
183 {
184 case NOP_EXPR:
185 case CONVERT_EXPR:
186 case NON_LVALUE_EXPR:
187 exp = TREE_OPERAND (exp, 0);
188 if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
189 return align;
325d1c45 190
53800dbe 191 inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
192 align = MIN (inner, max_align);
193 break;
194
195 case PLUS_EXPR:
196 /* If sum of pointer + int, restrict our maximum alignment to that
197 imposed by the integer. If not, we can't do any better than
198 ALIGN. */
325d1c45 199 if (! host_integerp (TREE_OPERAND (exp, 1), 1))
53800dbe 200 return align;
201
0994d2ed 202 while (((tree_low_cst (TREE_OPERAND (exp, 1), 1))
203 & (max_align / BITS_PER_UNIT - 1))
53800dbe 204 != 0)
205 max_align >>= 1;
206
207 exp = TREE_OPERAND (exp, 0);
208 break;
209
210 case ADDR_EXPR:
211 /* See what we are pointing at and look at its alignment. */
212 exp = TREE_OPERAND (exp, 0);
213 if (TREE_CODE (exp) == FUNCTION_DECL)
214 align = FUNCTION_BOUNDARY;
9308e976 215 else if (DECL_P (exp))
53800dbe 216 align = DECL_ALIGN (exp);
217#ifdef CONSTANT_ALIGNMENT
218 else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c')
219 align = CONSTANT_ALIGNMENT (exp, align);
220#endif
221 return MIN (align, max_align);
222
223 default:
224 return align;
225 }
226 }
227}
228
229/* Compute the length of a C string. TREE_STRING_LENGTH is not the right
230 way, because it could contain a zero byte in the middle.
231 TREE_STRING_LENGTH is the size of the character array, not the string.
232
4172d65e 233 ONLY_VALUE should be nonzero if the result is not going to be emitted
c09841f6 234 into the instruction stream and zero if it is going to be expanded.
4172d65e 235 E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
681fab1e 236 is returned, otherwise NULL, since
237 len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
238 evaluate the side-effects.
239
902de8ed 240 The value returned is of type `ssizetype'.
241
53800dbe 242 Unfortunately, string_constant can't access the values of const char
243 arrays with initializers, so neither can we do so here. */
244
245static tree
681fab1e 246c_strlen (tree src, int only_value)
53800dbe 247{
248 tree offset_node;
27d0c333 249 HOST_WIDE_INT offset;
250 int max;
44acf429 251 const char *ptr;
53800dbe 252
681fab1e 253 STRIP_NOPS (src);
254 if (TREE_CODE (src) == COND_EXPR
255 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
256 {
257 tree len1, len2;
258
259 len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
260 len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
261 if (tree_int_cst_equal (len1, len2))
262 return len1;
263 }
264
265 if (TREE_CODE (src) == COMPOUND_EXPR
266 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
267 return c_strlen (TREE_OPERAND (src, 1), only_value);
268
53800dbe 269 src = string_constant (src, &offset_node);
270 if (src == 0)
271 return 0;
902de8ed 272
83d79705 273 max = TREE_STRING_LENGTH (src) - 1;
53800dbe 274 ptr = TREE_STRING_POINTER (src);
902de8ed 275
53800dbe 276 if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
277 {
278 /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
279 compute the offset to the following null if we don't know where to
280 start searching for it. */
281 int i;
902de8ed 282
53800dbe 283 for (i = 0; i < max; i++)
284 if (ptr[i] == 0)
285 return 0;
902de8ed 286
53800dbe 287 /* We don't know the starting offset, but we do know that the string
288 has no internal zero bytes. We can assume that the offset falls
289 within the bounds of the string; otherwise, the programmer deserves
290 what he gets. Subtract the offset from the length of the string,
902de8ed 291 and return that. This would perhaps not be valid if we were dealing
292 with named arrays in addition to literal string constants. */
293
294 return size_diffop (size_int (max), offset_node);
53800dbe 295 }
296
297 /* We have a known offset into the string. Start searching there for
27d0c333 298 a null character if we can represent it as a single HOST_WIDE_INT. */
dabc4084 299 if (offset_node == 0)
53800dbe 300 offset = 0;
dabc4084 301 else if (! host_integerp (offset_node, 0))
302 offset = -1;
53800dbe 303 else
27d0c333 304 offset = tree_low_cst (offset_node, 0);
902de8ed 305
53800dbe 306 /* If the offset is known to be out of bounds, warn, and call strlen at
307 runtime. */
308 if (offset < 0 || offset > max)
309 {
310 warning ("offset outside bounds of constant string");
311 return 0;
312 }
902de8ed 313
53800dbe 314 /* Use strlen to search for the first zero byte. Since any strings
315 constructed with build_string will have nulls appended, we win even
316 if we get handed something like (char[4])"abcd".
317
318 Since OFFSET is our starting index into the string, no further
319 calculation is needed. */
902de8ed 320 return ssize_int (strlen (ptr + offset));
53800dbe 321}
322
83d79705 323/* Return a char pointer for a C string if it is a string constant
324 or sum of string constant and integer constant. */
325
326static const char *
aecda0d6 327c_getstr (tree src)
83d79705 328{
329 tree offset_node;
83d79705 330
331 src = string_constant (src, &offset_node);
332 if (src == 0)
333 return 0;
334
8c85fcb7 335 if (offset_node == 0)
336 return TREE_STRING_POINTER (src);
337 else if (!host_integerp (offset_node, 1)
338 || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
83d79705 339 return 0;
83d79705 340
8c85fcb7 341 return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
83d79705 342}
343
8c85fcb7 344/* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
345 GET_MODE_BITSIZE (MODE) bits from string constant STR. */
ecc318ff 346
6840589f 347static rtx
aecda0d6 348c_readstr (const char *str, enum machine_mode mode)
6840589f 349{
350 HOST_WIDE_INT c[2];
351 HOST_WIDE_INT ch;
352 unsigned int i, j;
353
354 if (GET_MODE_CLASS (mode) != MODE_INT)
355 abort ();
356 c[0] = 0;
357 c[1] = 0;
358 ch = 1;
359 for (i = 0; i < GET_MODE_SIZE (mode); i++)
360 {
361 j = i;
362 if (WORDS_BIG_ENDIAN)
363 j = GET_MODE_SIZE (mode) - i - 1;
364 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
365 && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
366 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
367 j *= BITS_PER_UNIT;
368 if (j > 2 * HOST_BITS_PER_WIDE_INT)
369 abort ();
370 if (ch)
371 ch = (unsigned char) str[i];
372 c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
373 }
374 return immed_double_const (c[0], c[1], mode);
375}
376
ecc318ff 377/* Cast a target constant CST to target CHAR and if that value fits into
378 host char type, return zero and put that value into variable pointed by
379 P. */
380
381static int
aecda0d6 382target_char_cast (tree cst, char *p)
ecc318ff 383{
384 unsigned HOST_WIDE_INT val, hostval;
385
27d0c333 386 if (!host_integerp (cst, 1)
ecc318ff 387 || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
388 return 1;
389
27d0c333 390 val = tree_low_cst (cst, 1);
ecc318ff 391 if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
392 val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
393
394 hostval = val;
395 if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
396 hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
397
398 if (val != hostval)
399 return 1;
400
401 *p = hostval;
402 return 0;
403}
404
53800dbe 405/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
406 times to get the address of either a higher stack frame, or a return
407 address located within it (depending on FNDECL_CODE). */
902de8ed 408
53800dbe 409rtx
aecda0d6 410expand_builtin_return_addr (enum built_in_function fndecl_code, int count,
411 rtx tem)
53800dbe 412{
413 int i;
414
415 /* Some machines need special handling before we can access
416 arbitrary frames. For example, on the sparc, we must first flush
417 all register windows to the stack. */
418#ifdef SETUP_FRAME_ADDRESSES
419 if (count > 0)
420 SETUP_FRAME_ADDRESSES ();
421#endif
422
423 /* On the sparc, the return address is not in the frame, it is in a
424 register. There is no way to access it off of the current frame
425 pointer, but it can be accessed off the previous frame pointer by
426 reading the value from the register window save area. */
427#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
428 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
429 count--;
430#endif
431
432 /* Scan back COUNT frames to the specified frame. */
433 for (i = 0; i < count; i++)
434 {
435 /* Assume the dynamic chain pointer is in the word that the
436 frame address points to, unless otherwise specified. */
437#ifdef DYNAMIC_CHAIN_ADDRESS
438 tem = DYNAMIC_CHAIN_ADDRESS (tem);
439#endif
440 tem = memory_address (Pmode, tem);
83fc1478 441 tem = gen_rtx_MEM (Pmode, tem);
ab6ab77e 442 set_mem_alias_set (tem, get_frame_alias_set ());
83fc1478 443 tem = copy_to_reg (tem);
53800dbe 444 }
445
446 /* For __builtin_frame_address, return what we've got. */
447 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
448 return tem;
449
450 /* For __builtin_return_address, Get the return address from that
451 frame. */
452#ifdef RETURN_ADDR_RTX
453 tem = RETURN_ADDR_RTX (count, tem);
454#else
455 tem = memory_address (Pmode,
456 plus_constant (tem, GET_MODE_SIZE (Pmode)));
457 tem = gen_rtx_MEM (Pmode, tem);
ab6ab77e 458 set_mem_alias_set (tem, get_frame_alias_set ());
53800dbe 459#endif
460 return tem;
461}
462
f7c44134 463/* Alias set used for setjmp buffer. */
464static HOST_WIDE_INT setjmp_alias_set = -1;
465
6b7f6858 466/* Construct the leading half of a __builtin_setjmp call. Control will
467 return to RECEIVER_LABEL. This is used directly by sjlj exception
468 handling code. */
53800dbe 469
6b7f6858 470void
aecda0d6 471expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
53800dbe 472{
53800dbe 473 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
53800dbe 474 rtx stack_save;
f7c44134 475 rtx mem;
53800dbe 476
f7c44134 477 if (setjmp_alias_set == -1)
478 setjmp_alias_set = new_alias_set ();
479
85d654dd 480 buf_addr = convert_memory_address (Pmode, buf_addr);
53800dbe 481
37ae8504 482 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
53800dbe 483
53800dbe 484 emit_queue ();
485
6b7f6858 486 /* We store the frame pointer and the address of receiver_label in
487 the buffer and use the rest of it for the stack save area, which
488 is machine-dependent. */
53800dbe 489
490#ifndef BUILTIN_SETJMP_FRAME_VALUE
491#define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx
492#endif
493
f7c44134 494 mem = gen_rtx_MEM (Pmode, buf_addr);
ab6ab77e 495 set_mem_alias_set (mem, setjmp_alias_set);
f7c44134 496 emit_move_insn (mem, BUILTIN_SETJMP_FRAME_VALUE);
497
498 mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
ab6ab77e 499 set_mem_alias_set (mem, setjmp_alias_set);
f7c44134 500
501 emit_move_insn (validize_mem (mem),
6b7f6858 502 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
53800dbe 503
504 stack_save = gen_rtx_MEM (sa_mode,
505 plus_constant (buf_addr,
506 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 507 set_mem_alias_set (stack_save, setjmp_alias_set);
53800dbe 508 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
509
510 /* If there is further processing to do, do it. */
511#ifdef HAVE_builtin_setjmp_setup
512 if (HAVE_builtin_setjmp_setup)
513 emit_insn (gen_builtin_setjmp_setup (buf_addr));
514#endif
515
6b7f6858 516 /* Tell optimize_save_area_alloca that extra work is going to
517 need to go on during alloca. */
3b0fa6b6 518 current_function_calls_setjmp = 1;
80ab81b9 519
520 /* Set this so all the registers get saved in our frame; we need to be
2c0e001b 521 able to copy the saved values for any registers from frames we unwind. */
80ab81b9 522 current_function_has_nonlocal_label = 1;
6b7f6858 523}
53800dbe 524
6b7f6858 525/* Construct the trailing part of a __builtin_setjmp call.
526 This is used directly by sjlj exception handling code. */
527
528void
aecda0d6 529expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
6b7f6858 530{
53800dbe 531 /* Clobber the FP when we get here, so we have to make sure it's
532 marked as used by this function. */
533 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
534
535 /* Mark the static chain as clobbered here so life information
536 doesn't get messed up for it. */
537 emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
538
539 /* Now put in the code to restore the frame pointer, and argument
540 pointer, if needed. The code below is from expand_end_bindings
541 in stmt.c; see detailed documentation there. */
542#ifdef HAVE_nonlocal_goto
543 if (! HAVE_nonlocal_goto)
544#endif
545 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
546
547#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
548 if (fixed_regs[ARG_POINTER_REGNUM])
549 {
550#ifdef ELIMINABLE_REGS
551 size_t i;
e99c3a1d 552 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
53800dbe 553
3098b2d3 554 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
53800dbe 555 if (elim_regs[i].from == ARG_POINTER_REGNUM
556 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
557 break;
558
3098b2d3 559 if (i == ARRAY_SIZE (elim_regs))
53800dbe 560#endif
561 {
562 /* Now restore our arg pointer from the address at which it
05927e40 563 was saved in our stack frame. */
53800dbe 564 emit_move_insn (virtual_incoming_args_rtx,
05927e40 565 copy_to_reg (get_arg_pointer_save_area (cfun)));
53800dbe 566 }
567 }
568#endif
569
570#ifdef HAVE_builtin_setjmp_receiver
571 if (HAVE_builtin_setjmp_receiver)
6b7f6858 572 emit_insn (gen_builtin_setjmp_receiver (receiver_label));
53800dbe 573 else
574#endif
575#ifdef HAVE_nonlocal_goto_receiver
576 if (HAVE_nonlocal_goto_receiver)
577 emit_insn (gen_nonlocal_goto_receiver ());
578 else
579#endif
6b7f6858 580 { /* Nothing */ }
57f6bb94 581
582 /* @@@ This is a kludge. Not all machine descriptions define a blockage
583 insn, but we must not allow the code we just generated to be reordered
584 by scheduling. Specifically, the update of the frame pointer must
585 happen immediately, not later. So emit an ASM_INPUT to act as blockage
586 insn. */
587 emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
6b7f6858 588}
53800dbe 589
6b7f6858 590/* __builtin_setjmp is passed a pointer to an array of five words (not
591 all will be used on all machines). It operates similarly to the C
592 library function of the same name, but is more efficient. Much of
593 the code below (and for longjmp) is copied from the handling of
594 non-local gotos.
595
596 NOTE: This is intended for use by GNAT and the exception handling
597 scheme in the compiler and will only work in the method used by
598 them. */
599
600static rtx
aecda0d6 601expand_builtin_setjmp (tree arglist, rtx target)
6b7f6858 602{
603 rtx buf_addr, next_lab, cont_lab;
604
0eb671f7 605 if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6b7f6858 606 return NULL_RTX;
607
608 if (target == 0 || GET_CODE (target) != REG
609 || REGNO (target) < FIRST_PSEUDO_REGISTER)
610 target = gen_reg_rtx (TYPE_MODE (integer_type_node));
611
612 buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
613
614 next_lab = gen_label_rtx ();
615 cont_lab = gen_label_rtx ();
616
617 expand_builtin_setjmp_setup (buf_addr, next_lab);
618
101a5a9d 619 /* Set TARGET to zero and branch to the continue label. Use emit_jump to
620 ensure that pending stack adjustments are flushed. */
6b7f6858 621 emit_move_insn (target, const0_rtx);
101a5a9d 622 emit_jump (cont_lab);
623
6b7f6858 624 emit_label (next_lab);
625
626 expand_builtin_setjmp_receiver (next_lab);
627
628 /* Set TARGET to one. */
629 emit_move_insn (target, const1_rtx);
630 emit_label (cont_lab);
631
632 /* Tell flow about the strange goings on. Putting `next_lab' on
633 `nonlocal_goto_handler_labels' to indicates that function
634 calls may traverse the arc back to this label. */
635
636 current_function_has_nonlocal_label = 1;
637 nonlocal_goto_handler_labels
638 = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels);
53800dbe 639
640 return target;
641}
642
643/* __builtin_longjmp is passed a pointer to an array of five words (not
644 all will be used on all machines). It operates similarly to the C
645 library function of the same name, but is more efficient. Much of
646 the code below is copied from the handling of non-local gotos.
647
648 NOTE: This is intended for use by GNAT and the exception handling
649 scheme in the compiler and will only work in the method used by
650 them. */
651
652void
aecda0d6 653expand_builtin_longjmp (rtx buf_addr, rtx value)
53800dbe 654{
4712c7d6 655 rtx fp, lab, stack, insn, last;
53800dbe 656 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
657
f7c44134 658 if (setjmp_alias_set == -1)
659 setjmp_alias_set = new_alias_set ();
660
85d654dd 661 buf_addr = convert_memory_address (Pmode, buf_addr);
479e4d5e 662
53800dbe 663 buf_addr = force_reg (Pmode, buf_addr);
664
665 /* We used to store value in static_chain_rtx, but that fails if pointers
666 are smaller than integers. We instead require that the user must pass
667 a second argument of 1, because that is what builtin_setjmp will
668 return. This also makes EH slightly more efficient, since we are no
669 longer copying around a value that we don't care about. */
670 if (value != const1_rtx)
671 abort ();
672
3b0fa6b6 673 current_function_calls_longjmp = 1;
674
4712c7d6 675 last = get_last_insn ();
53800dbe 676#ifdef HAVE_builtin_longjmp
677 if (HAVE_builtin_longjmp)
678 emit_insn (gen_builtin_longjmp (buf_addr));
679 else
680#endif
681 {
682 fp = gen_rtx_MEM (Pmode, buf_addr);
683 lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
684 GET_MODE_SIZE (Pmode)));
685
686 stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
687 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 688 set_mem_alias_set (fp, setjmp_alias_set);
689 set_mem_alias_set (lab, setjmp_alias_set);
690 set_mem_alias_set (stack, setjmp_alias_set);
53800dbe 691
692 /* Pick up FP, label, and SP from the block and jump. This code is
693 from expand_goto in stmt.c; see there for detailed comments. */
694#if HAVE_nonlocal_goto
695 if (HAVE_nonlocal_goto)
696 /* We have to pass a value to the nonlocal_goto pattern that will
697 get copied into the static_chain pointer, but it does not matter
698 what that value is, because builtin_setjmp does not use it. */
28d202a8 699 emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
53800dbe 700 else
701#endif
702 {
703 lab = copy_to_reg (lab);
704
705 emit_move_insn (hard_frame_pointer_rtx, fp);
706 emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
707
708 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
709 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
710 emit_indirect_jump (lab);
711 }
712 }
615166bb 713
714 /* Search backwards and mark the jump insn as a non-local goto.
715 Note that this precludes the use of __builtin_longjmp to a
716 __builtin_setjmp target in the same function. However, we've
717 already cautioned the user that these functions are for
718 internal exception handling use only. */
449c0509 719 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
720 {
4712c7d6 721 if (insn == last)
722 abort ();
449c0509 723 if (GET_CODE (insn) == JUMP_INSN)
724 {
725 REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
726 REG_NOTES (insn));
727 break;
728 }
729 else if (GET_CODE (insn) == CALL_INSN)
9342ee68 730 break;
449c0509 731 }
53800dbe 732}
733
5e3608d8 734/* Expand a call to __builtin_prefetch. For a target that does not support
735 data prefetch, evaluate the memory address argument in case it has side
736 effects. */
737
738static void
aecda0d6 739expand_builtin_prefetch (tree arglist)
5e3608d8 740{
741 tree arg0, arg1, arg2;
742 rtx op0, op1, op2;
743
26a5cadb 744 if (!validate_arglist (arglist, POINTER_TYPE, 0))
745 return;
746
5e3608d8 747 arg0 = TREE_VALUE (arglist);
26a5cadb 748 /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
749 zero (read) and argument 2 (locality) defaults to 3 (high degree of
750 locality). */
751 if (TREE_CHAIN (arglist))
752 {
753 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
754 if (TREE_CHAIN (TREE_CHAIN (arglist)))
9342ee68 755 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
26a5cadb 756 else
757 arg2 = build_int_2 (3, 0);
758 }
759 else
760 {
761 arg1 = integer_zero_node;
762 arg2 = build_int_2 (3, 0);
763 }
5e3608d8 764
765 /* Argument 0 is an address. */
766 op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
767
768 /* Argument 1 (read/write flag) must be a compile-time constant int. */
769 if (TREE_CODE (arg1) != INTEGER_CST)
770 {
9342ee68 771 error ("second arg to `__builtin_prefetch' must be a constant");
772 arg1 = integer_zero_node;
5e3608d8 773 }
bf8e3599 774 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5e3608d8 775 /* Argument 1 must be either zero or one. */
776 if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
777 {
778 warning ("invalid second arg to __builtin_prefetch; using zero");
779 op1 = const0_rtx;
780 }
781
782 /* Argument 2 (locality) must be a compile-time constant int. */
783 if (TREE_CODE (arg2) != INTEGER_CST)
784 {
785 error ("third arg to `__builtin_prefetch' must be a constant");
786 arg2 = integer_zero_node;
787 }
bf8e3599 788 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
5e3608d8 789 /* Argument 2 must be 0, 1, 2, or 3. */
790 if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
791 {
792 warning ("invalid third arg to __builtin_prefetch; using zero");
793 op2 = const0_rtx;
794 }
795
796#ifdef HAVE_prefetch
797 if (HAVE_prefetch)
798 {
f0ce3b1f 799 if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate)
4cd21437 800 (op0,
f0ce3b1f 801 insn_data[(int) CODE_FOR_prefetch].operand[0].mode))
19bf118a 802 || (GET_MODE (op0) != Pmode))
9342ee68 803 {
85d654dd 804 op0 = convert_memory_address (Pmode, op0);
9342ee68 805 op0 = force_reg (Pmode, op0);
806 }
5e3608d8 807 emit_insn (gen_prefetch (op0, op1, op2));
808 }
809 else
810#endif
811 op0 = protect_from_queue (op0, 0);
f0ce3b1f 812 /* Don't do anything with direct references to volatile memory, but
813 generate code to handle other side effects. */
814 if (GET_CODE (op0) != MEM && side_effects_p (op0))
815 emit_insn (op0);
5e3608d8 816}
817
f7c44134 818/* Get a MEM rtx for expression EXP which is the address of an operand
819 to be used to be used in a string instruction (cmpstrsi, movstrsi, ..). */
820
53800dbe 821static rtx
aecda0d6 822get_memory_rtx (tree exp)
53800dbe 823{
726ec87c 824 rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_SUM);
825 rtx mem;
f7c44134 826
85d654dd 827 addr = convert_memory_address (Pmode, addr);
726ec87c 828
829 mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
2a631e19 830
f7c44134 831 /* Get an expression we can use to find the attributes to assign to MEM.
832 If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
833 we can. First remove any nops. */
834 while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
f0ce3b1f 835 || TREE_CODE (exp) == NON_LVALUE_EXPR)
f7c44134 836 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
837 exp = TREE_OPERAND (exp, 0);
838
839 if (TREE_CODE (exp) == ADDR_EXPR)
eec8e941 840 {
841 exp = TREE_OPERAND (exp, 0);
842 set_mem_attributes (mem, exp, 0);
843 }
f7c44134 844 else if (POINTER_TYPE_P (TREE_TYPE (exp)))
eec8e941 845 {
846 exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
847 /* memcpy, memset and other builtin stringops can alias with anything. */
848 set_mem_alias_set (mem, 0);
849 }
53800dbe 850
53800dbe 851 return mem;
852}
853\f
854/* Built-in functions to perform an untyped call and return. */
855
856/* For each register that may be used for calling a function, this
857 gives a mode used to copy the register's value. VOIDmode indicates
858 the register is not used for calling a function. If the machine
859 has register windows, this gives only the outbound registers.
860 INCOMING_REGNO gives the corresponding inbound register. */
861static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
862
863/* For each register that may be used for returning values, this gives
864 a mode used to copy the register's value. VOIDmode indicates the
865 register is not used for returning values. If the machine has
866 register windows, this gives only the outbound registers.
867 INCOMING_REGNO gives the corresponding inbound register. */
868static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
869
870/* For each register that may be used for calling a function, this
871 gives the offset of that register into the block returned by
872 __builtin_apply_args. 0 indicates that the register is not
873 used for calling a function. */
874static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
875
bf8e3599 876/* Return the offset of register REGNO into the block returned by
53800dbe 877 __builtin_apply_args. This is not declared static, since it is
878 needed in objc-act.c. */
879
bf8e3599 880int
aecda0d6 881apply_args_register_offset (int regno)
53800dbe 882{
883 apply_args_size ();
884
885 /* Arguments are always put in outgoing registers (in the argument
886 block) if such make sense. */
887#ifdef OUTGOING_REGNO
f0ce3b1f 888 regno = OUTGOING_REGNO (regno);
53800dbe 889#endif
890 return apply_args_reg_offset[regno];
891}
892
893/* Return the size required for the block returned by __builtin_apply_args,
894 and initialize apply_args_mode. */
895
896static int
aecda0d6 897apply_args_size (void)
53800dbe 898{
899 static int size = -1;
58e9ce8f 900 int align;
901 unsigned int regno;
53800dbe 902 enum machine_mode mode;
903
904 /* The values computed by this function never change. */
905 if (size < 0)
906 {
907 /* The first value is the incoming arg-pointer. */
908 size = GET_MODE_SIZE (Pmode);
909
910 /* The second value is the structure value address unless this is
911 passed as an "invisible" first argument. */
6812c89e 912 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 913 size += GET_MODE_SIZE (Pmode);
914
915 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
916 if (FUNCTION_ARG_REGNO_P (regno))
917 {
918 /* Search for the proper mode for copying this register's
919 value. I'm not sure this is right, but it works so far. */
920 enum machine_mode best_mode = VOIDmode;
921
922 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
923 mode != VOIDmode;
924 mode = GET_MODE_WIDER_MODE (mode))
925 if (HARD_REGNO_MODE_OK (regno, mode)
926 && HARD_REGNO_NREGS (regno, mode) == 1)
927 best_mode = mode;
928
929 if (best_mode == VOIDmode)
930 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
931 mode != VOIDmode;
932 mode = GET_MODE_WIDER_MODE (mode))
933 if (HARD_REGNO_MODE_OK (regno, mode)
ad99e708 934 && have_insn_for (SET, mode))
53800dbe 935 best_mode = mode;
936
223097eb 937 if (best_mode == VOIDmode)
938 for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
939 mode != VOIDmode;
940 mode = GET_MODE_WIDER_MODE (mode))
941 if (HARD_REGNO_MODE_OK (regno, mode)
942 && have_insn_for (SET, mode))
943 best_mode = mode;
944
945 if (best_mode == VOIDmode)
946 for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
947 mode != VOIDmode;
948 mode = GET_MODE_WIDER_MODE (mode))
949 if (HARD_REGNO_MODE_OK (regno, mode)
950 && have_insn_for (SET, mode))
951 best_mode = mode;
952
53800dbe 953 mode = best_mode;
954 if (mode == VOIDmode)
955 abort ();
956
957 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
958 if (size % align != 0)
959 size = CEIL (size, align) * align;
960 apply_args_reg_offset[regno] = size;
961 size += GET_MODE_SIZE (mode);
962 apply_args_mode[regno] = mode;
963 }
964 else
965 {
966 apply_args_mode[regno] = VOIDmode;
967 apply_args_reg_offset[regno] = 0;
968 }
969 }
970 return size;
971}
972
973/* Return the size required for the block returned by __builtin_apply,
974 and initialize apply_result_mode. */
975
976static int
aecda0d6 977apply_result_size (void)
53800dbe 978{
979 static int size = -1;
980 int align, regno;
981 enum machine_mode mode;
982
983 /* The values computed by this function never change. */
984 if (size < 0)
985 {
986 size = 0;
987
988 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
989 if (FUNCTION_VALUE_REGNO_P (regno))
990 {
991 /* Search for the proper mode for copying this register's
992 value. I'm not sure this is right, but it works so far. */
993 enum machine_mode best_mode = VOIDmode;
994
995 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
996 mode != TImode;
997 mode = GET_MODE_WIDER_MODE (mode))
998 if (HARD_REGNO_MODE_OK (regno, mode))
999 best_mode = mode;
1000
1001 if (best_mode == VOIDmode)
1002 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
1003 mode != VOIDmode;
1004 mode = GET_MODE_WIDER_MODE (mode))
1005 if (HARD_REGNO_MODE_OK (regno, mode)
ad99e708 1006 && have_insn_for (SET, mode))
53800dbe 1007 best_mode = mode;
1008
223097eb 1009 if (best_mode == VOIDmode)
1010 for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
1011 mode != VOIDmode;
1012 mode = GET_MODE_WIDER_MODE (mode))
1013 if (HARD_REGNO_MODE_OK (regno, mode)
1014 && have_insn_for (SET, mode))
f0ce3b1f 1015 best_mode = mode;
223097eb 1016
1017 if (best_mode == VOIDmode)
1018 for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
1019 mode != VOIDmode;
1020 mode = GET_MODE_WIDER_MODE (mode))
1021 if (HARD_REGNO_MODE_OK (regno, mode)
1022 && have_insn_for (SET, mode))
1023 best_mode = mode;
1024
53800dbe 1025 mode = best_mode;
1026 if (mode == VOIDmode)
1027 abort ();
1028
1029 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1030 if (size % align != 0)
1031 size = CEIL (size, align) * align;
1032 size += GET_MODE_SIZE (mode);
1033 apply_result_mode[regno] = mode;
1034 }
1035 else
1036 apply_result_mode[regno] = VOIDmode;
1037
1038 /* Allow targets that use untyped_call and untyped_return to override
1039 the size so that machine-specific information can be stored here. */
1040#ifdef APPLY_RESULT_SIZE
1041 size = APPLY_RESULT_SIZE;
1042#endif
1043 }
1044 return size;
1045}
1046
1047#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1048/* Create a vector describing the result block RESULT. If SAVEP is true,
1049 the result block is used to save the values; otherwise it is used to
1050 restore the values. */
1051
1052static rtx
aecda0d6 1053result_vector (int savep, rtx result)
53800dbe 1054{
1055 int regno, size, align, nelts;
1056 enum machine_mode mode;
1057 rtx reg, mem;
f0af5a88 1058 rtx *savevec = alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
bf8e3599 1059
53800dbe 1060 size = nelts = 0;
1061 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1062 if ((mode = apply_result_mode[regno]) != VOIDmode)
1063 {
1064 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1065 if (size % align != 0)
1066 size = CEIL (size, align) * align;
1067 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
e513d163 1068 mem = adjust_address (result, mode, size);
53800dbe 1069 savevec[nelts++] = (savep
1070 ? gen_rtx_SET (VOIDmode, mem, reg)
1071 : gen_rtx_SET (VOIDmode, reg, mem));
1072 size += GET_MODE_SIZE (mode);
1073 }
1074 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1075}
1076#endif /* HAVE_untyped_call or HAVE_untyped_return */
1077
1078/* Save the state required to perform an untyped call with the same
1079 arguments as were passed to the current function. */
1080
1081static rtx
aecda0d6 1082expand_builtin_apply_args_1 (void)
53800dbe 1083{
1084 rtx registers;
1085 int size, align, regno;
1086 enum machine_mode mode;
6812c89e 1087 rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
53800dbe 1088
1089 /* Create a block where the arg-pointer, structure value address,
1090 and argument registers can be saved. */
1091 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1092
1093 /* Walk past the arg-pointer and structure value address. */
1094 size = GET_MODE_SIZE (Pmode);
6812c89e 1095 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1096 size += GET_MODE_SIZE (Pmode);
1097
1098 /* Save each register used in calling a function to the block. */
1099 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1100 if ((mode = apply_args_mode[regno]) != VOIDmode)
1101 {
1102 rtx tem;
1103
1104 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1105 if (size % align != 0)
1106 size = CEIL (size, align) * align;
1107
1108 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1109
e513d163 1110 emit_move_insn (adjust_address (registers, mode, size), tem);
53800dbe 1111 size += GET_MODE_SIZE (mode);
1112 }
1113
1114 /* Save the arg pointer to the block. */
e513d163 1115 emit_move_insn (adjust_address (registers, Pmode, 0),
53800dbe 1116 copy_to_reg (virtual_incoming_args_rtx));
1117 size = GET_MODE_SIZE (Pmode);
1118
1119 /* Save the structure value address unless this is passed as an
1120 "invisible" first argument. */
45550790 1121 if (struct_incoming_value)
53800dbe 1122 {
e513d163 1123 emit_move_insn (adjust_address (registers, Pmode, size),
45550790 1124 copy_to_reg (struct_incoming_value));
53800dbe 1125 size += GET_MODE_SIZE (Pmode);
1126 }
1127
1128 /* Return the address of the block. */
1129 return copy_addr_to_reg (XEXP (registers, 0));
1130}
1131
1132/* __builtin_apply_args returns block of memory allocated on
1133 the stack into which is stored the arg pointer, structure
1134 value address, static chain, and all the registers that might
1135 possibly be used in performing a function call. The code is
1136 moved to the start of the function so the incoming values are
1137 saved. */
27d0c333 1138
53800dbe 1139static rtx
aecda0d6 1140expand_builtin_apply_args (void)
53800dbe 1141{
1142 /* Don't do __builtin_apply_args more than once in a function.
1143 Save the result of the first call and reuse it. */
1144 if (apply_args_value != 0)
1145 return apply_args_value;
1146 {
1147 /* When this function is called, it means that registers must be
1148 saved on entry to this function. So we migrate the
1149 call to the first insn of this function. */
1150 rtx temp;
1151 rtx seq;
1152
1153 start_sequence ();
1154 temp = expand_builtin_apply_args_1 ();
1155 seq = get_insns ();
1156 end_sequence ();
1157
1158 apply_args_value = temp;
1159
31d3e01c 1160 /* Put the insns after the NOTE that starts the function.
1161 If this is inside a start_sequence, make the outer-level insn
53800dbe 1162 chain current, so the code is placed at the start of the
1163 function. */
1164 push_topmost_sequence ();
31d3e01c 1165 emit_insn_before (seq, NEXT_INSN (get_insns ()));
53800dbe 1166 pop_topmost_sequence ();
1167 return temp;
1168 }
1169}
1170
1171/* Perform an untyped call and save the state required to perform an
1172 untyped return of whatever value was returned by the given function. */
1173
1174static rtx
aecda0d6 1175expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
53800dbe 1176{
1177 int size, align, regno;
1178 enum machine_mode mode;
2a631e19 1179 rtx incoming_args, result, reg, dest, src, call_insn;
53800dbe 1180 rtx old_stack_level = 0;
1181 rtx call_fusage = 0;
6812c89e 1182 rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
53800dbe 1183
85d654dd 1184 arguments = convert_memory_address (Pmode, arguments);
726ec87c 1185
53800dbe 1186 /* Create a block where the return registers can be saved. */
1187 result = assign_stack_local (BLKmode, apply_result_size (), -1);
1188
53800dbe 1189 /* Fetch the arg pointer from the ARGUMENTS block. */
1190 incoming_args = gen_reg_rtx (Pmode);
726ec87c 1191 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
53800dbe 1192#ifndef STACK_GROWS_DOWNWARD
ad99e708 1193 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1194 incoming_args, 0, OPTAB_LIB_WIDEN);
53800dbe 1195#endif
1196
1197 /* Perform postincrements before actually calling the function. */
1198 emit_queue ();
1199
04a46d40 1200 /* Push a new argument block and copy the arguments. Do not allow
1201 the (potential) memcpy call below to interfere with our stack
1202 manipulations. */
53800dbe 1203 do_pending_stack_adjust ();
04a46d40 1204 NO_DEFER_POP;
53800dbe 1205
2358393e 1206 /* Save the stack with nonlocal if available. */
53800dbe 1207#ifdef HAVE_save_stack_nonlocal
1208 if (HAVE_save_stack_nonlocal)
1209 emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
1210 else
1211#endif
1212 emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
1213
1214 /* Push a block of memory onto the stack to store the memory arguments.
1215 Save the address in a register, and copy the memory arguments. ??? I
1216 haven't figured out how the calling convention macros effect this,
1217 but it's likely that the source and/or destination addresses in
1218 the block copy will need updating in machine specific ways. */
91b70175 1219 dest = allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
2a631e19 1220 dest = gen_rtx_MEM (BLKmode, dest);
1221 set_mem_align (dest, PARM_BOUNDARY);
1222 src = gen_rtx_MEM (BLKmode, incoming_args);
1223 set_mem_align (src, PARM_BOUNDARY);
0378dbdc 1224 emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
53800dbe 1225
1226 /* Refer to the argument block. */
1227 apply_args_size ();
1228 arguments = gen_rtx_MEM (BLKmode, arguments);
2a631e19 1229 set_mem_align (arguments, PARM_BOUNDARY);
53800dbe 1230
1231 /* Walk past the arg-pointer and structure value address. */
1232 size = GET_MODE_SIZE (Pmode);
45550790 1233 if (struct_value)
53800dbe 1234 size += GET_MODE_SIZE (Pmode);
1235
1236 /* Restore each of the registers previously saved. Make USE insns
1237 for each of these registers for use in making the call. */
1238 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1239 if ((mode = apply_args_mode[regno]) != VOIDmode)
1240 {
1241 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1242 if (size % align != 0)
1243 size = CEIL (size, align) * align;
1244 reg = gen_rtx_REG (mode, regno);
e513d163 1245 emit_move_insn (reg, adjust_address (arguments, mode, size));
53800dbe 1246 use_reg (&call_fusage, reg);
1247 size += GET_MODE_SIZE (mode);
1248 }
1249
1250 /* Restore the structure value address unless this is passed as an
1251 "invisible" first argument. */
1252 size = GET_MODE_SIZE (Pmode);
45550790 1253 if (struct_value)
53800dbe 1254 {
1255 rtx value = gen_reg_rtx (Pmode);
e513d163 1256 emit_move_insn (value, adjust_address (arguments, Pmode, size));
45550790 1257 emit_move_insn (struct_value, value);
1258 if (GET_CODE (struct_value) == REG)
1259 use_reg (&call_fusage, struct_value);
53800dbe 1260 size += GET_MODE_SIZE (Pmode);
1261 }
1262
1263 /* All arguments and registers used for the call are set up by now! */
707ff8b1 1264 function = prepare_call_address (function, NULL_TREE, &call_fusage, 0, 0);
53800dbe 1265
1266 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1267 and we don't want to load it into a register as an optimization,
1268 because prepare_call_address already did it if it should be done. */
1269 if (GET_CODE (function) != SYMBOL_REF)
1270 function = memory_address (FUNCTION_MODE, function);
1271
1272 /* Generate the actual call instruction and save the return value. */
1273#ifdef HAVE_untyped_call
1274 if (HAVE_untyped_call)
1275 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1276 result, result_vector (1, result)));
1277 else
1278#endif
1279#ifdef HAVE_call_value
1280 if (HAVE_call_value)
1281 {
1282 rtx valreg = 0;
1283
1284 /* Locate the unique return register. It is not possible to
1285 express a call that sets more than one return register using
1286 call_value; use untyped_call for that. In fact, untyped_call
1287 only needs to save the return registers in the given block. */
1288 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1289 if ((mode = apply_result_mode[regno]) != VOIDmode)
1290 {
1291 if (valreg)
1292 abort (); /* HAVE_untyped_call required. */
1293 valreg = gen_rtx_REG (mode, regno);
1294 }
1295
2ed6c343 1296 emit_call_insn (GEN_CALL_VALUE (valreg,
53800dbe 1297 gen_rtx_MEM (FUNCTION_MODE, function),
1298 const0_rtx, NULL_RTX, const0_rtx));
1299
e513d163 1300 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
53800dbe 1301 }
1302 else
1303#endif
1304 abort ();
1305
d5f9786f 1306 /* Find the CALL insn we just emitted, and attach the register usage
1307 information. */
1308 call_insn = last_call_insn ();
1309 add_function_usage_to (call_insn, call_fusage);
53800dbe 1310
1311 /* Restore the stack. */
1312#ifdef HAVE_save_stack_nonlocal
1313 if (HAVE_save_stack_nonlocal)
1314 emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1315 else
1316#endif
1317 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1318
04a46d40 1319 OK_DEFER_POP;
1320
53800dbe 1321 /* Return the address of the result block. */
85d654dd 1322 result = copy_addr_to_reg (XEXP (result, 0));
1323 return convert_memory_address (ptr_mode, result);
53800dbe 1324}
1325
1326/* Perform an untyped return. */
1327
1328static void
aecda0d6 1329expand_builtin_return (rtx result)
53800dbe 1330{
1331 int size, align, regno;
1332 enum machine_mode mode;
1333 rtx reg;
1334 rtx call_fusage = 0;
1335
85d654dd 1336 result = convert_memory_address (Pmode, result);
726ec87c 1337
53800dbe 1338 apply_result_size ();
1339 result = gen_rtx_MEM (BLKmode, result);
1340
1341#ifdef HAVE_untyped_return
1342 if (HAVE_untyped_return)
1343 {
1344 emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1345 emit_barrier ();
1346 return;
1347 }
1348#endif
1349
1350 /* Restore the return value and note that each value is used. */
1351 size = 0;
1352 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1353 if ((mode = apply_result_mode[regno]) != VOIDmode)
1354 {
1355 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1356 if (size % align != 0)
1357 size = CEIL (size, align) * align;
1358 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
e513d163 1359 emit_move_insn (reg, adjust_address (result, mode, size));
53800dbe 1360
1361 push_to_sequence (call_fusage);
1362 emit_insn (gen_rtx_USE (VOIDmode, reg));
1363 call_fusage = get_insns ();
1364 end_sequence ();
1365 size += GET_MODE_SIZE (mode);
1366 }
1367
1368 /* Put the USE insns before the return. */
31d3e01c 1369 emit_insn (call_fusage);
53800dbe 1370
1371 /* Return whatever values was restored by jumping directly to the end
1372 of the function. */
1373 expand_null_return ();
1374}
1375
539a3a92 1376/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
27d0c333 1377
539a3a92 1378static enum type_class
aecda0d6 1379type_to_class (tree type)
539a3a92 1380{
1381 switch (TREE_CODE (type))
1382 {
1383 case VOID_TYPE: return void_type_class;
1384 case INTEGER_TYPE: return integer_type_class;
1385 case CHAR_TYPE: return char_type_class;
1386 case ENUMERAL_TYPE: return enumeral_type_class;
1387 case BOOLEAN_TYPE: return boolean_type_class;
1388 case POINTER_TYPE: return pointer_type_class;
1389 case REFERENCE_TYPE: return reference_type_class;
1390 case OFFSET_TYPE: return offset_type_class;
1391 case REAL_TYPE: return real_type_class;
1392 case COMPLEX_TYPE: return complex_type_class;
1393 case FUNCTION_TYPE: return function_type_class;
1394 case METHOD_TYPE: return method_type_class;
1395 case RECORD_TYPE: return record_type_class;
1396 case UNION_TYPE:
1397 case QUAL_UNION_TYPE: return union_type_class;
1398 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1399 ? string_type_class : array_type_class);
1400 case SET_TYPE: return set_type_class;
1401 case FILE_TYPE: return file_type_class;
1402 case LANG_TYPE: return lang_type_class;
1403 default: return no_type_class;
1404 }
1405}
bf8e3599 1406
53800dbe 1407/* Expand a call to __builtin_classify_type with arguments found in
1408 ARGLIST. */
27d0c333 1409
53800dbe 1410static rtx
aecda0d6 1411expand_builtin_classify_type (tree arglist)
53800dbe 1412{
1413 if (arglist != 0)
539a3a92 1414 return GEN_INT (type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
53800dbe 1415 return GEN_INT (no_type_class);
1416}
1417
1418/* Expand expression EXP, which is a call to __builtin_constant_p. */
27d0c333 1419
53800dbe 1420static rtx
aecda0d6 1421expand_builtin_constant_p (tree arglist, enum machine_mode target_mode)
53800dbe 1422{
650e4c94 1423 rtx tmp;
53800dbe 1424
1425 if (arglist == 0)
1426 return const0_rtx;
650e4c94 1427 arglist = TREE_VALUE (arglist);
53800dbe 1428
650e4c94 1429 /* We have taken care of the easy cases during constant folding. This
c7926a82 1430 case is not obvious, so emit (constant_p_rtx (ARGLIST)) and let CSE
1fb4300c 1431 get a chance to see if it can deduce whether ARGLIST is constant.
1432 If CSE isn't going to run, of course, don't bother waiting. */
1433
1434 if (cse_not_expected)
1435 return const0_rtx;
53800dbe 1436
e6f295fb 1437 current_function_calls_constant_p = 1;
1438
650e4c94 1439 tmp = expand_expr (arglist, NULL_RTX, VOIDmode, 0);
80cd7a5e 1440 tmp = gen_rtx_CONSTANT_P_RTX (target_mode, tmp);
650e4c94 1441 return tmp;
53800dbe 1442}
1443
07976da7 1444/* This helper macro, meant to be used in mathfn_built_in below,
1445 determines which among a set of three builtin math functions is
1446 appropriate for a given type mode. The `F' and `L' cases are
1447 automatically generated from the `double' case. */
1448#define CASE_MATHFN(BUILT_IN_MATHFN) \
1449 case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1450 fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1451 fcodel = BUILT_IN_MATHFN##L ; break;
1452
1453/* Return mathematic function equivalent to FN but operating directly
1454 on TYPE, if available. If we can't do the conversion, return zero. */
0a68165a 1455tree
aecda0d6 1456mathfn_built_in (tree type, enum built_in_function fn)
0a68165a 1457{
07976da7 1458 const enum machine_mode type_mode = TYPE_MODE (type);
1459 enum built_in_function fcode, fcodef, fcodel;
1460
1461 switch (fn)
1462 {
746114e8 1463 CASE_MATHFN (BUILT_IN_ACOS)
1464 CASE_MATHFN (BUILT_IN_ACOSH)
1465 CASE_MATHFN (BUILT_IN_ASIN)
1466 CASE_MATHFN (BUILT_IN_ASINH)
07976da7 1467 CASE_MATHFN (BUILT_IN_ATAN)
746114e8 1468 CASE_MATHFN (BUILT_IN_ATAN2)
1469 CASE_MATHFN (BUILT_IN_ATANH)
1470 CASE_MATHFN (BUILT_IN_CBRT)
07976da7 1471 CASE_MATHFN (BUILT_IN_CEIL)
746114e8 1472 CASE_MATHFN (BUILT_IN_COPYSIGN)
07976da7 1473 CASE_MATHFN (BUILT_IN_COS)
746114e8 1474 CASE_MATHFN (BUILT_IN_COSH)
1475 CASE_MATHFN (BUILT_IN_DREM)
1476 CASE_MATHFN (BUILT_IN_ERF)
1477 CASE_MATHFN (BUILT_IN_ERFC)
07976da7 1478 CASE_MATHFN (BUILT_IN_EXP)
746114e8 1479 CASE_MATHFN (BUILT_IN_EXP10)
1480 CASE_MATHFN (BUILT_IN_EXP2)
1481 CASE_MATHFN (BUILT_IN_EXPM1)
1482 CASE_MATHFN (BUILT_IN_FABS)
1483 CASE_MATHFN (BUILT_IN_FDIM)
07976da7 1484 CASE_MATHFN (BUILT_IN_FLOOR)
746114e8 1485 CASE_MATHFN (BUILT_IN_FMA)
1486 CASE_MATHFN (BUILT_IN_FMAX)
1487 CASE_MATHFN (BUILT_IN_FMIN)
1488 CASE_MATHFN (BUILT_IN_FMOD)
1489 CASE_MATHFN (BUILT_IN_FREXP)
1490 CASE_MATHFN (BUILT_IN_GAMMA)
1491 CASE_MATHFN (BUILT_IN_HUGE_VAL)
1492 CASE_MATHFN (BUILT_IN_HYPOT)
1493 CASE_MATHFN (BUILT_IN_ILOGB)
1494 CASE_MATHFN (BUILT_IN_INF)
1495 CASE_MATHFN (BUILT_IN_J0)
1496 CASE_MATHFN (BUILT_IN_J1)
1497 CASE_MATHFN (BUILT_IN_JN)
1498 CASE_MATHFN (BUILT_IN_LDEXP)
1499 CASE_MATHFN (BUILT_IN_LGAMMA)
1500 CASE_MATHFN (BUILT_IN_LLRINT)
1501 CASE_MATHFN (BUILT_IN_LLROUND)
07976da7 1502 CASE_MATHFN (BUILT_IN_LOG)
746114e8 1503 CASE_MATHFN (BUILT_IN_LOG10)
1504 CASE_MATHFN (BUILT_IN_LOG1P)
1505 CASE_MATHFN (BUILT_IN_LOG2)
1506 CASE_MATHFN (BUILT_IN_LOGB)
1507 CASE_MATHFN (BUILT_IN_LRINT)
1508 CASE_MATHFN (BUILT_IN_LROUND)
1509 CASE_MATHFN (BUILT_IN_MODF)
1510 CASE_MATHFN (BUILT_IN_NAN)
1511 CASE_MATHFN (BUILT_IN_NANS)
07976da7 1512 CASE_MATHFN (BUILT_IN_NEARBYINT)
746114e8 1513 CASE_MATHFN (BUILT_IN_NEXTAFTER)
1514 CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1515 CASE_MATHFN (BUILT_IN_POW)
1516 CASE_MATHFN (BUILT_IN_POW10)
1517 CASE_MATHFN (BUILT_IN_REMAINDER)
1518 CASE_MATHFN (BUILT_IN_REMQUO)
1519 CASE_MATHFN (BUILT_IN_RINT)
07976da7 1520 CASE_MATHFN (BUILT_IN_ROUND)
746114e8 1521 CASE_MATHFN (BUILT_IN_SCALB)
1522 CASE_MATHFN (BUILT_IN_SCALBLN)
1523 CASE_MATHFN (BUILT_IN_SCALBN)
1524 CASE_MATHFN (BUILT_IN_SIGNIFICAND)
07976da7 1525 CASE_MATHFN (BUILT_IN_SIN)
746114e8 1526 CASE_MATHFN (BUILT_IN_SINCOS)
1527 CASE_MATHFN (BUILT_IN_SINH)
07976da7 1528 CASE_MATHFN (BUILT_IN_SQRT)
1529 CASE_MATHFN (BUILT_IN_TAN)
746114e8 1530 CASE_MATHFN (BUILT_IN_TANH)
1531 CASE_MATHFN (BUILT_IN_TGAMMA)
07976da7 1532 CASE_MATHFN (BUILT_IN_TRUNC)
746114e8 1533 CASE_MATHFN (BUILT_IN_Y0)
1534 CASE_MATHFN (BUILT_IN_Y1)
1535 CASE_MATHFN (BUILT_IN_YN)
07976da7 1536
0a68165a 1537 default:
07976da7 1538 return 0;
0a68165a 1539 }
07976da7 1540
1541 if (type_mode == TYPE_MODE (double_type_node))
1542 return implicit_built_in_decls[fcode];
1543 else if (type_mode == TYPE_MODE (float_type_node))
1544 return implicit_built_in_decls[fcodef];
1545 else if (type_mode == TYPE_MODE (long_double_type_node))
1546 return implicit_built_in_decls[fcodel];
1547 else
1548 return 0;
0a68165a 1549}
1550
0fd605a5 1551/* If errno must be maintained, expand the RTL to check if the result,
1552 TARGET, of a built-in function call, EXP, is NaN, and if so set
1553 errno to EDOM. */
1554
1555static void
aecda0d6 1556expand_errno_check (tree exp, rtx target)
0fd605a5 1557{
7f05340e 1558 rtx lab = gen_label_rtx ();
0fd605a5 1559
7f05340e 1560 /* Test the result; if it is NaN, set errno=EDOM because
1561 the argument was not in the domain. */
1562 emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
1563 0, lab);
0fd605a5 1564
1565#ifdef TARGET_EDOM
7f05340e 1566 /* If this built-in doesn't throw an exception, set errno directly. */
1567 if (TREE_NOTHROW (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
1568 {
0fd605a5 1569#ifdef GEN_ERRNO_RTX
7f05340e 1570 rtx errno_rtx = GEN_ERRNO_RTX;
0fd605a5 1571#else
7f05340e 1572 rtx errno_rtx
0fd605a5 1573 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1574#endif
7f05340e 1575 emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
0fd605a5 1576 emit_label (lab);
7f05340e 1577 return;
0fd605a5 1578 }
7f05340e 1579#endif
1580
1581 /* We can't set errno=EDOM directly; let the library call do it.
1582 Pop the arguments right away in case the call gets deleted. */
1583 NO_DEFER_POP;
1584 expand_call (exp, target, 0);
1585 OK_DEFER_POP;
1586 emit_label (lab);
0fd605a5 1587}
1588
1589
53800dbe 1590/* Expand a call to one of the builtin math functions (sin, cos, or sqrt).
1591 Return 0 if a normal call should be emitted rather than expanding the
1592 function in-line. EXP is the expression that is a call to the builtin
1593 function; if convenient, the result should be placed in TARGET.
1594 SUBTARGET may be used as the target for computing one of EXP's operands. */
27d0c333 1595
53800dbe 1596static rtx
aecda0d6 1597expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
53800dbe 1598{
bf8e3599 1599 optab builtin_optab;
bd421108 1600 rtx op0, insns, before_call;
c6e6ecb1 1601 tree fndecl = get_callee_fndecl (exp);
53800dbe 1602 tree arglist = TREE_OPERAND (exp, 1);
7f05340e 1603 enum machine_mode mode;
528ee710 1604 bool errno_set = false;
68e6cb9d 1605 tree arg, narg;
53800dbe 1606
0eb671f7 1607 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
53800dbe 1608 return 0;
1609
7f05340e 1610 arg = TREE_VALUE (arglist);
53800dbe 1611
1612 switch (DECL_FUNCTION_CODE (fndecl))
1613 {
d2d4bdde 1614 case BUILT_IN_SIN:
1615 case BUILT_IN_SINF:
1616 case BUILT_IN_SINL:
53800dbe 1617 builtin_optab = sin_optab; break;
d2d4bdde 1618 case BUILT_IN_COS:
1619 case BUILT_IN_COSF:
1620 case BUILT_IN_COSL:
53800dbe 1621 builtin_optab = cos_optab; break;
75357f66 1622 case BUILT_IN_SQRT:
d2d4bdde 1623 case BUILT_IN_SQRTF:
1624 case BUILT_IN_SQRTL:
7f05340e 1625 errno_set = ! tree_expr_nonnegative_p (arg);
1626 builtin_optab = sqrt_optab;
1627 break;
42721db0 1628 case BUILT_IN_EXP:
1629 case BUILT_IN_EXPF:
1630 case BUILT_IN_EXPL:
528ee710 1631 errno_set = true; builtin_optab = exp_optab; break;
42721db0 1632 case BUILT_IN_LOG:
1633 case BUILT_IN_LOGF:
1634 case BUILT_IN_LOGL:
528ee710 1635 errno_set = true; builtin_optab = log_optab; break;
1636 case BUILT_IN_TAN:
1637 case BUILT_IN_TANF:
1638 case BUILT_IN_TANL:
1639 builtin_optab = tan_optab; break;
1640 case BUILT_IN_ATAN:
1641 case BUILT_IN_ATANF:
1642 case BUILT_IN_ATANL:
1643 builtin_optab = atan_optab; break;
805e22b2 1644 case BUILT_IN_FLOOR:
1645 case BUILT_IN_FLOORF:
1646 case BUILT_IN_FLOORL:
528ee710 1647 builtin_optab = floor_optab; break;
805e22b2 1648 case BUILT_IN_CEIL:
1649 case BUILT_IN_CEILF:
1650 case BUILT_IN_CEILL:
528ee710 1651 builtin_optab = ceil_optab; break;
805e22b2 1652 case BUILT_IN_TRUNC:
1653 case BUILT_IN_TRUNCF:
1654 case BUILT_IN_TRUNCL:
a7cc195f 1655 builtin_optab = btrunc_optab; break;
805e22b2 1656 case BUILT_IN_ROUND:
1657 case BUILT_IN_ROUNDF:
1658 case BUILT_IN_ROUNDL:
528ee710 1659 builtin_optab = round_optab; break;
805e22b2 1660 case BUILT_IN_NEARBYINT:
1661 case BUILT_IN_NEARBYINTF:
1662 case BUILT_IN_NEARBYINTL:
528ee710 1663 builtin_optab = nearbyint_optab; break;
42721db0 1664 default:
53800dbe 1665 abort ();
1666 }
1667
7f05340e 1668 /* Make a suitable register to place result in. */
1669 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 1670
7f05340e 1671 if (! flag_errno_math || ! HONOR_NANS (mode))
1672 errno_set = false;
1673
bd421108 1674 /* Before working hard, check whether the instruction is available. */
1675 if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
68e6cb9d 1676 {
bd421108 1677 target = gen_reg_rtx (mode);
7f05340e 1678
bd421108 1679 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
1680 need to expand the argument again. This way, we will not perform
1681 side-effects more the once. */
1682 narg = save_expr (arg);
1683 if (narg != arg)
1684 {
1685 arglist = build_tree_list (NULL_TREE, arg);
1686 exp = build_function_call_expr (fndecl, arglist);
1687 }
7f05340e 1688
bd421108 1689 op0 = expand_expr (arg, subtarget, VOIDmode, 0);
7f05340e 1690
bd421108 1691 emit_queue ();
1692 start_sequence ();
53800dbe 1693
bd421108 1694 /* Compute into TARGET.
1695 Set TARGET to wherever the result comes back. */
1696 target = expand_unop (mode, builtin_optab, op0, target, 0);
1697
1698 if (target != 0)
1699 {
1700 if (errno_set)
1701 expand_errno_check (exp, target);
1702
1703 /* Output the entire sequence. */
1704 insns = get_insns ();
1705 end_sequence ();
1706 emit_insn (insns);
1707 return target;
1708 }
1709
1710 /* If we were unable to expand via the builtin, stop the sequence
1711 (without outputting the insns) and call to the library function
1712 with the stabilized argument list. */
53800dbe 1713 end_sequence ();
53800dbe 1714 }
1715
bd421108 1716 before_call = get_last_insn ();
1717
1718 target = expand_call (exp, target, target == const0_rtx);
53800dbe 1719
bd421108 1720 /* If this is a sqrt operation and we don't care about errno, try to
1721 attach a REG_EQUAL note with a SQRT rtx to the emitted libcall.
1722 This allows the semantics of the libcall to be visible to the RTL
1723 optimizers. */
1724 if (builtin_optab == sqrt_optab && !errno_set)
1725 {
1726 /* Search backwards through the insns emitted by expand_call looking
1727 for the instruction with the REG_RETVAL note. */
1728 rtx last = get_last_insn ();
1729 while (last != before_call)
1730 {
1731 if (find_reg_note (last, REG_RETVAL, NULL))
1732 {
1733 rtx note = find_reg_note (last, REG_EQUAL, NULL);
1734 /* Check that the REQ_EQUAL note is an EXPR_LIST with
1735 two elements, i.e. symbol_ref(sqrt) and the operand. */
1736 if (note
1737 && GET_CODE (note) == EXPR_LIST
1738 && GET_CODE (XEXP (note, 0)) == EXPR_LIST
1739 && XEXP (XEXP (note, 0), 1) != NULL_RTX
1740 && XEXP (XEXP (XEXP (note, 0), 1), 1) == NULL_RTX)
1741 {
1742 rtx operand = XEXP (XEXP (XEXP (note, 0), 1), 0);
1743 /* Check operand is a register with expected mode. */
1744 if (operand
1745 && GET_CODE (operand) == REG
1746 && GET_MODE (operand) == mode)
1747 {
1748 /* Replace the REG_EQUAL note with a SQRT rtx. */
1749 rtx equiv = gen_rtx_SQRT (mode, operand);
1750 set_unique_reg_note (last, REG_EQUAL, equiv);
1751 }
1752 }
1753 break;
1754 }
1755 last = PREV_INSN (last);
1756 }
1757 }
0fd605a5 1758
1759 return target;
1760}
1761
1762/* Expand a call to the builtin binary math functions (pow and atan2).
1763 Return 0 if a normal call should be emitted rather than expanding the
1764 function in-line. EXP is the expression that is a call to the builtin
1765 function; if convenient, the result should be placed in TARGET.
1766 SUBTARGET may be used as the target for computing one of EXP's
1767 operands. */
1768
1769static rtx
aecda0d6 1770expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
0fd605a5 1771{
1772 optab builtin_optab;
1773 rtx op0, op1, insns;
c6e6ecb1 1774 tree fndecl = get_callee_fndecl (exp);
0fd605a5 1775 tree arglist = TREE_OPERAND (exp, 1);
68e6cb9d 1776 tree arg0, arg1, temp, narg;
7f05340e 1777 enum machine_mode mode;
0fd605a5 1778 bool errno_set = true;
1779 bool stable = true;
1780
1781 if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
1782 return 0;
1783
1784 arg0 = TREE_VALUE (arglist);
1785 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
1786
0fd605a5 1787 switch (DECL_FUNCTION_CODE (fndecl))
1788 {
1789 case BUILT_IN_POW:
1790 case BUILT_IN_POWF:
1791 case BUILT_IN_POWL:
1792 builtin_optab = pow_optab; break;
1793 case BUILT_IN_ATAN2:
1794 case BUILT_IN_ATAN2F:
1795 case BUILT_IN_ATAN2L:
1796 builtin_optab = atan2_optab; break;
1797 default:
1798 abort ();
1799 }
1800
7f05340e 1801 /* Make a suitable register to place result in. */
1802 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 1803
1804 /* Before working hard, check whether the instruction is available. */
1805 if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
1806 return 0;
1807
7f05340e 1808 target = gen_reg_rtx (mode);
1809
1810 if (! flag_errno_math || ! HONOR_NANS (mode))
1811 errno_set = false;
1812
68e6cb9d 1813 /* Alway stabilize the argument list. */
1814 narg = save_expr (arg1);
1815 if (narg != arg1)
7f05340e 1816 {
68e6cb9d 1817 temp = build_tree_list (NULL_TREE, narg);
1818 stable = false;
1819 }
1820 else
1821 temp = TREE_CHAIN (arglist);
7f05340e 1822
68e6cb9d 1823 narg = save_expr (arg0);
1824 if (narg != arg0)
1825 {
1826 arglist = tree_cons (NULL_TREE, narg, temp);
1827 stable = false;
7f05340e 1828 }
68e6cb9d 1829 else if (! stable)
1830 arglist = tree_cons (NULL_TREE, arg0, temp);
1831
1832 if (! stable)
1833 exp = build_function_call_expr (fndecl, arglist);
7f05340e 1834
1835 op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
1836 op1 = expand_expr (arg1, 0, VOIDmode, 0);
1837
1838 emit_queue ();
1839 start_sequence ();
1840
0fd605a5 1841 /* Compute into TARGET.
1842 Set TARGET to wherever the result comes back. */
7f05340e 1843 target = expand_binop (mode, builtin_optab, op0, op1,
0fd605a5 1844 target, 0, OPTAB_DIRECT);
53800dbe 1845
68e6cb9d 1846 /* If we were unable to expand via the builtin, stop the sequence
1847 (without outputting the insns) and call to the library function
1848 with the stabilized argument list. */
0fd605a5 1849 if (target == 0)
1850 {
1851 end_sequence ();
68e6cb9d 1852 return expand_call (exp, target, target == const0_rtx);
53800dbe 1853 }
1854
a4356fb9 1855 if (errno_set)
1856 expand_errno_check (exp, target);
0fd605a5 1857
53800dbe 1858 /* Output the entire sequence. */
1859 insns = get_insns ();
1860 end_sequence ();
31d3e01c 1861 emit_insn (insns);
bf8e3599 1862
53800dbe 1863 return target;
1864}
1865
f1b844c6 1866/* To evaluate powi(x,n), the floating point value x raised to the
1867 constant integer exponent n, we use a hybrid algorithm that
1868 combines the "window method" with look-up tables. For an
1869 introduction to exponentiation algorithms and "addition chains",
1870 see section 4.6.3, "Evaluation of Powers" of Donald E. Knuth,
1871 "Seminumerical Algorithms", Vol. 2, "The Art of Computer Programming",
1872 3rd Edition, 1998, and Daniel M. Gordon, "A Survey of Fast Exponentiation
1873 Methods", Journal of Algorithms, Vol. 27, pp. 129-146, 1998. */
1874
1875/* Provide a default value for POWI_MAX_MULTS, the maximum number of
1876 multiplications to inline before calling the system library's pow
1877 function. powi(x,n) requires at worst 2*bits(n)-2 multiplications,
1878 so this default never requires calling pow, powf or powl. */
1879
1880#ifndef POWI_MAX_MULTS
1881#define POWI_MAX_MULTS (2*HOST_BITS_PER_WIDE_INT-2)
1882#endif
1883
1884/* The size of the "optimal power tree" lookup table. All
1885 exponents less than this value are simply looked up in the
1886 powi_table below. This threshold is also used to size the
1887 cache of pseudo registers that hold intermediate results. */
1888#define POWI_TABLE_SIZE 256
1889
1890/* The size, in bits of the window, used in the "window method"
1891 exponentiation algorithm. This is equivalent to a radix of
1892 (1<<POWI_WINDOW_SIZE) in the corresponding "m-ary method". */
1893#define POWI_WINDOW_SIZE 3
1894
1895/* The following table is an efficient representation of an
1896 "optimal power tree". For each value, i, the corresponding
1897 value, j, in the table states than an optimal evaluation
1898 sequence for calculating pow(x,i) can be found by evaluating
1899 pow(x,j)*pow(x,i-j). An optimal power tree for the first
1900 100 integers is given in Knuth's "Seminumerical algorithms". */
1901
1902static const unsigned char powi_table[POWI_TABLE_SIZE] =
1903 {
1904 0, 1, 1, 2, 2, 3, 3, 4, /* 0 - 7 */
1905 4, 6, 5, 6, 6, 10, 7, 9, /* 8 - 15 */
1906 8, 16, 9, 16, 10, 12, 11, 13, /* 16 - 23 */
1907 12, 17, 13, 18, 14, 24, 15, 26, /* 24 - 31 */
1908 16, 17, 17, 19, 18, 33, 19, 26, /* 32 - 39 */
1909 20, 25, 21, 40, 22, 27, 23, 44, /* 40 - 47 */
1910 24, 32, 25, 34, 26, 29, 27, 44, /* 48 - 55 */
1911 28, 31, 29, 34, 30, 60, 31, 36, /* 56 - 63 */
1912 32, 64, 33, 34, 34, 46, 35, 37, /* 64 - 71 */
1913 36, 65, 37, 50, 38, 48, 39, 69, /* 72 - 79 */
1914 40, 49, 41, 43, 42, 51, 43, 58, /* 80 - 87 */
1915 44, 64, 45, 47, 46, 59, 47, 76, /* 88 - 95 */
1916 48, 65, 49, 66, 50, 67, 51, 66, /* 96 - 103 */
1917 52, 70, 53, 74, 54, 104, 55, 74, /* 104 - 111 */
1918 56, 64, 57, 69, 58, 78, 59, 68, /* 112 - 119 */
1919 60, 61, 61, 80, 62, 75, 63, 68, /* 120 - 127 */
1920 64, 65, 65, 128, 66, 129, 67, 90, /* 128 - 135 */
1921 68, 73, 69, 131, 70, 94, 71, 88, /* 136 - 143 */
1922 72, 128, 73, 98, 74, 132, 75, 121, /* 144 - 151 */
1923 76, 102, 77, 124, 78, 132, 79, 106, /* 152 - 159 */
1924 80, 97, 81, 160, 82, 99, 83, 134, /* 160 - 167 */
1925 84, 86, 85, 95, 86, 160, 87, 100, /* 168 - 175 */
1926 88, 113, 89, 98, 90, 107, 91, 122, /* 176 - 183 */
1927 92, 111, 93, 102, 94, 126, 95, 150, /* 184 - 191 */
1928 96, 128, 97, 130, 98, 133, 99, 195, /* 192 - 199 */
1929 100, 128, 101, 123, 102, 164, 103, 138, /* 200 - 207 */
1930 104, 145, 105, 146, 106, 109, 107, 149, /* 208 - 215 */
1931 108, 200, 109, 146, 110, 170, 111, 157, /* 216 - 223 */
1932 112, 128, 113, 130, 114, 182, 115, 132, /* 224 - 231 */
1933 116, 200, 117, 132, 118, 158, 119, 206, /* 232 - 239 */
1934 120, 240, 121, 162, 122, 147, 123, 152, /* 240 - 247 */
1935 124, 166, 125, 214, 126, 138, 127, 153, /* 248 - 255 */
1936 };
1937
1938
1939/* Return the number of multiplications required to calculate
1940 powi(x,n) where n is less than POWI_TABLE_SIZE. This is a
1941 subroutine of powi_cost. CACHE is an array indicating
1942 which exponents have already been calculated. */
1943
1944static int
1945powi_lookup_cost (unsigned HOST_WIDE_INT n, bool *cache)
1946{
1947 /* If we've already calculated this exponent, then this evaluation
1948 doesn't require any additional multiplications. */
1949 if (cache[n])
1950 return 0;
1951
1952 cache[n] = true;
1953 return powi_lookup_cost (n - powi_table[n], cache)
1954 + powi_lookup_cost (powi_table[n], cache) + 1;
1955}
1956
1957/* Return the number of multiplications required to calculate
1958 powi(x,n) for an arbitrary x, given the exponent N. This
1959 function needs to be kept in sync with expand_powi below. */
1960
1961static int
1962powi_cost (HOST_WIDE_INT n)
1963{
1964 bool cache[POWI_TABLE_SIZE];
1965 unsigned HOST_WIDE_INT digit;
1966 unsigned HOST_WIDE_INT val;
1967 int result;
1968
1969 if (n == 0)
1970 return 0;
1971
1972 /* Ignore the reciprocal when calculating the cost. */
1973 val = (n < 0) ? -n : n;
1974
1975 /* Initialize the exponent cache. */
1976 memset (cache, 0, POWI_TABLE_SIZE * sizeof (bool));
1977 cache[1] = true;
1978
1979 result = 0;
1980
1981 while (val >= POWI_TABLE_SIZE)
1982 {
1983 if (val & 1)
1984 {
1985 digit = val & ((1 << POWI_WINDOW_SIZE) - 1);
1986 result += powi_lookup_cost (digit, cache)
1987 + POWI_WINDOW_SIZE + 1;
1988 val >>= POWI_WINDOW_SIZE;
1989 }
1990 else
1991 {
1992 val >>= 1;
1993 result++;
1994 }
1995 }
1996
6881dbab 1997 return result + powi_lookup_cost (val, cache);
f1b844c6 1998}
1999
2000/* Recursive subroutine of expand_powi. This function takes the array,
2001 CACHE, of already calculated exponents and an exponent N and returns
2002 an RTX that corresponds to CACHE[1]**N, as calculated in mode MODE. */
2003
2004static rtx
2005expand_powi_1 (enum machine_mode mode, unsigned HOST_WIDE_INT n, rtx *cache)
2006{
2007 unsigned HOST_WIDE_INT digit;
2008 rtx target, result;
2009 rtx op0, op1;
2010
2011 if (n < POWI_TABLE_SIZE)
2012 {
2013 if (cache[n])
2014 return cache[n];
2015
2016 target = gen_reg_rtx (mode);
2017 cache[n] = target;
2018
2019 op0 = expand_powi_1 (mode, n - powi_table[n], cache);
2020 op1 = expand_powi_1 (mode, powi_table[n], cache);
2021 }
2022 else if (n & 1)
2023 {
2024 target = gen_reg_rtx (mode);
2025 digit = n & ((1 << POWI_WINDOW_SIZE) - 1);
2026 op0 = expand_powi_1 (mode, n - digit, cache);
2027 op1 = expand_powi_1 (mode, digit, cache);
2028 }
2029 else
2030 {
2031 target = gen_reg_rtx (mode);
2032 op0 = expand_powi_1 (mode, n >> 1, cache);
2033 op1 = op0;
2034 }
2035
2036 result = expand_mult (mode, op0, op1, target, 0);
2037 if (result != target)
2038 emit_move_insn (target, result);
2039 return target;
2040}
2041
2042/* Expand the RTL to evaluate powi(x,n) in mode MODE. X is the
2043 floating point operand in mode MODE, and N is the exponent. This
2044 function needs to be kept in sync with powi_cost above. */
2045
2046static rtx
2047expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n)
2048{
2049 unsigned HOST_WIDE_INT val;
2050 rtx cache[POWI_TABLE_SIZE];
2051 rtx result;
2052
2053 if (n == 0)
2054 return CONST1_RTX (mode);
2055
2056 val = (n < 0) ? -n : n;
2057
19bf118a 2058 memset (cache, 0, sizeof (cache));
f1b844c6 2059 cache[1] = x;
2060
2061 result = expand_powi_1 (mode, (n < 0) ? -n : n, cache);
2062
2063 /* If the original exponent was negative, reciprocate the result. */
2064 if (n < 0)
2065 result = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2066 result, NULL_RTX, 0, OPTAB_LIB_WIDEN);
2067
2068 return result;
2069}
2070
2071/* Expand a call to the pow built-in mathematical function. Return 0 if
2072 a normal call should be emitted rather than expanding the function
2073 in-line. EXP is the expression that is a call to the builtin
2074 function; if convenient, the result should be placed in TARGET. */
2075
2076static rtx
2077expand_builtin_pow (tree exp, rtx target, rtx subtarget)
2078{
2079 tree arglist = TREE_OPERAND (exp, 1);
2080 tree arg0, arg1;
2081
2082 if (! validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2083 return 0;
2084
2085 arg0 = TREE_VALUE (arglist);
2086 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
2087
8c5cac78 2088 if (TREE_CODE (arg1) == REAL_CST
f1b844c6 2089 && ! TREE_CONSTANT_OVERFLOW (arg1))
2090 {
2091 REAL_VALUE_TYPE cint;
2092 REAL_VALUE_TYPE c;
2093 HOST_WIDE_INT n;
2094
2095 c = TREE_REAL_CST (arg1);
2096 n = real_to_integer (&c);
2097 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
8c5cac78 2098 if (real_identical (&c, &cint))
f1b844c6 2099 {
8c5cac78 2100 /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
2101 Otherwise, check the number of multiplications required.
2102 Note that pow never sets errno for an integer exponent. */
2103 if ((n >= -1 && n <= 2)
2104 || (flag_unsafe_math_optimizations
2105 && ! optimize_size
2106 && powi_cost (n) <= POWI_MAX_MULTS))
2107 {
2108 enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
2109 rtx op = expand_expr (arg0, subtarget, VOIDmode, 0);
2110 op = force_reg (mode, op);
2111 return expand_powi (op, mode, n);
2112 }
f1b844c6 2113 }
2114 }
2115 return expand_builtin_mathfn_2 (exp, target, NULL_RTX);
2116}
2117
53800dbe 2118/* Expand expression EXP which is a call to the strlen builtin. Return 0
2119 if we failed the caller should emit a normal call, otherwise
aed0bd19 2120 try to get the result in TARGET, if convenient. */
f7c44134 2121
53800dbe 2122static rtx
aecda0d6 2123expand_builtin_strlen (tree arglist, rtx target,
2124 enum machine_mode target_mode)
53800dbe 2125{
0eb671f7 2126 if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
53800dbe 2127 return 0;
2128 else
2129 {
911c0150 2130 rtx pat;
6248e345 2131 tree len, src = TREE_VALUE (arglist);
911c0150 2132 rtx result, src_reg, char_rtx, before_strlen;
80cd7a5e 2133 enum machine_mode insn_mode = target_mode, char_mode;
ef2c4a29 2134 enum insn_code icode = CODE_FOR_nothing;
6248e345 2135 int align;
2136
2137 /* If the length can be computed at compile-time, return it. */
681fab1e 2138 len = c_strlen (src, 0);
6248e345 2139 if (len)
80cd7a5e 2140 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
6248e345 2141
681fab1e 2142 /* If the length can be computed at compile-time and is constant
2143 integer, but there are side-effects in src, evaluate
2144 src for side-effects, then return len.
2145 E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
2146 can be optimized into: i++; x = 3; */
2147 len = c_strlen (src, 1);
2148 if (len && TREE_CODE (len) == INTEGER_CST)
2149 {
2150 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2151 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
2152 }
2153
6248e345 2154 align = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
53800dbe 2155
53800dbe 2156 /* If SRC is not a pointer type, don't do this operation inline. */
2157 if (align == 0)
2158 return 0;
2159
911c0150 2160 /* Bail out if we can't compute strlen in the right mode. */
53800dbe 2161 while (insn_mode != VOIDmode)
2162 {
2163 icode = strlen_optab->handlers[(int) insn_mode].insn_code;
2164 if (icode != CODE_FOR_nothing)
c28ae87f 2165 break;
53800dbe 2166
2167 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
2168 }
2169 if (insn_mode == VOIDmode)
2170 return 0;
2171
2172 /* Make a place to write the result of the instruction. */
2173 result = target;
2174 if (! (result != 0
2175 && GET_CODE (result) == REG
2176 && GET_MODE (result) == insn_mode
2177 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
2178 result = gen_reg_rtx (insn_mode);
2179
911c0150 2180 /* Make a place to hold the source address. We will not expand
2181 the actual source until we are sure that the expansion will
2182 not fail -- there are trees that cannot be expanded twice. */
2183 src_reg = gen_reg_rtx (Pmode);
53800dbe 2184
911c0150 2185 /* Mark the beginning of the strlen sequence so we can emit the
2186 source operand later. */
f0ce3b1f 2187 before_strlen = get_last_insn ();
53800dbe 2188
53800dbe 2189 char_rtx = const0_rtx;
f7c44134 2190 char_mode = insn_data[(int) icode].operand[2].mode;
2191 if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
2192 char_mode))
53800dbe 2193 char_rtx = copy_to_mode_reg (char_mode, char_rtx);
2194
911c0150 2195 pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
2196 char_rtx, GEN_INT (align));
2197 if (! pat)
2198 return 0;
2199 emit_insn (pat);
2200
2201 /* Now that we are assured of success, expand the source. */
2202 start_sequence ();
bf8e3599 2203 pat = memory_address (BLKmode,
f7c44134 2204 expand_expr (src, src_reg, ptr_mode, EXPAND_SUM));
911c0150 2205 if (pat != src_reg)
2206 emit_move_insn (src_reg, pat);
31d3e01c 2207 pat = get_insns ();
911c0150 2208 end_sequence ();
bceb0d1f 2209
2210 if (before_strlen)
2211 emit_insn_after (pat, before_strlen);
2212 else
2213 emit_insn_before (pat, get_insns ());
53800dbe 2214
2215 /* Return the value in the proper mode for this function. */
80cd7a5e 2216 if (GET_MODE (result) == target_mode)
911c0150 2217 target = result;
53800dbe 2218 else if (target != 0)
911c0150 2219 convert_move (target, result, 0);
53800dbe 2220 else
80cd7a5e 2221 target = convert_to_mode (target_mode, result, 0);
911c0150 2222
2223 return target;
53800dbe 2224 }
2225}
2226
17f5ea87 2227/* Expand a call to the strstr builtin. Return 0 if we failed the
2228 caller should emit a normal call, otherwise try to get the result
2229 in TARGET, if convenient (and in mode MODE if that's convenient). */
2230
2231static rtx
aecda0d6 2232expand_builtin_strstr (tree arglist, rtx target, enum machine_mode mode)
17f5ea87 2233{
8a06f2d4 2234 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
17f5ea87 2235 return 0;
2236 else
2237 {
2238 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
7e15618b 2239 tree fn;
83d79705 2240 const char *p1, *p2;
17f5ea87 2241
83d79705 2242 p2 = c_getstr (s2);
2243 if (p2 == NULL)
17f5ea87 2244 return 0;
2245
83d79705 2246 p1 = c_getstr (s1);
2247 if (p1 != NULL)
2248 {
2249 const char *r = strstr (p1, p2);
17f5ea87 2250
83d79705 2251 if (r == NULL)
2252 return const0_rtx;
17f5ea87 2253
83d79705 2254 /* Return an offset into the constant string argument. */
2255 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
2256 s1, ssize_int (r - p1))),
2257 target, mode, EXPAND_NORMAL);
17f5ea87 2258 }
83d79705 2259
2260 if (p2[0] == '\0')
2261 return expand_expr (s1, target, mode, EXPAND_NORMAL);
2262
2263 if (p2[1] != '\0')
2264 return 0;
2265
0a68165a 2266 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
83d79705 2267 if (!fn)
2268 return 0;
2269
2270 /* New argument list transforming strstr(s1, s2) to
2271 strchr(s1, s2[0]). */
2272 arglist =
2273 build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
2274 arglist = tree_cons (NULL_TREE, s1, arglist);
7e15618b 2275 return expand_expr (build_function_call_expr (fn, arglist),
2276 target, mode, EXPAND_NORMAL);
17f5ea87 2277 }
2278}
2279
83d79705 2280/* Expand a call to the strchr builtin. Return 0 if we failed the
46f3a74a 2281 caller should emit a normal call, otherwise try to get the result
2282 in TARGET, if convenient (and in mode MODE if that's convenient). */
2283
2284static rtx
aecda0d6 2285expand_builtin_strchr (tree arglist, rtx target, enum machine_mode mode)
46f3a74a 2286{
8a06f2d4 2287 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
46f3a74a 2288 return 0;
2289 else
2290 {
2291 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
83d79705 2292 const char *p1;
46f3a74a 2293
83d79705 2294 if (TREE_CODE (s2) != INTEGER_CST)
2295 return 0;
2296
2297 p1 = c_getstr (s1);
2298 if (p1 != NULL)
2299 {
ecc318ff 2300 char c;
2301 const char *r;
2302
2303 if (target_char_cast (s2, &c))
2304 return 0;
2305
2306 r = strchr (p1, c);
83d79705 2307
2308 if (r == NULL)
46f3a74a 2309 return const0_rtx;
83d79705 2310
2311 /* Return an offset into the constant string argument. */
2312 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
2313 s1, ssize_int (r - p1))),
2314 target, mode, EXPAND_NORMAL);
46f3a74a 2315 }
2316
83d79705 2317 /* FIXME: Should use here strchrM optab so that ports can optimize
2318 this. */
2319 return 0;
2320 }
2321}
2322
2323/* Expand a call to the strrchr builtin. Return 0 if we failed the
2324 caller should emit a normal call, otherwise try to get the result
2325 in TARGET, if convenient (and in mode MODE if that's convenient). */
2326
2327static rtx
aecda0d6 2328expand_builtin_strrchr (tree arglist, rtx target, enum machine_mode mode)
83d79705 2329{
8a06f2d4 2330 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
83d79705 2331 return 0;
2332 else
2333 {
2334 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
7e15618b 2335 tree fn;
83d79705 2336 const char *p1;
2337
2338 if (TREE_CODE (s2) != INTEGER_CST)
46f3a74a 2339 return 0;
2340
83d79705 2341 p1 = c_getstr (s1);
2342 if (p1 != NULL)
2343 {
ecc318ff 2344 char c;
2345 const char *r;
2346
2347 if (target_char_cast (s2, &c))
2348 return 0;
2349
2350 r = strrchr (p1, c);
83d79705 2351
2352 if (r == NULL)
46f3a74a 2353 return const0_rtx;
46f3a74a 2354
83d79705 2355 /* Return an offset into the constant string argument. */
2356 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
2357 s1, ssize_int (r - p1))),
2358 target, mode, EXPAND_NORMAL);
2359 }
46f3a74a 2360
83d79705 2361 if (! integer_zerop (s2))
2362 return 0;
2363
0a68165a 2364 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
83d79705 2365 if (!fn)
2366 return 0;
2367
2368 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
7e15618b 2369 return expand_expr (build_function_call_expr (fn, arglist),
2370 target, mode, EXPAND_NORMAL);
83d79705 2371 }
2372}
2373
2374/* Expand a call to the strpbrk builtin. Return 0 if we failed the
2375 caller should emit a normal call, otherwise try to get the result
2376 in TARGET, if convenient (and in mode MODE if that's convenient). */
2377
2378static rtx
aecda0d6 2379expand_builtin_strpbrk (tree arglist, rtx target, enum machine_mode mode)
83d79705 2380{
8a06f2d4 2381 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
83d79705 2382 return 0;
2383 else
2384 {
2385 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
7e15618b 2386 tree fn;
83d79705 2387 const char *p1, *p2;
2388
2389 p2 = c_getstr (s2);
2390 if (p2 == NULL)
2391 return 0;
2392
2393 p1 = c_getstr (s1);
2394 if (p1 != NULL)
2395 {
2396 const char *r = strpbrk (p1, p2);
2397
2398 if (r == NULL)
2399 return const0_rtx;
2400
2401 /* Return an offset into the constant string argument. */
2402 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
2403 s1, ssize_int (r - p1))),
2404 target, mode, EXPAND_NORMAL);
46f3a74a 2405 }
83d79705 2406
2407 if (p2[0] == '\0')
2408 {
2409 /* strpbrk(x, "") == NULL.
2410 Evaluate and ignore the arguments in case they had
2411 side-effects. */
2412 expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2413 return const0_rtx;
2414 }
2415
2416 if (p2[1] != '\0')
2417 return 0; /* Really call strpbrk. */
2418
0a68165a 2419 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
83d79705 2420 if (!fn)
2421 return 0;
2422
2423 /* New argument list transforming strpbrk(s1, s2) to
2424 strchr(s1, s2[0]). */
2425 arglist =
2426 build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
2427 arglist = tree_cons (NULL_TREE, s1, arglist);
7e15618b 2428 return expand_expr (build_function_call_expr (fn, arglist),
2429 target, mode, EXPAND_NORMAL);
46f3a74a 2430 }
2431}
2432
6840589f 2433/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
2434 bytes from constant string DATA + OFFSET and return it as target
2435 constant. */
2436
2437static rtx
aecda0d6 2438builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
2439 enum machine_mode mode)
6840589f 2440{
2441 const char *str = (const char *) data;
2442
27d0c333 2443 if (offset < 0
2444 || ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
2445 > strlen (str) + 1))
6840589f 2446 abort (); /* Attempt to read past the end of constant string. */
2447
2448 return c_readstr (str + offset, mode);
2449}
2450
6f428e8b 2451/* Expand a call to the memcpy builtin, with arguments in ARGLIST.
3b824fa6 2452 Return 0 if we failed, the caller should emit a normal call,
2453 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 2454 mode MODE if that's convenient). */
53800dbe 2455static rtx
aecda0d6 2456expand_builtin_memcpy (tree arglist, rtx target, enum machine_mode mode)
53800dbe 2457{
0eb671f7 2458 if (!validate_arglist (arglist,
2459 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 2460 return 0;
2461 else
2462 {
2463 tree dest = TREE_VALUE (arglist);
2464 tree src = TREE_VALUE (TREE_CHAIN (arglist));
2465 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
6840589f 2466 const char *src_str;
27d0c333 2467 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
2468 unsigned int dest_align
2469 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
53800dbe 2470 rtx dest_mem, src_mem, dest_addr, len_rtx;
2471
6f428e8b 2472 /* If DEST is not a pointer type, call the normal function. */
2473 if (dest_align == 0)
9342ee68 2474 return 0;
6f428e8b 2475
2476 /* If the LEN parameter is zero, return DEST. */
2477 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
9342ee68 2478 {
2479 /* Evaluate and ignore SRC in case it has side-effects. */
2480 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2481 return expand_expr (dest, target, mode, EXPAND_NORMAL);
2482 }
6f428e8b 2483
2484 /* If either SRC is not a pointer type, don't do this
2485 operation in-line. */
2486 if (src_align == 0)
9342ee68 2487 return 0;
53800dbe 2488
2489 dest_mem = get_memory_rtx (dest);
2a631e19 2490 set_mem_align (dest_mem, dest_align);
53800dbe 2491 len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
6840589f 2492 src_str = c_getstr (src);
2493
2494 /* If SRC is a string constant and block move would be done
2495 by pieces, we can avoid loading the string from memory
2496 and only stored the computed constants. */
2497 if (src_str
6840589f 2498 && GET_CODE (len_rtx) == CONST_INT
2499 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
2500 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
b9a7cc69 2501 (void *) src_str, dest_align))
6840589f 2502 {
9fe0e1b8 2503 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
2504 builtin_memcpy_read_str,
b9a7cc69 2505 (void *) src_str, dest_align, 0);
e5716f7e 2506 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 2507 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 2508 return dest_mem;
6840589f 2509 }
2510
2511 src_mem = get_memory_rtx (src);
2a631e19 2512 set_mem_align (src_mem, src_align);
53800dbe 2513
53800dbe 2514 /* Copy word part most expediently. */
0378dbdc 2515 dest_addr = emit_block_move (dest_mem, src_mem, len_rtx,
2516 BLOCK_OP_NORMAL);
53800dbe 2517
2518 if (dest_addr == 0)
e5716f7e 2519 {
2520 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 2521 dest_addr = convert_memory_address (ptr_mode, dest_addr);
e5716f7e 2522 }
9fe0e1b8 2523 return dest_addr;
53800dbe 2524 }
2525}
2526
647661c6 2527/* Expand a call to the mempcpy builtin, with arguments in ARGLIST.
2528 Return 0 if we failed the caller should emit a normal call,
2529 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 2530 mode MODE if that's convenient). If ENDP is 0 return the
2531 destination pointer, if ENDP is 1 return the end pointer ala
2532 mempcpy, and if ENDP is 2 return the end pointer minus one ala
2533 stpcpy. */
647661c6 2534
2535static rtx
aecda0d6 2536expand_builtin_mempcpy (tree arglist, rtx target, enum machine_mode mode,
2537 int endp)
647661c6 2538{
2539 if (!validate_arglist (arglist,
2540 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2541 return 0;
9fe0e1b8 2542 /* If return value is ignored, transform mempcpy into memcpy. */
2543 else if (target == const0_rtx)
2544 {
2545 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
2546
2547 if (!fn)
2548 return 0;
2549
2550 return expand_expr (build_function_call_expr (fn, arglist),
2551 target, mode, EXPAND_NORMAL);
2552 }
647661c6 2553 else
2554 {
9fe0e1b8 2555 tree dest = TREE_VALUE (arglist);
2556 tree src = TREE_VALUE (TREE_CHAIN (arglist));
2557 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2558 const char *src_str;
2559 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
2560 unsigned int dest_align
2561 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2562 rtx dest_mem, src_mem, len_rtx;
2563
6217c238 2564 /* If DEST is not a pointer type, call the normal function. */
2565 if (dest_align == 0)
9fe0e1b8 2566 return 0;
2567
6217c238 2568 /* If SRC and DEST are the same (and not volatile), do nothing. */
2569 if (operand_equal_p (src, dest, 0))
2570 {
2571 tree expr;
2572
2573 if (endp == 0)
2574 {
2575 /* Evaluate and ignore LEN in case it has side-effects. */
2576 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
2577 return expand_expr (dest, target, mode, EXPAND_NORMAL);
2578 }
2579
2580 if (endp == 2)
2581 len = fold (build (MINUS_EXPR, TREE_TYPE (len), dest,
2582 integer_one_node));
2583 len = convert (TREE_TYPE (dest), len);
2584 expr = fold (build (PLUS_EXPR, TREE_TYPE (dest), dest, len));
2585 return expand_expr (expr, target, mode, EXPAND_NORMAL);
2586 }
2587
2588 /* If LEN is not constant, call the normal function. */
2589 if (! host_integerp (len, 1))
2590 return 0;
2591
9fe0e1b8 2592 /* If the LEN parameter is zero, return DEST. */
2593 if (tree_low_cst (len, 1) == 0)
647661c6 2594 {
9fe0e1b8 2595 /* Evaluate and ignore SRC in case it has side-effects. */
2596 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2597 return expand_expr (dest, target, mode, EXPAND_NORMAL);
2598 }
647661c6 2599
6217c238 2600 /* If SRC and DEST are the same (and not volatile), return DEST. */
2601 if (operand_equal_p (src, dest, 0))
2602 {
2603 /* Evaluate and ignore LEN in case it has side-effects. */
2604 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
2605 return expand_expr (dest, target, mode, EXPAND_NORMAL);
2606 }
2607
9fe0e1b8 2608 /* If either SRC is not a pointer type, don't do this
2609 operation in-line. */
2610 if (src_align == 0)
2611 return 0;
647661c6 2612
9fe0e1b8 2613 len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2614 src_str = c_getstr (src);
647661c6 2615
9fe0e1b8 2616 /* If SRC is a string constant and block move would be done
2617 by pieces, we can avoid loading the string from memory
2618 and only stored the computed constants. */
2619 if (src_str
2620 && GET_CODE (len_rtx) == CONST_INT
2621 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
2622 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
b9a7cc69 2623 (void *) src_str, dest_align))
9fe0e1b8 2624 {
2625 dest_mem = get_memory_rtx (dest);
2626 set_mem_align (dest_mem, dest_align);
2627 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
2628 builtin_memcpy_read_str,
b9a7cc69 2629 (void *) src_str, dest_align, endp);
9fe0e1b8 2630 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 2631 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 2632 return dest_mem;
647661c6 2633 }
2634
9fe0e1b8 2635 if (GET_CODE (len_rtx) == CONST_INT
2636 && can_move_by_pieces (INTVAL (len_rtx),
2637 MIN (dest_align, src_align)))
2638 {
2639 dest_mem = get_memory_rtx (dest);
2640 set_mem_align (dest_mem, dest_align);
2641 src_mem = get_memory_rtx (src);
2642 set_mem_align (src_mem, src_align);
2643 dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
2644 MIN (dest_align, src_align), endp);
2645 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 2646 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 2647 return dest_mem;
2648 }
2649
2650 return 0;
647661c6 2651 }
2652}
2653
c4950093 2654/* Expand expression EXP, which is a call to the memmove builtin. Return 0
2655 if we failed the caller should emit a normal call. */
2656
2657static rtx
aecda0d6 2658expand_builtin_memmove (tree arglist, rtx target, enum machine_mode mode)
c4950093 2659{
2660 if (!validate_arglist (arglist,
2661 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2662 return 0;
2663 else
2664 {
2665 tree dest = TREE_VALUE (arglist);
2666 tree src = TREE_VALUE (TREE_CHAIN (arglist));
2667 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2668
2669 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
2670 unsigned int dest_align
2671 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2672
2673 /* If DEST is not a pointer type, call the normal function. */
2674 if (dest_align == 0)
2675 return 0;
2676
2677 /* If the LEN parameter is zero, return DEST. */
2678 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
2679 {
2680 /* Evaluate and ignore SRC in case it has side-effects. */
2681 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2682 return expand_expr (dest, target, mode, EXPAND_NORMAL);
2683 }
2684
6217c238 2685 /* If SRC and DEST are the same (and not volatile), return DEST. */
2686 if (operand_equal_p (src, dest, 0))
2687 {
2688 /* Evaluate and ignore LEN in case it has side-effects. */
2689 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
2690 return expand_expr (dest, target, mode, EXPAND_NORMAL);
2691 }
2692
c4950093 2693 /* If either SRC is not a pointer type, don't do this
2694 operation in-line. */
2695 if (src_align == 0)
2696 return 0;
2697
01537105 2698 /* If src is categorized for a readonly section we can use
2699 normal memcpy. */
2700 if (readonly_data_expr (src))
2701 {
2702 tree const fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
2703 if (!fn)
2704 return 0;
2705 return expand_expr (build_function_call_expr (fn, arglist),
2706 target, mode, EXPAND_NORMAL);
2707 }
c4950093 2708
2709 /* Otherwise, call the normal function. */
2710 return 0;
2711 }
2712}
2713
2714/* Expand expression EXP, which is a call to the bcopy builtin. Return 0
2715 if we failed the caller should emit a normal call. */
2716
2717static rtx
aecda0d6 2718expand_builtin_bcopy (tree arglist)
c4950093 2719{
2720 tree src, dest, size, newarglist;
2721
2722 if (!validate_arglist (arglist,
2723 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2724 return NULL_RTX;
2725
2726 src = TREE_VALUE (arglist);
2727 dest = TREE_VALUE (TREE_CHAIN (arglist));
2728 size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2729
2730 /* New argument list transforming bcopy(ptr x, ptr y, int z) to
2731 memmove(ptr y, ptr x, size_t z). This is done this way
2732 so that if it isn't expanded inline, we fallback to
2733 calling bcopy instead of memmove. */
2734
2735 newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
2736 newarglist = tree_cons (NULL_TREE, src, newarglist);
2737 newarglist = tree_cons (NULL_TREE, dest, newarglist);
2738
2739 return expand_builtin_memmove (newarglist, const0_rtx, VOIDmode);
2740}
2741
53800dbe 2742/* Expand expression EXP, which is a call to the strcpy builtin. Return 0
6f428e8b 2743 if we failed the caller should emit a normal call, otherwise try to get
2744 the result in TARGET, if convenient (and in mode MODE if that's
2745 convenient). */
902de8ed 2746
53800dbe 2747static rtx
aecda0d6 2748expand_builtin_strcpy (tree arglist, rtx target, enum machine_mode mode)
53800dbe 2749{
6411575e 2750 tree fn, len, src, dst;
53800dbe 2751
0eb671f7 2752 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
53800dbe 2753 return 0;
53800dbe 2754
6217c238 2755 src = TREE_VALUE (TREE_CHAIN (arglist));
2756 dst = TREE_VALUE (arglist);
2757
2758 /* If SRC and DST are equal (and not volatile), return DST. */
2759 if (operand_equal_p (src, dst, 0))
2760 return expand_expr (dst, target, mode, EXPAND_NORMAL);
2761
0a68165a 2762 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
6f428e8b 2763 if (!fn)
2764 return 0;
902de8ed 2765
681fab1e 2766 len = c_strlen (src, 1);
5c23237b 2767 if (len == 0 || TREE_SIDE_EFFECTS (len))
6f428e8b 2768 return 0;
902de8ed 2769
6f428e8b 2770 len = size_binop (PLUS_EXPR, len, ssize_int (1));
6411575e 2771 arglist = build_tree_list (NULL_TREE, len);
2772 arglist = tree_cons (NULL_TREE, src, arglist);
2773 arglist = tree_cons (NULL_TREE, dst, arglist);
6f428e8b 2774 return expand_expr (build_function_call_expr (fn, arglist),
9342ee68 2775 target, mode, EXPAND_NORMAL);
53800dbe 2776}
2777
3b824fa6 2778/* Expand a call to the stpcpy builtin, with arguments in ARGLIST.
2779 Return 0 if we failed the caller should emit a normal call,
2780 otherwise try to get the result in TARGET, if convenient (and in
2781 mode MODE if that's convenient). */
2782
2783static rtx
aecda0d6 2784expand_builtin_stpcpy (tree arglist, rtx target, enum machine_mode mode)
3b824fa6 2785{
2786 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2787 return 0;
2788 else
2789 {
6411575e 2790 tree dst, src, len;
647661c6 2791
2792 /* If return value is ignored, transform stpcpy into strcpy. */
2793 if (target == const0_rtx)
2794 {
9fe0e1b8 2795 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
647661c6 2796 if (!fn)
2797 return 0;
2798
2799 return expand_expr (build_function_call_expr (fn, arglist),
2800 target, mode, EXPAND_NORMAL);
2801 }
2802
9fe0e1b8 2803 /* Ensure we get an actual string whose length can be evaluated at
c04062e9 2804 compile-time, not an expression containing a string. This is
2805 because the latter will potentially produce pessimized code
2806 when used to produce the return value. */
2807 src = TREE_VALUE (TREE_CHAIN (arglist));
681fab1e 2808 if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
3b824fa6 2809 return 0;
2810
6411575e 2811 dst = TREE_VALUE (arglist);
3b824fa6 2812 len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
6411575e 2813 arglist = build_tree_list (NULL_TREE, len);
2814 arglist = tree_cons (NULL_TREE, src, arglist);
2815 arglist = tree_cons (NULL_TREE, dst, arglist);
2816 return expand_builtin_mempcpy (arglist, target, mode, /*endp=*/2);
3b824fa6 2817 }
2818}
2819
6840589f 2820/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
2821 bytes from constant string DATA + OFFSET and return it as target
2822 constant. */
2823
2824static rtx
aecda0d6 2825builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
2826 enum machine_mode mode)
6840589f 2827{
2828 const char *str = (const char *) data;
2829
2830 if ((unsigned HOST_WIDE_INT) offset > strlen (str))
2831 return const0_rtx;
2832
2833 return c_readstr (str + offset, mode);
2834}
2835
ed09096d 2836/* Expand expression EXP, which is a call to the strncpy builtin. Return 0
2837 if we failed the caller should emit a normal call. */
2838
2839static rtx
aecda0d6 2840expand_builtin_strncpy (tree arglist, rtx target, enum machine_mode mode)
ed09096d 2841{
0eb671f7 2842 if (!validate_arglist (arglist,
2843 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
ed09096d 2844 return 0;
2845 else
2846 {
681fab1e 2847 tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)), 1);
ed09096d 2848 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
6f428e8b 2849 tree fn;
ed09096d 2850
2851 /* We must be passed a constant len parameter. */
2852 if (TREE_CODE (len) != INTEGER_CST)
2853 return 0;
2854
2855 /* If the len parameter is zero, return the dst parameter. */
df5c389e 2856 if (integer_zerop (len))
9342ee68 2857 {
2858 /* Evaluate and ignore the src argument in case it has
2859 side-effects. */
ed09096d 2860 expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
2861 VOIDmode, EXPAND_NORMAL);
bf8e3599 2862 /* Return the dst parameter. */
ed09096d 2863 return expand_expr (TREE_VALUE (arglist), target, mode,
2864 EXPAND_NORMAL);
2865 }
6840589f 2866
ed09096d 2867 /* Now, we must be passed a constant src ptr parameter. */
6840589f 2868 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
ed09096d 2869 return 0;
2870
2871 slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
2872
2873 /* We're required to pad with trailing zeros if the requested
6840589f 2874 len is greater than strlen(s2)+1. In that case try to
2875 use store_by_pieces, if it fails, punt. */
ed09096d 2876 if (tree_int_cst_lt (slen, len))
6840589f 2877 {
2878 tree dest = TREE_VALUE (arglist);
27d0c333 2879 unsigned int dest_align
2880 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
6840589f 2881 const char *p = c_getstr (TREE_VALUE (TREE_CHAIN (arglist)));
2882 rtx dest_mem;
2883
27d0c333 2884 if (!p || dest_align == 0 || !host_integerp (len, 1)
2885 || !can_store_by_pieces (tree_low_cst (len, 1),
6840589f 2886 builtin_strncpy_read_str,
b9a7cc69 2887 (void *) p, dest_align))
6840589f 2888 return 0;
2889
2890 dest_mem = get_memory_rtx (dest);
27d0c333 2891 store_by_pieces (dest_mem, tree_low_cst (len, 1),
6840589f 2892 builtin_strncpy_read_str,
b9a7cc69 2893 (void *) p, dest_align, 0);
e5716f7e 2894 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 2895 dest_mem = convert_memory_address (ptr_mode, dest_mem);
e5716f7e 2896 return dest_mem;
6840589f 2897 }
bf8e3599 2898
ed09096d 2899 /* OK transform into builtin memcpy. */
0a68165a 2900 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
6f428e8b 2901 if (!fn)
9342ee68 2902 return 0;
6f428e8b 2903 return expand_expr (build_function_call_expr (fn, arglist),
9342ee68 2904 target, mode, EXPAND_NORMAL);
ed09096d 2905 }
2906}
2907
ecc318ff 2908/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
2909 bytes from constant string DATA + OFFSET and return it as target
2910 constant. */
2911
2912static rtx
aecda0d6 2913builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
2914 enum machine_mode mode)
ecc318ff 2915{
2916 const char *c = (const char *) data;
2917 char *p = alloca (GET_MODE_SIZE (mode));
2918
2919 memset (p, *c, GET_MODE_SIZE (mode));
2920
2921 return c_readstr (p, mode);
2922}
2923
a7ec6974 2924/* Callback routine for store_by_pieces. Return the RTL of a register
2925 containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
2926 char value given in the RTL register data. For example, if mode is
2927 4 bytes wide, return the RTL for 0x01010101*data. */
2928
2929static rtx
aecda0d6 2930builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
2931 enum machine_mode mode)
a7ec6974 2932{
2933 rtx target, coeff;
2934 size_t size;
2935 char *p;
2936
2937 size = GET_MODE_SIZE (mode);
f0ce3b1f 2938 if (size == 1)
2939 return (rtx) data;
a7ec6974 2940
2941 p = alloca (size);
2942 memset (p, 1, size);
2943 coeff = c_readstr (p, mode);
2944
f0ce3b1f 2945 target = convert_to_mode (mode, (rtx) data, 1);
a7ec6974 2946 target = expand_mult (mode, target, coeff, NULL_RTX, 1);
2947 return force_reg (mode, target);
2948}
2949
53800dbe 2950/* Expand expression EXP, which is a call to the memset builtin. Return 0
6f428e8b 2951 if we failed the caller should emit a normal call, otherwise try to get
2952 the result in TARGET, if convenient (and in mode MODE if that's
2953 convenient). */
902de8ed 2954
53800dbe 2955static rtx
aecda0d6 2956expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode)
53800dbe 2957{
0eb671f7 2958 if (!validate_arglist (arglist,
2959 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 2960 return 0;
2961 else
2962 {
2963 tree dest = TREE_VALUE (arglist);
2964 tree val = TREE_VALUE (TREE_CHAIN (arglist));
2965 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
ecc318ff 2966 char c;
53800dbe 2967
27d0c333 2968 unsigned int dest_align
2969 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
53800dbe 2970 rtx dest_mem, dest_addr, len_rtx;
2971
bf8e3599 2972 /* If DEST is not a pointer type, don't do this
53800dbe 2973 operation in-line. */
2974 if (dest_align == 0)
2975 return 0;
2976
6f428e8b 2977 /* If the LEN parameter is zero, return DEST. */
2978 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
9342ee68 2979 {
2980 /* Evaluate and ignore VAL in case it has side-effects. */
2981 expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
2982 return expand_expr (dest, target, mode, EXPAND_NORMAL);
2983 }
6f428e8b 2984
ecc318ff 2985 if (TREE_CODE (val) != INTEGER_CST)
9342ee68 2986 {
2987 rtx val_rtx;
a7ec6974 2988
9342ee68 2989 if (!host_integerp (len, 1))
2990 return 0;
a7ec6974 2991
9342ee68 2992 if (optimize_size && tree_low_cst (len, 1) > 1)
2993 return 0;
a7ec6974 2994
9342ee68 2995 /* Assume that we can memset by pieces if we can store the
2996 * the coefficients by pieces (in the required modes).
2997 * We can't pass builtin_memset_gen_str as that emits RTL. */
2998 c = 1;
a7ec6974 2999 if (!can_store_by_pieces (tree_low_cst (len, 1),
3000 builtin_memset_read_str,
b9a7cc69 3001 &c, dest_align))
a7ec6974 3002 return 0;
3003
9342ee68 3004 val = fold (build1 (CONVERT_EXPR, unsigned_char_type_node, val));
3005 val_rtx = expand_expr (val, NULL_RTX, VOIDmode, 0);
3006 val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
3007 val_rtx);
a7ec6974 3008 dest_mem = get_memory_rtx (dest);
3009 store_by_pieces (dest_mem, tree_low_cst (len, 1),
3010 builtin_memset_gen_str,
b9a7cc69 3011 val_rtx, dest_align, 0);
e5716f7e 3012 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3013 dest_mem = convert_memory_address (ptr_mode, dest_mem);
e5716f7e 3014 return dest_mem;
9342ee68 3015 }
53800dbe 3016
ecc318ff 3017 if (target_char_cast (val, &c))
53800dbe 3018 return 0;
3019
ecc318ff 3020 if (c)
3021 {
27d0c333 3022 if (!host_integerp (len, 1))
ecc318ff 3023 return 0;
8a06f2d4 3024 if (!can_store_by_pieces (tree_low_cst (len, 1),
b9a7cc69 3025 builtin_memset_read_str, &c,
8a06f2d4 3026 dest_align))
ecc318ff 3027 return 0;
3028
3029 dest_mem = get_memory_rtx (dest);
27d0c333 3030 store_by_pieces (dest_mem, tree_low_cst (len, 1),
ecc318ff 3031 builtin_memset_read_str,
b9a7cc69 3032 &c, dest_align, 0);
e5716f7e 3033 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3034 dest_mem = convert_memory_address (ptr_mode, dest_mem);
e5716f7e 3035 return dest_mem;
ecc318ff 3036 }
3037
53800dbe 3038 len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
53800dbe 3039
3040 dest_mem = get_memory_rtx (dest);
2a631e19 3041 set_mem_align (dest_mem, dest_align);
2a631e19 3042 dest_addr = clear_storage (dest_mem, len_rtx);
53800dbe 3043
3044 if (dest_addr == 0)
e5716f7e 3045 {
3046 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3047 dest_addr = convert_memory_address (ptr_mode, dest_addr);
e5716f7e 3048 }
53800dbe 3049
3050 return dest_addr;
3051 }
3052}
3053
ffc83088 3054/* Expand expression EXP, which is a call to the bzero builtin. Return 0
3055 if we failed the caller should emit a normal call. */
27d0c333 3056
ffc83088 3057static rtx
aecda0d6 3058expand_builtin_bzero (tree arglist)
ffc83088 3059{
7369e7ba 3060 tree dest, size, newarglist;
ffc83088 3061
0eb671f7 3062 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
7369e7ba 3063 return NULL_RTX;
ffc83088 3064
0eb671f7 3065 dest = TREE_VALUE (arglist);
3066 size = TREE_VALUE (TREE_CHAIN (arglist));
bf8e3599 3067
7369e7ba 3068 /* New argument list transforming bzero(ptr x, int y) to
6f428e8b 3069 memset(ptr x, int 0, size_t y). This is done this way
3070 so that if it isn't expanded inline, we fallback to
3071 calling bzero instead of memset. */
bf8e3599 3072
7369e7ba 3073 newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
3074 newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
3075 newarglist = tree_cons (NULL_TREE, dest, newarglist);
ffc83088 3076
80cd7a5e 3077 return expand_builtin_memset (newarglist, const0_rtx, VOIDmode);
ffc83088 3078}
3079
7a3f89b5 3080/* Expand expression EXP, which is a call to the memcmp built-in function.
53800dbe 3081 ARGLIST is the argument list for this call. Return 0 if we failed and the
3082 caller should emit a normal call, otherwise try to get the result in
6f428e8b 3083 TARGET, if convenient (and in mode MODE, if that's convenient). */
27d0c333 3084
53800dbe 3085static rtx
aecda0d6 3086expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
3087 enum machine_mode mode)
53800dbe 3088{
6f428e8b 3089 tree arg1, arg2, len;
d470d782 3090 const char *p1, *p2;
6f428e8b 3091
0eb671f7 3092 if (!validate_arglist (arglist,
9342ee68 3093 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 3094 return 0;
53800dbe 3095
6f428e8b 3096 arg1 = TREE_VALUE (arglist);
3097 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3098 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3099
3100 /* If the len parameter is zero, return zero. */
3101 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
3102 {
3103 /* Evaluate and ignore arg1 and arg2 in case they have
3104 side-effects. */
3105 expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
3106 expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
3107 return const0_rtx;
3108 }
3109
6217c238 3110 /* If both arguments are equal (and not volatile), return zero. */
3111 if (operand_equal_p (arg1, arg2, 0))
3112 {
3113 /* Evaluate and ignore len in case it has side-effects. */
3114 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
3115 return const0_rtx;
3116 }
3117
d470d782 3118 p1 = c_getstr (arg1);
3119 p2 = c_getstr (arg2);
3120
3121 /* If all arguments are constant, and the value of len is not greater
3122 than the lengths of arg1 and arg2, evaluate at compile-time. */
3123 if (host_integerp (len, 1) && p1 && p2
df5c389e 3124 && compare_tree_int (len, strlen (p1) + 1) <= 0
3125 && compare_tree_int (len, strlen (p2) + 1) <= 0)
d470d782 3126 {
3127 const int r = memcmp (p1, p2, tree_low_cst (len, 1));
df5c389e 3128
d470d782 3129 return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
3130 }
3131
6f428e8b 3132 /* If len parameter is one, return an expression corresponding to
3133 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
3134 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
3135 {
3136 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
3137 tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
3138 tree ind1 =
3139 fold (build1 (CONVERT_EXPR, integer_type_node,
9342ee68 3140 build1 (INDIRECT_REF, cst_uchar_node,
3141 build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
6f428e8b 3142 tree ind2 =
3143 fold (build1 (CONVERT_EXPR, integer_type_node,
9342ee68 3144 build1 (INDIRECT_REF, cst_uchar_node,
3145 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
6f428e8b 3146 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
3147 return expand_expr (result, target, mode, EXPAND_NORMAL);
3148 }
3149
b428c0a5 3150#if defined HAVE_cmpmemsi || defined HAVE_cmpstrsi
53800dbe 3151 {
0cd832f0 3152 rtx arg1_rtx, arg2_rtx, arg3_rtx;
53800dbe 3153 rtx result;
0cd832f0 3154 rtx insn;
53800dbe 3155
3156 int arg1_align
3157 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3158 int arg2_align
3159 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
b428c0a5 3160 enum machine_mode insn_mode;
3161
3162#ifdef HAVE_cmpmemsi
3163 if (HAVE_cmpmemsi)
3164 insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
3165 else
3166#endif
3167#ifdef HAVE_cmpstrsi
3168 if (HAVE_cmpstrsi)
3169 insn_mode = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3170 else
3171#endif
3172 return 0;
53800dbe 3173
3174 /* If we don't have POINTER_TYPE, call the function. */
3175 if (arg1_align == 0 || arg2_align == 0)
3176 return 0;
3177
3178 /* Make a place to write the result of the instruction. */
3179 result = target;
3180 if (! (result != 0
3181 && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
3182 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3183 result = gen_reg_rtx (insn_mode);
3184
0cd832f0 3185 arg1_rtx = get_memory_rtx (arg1);
3186 arg2_rtx = get_memory_rtx (arg2);
3187 arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
b428c0a5 3188#ifdef HAVE_cmpmemsi
3189 if (HAVE_cmpmemsi)
3190 insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3191 GEN_INT (MIN (arg1_align, arg2_align)));
0cd832f0 3192 else
b428c0a5 3193#endif
3194#ifdef HAVE_cmpstrsi
3195 if (HAVE_cmpstrsi)
0cd832f0 3196 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3197 GEN_INT (MIN (arg1_align, arg2_align)));
b428c0a5 3198 else
3199#endif
3200 abort ();
0cd832f0 3201
3202 if (insn)
3203 emit_insn (insn);
3204 else
2c5d421b 3205 emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK,
0cd832f0 3206 TYPE_MODE (integer_type_node), 3,
3207 XEXP (arg1_rtx, 0), Pmode,
3208 XEXP (arg2_rtx, 0), Pmode,
3209 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
3210 TREE_UNSIGNED (sizetype)),
3211 TYPE_MODE (sizetype));
53800dbe 3212
3213 /* Return the value in the proper mode for this function. */
3214 mode = TYPE_MODE (TREE_TYPE (exp));
3215 if (GET_MODE (result) == mode)
3216 return result;
3217 else if (target != 0)
3218 {
3219 convert_move (target, result, 0);
3220 return target;
3221 }
3222 else
3223 return convert_to_mode (mode, result, 0);
3224 }
83d79705 3225#endif
53800dbe 3226
6f428e8b 3227 return 0;
3228}
3229
53800dbe 3230/* Expand expression EXP, which is a call to the strcmp builtin. Return 0
3231 if we failed the caller should emit a normal call, otherwise try to get
3232 the result in TARGET, if convenient. */
902de8ed 3233
53800dbe 3234static rtx
aecda0d6 3235expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
53800dbe 3236{
3237 tree arglist = TREE_OPERAND (exp, 1);
7a3f89b5 3238 tree arg1, arg2;
83d79705 3239 const char *p1, *p2;
53800dbe 3240
0eb671f7 3241 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
53800dbe 3242 return 0;
902de8ed 3243
83d79705 3244 arg1 = TREE_VALUE (arglist);
3245 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3246
6217c238 3247 /* If both arguments are equal (and not volatile), return zero. */
3248 if (operand_equal_p (arg1, arg2, 0))
3249 return const0_rtx;
3250
83d79705 3251 p1 = c_getstr (arg1);
3252 p2 = c_getstr (arg2);
3253
3254 if (p1 && p2)
3255 {
ef6c187e 3256 const int i = strcmp (p1, p2);
3257 return (i < 0 ? constm1_rtx : (i > 0 ? const1_rtx : const0_rtx));
83d79705 3258 }
3259
ef6c187e 3260 /* If either arg is "", return an expression corresponding to
3261 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
3262 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
3263 {
3264 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
3265 tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
3266 tree ind1 =
3267 fold (build1 (CONVERT_EXPR, integer_type_node,
3268 build1 (INDIRECT_REF, cst_uchar_node,
3269 build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
3270 tree ind2 =
3271 fold (build1 (CONVERT_EXPR, integer_type_node,
3272 build1 (INDIRECT_REF, cst_uchar_node,
3273 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
3274 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
3275 return expand_expr (result, target, mode, EXPAND_NORMAL);
3276 }
bf8e3599 3277
7a3f89b5 3278#ifdef HAVE_cmpstrsi
3279 if (HAVE_cmpstrsi)
3280 {
3281 tree len, len1, len2;
3282 rtx arg1_rtx, arg2_rtx, arg3_rtx;
3283 rtx result, insn;
902de8ed 3284
7a3f89b5 3285 int arg1_align
3286 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3287 int arg2_align
3288 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3289 enum machine_mode insn_mode
3290 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
902de8ed 3291
681fab1e 3292 len1 = c_strlen (arg1, 1);
3293 len2 = c_strlen (arg2, 1);
7a3f89b5 3294
3295 if (len1)
3296 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3297 if (len2)
3298 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3299
3300 /* If we don't have a constant length for the first, use the length
3301 of the second, if we know it. We don't require a constant for
3302 this case; some cost analysis could be done if both are available
3303 but neither is constant. For now, assume they're equally cheap,
3304 unless one has side effects. If both strings have constant lengths,
3305 use the smaller. */
3306
3307 if (!len1)
3308 len = len2;
3309 else if (!len2)
3310 len = len1;
3311 else if (TREE_SIDE_EFFECTS (len1))
3312 len = len2;
3313 else if (TREE_SIDE_EFFECTS (len2))
3314 len = len1;
3315 else if (TREE_CODE (len1) != INTEGER_CST)
3316 len = len2;
3317 else if (TREE_CODE (len2) != INTEGER_CST)
3318 len = len1;
3319 else if (tree_int_cst_lt (len1, len2))
3320 len = len1;
3321 else
3322 len = len2;
53800dbe 3323
7a3f89b5 3324 /* If both arguments have side effects, we cannot optimize. */
3325 if (!len || TREE_SIDE_EFFECTS (len))
3326 return 0;
53800dbe 3327
7a3f89b5 3328 /* If we don't have POINTER_TYPE, call the function. */
3329 if (arg1_align == 0 || arg2_align == 0)
3330 return 0;
902de8ed 3331
7a3f89b5 3332 /* Make a place to write the result of the instruction. */
3333 result = target;
3334 if (! (result != 0
3335 && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
3336 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3337 result = gen_reg_rtx (insn_mode);
53800dbe 3338
7a3f89b5 3339 arg1_rtx = get_memory_rtx (arg1);
3340 arg2_rtx = get_memory_rtx (arg2);
3341 arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3342 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3343 GEN_INT (MIN (arg1_align, arg2_align)));
3344 if (!insn)
3345 return 0;
6840589f 3346
7a3f89b5 3347 emit_insn (insn);
902de8ed 3348
7a3f89b5 3349 /* Return the value in the proper mode for this function. */
3350 mode = TYPE_MODE (TREE_TYPE (exp));
3351 if (GET_MODE (result) == mode)
3352 return result;
3353 if (target == 0)
3354 return convert_to_mode (mode, result, 0);
3355 convert_move (target, result, 0);
3356 return target;
3357 }
3358#endif
3359 return 0;
83d79705 3360}
53800dbe 3361
ed09096d 3362/* Expand expression EXP, which is a call to the strncmp builtin. Return 0
3363 if we failed the caller should emit a normal call, otherwise try to get
3364 the result in TARGET, if convenient. */
27d0c333 3365
ed09096d 3366static rtx
aecda0d6 3367expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
ed09096d 3368{
3369 tree arglist = TREE_OPERAND (exp, 1);
3370 tree arg1, arg2, arg3;
3371 const char *p1, *p2;
3372
0eb671f7 3373 if (!validate_arglist (arglist,
3374 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
ed09096d 3375 return 0;
3376
3377 arg1 = TREE_VALUE (arglist);
3378 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3379 arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3380
ed09096d 3381 /* If the len parameter is zero, return zero. */
6e34e617 3382 if (host_integerp (arg3, 1) && tree_low_cst (arg3, 1) == 0)
9342ee68 3383 {
3384 /* Evaluate and ignore arg1 and arg2 in case they have
3385 side-effects. */
3386 expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
3387 expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
3388 return const0_rtx;
3389 }
ed09096d 3390
6217c238 3391 /* If arg1 and arg2 are equal (and not volatile), return zero. */
3392 if (operand_equal_p (arg1, arg2, 0))
3393 {
3394 /* Evaluate and ignore arg3 in case it has side-effects. */
3395 expand_expr (arg3, const0_rtx, VOIDmode, EXPAND_NORMAL);
3396 return const0_rtx;
3397 }
3398
ed09096d 3399 p1 = c_getstr (arg1);
3400 p2 = c_getstr (arg2);
3401
3402 /* If all arguments are constant, evaluate at compile-time. */
6e34e617 3403 if (host_integerp (arg3, 1) && p1 && p2)
9342ee68 3404 {
3405 const int r = strncmp (p1, p2, tree_low_cst (arg3, 1));
3406 return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
3407 }
ed09096d 3408
ef6c187e 3409 /* If len == 1 or (either string parameter is "" and (len >= 1)),
6e34e617 3410 return (*(const u_char*)arg1 - *(const u_char*)arg2). */
3411 if (host_integerp (arg3, 1)
3412 && (tree_low_cst (arg3, 1) == 1
3413 || (tree_low_cst (arg3, 1) > 1
3414 && ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')))))
ef6c187e 3415 {
3416 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
3417 tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
3418 tree ind1 =
3419 fold (build1 (CONVERT_EXPR, integer_type_node,
3420 build1 (INDIRECT_REF, cst_uchar_node,
3421 build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
3422 tree ind2 =
3423 fold (build1 (CONVERT_EXPR, integer_type_node,
3424 build1 (INDIRECT_REF, cst_uchar_node,
3425 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
3426 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
3427 return expand_expr (result, target, mode, EXPAND_NORMAL);
3428 }
ed09096d 3429
6e34e617 3430 /* If c_strlen can determine an expression for one of the string
7a3f89b5 3431 lengths, and it doesn't have side effects, then emit cmpstrsi
3432 using length MIN(strlen(string)+1, arg3). */
3433#ifdef HAVE_cmpstrsi
3434 if (HAVE_cmpstrsi)
3435 {
3436 tree len, len1, len2;
3437 rtx arg1_rtx, arg2_rtx, arg3_rtx;
3438 rtx result, insn;
6f428e8b 3439
7a3f89b5 3440 int arg1_align
3441 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3442 int arg2_align
3443 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3444 enum machine_mode insn_mode
3445 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
bf8e3599 3446
681fab1e 3447 len1 = c_strlen (arg1, 1);
3448 len2 = c_strlen (arg2, 1);
7a3f89b5 3449
3450 if (len1)
3451 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3452 if (len2)
3453 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3454
3455 /* If we don't have a constant length for the first, use the length
3456 of the second, if we know it. We don't require a constant for
3457 this case; some cost analysis could be done if both are available
3458 but neither is constant. For now, assume they're equally cheap,
3459 unless one has side effects. If both strings have constant lengths,
3460 use the smaller. */
3461
3462 if (!len1)
3463 len = len2;
3464 else if (!len2)
3465 len = len1;
3466 else if (TREE_SIDE_EFFECTS (len1))
3467 len = len2;
3468 else if (TREE_SIDE_EFFECTS (len2))
3469 len = len1;
3470 else if (TREE_CODE (len1) != INTEGER_CST)
3471 len = len2;
3472 else if (TREE_CODE (len2) != INTEGER_CST)
3473 len = len1;
3474 else if (tree_int_cst_lt (len1, len2))
3475 len = len1;
3476 else
3477 len = len2;
6e34e617 3478
7a3f89b5 3479 /* If both arguments have side effects, we cannot optimize. */
3480 if (!len || TREE_SIDE_EFFECTS (len))
3481 return 0;
bf8e3599 3482
7a3f89b5 3483 /* The actual new length parameter is MIN(len,arg3). */
3484 len = fold (build (MIN_EXPR, TREE_TYPE (len), len, arg3));
3485
3486 /* If we don't have POINTER_TYPE, call the function. */
3487 if (arg1_align == 0 || arg2_align == 0)
3488 return 0;
3489
3490 /* Make a place to write the result of the instruction. */
3491 result = target;
3492 if (! (result != 0
3493 && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
3494 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3495 result = gen_reg_rtx (insn_mode);
3496
3497 arg1_rtx = get_memory_rtx (arg1);
3498 arg2_rtx = get_memory_rtx (arg2);
3499 arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3500 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3501 GEN_INT (MIN (arg1_align, arg2_align)));
3502 if (!insn)
3503 return 0;
3504
3505 emit_insn (insn);
3506
3507 /* Return the value in the proper mode for this function. */
3508 mode = TYPE_MODE (TREE_TYPE (exp));
3509 if (GET_MODE (result) == mode)
3510 return result;
3511 if (target == 0)
3512 return convert_to_mode (mode, result, 0);
3513 convert_move (target, result, 0);
3514 return target;
3515 }
3516#endif
3517 return 0;
ed09096d 3518}
3519
49f0327b 3520/* Expand expression EXP, which is a call to the strcat builtin.
3521 Return 0 if we failed the caller should emit a normal call,
3522 otherwise try to get the result in TARGET, if convenient. */
27d0c333 3523
49f0327b 3524static rtx
aecda0d6 3525expand_builtin_strcat (tree arglist, rtx target, enum machine_mode mode)
49f0327b 3526{
0eb671f7 3527 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
49f0327b 3528 return 0;
3529 else
3530 {
3531 tree dst = TREE_VALUE (arglist),
3532 src = TREE_VALUE (TREE_CHAIN (arglist));
3533 const char *p = c_getstr (src);
3534
ca71f89b 3535 if (p)
3536 {
3537 /* If the string length is zero, return the dst parameter. */
3538 if (*p == '\0')
3539 return expand_expr (dst, target, mode, EXPAND_NORMAL);
3540 else if (!optimize_size)
3541 {
3542 /* Otherwise if !optimize_size, see if we can store by
3543 pieces into (dst + strlen(dst)). */
3544 tree newdst, arglist,
3545 strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
3546
3547 /* This is the length argument. */
3548 arglist = build_tree_list (NULL_TREE,
3549 fold (size_binop (PLUS_EXPR,
3550 c_strlen (src, 0),
3551 ssize_int (1))));
3552 /* Prepend src argument. */
3553 arglist = tree_cons (NULL_TREE, src, arglist);
3554
3555 /* We're going to use dst more than once. */
3556 dst = save_expr (dst);
3557
3558 /* Create strlen (dst). */
3559 newdst =
3560 fold (build_function_call_expr (strlen_fn,
3561 build_tree_list (NULL_TREE,
3562 dst)));
3563 /* Create (dst + strlen (dst)). */
3564 newdst = fold (build (PLUS_EXPR, TREE_TYPE (dst), dst, newdst));
3565
3566 /* Prepend the new dst argument. */
3567 arglist = tree_cons (NULL_TREE, newdst, arglist);
3568
3569 /* We don't want to get turned into a memcpy if the
3570 target is const0_rtx, i.e. when the return value
3571 isn't used. That would produce pessimized code so
3572 pass in a target of zero, it should never actually be
3573 used. If this was successful return the original
3574 dst, not the result of mempcpy. */
3575 if (expand_builtin_mempcpy (arglist, /*target=*/0, mode, /*endp=*/0))
3576 return expand_expr (dst, target, mode, EXPAND_NORMAL);
3577 else
3578 return 0;
3579 }
3580 }
49f0327b 3581
3582 return 0;
3583 }
3584}
3585
3586/* Expand expression EXP, which is a call to the strncat builtin.
3587 Return 0 if we failed the caller should emit a normal call,
3588 otherwise try to get the result in TARGET, if convenient. */
27d0c333 3589
49f0327b 3590static rtx
aecda0d6 3591expand_builtin_strncat (tree arglist, rtx target, enum machine_mode mode)
49f0327b 3592{
0eb671f7 3593 if (!validate_arglist (arglist,
3594 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
49f0327b 3595 return 0;
3596 else
3597 {
3598 tree dst = TREE_VALUE (arglist),
3599 src = TREE_VALUE (TREE_CHAIN (arglist)),
3600 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3601 const char *p = c_getstr (src);
3602
3603 /* If the requested length is zero, or the src parameter string
3604 length is zero, return the dst parameter. */
b527e67e 3605 if (integer_zerop (len) || (p && *p == '\0'))
9342ee68 3606 {
49f0327b 3607 /* Evaluate and ignore the src and len parameters in case
3608 they have side-effects. */
3609 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
3610 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
3611 return expand_expr (dst, target, mode, EXPAND_NORMAL);
3612 }
3613
3614 /* If the requested len is greater than or equal to the string
3615 length, call strcat. */
3616 if (TREE_CODE (len) == INTEGER_CST && p
3617 && compare_tree_int (len, strlen (p)) >= 0)
9342ee68 3618 {
df5c389e 3619 tree newarglist
3620 = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src));
0a68165a 3621 tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
bf8e3599 3622
49f0327b 3623 /* If the replacement _DECL isn't initialized, don't do the
2c0e001b 3624 transformation. */
49f0327b 3625 if (!fn)
3626 return 0;
3627
7e15618b 3628 return expand_expr (build_function_call_expr (fn, newarglist),
3629 target, mode, EXPAND_NORMAL);
49f0327b 3630 }
3631 return 0;
3632 }
3633}
3634
3635/* Expand expression EXP, which is a call to the strspn builtin.
3636 Return 0 if we failed the caller should emit a normal call,
3637 otherwise try to get the result in TARGET, if convenient. */
27d0c333 3638
49f0327b 3639static rtx
aecda0d6 3640expand_builtin_strspn (tree arglist, rtx target, enum machine_mode mode)
49f0327b 3641{
0eb671f7 3642 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
49f0327b 3643 return 0;
3644 else
3645 {
3646 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
3647 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
bf8e3599 3648
49f0327b 3649 /* If both arguments are constants, evaluate at compile-time. */
3650 if (p1 && p2)
9342ee68 3651 {
49f0327b 3652 const size_t r = strspn (p1, p2);
3653 return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
3654 }
bf8e3599 3655
fb1f44c5 3656 /* If either argument is "", return 0. */
3657 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9342ee68 3658 {
fb1f44c5 3659 /* Evaluate and ignore both arguments in case either one has
49f0327b 3660 side-effects. */
3661 expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
fb1f44c5 3662 expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
49f0327b 3663 return const0_rtx;
3664 }
3665 return 0;
3666 }
3667}
3668
3669/* Expand expression EXP, which is a call to the strcspn builtin.
3670 Return 0 if we failed the caller should emit a normal call,
3671 otherwise try to get the result in TARGET, if convenient. */
27d0c333 3672
49f0327b 3673static rtx
aecda0d6 3674expand_builtin_strcspn (tree arglist, rtx target, enum machine_mode mode)
49f0327b 3675{
0eb671f7 3676 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
49f0327b 3677 return 0;
3678 else
3679 {
3680 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
3681 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
bf8e3599 3682
49f0327b 3683 /* If both arguments are constants, evaluate at compile-time. */
3684 if (p1 && p2)
9342ee68 3685 {
49f0327b 3686 const size_t r = strcspn (p1, p2);
3687 return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
3688 }
bf8e3599 3689
fb1f44c5 3690 /* If the first argument is "", return 0. */
3691 if (p1 && *p1 == '\0')
9342ee68 3692 {
fb1f44c5 3693 /* Evaluate and ignore argument s2 in case it has
3694 side-effects. */
3695 expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
3696 return const0_rtx;
3697 }
3698
49f0327b 3699 /* If the second argument is "", return __builtin_strlen(s1). */
3700 if (p2 && *p2 == '\0')
9342ee68 3701 {
7e15618b 3702 tree newarglist = build_tree_list (NULL_TREE, s1),
0a68165a 3703 fn = implicit_built_in_decls[BUILT_IN_STRLEN];
bf8e3599 3704
49f0327b 3705 /* If the replacement _DECL isn't initialized, don't do the
2c0e001b 3706 transformation. */
49f0327b 3707 if (!fn)
3708 return 0;
3709
7e15618b 3710 return expand_expr (build_function_call_expr (fn, newarglist),
3711 target, mode, EXPAND_NORMAL);
49f0327b 3712 }
3713 return 0;
3714 }
3715}
3716
a66c9326 3717/* Expand a call to __builtin_saveregs, generating the result in TARGET,
3718 if that's convenient. */
902de8ed 3719
a66c9326 3720rtx
aecda0d6 3721expand_builtin_saveregs (void)
53800dbe 3722{
a66c9326 3723 rtx val, seq;
53800dbe 3724
3725 /* Don't do __builtin_saveregs more than once in a function.
3726 Save the result of the first call and reuse it. */
3727 if (saveregs_value != 0)
3728 return saveregs_value;
53800dbe 3729
a66c9326 3730 /* When this function is called, it means that registers must be
3731 saved on entry to this function. So we migrate the call to the
3732 first insn of this function. */
3733
3734 start_sequence ();
53800dbe 3735
a66c9326 3736 /* Do whatever the machine needs done in this case. */
45550790 3737 val = targetm.calls.expand_builtin_saveregs ();
53800dbe 3738
a66c9326 3739 seq = get_insns ();
3740 end_sequence ();
53800dbe 3741
a66c9326 3742 saveregs_value = val;
53800dbe 3743
31d3e01c 3744 /* Put the insns after the NOTE that starts the function. If this
3745 is inside a start_sequence, make the outer-level insn chain current, so
a66c9326 3746 the code is placed at the start of the function. */
3747 push_topmost_sequence ();
31d3e01c 3748 emit_insn_after (seq, get_insns ());
a66c9326 3749 pop_topmost_sequence ();
3750
3751 return val;
53800dbe 3752}
3753
3754/* __builtin_args_info (N) returns word N of the arg space info
3755 for the current function. The number and meanings of words
3756 is controlled by the definition of CUMULATIVE_ARGS. */
f7c44134 3757
53800dbe 3758static rtx
aecda0d6 3759expand_builtin_args_info (tree arglist)
53800dbe 3760{
53800dbe 3761 int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
3762 int *word_ptr = (int *) &current_function_args_info;
53800dbe 3763
3764 if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0)
dda90815 3765 abort ();
53800dbe 3766
3767 if (arglist != 0)
3768 {
27d0c333 3769 if (!host_integerp (TREE_VALUE (arglist), 0))
53800dbe 3770 error ("argument of `__builtin_args_info' must be constant");
3771 else
3772 {
27d0c333 3773 HOST_WIDE_INT wordnum = tree_low_cst (TREE_VALUE (arglist), 0);
53800dbe 3774
27d0c333 3775 if (wordnum < 0 || wordnum >= nwords)
53800dbe 3776 error ("argument of `__builtin_args_info' out of range");
3777 else
3778 return GEN_INT (word_ptr[wordnum]);
3779 }
3780 }
3781 else
3782 error ("missing argument in `__builtin_args_info'");
3783
3784 return const0_rtx;
53800dbe 3785}
3786
a66c9326 3787/* Expand ARGLIST, from a call to __builtin_next_arg. */
27d0c333 3788
53800dbe 3789static rtx
aecda0d6 3790expand_builtin_next_arg (tree arglist)
53800dbe 3791{
53800dbe 3792 tree fntype = TREE_TYPE (current_function_decl);
3793
7ccc713a 3794 if (TYPE_ARG_TYPES (fntype) == 0
3795 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
3796 == void_type_node))
53800dbe 3797 {
3798 error ("`va_start' used in function with fixed args");
3799 return const0_rtx;
3800 }
3801
3802 if (arglist)
3803 {
3804 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
3805 tree arg = TREE_VALUE (arglist);
3806
3807 /* Strip off all nops for the sake of the comparison. This
bf8e3599 3808 is not quite the same as STRIP_NOPS. It does more.
53800dbe 3809 We must also strip off INDIRECT_EXPR for C++ reference
3810 parameters. */
3811 while (TREE_CODE (arg) == NOP_EXPR
3812 || TREE_CODE (arg) == CONVERT_EXPR
3813 || TREE_CODE (arg) == NON_LVALUE_EXPR
3814 || TREE_CODE (arg) == INDIRECT_REF)
3815 arg = TREE_OPERAND (arg, 0);
3816 if (arg != last_parm)
3817 warning ("second parameter of `va_start' not last named argument");
3818 }
7ccc713a 3819 else
53800dbe 3820 /* Evidently an out of date version of <stdarg.h>; can't validate
3821 va_start's second argument, but can still work as intended. */
3822 warning ("`__builtin_next_arg' called without an argument");
3823
3824 return expand_binop (Pmode, add_optab,
3825 current_function_internal_arg_pointer,
3826 current_function_arg_offset_rtx,
3827 NULL_RTX, 0, OPTAB_LIB_WIDEN);
3828}
3829
a66c9326 3830/* Make it easier for the backends by protecting the valist argument
3831 from multiple evaluations. */
3832
3833static tree
aecda0d6 3834stabilize_va_list (tree valist, int needs_lvalue)
a66c9326 3835{
11a61dea 3836 if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
a66c9326 3837 {
2d47cc32 3838 if (TREE_SIDE_EFFECTS (valist))
3839 valist = save_expr (valist);
11a61dea 3840
2d47cc32 3841 /* For this case, the backends will be expecting a pointer to
3842 TREE_TYPE (va_list_type_node), but it's possible we've
3843 actually been given an array (an actual va_list_type_node).
3844 So fix it. */
3845 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
8a15c04a 3846 {
bf8e3599 3847 tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
3848 tree p2 = build_pointer_type (va_list_type_node);
325d1c45 3849
bf8e3599 3850 valist = build1 (ADDR_EXPR, p2, valist);
2d47cc32 3851 valist = fold (build1 (NOP_EXPR, p1, valist));
8a15c04a 3852 }
a66c9326 3853 }
11a61dea 3854 else
a66c9326 3855 {
2d47cc32 3856 tree pt;
11a61dea 3857
2d47cc32 3858 if (! needs_lvalue)
3859 {
11a61dea 3860 if (! TREE_SIDE_EFFECTS (valist))
3861 return valist;
bf8e3599 3862
11a61dea 3863 pt = build_pointer_type (va_list_type_node);
2d47cc32 3864 valist = fold (build1 (ADDR_EXPR, pt, valist));
a66c9326 3865 TREE_SIDE_EFFECTS (valist) = 1;
a66c9326 3866 }
2d47cc32 3867
11a61dea 3868 if (TREE_SIDE_EFFECTS (valist))
2d47cc32 3869 valist = save_expr (valist);
11a61dea 3870 valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)),
3871 valist));
a66c9326 3872 }
3873
3874 return valist;
3875}
3876
3877/* The "standard" implementation of va_start: just assign `nextarg' to
3878 the variable. */
27d0c333 3879
a66c9326 3880void
aecda0d6 3881std_expand_builtin_va_start (tree valist, rtx nextarg)
a66c9326 3882{
3883 tree t;
3884
3885 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
3886 make_tree (ptr_type_node, nextarg));
3887 TREE_SIDE_EFFECTS (t) = 1;
3888
3889 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3890}
3891
7ccc713a 3892/* Expand ARGLIST, from a call to __builtin_va_start. */
27d0c333 3893
a66c9326 3894static rtx
aecda0d6 3895expand_builtin_va_start (tree arglist)
a66c9326 3896{
3897 rtx nextarg;
7ccc713a 3898 tree chain, valist;
a66c9326 3899
7ccc713a 3900 chain = TREE_CHAIN (arglist);
a66c9326 3901
3902 if (TREE_CHAIN (chain))
3903 error ("too many arguments to function `va_start'");
3904
7ccc713a 3905 nextarg = expand_builtin_next_arg (chain);
a66c9326 3906 valist = stabilize_va_list (TREE_VALUE (arglist), 1);
3907
3908#ifdef EXPAND_BUILTIN_VA_START
7df226a2 3909 EXPAND_BUILTIN_VA_START (valist, nextarg);
a66c9326 3910#else
7df226a2 3911 std_expand_builtin_va_start (valist, nextarg);
a66c9326 3912#endif
3913
3914 return const0_rtx;
3915}
3916
a66c9326 3917/* The "standard" implementation of va_arg: read the value from the
3918 current (padded) address and increment by the (padded) size. */
f7c44134 3919
a66c9326 3920rtx
aecda0d6 3921std_expand_builtin_va_arg (tree valist, tree type)
a66c9326 3922{
91f95e00 3923 tree addr_tree, t, type_size = NULL;
3924 tree align, alignm1;
3925 tree rounded_size;
a66c9326 3926 rtx addr;
3927
3928 /* Compute the rounded size of the type. */
91f95e00 3929 align = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
3930 alignm1 = size_int (PARM_BOUNDARY / BITS_PER_UNIT - 1);
3931 if (type == error_mark_node
3932 || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
3933 || TREE_OVERFLOW (type_size))
3934 rounded_size = size_zero_node;
3935 else
3936 rounded_size = fold (build (MULT_EXPR, sizetype,
3937 fold (build (TRUNC_DIV_EXPR, sizetype,
3938 fold (build (PLUS_EXPR, sizetype,
3939 type_size, alignm1)),
3940 align)),
3941 align));
a66c9326 3942
3943 /* Get AP. */
3944 addr_tree = valist;
91f95e00 3945 if (PAD_VARARGS_DOWN && ! integer_zerop (rounded_size))
a66c9326 3946 {
3947 /* Small args are padded downward. */
91f95e00 3948 addr_tree = fold (build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
3949 fold (build (COND_EXPR, sizetype,
3950 fold (build (GT_EXPR, sizetype,
3951 rounded_size,
3952 align)),
3953 size_zero_node,
3954 fold (build (MINUS_EXPR, sizetype,
3955 rounded_size,
3956 type_size))))));
a66c9326 3957 }
3958
3959 addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
3960 addr = copy_to_reg (addr);
3961
3962 /* Compute new value for AP. */
91f95e00 3963 if (! integer_zerop (rounded_size))
3964 {
3965 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
3966 build (PLUS_EXPR, TREE_TYPE (valist), valist,
3967 rounded_size));
3968 TREE_SIDE_EFFECTS (t) = 1;
3969 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3970 }
a66c9326 3971
3972 return addr;
3973}
3974
3975/* Expand __builtin_va_arg, which is not really a builtin function, but
3976 a very special sort of operator. */
f7c44134 3977
a66c9326 3978rtx
aecda0d6 3979expand_builtin_va_arg (tree valist, tree type)
a66c9326 3980{
3981 rtx addr, result;
6cd005c9 3982 tree promoted_type, want_va_type, have_va_type;
a66c9326 3983
6cd005c9 3984 /* Verify that valist is of the proper type. */
3985
3986 want_va_type = va_list_type_node;
3987 have_va_type = TREE_TYPE (valist);
3988 if (TREE_CODE (want_va_type) == ARRAY_TYPE)
3989 {
bf8e3599 3990 /* If va_list is an array type, the argument may have decayed
6cd005c9 3991 to a pointer type, e.g. by being passed to another function.
3992 In that case, unwrap both types so that we can compare the
3993 underlying records. */
3994 if (TREE_CODE (have_va_type) == ARRAY_TYPE
3995 || TREE_CODE (have_va_type) == POINTER_TYPE)
3996 {
3997 want_va_type = TREE_TYPE (want_va_type);
3998 have_va_type = TREE_TYPE (have_va_type);
3999 }
4000 }
4001 if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
a66c9326 4002 {
e94026da 4003 error ("first argument to `va_arg' not of type `va_list'");
4004 addr = const0_rtx;
4005 }
6cd005c9 4006
4007 /* Generate a diagnostic for requesting data of a type that cannot
4008 be passed through `...' due to type promotion at the call site. */
63c62881 4009 else if ((promoted_type = (*lang_hooks.types.type_promotes_to) (type))
4010 != type)
e94026da 4011 {
01ce7a1b 4012 const char *name = "<anonymous type>", *pname = 0;
a0ef1725 4013 static bool gave_help;
e94026da 4014
4015 if (TYPE_NAME (type))
4016 {
4017 if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
4018 name = IDENTIFIER_POINTER (TYPE_NAME (type));
4019 else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
4020 && DECL_NAME (TYPE_NAME (type)))
4021 name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
4022 }
4023 if (TYPE_NAME (promoted_type))
4024 {
4025 if (TREE_CODE (TYPE_NAME (promoted_type)) == IDENTIFIER_NODE)
4026 pname = IDENTIFIER_POINTER (TYPE_NAME (promoted_type));
4027 else if (TREE_CODE (TYPE_NAME (promoted_type)) == TYPE_DECL
4028 && DECL_NAME (TYPE_NAME (promoted_type)))
4029 pname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (promoted_type)));
4030 }
4031
a0ef1725 4032 /* Unfortunately, this is merely undefined, rather than a constraint
4033 violation, so we cannot make this an error. If this call is never
4034 executed, the program is still strictly conforming. */
4035 warning ("`%s' is promoted to `%s' when passed through `...'",
4036 name, pname);
e94026da 4037 if (! gave_help)
4038 {
a0ef1725 4039 gave_help = true;
4040 warning ("(so you should pass `%s' not `%s' to `va_arg')",
4041 pname, name);
e94026da 4042 }
4043
a0ef1725 4044 /* We can, however, treat "undefined" any way we please.
4045 Call abort to encourage the user to fix the program. */
4046 expand_builtin_trap ();
4047
4048 /* This is dead code, but go ahead and finish so that the
4049 mode of the result comes out right. */
a66c9326 4050 addr = const0_rtx;
4051 }
4052 else
4053 {
4054 /* Make it easier for the backends by protecting the valist argument
4055 from multiple evaluations. */
4056 valist = stabilize_va_list (valist, 0);
4057
4058#ifdef EXPAND_BUILTIN_VA_ARG
4059 addr = EXPAND_BUILTIN_VA_ARG (valist, type);
4060#else
4061 addr = std_expand_builtin_va_arg (valist, type);
4062#endif
4063 }
4064
85d654dd 4065 addr = convert_memory_address (Pmode, addr);
726ec87c 4066
a66c9326 4067 result = gen_rtx_MEM (TYPE_MODE (type), addr);
ab6ab77e 4068 set_mem_alias_set (result, get_varargs_alias_set ());
a66c9326 4069
4070 return result;
4071}
4072
4073/* Expand ARGLIST, from a call to __builtin_va_end. */
f7c44134 4074
a66c9326 4075static rtx
aecda0d6 4076expand_builtin_va_end (tree arglist)
a66c9326 4077{
8a15c04a 4078 tree valist = TREE_VALUE (arglist);
4079
a66c9326 4080#ifdef EXPAND_BUILTIN_VA_END
a66c9326 4081 valist = stabilize_va_list (valist, 0);
f0ce3b1f 4082 EXPAND_BUILTIN_VA_END (arglist);
8a15c04a 4083#else
4084 /* Evaluate for side effects, if needed. I hate macros that don't
4085 do that. */
4086 if (TREE_SIDE_EFFECTS (valist))
4087 expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
a66c9326 4088#endif
4089
4090 return const0_rtx;
4091}
4092
bf8e3599 4093/* Expand ARGLIST, from a call to __builtin_va_copy. We do this as a
a66c9326 4094 builtin rather than just as an assignment in stdarg.h because of the
4095 nastiness of array-type va_list types. */
f7c44134 4096
a66c9326 4097static rtx
aecda0d6 4098expand_builtin_va_copy (tree arglist)
a66c9326 4099{
4100 tree dst, src, t;
4101
4102 dst = TREE_VALUE (arglist);
4103 src = TREE_VALUE (TREE_CHAIN (arglist));
4104
4105 dst = stabilize_va_list (dst, 1);
4106 src = stabilize_va_list (src, 0);
4107
4108 if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
4109 {
4110 t = build (MODIFY_EXPR, va_list_type_node, dst, src);
4111 TREE_SIDE_EFFECTS (t) = 1;
4112 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4113 }
4114 else
4115 {
11a61dea 4116 rtx dstb, srcb, size;
4117
4118 /* Evaluate to pointers. */
4119 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
4120 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
4121 size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
4122 VOIDmode, EXPAND_NORMAL);
4123
85d654dd 4124 dstb = convert_memory_address (Pmode, dstb);
4125 srcb = convert_memory_address (Pmode, srcb);
726ec87c 4126
11a61dea 4127 /* "Dereference" to BLKmode memories. */
4128 dstb = gen_rtx_MEM (BLKmode, dstb);
ab6ab77e 4129 set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
2a631e19 4130 set_mem_align (dstb, TYPE_ALIGN (va_list_type_node));
11a61dea 4131 srcb = gen_rtx_MEM (BLKmode, srcb);
ab6ab77e 4132 set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
2a631e19 4133 set_mem_align (srcb, TYPE_ALIGN (va_list_type_node));
11a61dea 4134
4135 /* Copy. */
0378dbdc 4136 emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
a66c9326 4137 }
4138
4139 return const0_rtx;
4140}
4141
53800dbe 4142/* Expand a call to one of the builtin functions __builtin_frame_address or
4143 __builtin_return_address. */
27d0c333 4144
53800dbe 4145static rtx
aecda0d6 4146expand_builtin_frame_address (tree fndecl, tree arglist)
53800dbe 4147{
53800dbe 4148 /* The argument must be a nonnegative integer constant.
4149 It counts the number of frames to scan up the stack.
4150 The value is the return address saved in that frame. */
4151 if (arglist == 0)
4152 /* Warning about missing arg was already issued. */
4153 return const0_rtx;
27d0c333 4154 else if (! host_integerp (TREE_VALUE (arglist), 1))
53800dbe 4155 {
4156 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4157 error ("invalid arg to `__builtin_frame_address'");
4158 else
4159 error ("invalid arg to `__builtin_return_address'");
4160 return const0_rtx;
4161 }
4162 else
4163 {
27d0c333 4164 rtx tem
4165 = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
4166 tree_low_cst (TREE_VALUE (arglist), 1),
4167 hard_frame_pointer_rtx);
53800dbe 4168
4169 /* Some ports cannot access arbitrary stack frames. */
4170 if (tem == NULL)
4171 {
4172 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4173 warning ("unsupported arg to `__builtin_frame_address'");
4174 else
4175 warning ("unsupported arg to `__builtin_return_address'");
4176 return const0_rtx;
4177 }
4178
4179 /* For __builtin_frame_address, return what we've got. */
4180 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4181 return tem;
4182
4183 if (GET_CODE (tem) != REG
4184 && ! CONSTANT_P (tem))
4185 tem = copy_to_mode_reg (Pmode, tem);
4186 return tem;
4187 }
4188}
4189
4190/* Expand a call to the alloca builtin, with arguments ARGLIST. Return 0 if
4191 we failed and the caller should emit a normal call, otherwise try to get
4192 the result in TARGET, if convenient. */
15c6cf6b 4193
53800dbe 4194static rtx
aecda0d6 4195expand_builtin_alloca (tree arglist, rtx target)
53800dbe 4196{
4197 rtx op0;
15c6cf6b 4198 rtx result;
53800dbe 4199
0eb671f7 4200 if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
53800dbe 4201 return 0;
4202
4203 /* Compute the argument. */
4204 op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
4205
4206 /* Allocate the desired space. */
15c6cf6b 4207 result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
85d654dd 4208 result = convert_memory_address (ptr_mode, result);
15c6cf6b 4209
4210 return result;
53800dbe 4211}
4212
6a08d0ab 4213/* Expand a call to a unary builtin. The arguments are in ARGLIST.
53800dbe 4214 Return 0 if a normal call should be emitted rather than expanding the
4215 function in-line. If convenient, the result should be placed in TARGET.
4216 SUBTARGET may be used as the target for computing one of EXP's operands. */
15c6cf6b 4217
53800dbe 4218static rtx
aecda0d6 4219expand_builtin_unop (enum machine_mode target_mode, tree arglist, rtx target,
4220 rtx subtarget, optab op_optab)
53800dbe 4221{
4222 rtx op0;
0eb671f7 4223 if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
53800dbe 4224 return 0;
4225
4226 /* Compute the argument. */
4227 op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
6a08d0ab 4228 /* Compute op, into TARGET if possible.
53800dbe 4229 Set TARGET to wherever the result comes back. */
4230 target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
6a08d0ab 4231 op_optab, op0, target, 1);
53800dbe 4232 if (target == 0)
4233 abort ();
efb070c8 4234
4235 return convert_to_mode (target_mode, target, 0);
53800dbe 4236}
89cfe6e5 4237
df94cd3b 4238/* If the string passed to fputs is a constant and is one character
2c0e001b 4239 long, we attempt to transform this call into __builtin_fputc(). */
15c6cf6b 4240
df94cd3b 4241static rtx
19bf118a 4242expand_builtin_fputs (tree arglist, rtx target, bool unlocked)
df94cd3b 4243{
c013a46e 4244 tree len, fn;
0a68165a 4245 tree fn_fputc = unlocked ? implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
4246 : implicit_built_in_decls[BUILT_IN_FPUTC];
4247 tree fn_fwrite = unlocked ? implicit_built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
4248 : implicit_built_in_decls[BUILT_IN_FWRITE];
df94cd3b 4249
4250 /* If the return value is used, or the replacement _DECL isn't
2c0e001b 4251 initialized, don't do the transformation. */
19bf118a 4252 if (target != const0_rtx || !fn_fputc || !fn_fwrite)
df94cd3b 4253 return 0;
4254
2c0e001b 4255 /* Verify the arguments in the original call. */
8a06f2d4 4256 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
df94cd3b 4257 return 0;
4258
ce1b14f4 4259 /* Get the length of the string passed to fputs. If the length
4260 can't be determined, punt. */
681fab1e 4261 if (!(len = c_strlen (TREE_VALUE (arglist), 1))
6840589f 4262 || TREE_CODE (len) != INTEGER_CST)
df94cd3b 4263 return 0;
4264
ce1b14f4 4265 switch (compare_tree_int (len, 1))
4266 {
4267 case -1: /* length is 0, delete the call entirely . */
6d42b7e4 4268 {
4269 /* Evaluate and ignore the argument in case it has
4270 side-effects. */
4271 expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
4272 VOIDmode, EXPAND_NORMAL);
4273 return const0_rtx;
4274 }
ce1b14f4 4275 case 0: /* length is 1, call fputc. */
4276 {
83d79705 4277 const char *p = c_getstr (TREE_VALUE (arglist));
df94cd3b 4278
83d79705 4279 if (p != NULL)
bf8e3599 4280 {
83d79705 4281 /* New argument list transforming fputs(string, stream) to
4282 fputc(string[0], stream). */
4283 arglist =
4284 build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
4285 arglist =
4286 tree_cons (NULL_TREE, build_int_2 (p[0], 0), arglist);
4287 fn = fn_fputc;
4288 break;
4289 }
ce1b14f4 4290 }
83d79705 4291 /* FALLTHROUGH */
ce1b14f4 4292 case 1: /* length is greater than 1, call fwrite. */
4293 {
4ec25652 4294 tree string_arg;
bf8e3599 4295
6473f3f4 4296 /* If optimizing for size keep fputs. */
4ec25652 4297 if (optimize_size)
4298 return 0;
4299 string_arg = TREE_VALUE (arglist);
ce1b14f4 4300 /* New argument list transforming fputs(string, stream) to
4301 fwrite(string, 1, len, stream). */
4302 arglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
4303 arglist = tree_cons (NULL_TREE, len, arglist);
38d76e41 4304 arglist = tree_cons (NULL_TREE, size_one_node, arglist);
ce1b14f4 4305 arglist = tree_cons (NULL_TREE, string_arg, arglist);
4306 fn = fn_fwrite;
4307 break;
4308 }
4309 default:
e17f5b23 4310 abort ();
ce1b14f4 4311 }
bf8e3599 4312
7e15618b 4313 return expand_expr (build_function_call_expr (fn, arglist),
19bf118a 4314 const0_rtx, VOIDmode, EXPAND_NORMAL);
3311f67b 4315}
4316
689df48e 4317/* Expand a call to __builtin_expect. We return our argument and emit a
4318 NOTE_INSN_EXPECTED_VALUE note. This is the expansion of __builtin_expect in
4319 a non-jump context. */
89cfe6e5 4320
4321static rtx
aecda0d6 4322expand_builtin_expect (tree arglist, rtx target)
89cfe6e5 4323{
4324 tree exp, c;
4325 rtx note, rtx_c;
4326
4327 if (arglist == NULL_TREE
4328 || TREE_CHAIN (arglist) == NULL_TREE)
4329 return const0_rtx;
4330 exp = TREE_VALUE (arglist);
4331 c = TREE_VALUE (TREE_CHAIN (arglist));
4332
4333 if (TREE_CODE (c) != INTEGER_CST)
4334 {
4335 error ("second arg to `__builtin_expect' must be a constant");
4336 c = integer_zero_node;
4337 }
4338
4339 target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
4340
4341 /* Don't bother with expected value notes for integral constants. */
b28bedce 4342 if (flag_guess_branch_prob && GET_CODE (target) != CONST_INT)
89cfe6e5 4343 {
4344 /* We do need to force this into a register so that we can be
4345 moderately sure to be able to correctly interpret the branch
4346 condition later. */
4347 target = force_reg (GET_MODE (target), target);
bf8e3599 4348
89cfe6e5 4349 rtx_c = expand_expr (c, NULL_RTX, GET_MODE (target), EXPAND_NORMAL);
4350
31b97e8f 4351 note = emit_note (NOTE_INSN_EXPECTED_VALUE);
89cfe6e5 4352 NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, target, rtx_c);
4353 }
4354
4355 return target;
4356}
689df48e 4357
4358/* Like expand_builtin_expect, except do this in a jump context. This is
4359 called from do_jump if the conditional is a __builtin_expect. Return either
31d3e01c 4360 a list of insns to emit the jump or NULL if we cannot optimize
689df48e 4361 __builtin_expect. We need to optimize this at jump time so that machines
4362 like the PowerPC don't turn the test into a SCC operation, and then jump
4363 based on the test being 0/1. */
4364
4365rtx
aecda0d6 4366expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
689df48e 4367{
4368 tree arglist = TREE_OPERAND (exp, 1);
4369 tree arg0 = TREE_VALUE (arglist);
4370 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4371 rtx ret = NULL_RTX;
4372
4373 /* Only handle __builtin_expect (test, 0) and
4374 __builtin_expect (test, 1). */
4375 if (TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
27d0c333 4376 && (integer_zerop (arg1) || integer_onep (arg1)))
689df48e 4377 {
689df48e 4378 int num_jumps = 0;
0d21cbc7 4379 int save_pending_stack_adjust = pending_stack_adjust;
31d3e01c 4380 rtx insn;
689df48e 4381
1dc55962 4382 /* If we fail to locate an appropriate conditional jump, we'll
4383 fall back to normal evaluation. Ensure that the expression
4384 can be re-evaluated. */
4385 switch (unsafe_for_reeval (arg0))
4386 {
4387 case 0: /* Safe. */
4388 break;
4389
4390 case 1: /* Mildly unsafe. */
4391 arg0 = unsave_expr (arg0);
4392 break;
4393
4394 case 2: /* Wildly unsafe. */
4395 return NULL_RTX;
4396 }
4397
689df48e 4398 /* Expand the jump insns. */
4399 start_sequence ();
4400 do_jump (arg0, if_false_label, if_true_label);
31d3e01c 4401 ret = get_insns ();
689df48e 4402 end_sequence ();
4403
4404 /* Now that the __builtin_expect has been validated, go through and add
4405 the expect's to each of the conditional jumps. If we run into an
4406 error, just give up and generate the 'safe' code of doing a SCC
4407 operation and then doing a branch on that. */
31d3e01c 4408 insn = ret;
4409 while (insn != NULL_RTX)
689df48e 4410 {
31d3e01c 4411 rtx next = NEXT_INSN (insn);
689df48e 4412
7caedf36 4413 if (GET_CODE (insn) == JUMP_INSN && any_condjump_p (insn))
689df48e 4414 {
7caedf36 4415 rtx ifelse = SET_SRC (pc_set (insn));
689df48e 4416 rtx label;
4417 int taken;
4418
689df48e 4419 if (GET_CODE (XEXP (ifelse, 1)) == LABEL_REF)
4420 {
4421 taken = 1;
4422 label = XEXP (XEXP (ifelse, 1), 0);
4423 }
4424 /* An inverted jump reverses the probabilities. */
4425 else if (GET_CODE (XEXP (ifelse, 2)) == LABEL_REF)
4426 {
4427 taken = 0;
4428 label = XEXP (XEXP (ifelse, 2), 0);
4429 }
4430 /* We shouldn't have to worry about conditional returns during
4431 the expansion stage, but handle it gracefully anyway. */
4432 else if (GET_CODE (XEXP (ifelse, 1)) == RETURN)
4433 {
4434 taken = 1;
4435 label = NULL_RTX;
4436 }
4437 /* An inverted return reverses the probabilities. */
4438 else if (GET_CODE (XEXP (ifelse, 2)) == RETURN)
4439 {
4440 taken = 0;
4441 label = NULL_RTX;
4442 }
4443 else
31d3e01c 4444 goto do_next_insn;
689df48e 4445
4446 /* If the test is expected to fail, reverse the
4447 probabilities. */
27d0c333 4448 if (integer_zerop (arg1))
689df48e 4449 taken = 1 - taken;
4450
4451 /* If we are jumping to the false label, reverse the
4452 probabilities. */
4453 if (label == NULL_RTX)
4454 ; /* conditional return */
4455 else if (label == if_false_label)
4456 taken = 1 - taken;
4457 else if (label != if_true_label)
31d3e01c 4458 goto do_next_insn;
689df48e 4459
4460 num_jumps++;
4461 predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
4462 }
31d3e01c 4463
4464 do_next_insn:
4465 insn = next;
689df48e 4466 }
4467
4468 /* If no jumps were modified, fail and do __builtin_expect the normal
4469 way. */
4470 if (num_jumps == 0)
0d21cbc7 4471 {
4472 ret = NULL_RTX;
4473 pending_stack_adjust = save_pending_stack_adjust;
4474 }
689df48e 4475 }
4476
4477 return ret;
4478}
a0ef1725 4479
4480void
aecda0d6 4481expand_builtin_trap (void)
a0ef1725 4482{
4483#ifdef HAVE_trap
4484 if (HAVE_trap)
4485 emit_insn (gen_trap ());
4486 else
4487#endif
4488 emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
4489 emit_barrier ();
4490}
78a74442 4491
4492/* Expand a call to fabs, fabsf or fabsl with arguments ARGLIST.
4493 Return 0 if a normal call should be emitted rather than expanding
4494 the function inline. If convenient, the result should be placed
4495 in TARGET. SUBTARGET may be used as the target for computing
4496 the operand. */
4497
4498static rtx
aecda0d6 4499expand_builtin_fabs (tree arglist, rtx target, rtx subtarget)
78a74442 4500{
4501 enum machine_mode mode;
4502 tree arg;
4503 rtx op0;
4504
4505 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
4506 return 0;
4507
4508 arg = TREE_VALUE (arglist);
4509 mode = TYPE_MODE (TREE_TYPE (arg));
4510 op0 = expand_expr (arg, subtarget, VOIDmode, 0);
4511 return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
4512}
4513
4514/* Expand a call to cabs, cabsf or cabsl with arguments ARGLIST.
4515 Return 0 if a normal call should be emitted rather than expanding
4516 the function inline. If convenient, the result should be placed
4517 in target. */
4518
4519static rtx
aecda0d6 4520expand_builtin_cabs (tree arglist, rtx target)
78a74442 4521{
4522 enum machine_mode mode;
4523 tree arg;
4524 rtx op0;
4525
4526 if (arglist == 0 || TREE_CHAIN (arglist))
4527 return 0;
4528 arg = TREE_VALUE (arglist);
4529 if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
4530 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
4531 return 0;
4532
4533 mode = TYPE_MODE (TREE_TYPE (arg));
4534 op0 = expand_expr (arg, NULL_RTX, VOIDmode, 0);
4535 return expand_complex_abs (mode, op0, target, 0);
4536}
4537
19bf118a 4538/* Create a new constant string literal and return a char* pointer to it.
4539 The STRING_CST value is the LEN characters at STR. */
4540static tree
4541build_string_literal (int len, const char *str)
4542{
4543 tree t, elem, index, type;
4544
4545 t = build_string (len, str);
4546 elem = build_type_variant (char_type_node, 1, 0);
4547 index = build_index_type (build_int_2 (len - 1, 0));
4548 type = build_array_type (elem, index);
4549 TREE_TYPE (t) = type;
4550 TREE_CONSTANT (t) = 1;
4551 TREE_READONLY (t) = 1;
4552 TREE_STATIC (t) = 1;
4553
4554 type = build_pointer_type (type);
4555 t = build1 (ADDR_EXPR, type, t);
4556
4557 type = build_pointer_type (elem);
4558 t = build1 (NOP_EXPR, type, t);
4559 return t;
4560}
4561
4562/* Expand a call to printf or printf_unlocked with argument list ARGLIST.
4563 Return 0 if a normal call should be emitted rather than transforming
4564 the function inline. If convenient, the result should be placed in
4565 TARGET with mode MODE. UNLOCKED indicates this is a printf_unlocked
4566 call. */
4567static rtx
4568expand_builtin_printf (tree arglist, rtx target, enum machine_mode mode,
4569 bool unlocked)
4570{
4571 tree fn_putchar = unlocked
4572 ? implicit_built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
4573 : implicit_built_in_decls[BUILT_IN_PUTCHAR];
4574 tree fn_puts = unlocked ? implicit_built_in_decls[BUILT_IN_PUTS_UNLOCKED]
4575 : implicit_built_in_decls[BUILT_IN_PUTS];
4576 const char *fmt_str;
4577 tree fn, fmt, arg;
4578
4579 /* If the return value is used, don't do the transformation. */
4580 if (target != const0_rtx)
4581 return 0;
4582
4583 /* Verify the required arguments in the original call. */
4584 if (! arglist)
4585 return 0;
4586 fmt = TREE_VALUE (arglist);
4587 if (TREE_CODE (TREE_TYPE (fmt)) != POINTER_TYPE)
4588 return 0;
4589 arglist = TREE_CHAIN (arglist);
4590
4591 /* Check whether the format is a literal string constant. */
4592 fmt_str = c_getstr (fmt);
4593 if (fmt_str == NULL)
4594 return 0;
4595
4596 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
4597 if (strcmp (fmt_str, "%s\n") == 0)
4598 {
4599 if (! arglist
4600 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
4601 || TREE_CHAIN (arglist))
4602 return 0;
4603 fn = fn_puts;
4604 }
4605 /* If the format specifier was "%c", call __builtin_putchar(arg). */
4606 else if (strcmp (fmt_str, "%c") == 0)
4607 {
4608 if (! arglist
4609 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
4610 || TREE_CHAIN (arglist))
4611 return 0;
4612 fn = fn_putchar;
4613 }
4614 else
4615 {
4616 /* We can't handle anything else with % args or %% ... yet. */
4617 if (strchr (fmt_str, '%'))
4618 return 0;
4619
4620 if (arglist)
4621 return 0;
4622
4623 /* If the format specifier was "", printf does nothing. */
4624 if (fmt_str[0] == '\0')
4625 return const0_rtx;
4626 /* If the format specifier has length of 1, call putchar. */
4627 if (fmt_str[1] == '\0')
4628 {
4629 /* Given printf("c"), (where c is any one character,)
4630 convert "c"[0] to an int and pass that to the replacement
4631 function. */
4632 arg = build_int_2 (fmt_str[0], 0);
4633 arglist = build_tree_list (NULL_TREE, arg);
4634 fn = fn_putchar;
4635 }
4636 else
4637 {
4638 /* If the format specifier was "string\n", call puts("string"). */
4639 size_t len = strlen (fmt_str);
4640 if (fmt_str[len - 1] == '\n')
4641 {
91c82c20 4642 /* Create a NUL-terminated string that's one char shorter
19bf118a 4643 than the original, stripping off the trailing '\n'. */
4644 char *newstr = (char *) alloca (len);
4645 memcpy (newstr, fmt_str, len - 1);
4646 newstr[len - 1] = 0;
4647
4648 arg = build_string_literal (len, newstr);
4649 arglist = build_tree_list (NULL_TREE, arg);
4650 fn = fn_puts;
4651 }
4652 else
4653 /* We'd like to arrange to call fputs(string,stdout) here,
4654 but we need stdout and don't have a way to get it yet. */
4655 return 0;
4656 }
4657 }
4658
4659 if (!fn)
4660 return 0;
4661 return expand_expr (build_function_call_expr (fn, arglist),
4662 target, mode, EXPAND_NORMAL);
4663}
4664
4665/* Expand a call to fprintf or fprintf_unlocked with argument list ARGLIST.
4666 Return 0 if a normal call should be emitted rather than transforming
4667 the function inline. If convenient, the result should be placed in
4668 TARGET with mode MODE. UNLOCKED indicates this is a fprintf_unlocked
4669 call. */
4670static rtx
4671expand_builtin_fprintf (tree arglist, rtx target, enum machine_mode mode,
4672 bool unlocked)
4673{
4674 tree fn_fputc = unlocked ? implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
4675 : implicit_built_in_decls[BUILT_IN_FPUTC];
4676 tree fn_fputs = unlocked ? implicit_built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
4677 : implicit_built_in_decls[BUILT_IN_FPUTS];
4678 const char *fmt_str;
4679 tree fn, fmt, fp, arg;
4680
4681 /* If the return value is used, don't do the transformation. */
4682 if (target != const0_rtx)
4683 return 0;
4684
4685 /* Verify the required arguments in the original call. */
4686 if (! arglist)
4687 return 0;
4688 fp = TREE_VALUE (arglist);
4689 if (TREE_CODE (TREE_TYPE (fp)) != POINTER_TYPE)
4690 return 0;
4691 arglist = TREE_CHAIN (arglist);
4692 if (! arglist)
4693 return 0;
4694 fmt = TREE_VALUE (arglist);
4695 if (TREE_CODE (TREE_TYPE (fmt)) != POINTER_TYPE)
4696 return 0;
4697 arglist = TREE_CHAIN (arglist);
4698
4699 /* Check whether the format is a literal string constant. */
4700 fmt_str = c_getstr (fmt);
4701 if (fmt_str == NULL)
4702 return 0;
4703
4704 /* If the format specifier was "%s", call __builtin_fputs(arg,fp). */
4705 if (strcmp (fmt_str, "%s") == 0)
4706 {
4707 if (! arglist
4708 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
4709 || TREE_CHAIN (arglist))
4710 return 0;
4711 arg = TREE_VALUE (arglist);
4712 arglist = build_tree_list (NULL_TREE, fp);
4713 arglist = tree_cons (NULL_TREE, arg, arglist);
4714 fn = fn_fputs;
4715 }
4716 /* If the format specifier was "%c", call __builtin_fputc(arg,fp). */
4717 else if (strcmp (fmt_str, "%c") == 0)
4718 {
4719 if (! arglist
4720 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
4721 || TREE_CHAIN (arglist))
4722 return 0;
4723 arg = TREE_VALUE (arglist);
4724 arglist = build_tree_list (NULL_TREE, fp);
4725 arglist = tree_cons (NULL_TREE, arg, arglist);
4726 fn = fn_fputc;
4727 }
4728 else
4729 {
4730 /* We can't handle anything else with % args or %% ... yet. */
4731 if (strchr (fmt_str, '%'))
4732 return 0;
4733
4734 if (arglist)
4735 return 0;
4736
4737 /* If the format specifier was "", fprintf does nothing. */
4738 if (fmt_str[0] == '\0')
4739 {
4740 /* Evaluate and ignore FILE* argument for side-effects. */
4741 expand_expr (fp, const0_rtx, VOIDmode, EXPAND_NORMAL);
4742 return const0_rtx;
4743 }
4744
4745 /* When "string" doesn't contain %, replace all cases of
4746 fprintf(stream,string) with fputs(string,stream). The fputs
4747 builtin will take care of special cases like length == 1. */
4748 arglist = build_tree_list (NULL_TREE, fp);
4749 arglist = tree_cons (NULL_TREE, fmt, arglist);
4750 fn = fn_fputs;
4751 }
4752
4753 if (!fn)
4754 return 0;
4755 return expand_expr (build_function_call_expr (fn, arglist),
4756 target, mode, EXPAND_NORMAL);
4757}
4758
6411575e 4759/* Expand a call to sprintf with argument list ARGLIST. Return 0 if
4760 a normal call should be emitted rather than expanding the function
4761 inline. If convenient, the result should be placed in TARGET with
4762 mode MODE. */
4763
4764static rtx
4765expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
4766{
a7a723f0 4767 tree orig_arglist, dest, fmt;
4768 const char *fmt_str;
6411575e 4769
4770 orig_arglist = arglist;
4771
4772 /* Verify the required arguments in the original call. */
4773 if (! arglist)
4774 return 0;
4775 dest = TREE_VALUE (arglist);
4776 if (TREE_CODE (TREE_TYPE (dest)) != POINTER_TYPE)
4777 return 0;
4778 arglist = TREE_CHAIN (arglist);
4779 if (! arglist)
4780 return 0;
4781 fmt = TREE_VALUE (arglist);
19bf118a 4782 if (TREE_CODE (TREE_TYPE (fmt)) != POINTER_TYPE)
6411575e 4783 return 0;
4784 arglist = TREE_CHAIN (arglist);
4785
4786 /* Check whether the format is a literal string constant. */
a7a723f0 4787 fmt_str = c_getstr (fmt);
4788 if (fmt_str == NULL)
6411575e 4789 return 0;
4790
4791 /* If the format doesn't contain % args or %%, use strcpy. */
a7a723f0 4792 if (strchr (fmt_str, '%') == 0)
6411575e 4793 {
4794 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
4795 tree exp;
4796
a7a723f0 4797 if (arglist || ! fn)
6411575e 4798 return 0;
4799 expand_expr (build_function_call_expr (fn, orig_arglist),
4800 const0_rtx, VOIDmode, EXPAND_NORMAL);
4801 if (target == const0_rtx)
4802 return const0_rtx;
a7a723f0 4803 exp = build_int_2 (strlen (fmt_str), 0);
6411575e 4804 exp = fold (build1 (NOP_EXPR, integer_type_node, exp));
4805 return expand_expr (exp, target, mode, EXPAND_NORMAL);
4806 }
a7a723f0 4807 /* If the format is "%s", use strcpy if the result isn't used. */
4808 else if (strcmp (fmt_str, "%s") == 0)
6411575e 4809 {
a7a723f0 4810 tree fn, arg, len;
4811 fn = implicit_built_in_decls[BUILT_IN_STRCPY];
6411575e 4812
a7a723f0 4813 if (! fn)
6411575e 4814 return 0;
4815
4816 if (! arglist || TREE_CHAIN (arglist))
4817 return 0;
4818 arg = TREE_VALUE (arglist);
4819 if (TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE)
4820 return 0;
4821
4822 if (target != const0_rtx)
4823 {
681fab1e 4824 len = c_strlen (arg, 1);
a7a723f0 4825 if (! len || TREE_CODE (len) != INTEGER_CST)
6411575e 4826 return 0;
6411575e 4827 }
4828 else
a7a723f0 4829 len = NULL_TREE;
6411575e 4830
4831 arglist = build_tree_list (NULL_TREE, arg);
4832 arglist = tree_cons (NULL_TREE, dest, arglist);
a7a723f0 4833 expand_expr (build_function_call_expr (fn, arglist),
6411575e 4834 const0_rtx, VOIDmode, EXPAND_NORMAL);
4835
4836 if (target == const0_rtx)
4837 return const0_rtx;
a7a723f0 4838 return expand_expr (len, target, mode, EXPAND_NORMAL);
6411575e 4839 }
4840
4841 return 0;
4842}
53800dbe 4843\f
4844/* Expand an expression EXP that calls a built-in function,
4845 with result going to TARGET if that's convenient
4846 (and in mode MODE if that's convenient).
4847 SUBTARGET may be used as the target for computing one of EXP's operands.
4848 IGNORE is nonzero if the value is to be ignored. */
4849
4850rtx
aecda0d6 4851expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
4852 int ignore)
53800dbe 4853{
c6e6ecb1 4854 tree fndecl = get_callee_fndecl (exp);
53800dbe 4855 tree arglist = TREE_OPERAND (exp, 1);
4856 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
efb070c8 4857 enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
53800dbe 4858
cd9ff771 4859 /* Perform postincrements before expanding builtin functions. */
313b27fa 4860 emit_queue ();
4861
8305149e 4862 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
fc2a2dcb 4863 return (*targetm.expand_builtin) (exp, target, subtarget, mode, ignore);
bf8e3599 4864
53800dbe 4865 /* When not optimizing, generate calls to library functions for a certain
4866 set of builtins. */
cd9ff771 4867 if (!optimize
4868 && !CALLED_AS_BUILT_IN (fndecl)
4869 && DECL_ASSEMBLER_NAME_SET_P (fndecl)
4870 && fcode != BUILT_IN_ALLOCA)
4871 return expand_call (exp, target, ignore);
53800dbe 4872
8d6d7930 4873 /* The built-in function expanders test for target == const0_rtx
4874 to determine whether the function's result will be ignored. */
4875 if (ignore)
4876 target = const0_rtx;
4877
4878 /* If the result of a pure or const built-in function is ignored, and
4879 none of its arguments are volatile, we can avoid expanding the
4880 built-in call and just evaluate the arguments for side-effects. */
4881 if (target == const0_rtx
4882 && (DECL_IS_PURE (fndecl) || TREE_READONLY (fndecl)))
4883 {
4884 bool volatilep = false;
4885 tree arg;
4886
4887 for (arg = arglist; arg; arg = TREE_CHAIN (arg))
4888 if (TREE_THIS_VOLATILE (TREE_VALUE (arg)))
4889 {
4890 volatilep = true;
4891 break;
4892 }
4893
4894 if (! volatilep)
4895 {
4896 for (arg = arglist; arg; arg = TREE_CHAIN (arg))
4897 expand_expr (TREE_VALUE (arg), const0_rtx,
4898 VOIDmode, EXPAND_NORMAL);
4899 return const0_rtx;
4900 }
4901 }
4902
53800dbe 4903 switch (fcode)
4904 {
4905 case BUILT_IN_ABS:
d2d4bdde 4906 case BUILT_IN_LABS:
4907 case BUILT_IN_LLABS:
4908 case BUILT_IN_IMAXABS:
78a74442 4909 /* build_function_call changes these into ABS_EXPR. */
4910 abort ();
4911
53800dbe 4912 case BUILT_IN_FABS:
d2d4bdde 4913 case BUILT_IN_FABSF:
4914 case BUILT_IN_FABSL:
78a74442 4915 target = expand_builtin_fabs (arglist, target, subtarget);
4916 if (target)
4917 return target;
4918 break;
4919
4920 case BUILT_IN_CABS:
4921 case BUILT_IN_CABSF:
4922 case BUILT_IN_CABSL:
4923 if (flag_unsafe_math_optimizations)
4924 {
4925 target = expand_builtin_cabs (arglist, target);
4926 if (target)
4927 return target;
4928 }
4929 break;
53800dbe 4930
d30e4d04 4931 case BUILT_IN_CONJ:
d2d4bdde 4932 case BUILT_IN_CONJF:
4933 case BUILT_IN_CONJL:
d30e4d04 4934 case BUILT_IN_CREAL:
d2d4bdde 4935 case BUILT_IN_CREALF:
4936 case BUILT_IN_CREALL:
d30e4d04 4937 case BUILT_IN_CIMAG:
d2d4bdde 4938 case BUILT_IN_CIMAGF:
4939 case BUILT_IN_CIMAGL:
d30e4d04 4940 /* expand_tree_builtin changes these into CONJ_EXPR, REALPART_EXPR
4941 and IMAGPART_EXPR. */
4942 abort ();
4943
53800dbe 4944 case BUILT_IN_SIN:
d2d4bdde 4945 case BUILT_IN_SINF:
4946 case BUILT_IN_SINL:
53800dbe 4947 case BUILT_IN_COS:
d2d4bdde 4948 case BUILT_IN_COSF:
4949 case BUILT_IN_COSL:
42721db0 4950 case BUILT_IN_EXP:
4951 case BUILT_IN_EXPF:
4952 case BUILT_IN_EXPL:
4953 case BUILT_IN_LOG:
4954 case BUILT_IN_LOGF:
4955 case BUILT_IN_LOGL:
528ee710 4956 case BUILT_IN_TAN:
4957 case BUILT_IN_TANF:
4958 case BUILT_IN_TANL:
4959 case BUILT_IN_ATAN:
4960 case BUILT_IN_ATANF:
4961 case BUILT_IN_ATANL:
7f3be425 4962 /* Treat these like sqrt only if unsafe math optimizations are allowed,
4963 because of possible accuracy problems. */
4964 if (! flag_unsafe_math_optimizations)
53800dbe 4965 break;
75357f66 4966 case BUILT_IN_SQRT:
d2d4bdde 4967 case BUILT_IN_SQRTF:
4968 case BUILT_IN_SQRTL:
805e22b2 4969 case BUILT_IN_FLOOR:
4970 case BUILT_IN_FLOORF:
4971 case BUILT_IN_FLOORL:
4972 case BUILT_IN_CEIL:
4973 case BUILT_IN_CEILF:
4974 case BUILT_IN_CEILL:
4975 case BUILT_IN_TRUNC:
4976 case BUILT_IN_TRUNCF:
4977 case BUILT_IN_TRUNCL:
4978 case BUILT_IN_ROUND:
4979 case BUILT_IN_ROUNDF:
4980 case BUILT_IN_ROUNDL:
4981 case BUILT_IN_NEARBYINT:
4982 case BUILT_IN_NEARBYINTF:
4983 case BUILT_IN_NEARBYINTL:
53800dbe 4984 target = expand_builtin_mathfn (exp, target, subtarget);
4985 if (target)
4986 return target;
4987 break;
4988
0fd605a5 4989 case BUILT_IN_POW:
4990 case BUILT_IN_POWF:
4991 case BUILT_IN_POWL:
f1b844c6 4992 if (! flag_unsafe_math_optimizations)
4993 break;
4994 target = expand_builtin_pow (exp, target, subtarget);
4995 if (target)
4996 return target;
4997 break;
4998
0fd605a5 4999 case BUILT_IN_ATAN2:
5000 case BUILT_IN_ATAN2F:
5001 case BUILT_IN_ATAN2L:
5002 if (! flag_unsafe_math_optimizations)
5003 break;
5004 target = expand_builtin_mathfn_2 (exp, target, subtarget);
5005 if (target)
5006 return target;
5007 break;
5008
53800dbe 5009 case BUILT_IN_APPLY_ARGS:
5010 return expand_builtin_apply_args ();
5011
5012 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
5013 FUNCTION with a copy of the parameters described by
5014 ARGUMENTS, and ARGSIZE. It returns a block of memory
5015 allocated on the stack into which is stored all the registers
5016 that might possibly be used for returning the result of a
5017 function. ARGUMENTS is the value returned by
5018 __builtin_apply_args. ARGSIZE is the number of bytes of
5019 arguments that must be copied. ??? How should this value be
5020 computed? We'll also need a safe worst case value for varargs
5021 functions. */
5022 case BUILT_IN_APPLY:
0eb671f7 5023 if (!validate_arglist (arglist, POINTER_TYPE,
5024 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
5025 && !validate_arglist (arglist, REFERENCE_TYPE,
5026 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 5027 return const0_rtx;
5028 else
5029 {
5030 int i;
5031 tree t;
5032 rtx ops[3];
5033
5034 for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
5035 ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
5036
5037 return expand_builtin_apply (ops[0], ops[1], ops[2]);
5038 }
5039
5040 /* __builtin_return (RESULT) causes the function to return the
5041 value described by RESULT. RESULT is address of the block of
5042 memory returned by __builtin_apply. */
5043 case BUILT_IN_RETURN:
0eb671f7 5044 if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
53800dbe 5045 expand_builtin_return (expand_expr (TREE_VALUE (arglist),
5046 NULL_RTX, VOIDmode, 0));
5047 return const0_rtx;
5048
5049 case BUILT_IN_SAVEREGS:
a66c9326 5050 return expand_builtin_saveregs ();
53800dbe 5051
5052 case BUILT_IN_ARGS_INFO:
80cd7a5e 5053 return expand_builtin_args_info (arglist);
53800dbe 5054
5055 /* Return the address of the first anonymous stack arg. */
5056 case BUILT_IN_NEXT_ARG:
a66c9326 5057 return expand_builtin_next_arg (arglist);
53800dbe 5058
5059 case BUILT_IN_CLASSIFY_TYPE:
5060 return expand_builtin_classify_type (arglist);
5061
5062 case BUILT_IN_CONSTANT_P:
80cd7a5e 5063 return expand_builtin_constant_p (arglist, target_mode);
53800dbe 5064
5065 case BUILT_IN_FRAME_ADDRESS:
5066 case BUILT_IN_RETURN_ADDRESS:
80cd7a5e 5067 return expand_builtin_frame_address (fndecl, arglist);
53800dbe 5068
5069 /* Returns the address of the area where the structure is returned.
5070 0 otherwise. */
5071 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
5072 if (arglist != 0
9342ee68 5073 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
5074 || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM)
5075 return const0_rtx;
53800dbe 5076 else
9342ee68 5077 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
53800dbe 5078
5079 case BUILT_IN_ALLOCA:
5080 target = expand_builtin_alloca (arglist, target);
5081 if (target)
5082 return target;
5083 break;
5084
5085 case BUILT_IN_FFS:
6a08d0ab 5086 case BUILT_IN_FFSL:
5087 case BUILT_IN_FFSLL:
efb070c8 5088 target = expand_builtin_unop (target_mode, arglist, target,
5089 subtarget, ffs_optab);
6a08d0ab 5090 if (target)
5091 return target;
5092 break;
5093
5094 case BUILT_IN_CLZ:
5095 case BUILT_IN_CLZL:
5096 case BUILT_IN_CLZLL:
efb070c8 5097 target = expand_builtin_unop (target_mode, arglist, target,
5098 subtarget, clz_optab);
6a08d0ab 5099 if (target)
5100 return target;
5101 break;
5102
5103 case BUILT_IN_CTZ:
5104 case BUILT_IN_CTZL:
5105 case BUILT_IN_CTZLL:
efb070c8 5106 target = expand_builtin_unop (target_mode, arglist, target,
5107 subtarget, ctz_optab);
6a08d0ab 5108 if (target)
5109 return target;
5110 break;
5111
5112 case BUILT_IN_POPCOUNT:
5113 case BUILT_IN_POPCOUNTL:
5114 case BUILT_IN_POPCOUNTLL:
efb070c8 5115 target = expand_builtin_unop (target_mode, arglist, target,
5116 subtarget, popcount_optab);
6a08d0ab 5117 if (target)
5118 return target;
5119 break;
5120
5121 case BUILT_IN_PARITY:
5122 case BUILT_IN_PARITYL:
5123 case BUILT_IN_PARITYLL:
efb070c8 5124 target = expand_builtin_unop (target_mode, arglist, target,
5125 subtarget, parity_optab);
53800dbe 5126 if (target)
5127 return target;
5128 break;
5129
5130 case BUILT_IN_STRLEN:
80cd7a5e 5131 target = expand_builtin_strlen (arglist, target, target_mode);
53800dbe 5132 if (target)
5133 return target;
5134 break;
5135
5136 case BUILT_IN_STRCPY:
80cd7a5e 5137 target = expand_builtin_strcpy (arglist, target, mode);
53800dbe 5138 if (target)
5139 return target;
5140 break;
bf8e3599 5141
ed09096d 5142 case BUILT_IN_STRNCPY:
5143 target = expand_builtin_strncpy (arglist, target, mode);
5144 if (target)
5145 return target;
5146 break;
bf8e3599 5147
3b824fa6 5148 case BUILT_IN_STPCPY:
5149 target = expand_builtin_stpcpy (arglist, target, mode);
5150 if (target)
5151 return target;
5152 break;
5153
49f0327b 5154 case BUILT_IN_STRCAT:
5155 target = expand_builtin_strcat (arglist, target, mode);
5156 if (target)
5157 return target;
5158 break;
bf8e3599 5159
49f0327b 5160 case BUILT_IN_STRNCAT:
5161 target = expand_builtin_strncat (arglist, target, mode);
5162 if (target)
5163 return target;
5164 break;
bf8e3599 5165
49f0327b 5166 case BUILT_IN_STRSPN:
5167 target = expand_builtin_strspn (arglist, target, mode);
5168 if (target)
5169 return target;
5170 break;
bf8e3599 5171
49f0327b 5172 case BUILT_IN_STRCSPN:
5173 target = expand_builtin_strcspn (arglist, target, mode);
5174 if (target)
5175 return target;
5176 break;
bf8e3599 5177
17f5ea87 5178 case BUILT_IN_STRSTR:
5179 target = expand_builtin_strstr (arglist, target, mode);
5180 if (target)
5181 return target;
5182 break;
bf8e3599 5183
46f3a74a 5184 case BUILT_IN_STRPBRK:
5185 target = expand_builtin_strpbrk (arglist, target, mode);
5186 if (target)
5187 return target;
5188 break;
bf8e3599 5189
398aae36 5190 case BUILT_IN_INDEX:
83d79705 5191 case BUILT_IN_STRCHR:
5192 target = expand_builtin_strchr (arglist, target, mode);
5193 if (target)
5194 return target;
5195 break;
5196
398aae36 5197 case BUILT_IN_RINDEX:
83d79705 5198 case BUILT_IN_STRRCHR:
5199 target = expand_builtin_strrchr (arglist, target, mode);
5200 if (target)
5201 return target;
5202 break;
5203
53800dbe 5204 case BUILT_IN_MEMCPY:
9fe0e1b8 5205 target = expand_builtin_memcpy (arglist, target, mode);
3b824fa6 5206 if (target)
5207 return target;
5208 break;
5209
5210 case BUILT_IN_MEMPCPY:
9fe0e1b8 5211 target = expand_builtin_mempcpy (arglist, target, mode, /*endp=*/ 1);
53800dbe 5212 if (target)
5213 return target;
5214 break;
5215
c4950093 5216 case BUILT_IN_MEMMOVE:
5217 target = expand_builtin_memmove (arglist, target, mode);
5218 if (target)
5219 return target;
5220 break;
5221
5222 case BUILT_IN_BCOPY:
5223 target = expand_builtin_bcopy (arglist);
5224 if (target)
5225 return target;
5226 break;
5227
53800dbe 5228 case BUILT_IN_MEMSET:
80cd7a5e 5229 target = expand_builtin_memset (arglist, target, mode);
53800dbe 5230 if (target)
5231 return target;
5232 break;
5233
ffc83088 5234 case BUILT_IN_BZERO:
80cd7a5e 5235 target = expand_builtin_bzero (arglist);
ffc83088 5236 if (target)
5237 return target;
5238 break;
5239
53800dbe 5240 case BUILT_IN_STRCMP:
83d79705 5241 target = expand_builtin_strcmp (exp, target, mode);
53800dbe 5242 if (target)
5243 return target;
5244 break;
5245
ed09096d 5246 case BUILT_IN_STRNCMP:
5247 target = expand_builtin_strncmp (exp, target, mode);
5248 if (target)
5249 return target;
5250 break;
5251
071f1696 5252 case BUILT_IN_BCMP:
53800dbe 5253 case BUILT_IN_MEMCMP:
6f428e8b 5254 target = expand_builtin_memcmp (exp, arglist, target, mode);
53800dbe 5255 if (target)
5256 return target;
5257 break;
53800dbe 5258
5259 case BUILT_IN_SETJMP:
6b7f6858 5260 target = expand_builtin_setjmp (arglist, target);
5261 if (target)
5262 return target;
5263 break;
53800dbe 5264
5265 /* __builtin_longjmp is passed a pointer to an array of five words.
5266 It's similar to the C library longjmp function but works with
5267 __builtin_setjmp above. */
5268 case BUILT_IN_LONGJMP:
0eb671f7 5269 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 5270 break;
5271 else
5272 {
5273 rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
5274 VOIDmode, 0);
5275 rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
5276 NULL_RTX, VOIDmode, 0);
5277
5278 if (value != const1_rtx)
5279 {
5280 error ("__builtin_longjmp second argument must be 1");
5281 return const0_rtx;
5282 }
5283
5284 expand_builtin_longjmp (buf_addr, value);
5285 return const0_rtx;
5286 }
5287
5288 case BUILT_IN_TRAP:
a0ef1725 5289 expand_builtin_trap ();
53800dbe 5290 return const0_rtx;
5291
19bf118a 5292 case BUILT_IN_PRINTF:
5293 target = expand_builtin_printf (arglist, target, mode, false);
5294 if (target)
5295 return target;
5296 break;
5297
5298 case BUILT_IN_PRINTF_UNLOCKED:
5299 target = expand_builtin_printf (arglist, target, mode, true);
5300 if (target)
5301 return target;
5302 break;
5303
df94cd3b 5304 case BUILT_IN_FPUTS:
19bf118a 5305 target = expand_builtin_fputs (arglist, target, false);
c013a46e 5306 if (target)
5307 return target;
5308 break;
19bf118a 5309
c013a46e 5310 case BUILT_IN_FPUTS_UNLOCKED:
19bf118a 5311 target = expand_builtin_fputs (arglist, target, true);
5312 if (target)
5313 return target;
5314 break;
5315
5316 case BUILT_IN_FPRINTF:
5317 target = expand_builtin_fprintf (arglist, target, mode, false);
5318 if (target)
5319 return target;
5320 break;
5321
5322 case BUILT_IN_FPRINTF_UNLOCKED:
5323 target = expand_builtin_fprintf (arglist, target, mode, true);
df94cd3b 5324 if (target)
5325 return target;
5326 break;
bf8e3599 5327
6411575e 5328 case BUILT_IN_SPRINTF:
5329 target = expand_builtin_sprintf (arglist, target, mode);
5330 if (target)
5331 return target;
5332 break;
5333
53800dbe 5334 /* Various hooks for the DWARF 2 __throw routine. */
5335 case BUILT_IN_UNWIND_INIT:
5336 expand_builtin_unwind_init ();
5337 return const0_rtx;
5338 case BUILT_IN_DWARF_CFA:
5339 return virtual_cfa_rtx;
5340#ifdef DWARF2_UNWIND_INFO
f8f023a5 5341 case BUILT_IN_DWARF_SP_COLUMN:
5342 return expand_builtin_dwarf_sp_column ();
695e919b 5343 case BUILT_IN_INIT_DWARF_REG_SIZES:
5344 expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
5345 return const0_rtx;
53800dbe 5346#endif
5347 case BUILT_IN_FROB_RETURN_ADDR:
5348 return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
5349 case BUILT_IN_EXTRACT_RETURN_ADDR:
5350 return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
5351 case BUILT_IN_EH_RETURN:
5352 expand_builtin_eh_return (TREE_VALUE (arglist),
df4b504c 5353 TREE_VALUE (TREE_CHAIN (arglist)));
53800dbe 5354 return const0_rtx;
df4b504c 5355#ifdef EH_RETURN_DATA_REGNO
5356 case BUILT_IN_EH_RETURN_DATA_REGNO:
5357 return expand_builtin_eh_return_data_regno (arglist);
5358#endif
7ccc713a 5359 case BUILT_IN_VA_START:
a66c9326 5360 case BUILT_IN_STDARG_START:
7ccc713a 5361 return expand_builtin_va_start (arglist);
a66c9326 5362 case BUILT_IN_VA_END:
5363 return expand_builtin_va_end (arglist);
5364 case BUILT_IN_VA_COPY:
5365 return expand_builtin_va_copy (arglist);
89cfe6e5 5366 case BUILT_IN_EXPECT:
5367 return expand_builtin_expect (arglist, target);
5e3608d8 5368 case BUILT_IN_PREFETCH:
5369 expand_builtin_prefetch (arglist);
5370 return const0_rtx;
5371
53800dbe 5372
92482ee0 5373 default: /* just do library call, if unknown builtin */
5374 if (!DECL_ASSEMBLER_NAME_SET_P (fndecl))
5375 error ("built-in function `%s' not currently supported",
5376 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
53800dbe 5377 }
5378
5379 /* The switch statement above can drop through to cause the function
5380 to be called normally. */
5381 return expand_call (exp, target, ignore);
5382}
650e4c94 5383
805e22b2 5384/* Determine whether a tree node represents a call to a built-in
52203a9d 5385 function. If the tree T is a call to a built-in function with
5386 the right number of arguments of the appropriate types, return
5387 the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
5388 Otherwise the return value is END_BUILTINS. */
aecda0d6 5389
805e22b2 5390enum built_in_function
aecda0d6 5391builtin_mathfn_code (tree t)
805e22b2 5392{
52203a9d 5393 tree fndecl, arglist, parmlist;
5394 tree argtype, parmtype;
805e22b2 5395
5396 if (TREE_CODE (t) != CALL_EXPR
5397 || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR)
5398 return END_BUILTINS;
5399
c6e6ecb1 5400 fndecl = get_callee_fndecl (t);
5401 if (fndecl == NULL_TREE
52203a9d 5402 || TREE_CODE (fndecl) != FUNCTION_DECL
805e22b2 5403 || ! DECL_BUILT_IN (fndecl)
5404 || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
5405 return END_BUILTINS;
5406
5407 arglist = TREE_OPERAND (t, 1);
52203a9d 5408 parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
5409 for (; parmlist; parmlist = TREE_CHAIN (parmlist))
e9f80ff5 5410 {
52203a9d 5411 /* If a function doesn't take a variable number of arguments,
5412 the last element in the list will have type `void'. */
5413 parmtype = TREE_VALUE (parmlist);
5414 if (VOID_TYPE_P (parmtype))
5415 {
5416 if (arglist)
5417 return END_BUILTINS;
5418 return DECL_FUNCTION_CODE (fndecl);
5419 }
5420
5421 if (! arglist)
e9f80ff5 5422 return END_BUILTINS;
e9f80ff5 5423
52203a9d 5424 argtype = TREE_TYPE (TREE_VALUE (arglist));
5425
5426 if (SCALAR_FLOAT_TYPE_P (parmtype))
5427 {
5428 if (! SCALAR_FLOAT_TYPE_P (argtype))
5429 return END_BUILTINS;
5430 }
5431 else if (COMPLEX_FLOAT_TYPE_P (parmtype))
5432 {
5433 if (! COMPLEX_FLOAT_TYPE_P (argtype))
5434 return END_BUILTINS;
5435 }
5436 else if (POINTER_TYPE_P (parmtype))
5437 {
5438 if (! POINTER_TYPE_P (argtype))
5439 return END_BUILTINS;
5440 }
5441 else if (INTEGRAL_TYPE_P (parmtype))
5442 {
5443 if (! INTEGRAL_TYPE_P (argtype))
5444 return END_BUILTINS;
5445 }
5446 else
e9f80ff5 5447 return END_BUILTINS;
52203a9d 5448
5449 arglist = TREE_CHAIN (arglist);
e9f80ff5 5450 }
5451
52203a9d 5452 /* Variable-length argument list. */
805e22b2 5453 return DECL_FUNCTION_CODE (fndecl);
5454}
5455
650e4c94 5456/* Fold a call to __builtin_constant_p, if we know it will evaluate to a
5457 constant. ARGLIST is the argument list of the call. */
5458
5459static tree
aecda0d6 5460fold_builtin_constant_p (tree arglist)
650e4c94 5461{
5462 if (arglist == 0)
5463 return 0;
5464
5465 arglist = TREE_VALUE (arglist);
5466
5467 /* We return 1 for a numeric type that's known to be a constant
5468 value at compile-time or for an aggregate type that's a
5469 literal constant. */
5470 STRIP_NOPS (arglist);
5471
5472 /* If we know this is a constant, emit the constant of one. */
5473 if (TREE_CODE_CLASS (TREE_CODE (arglist)) == 'c'
5474 || (TREE_CODE (arglist) == CONSTRUCTOR
5475 && TREE_CONSTANT (arglist))
5476 || (TREE_CODE (arglist) == ADDR_EXPR
5477 && TREE_CODE (TREE_OPERAND (arglist, 0)) == STRING_CST))
5478 return integer_one_node;
5479
1fb4300c 5480 /* If this expression has side effects, show we don't know it to be a
5481 constant. Likewise if it's a pointer or aggregate type since in
5482 those case we only want literals, since those are only optimized
f97c71a1 5483 when generating RTL, not later.
5484 And finally, if we are compiling an initializer, not code, we
5485 need to return a definite result now; there's not going to be any
5486 more optimization done. */
1fb4300c 5487 if (TREE_SIDE_EFFECTS (arglist)
650e4c94 5488 || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
f97c71a1 5489 || POINTER_TYPE_P (TREE_TYPE (arglist))
5490 || cfun == 0)
650e4c94 5491 return integer_zero_node;
5492
5493 return 0;
5494}
5495
539a3a92 5496/* Fold a call to __builtin_classify_type. */
27d0c333 5497
539a3a92 5498static tree
aecda0d6 5499fold_builtin_classify_type (tree arglist)
539a3a92 5500{
5501 if (arglist == 0)
5502 return build_int_2 (no_type_class, 0);
5503
5504 return build_int_2 (type_to_class (TREE_TYPE (TREE_VALUE (arglist))), 0);
5505}
5506
92c43e3c 5507/* Fold a call to __builtin_inf or __builtin_huge_val. */
5508
5509static tree
aecda0d6 5510fold_builtin_inf (tree type, int warn)
92c43e3c 5511{
aa870c1b 5512 REAL_VALUE_TYPE real;
5513
92c43e3c 5514 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
5515 warning ("target format does not support infinity");
5516
aa870c1b 5517 real_inf (&real);
5518 return build_real (type, real);
92c43e3c 5519}
5520
b0db7939 5521/* Fold a call to __builtin_nan or __builtin_nans. */
5522
5523static tree
aecda0d6 5524fold_builtin_nan (tree arglist, tree type, int quiet)
b0db7939 5525{
5526 REAL_VALUE_TYPE real;
5527 const char *str;
5528
5529 if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
5530 return 0;
5531 str = c_getstr (TREE_VALUE (arglist));
5532 if (!str)
5533 return 0;
5534
5535 if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
5536 return 0;
5537
5538 return build_real (type, real);
5539}
5540
277f8dd2 5541/* Return true if the floating point expression T has an integer value.
5542 We also allow +Inf, -Inf and NaN to be considered integer values. */
5543
5544static bool
5545integer_valued_real_p (tree t)
5546{
5547 switch (TREE_CODE (t))
5548 {
5549 case FLOAT_EXPR:
5550 return true;
5551
5552 case ABS_EXPR:
5553 case SAVE_EXPR:
5554 case NON_LVALUE_EXPR:
5555 return integer_valued_real_p (TREE_OPERAND (t, 0));
5556
5557 case COMPOUND_EXPR:
5558 case MODIFY_EXPR:
5559 case BIND_EXPR:
5560 return integer_valued_real_p (TREE_OPERAND (t, 1));
5561
5562 case PLUS_EXPR:
5563 case MINUS_EXPR:
5564 case MULT_EXPR:
5565 case MIN_EXPR:
5566 case MAX_EXPR:
5567 return integer_valued_real_p (TREE_OPERAND (t, 0))
5568 && integer_valued_real_p (TREE_OPERAND (t, 1));
5569
5570 case COND_EXPR:
5571 return integer_valued_real_p (TREE_OPERAND (t, 1))
5572 && integer_valued_real_p (TREE_OPERAND (t, 2));
5573
5574 case REAL_CST:
5575 if (! TREE_CONSTANT_OVERFLOW (t))
5576 {
5577 REAL_VALUE_TYPE c, cint;
5578
5579 c = TREE_REAL_CST (t);
5580 real_trunc (&cint, TYPE_MODE (TREE_TYPE (t)), &c);
5581 return real_identical (&c, &cint);
5582 }
5583
5584 case NOP_EXPR:
5585 {
5586 tree type = TREE_TYPE (TREE_OPERAND (t, 0));
5587 if (TREE_CODE (type) == INTEGER_TYPE)
5588 return true;
5589 if (TREE_CODE (type) == REAL_TYPE)
5590 return integer_valued_real_p (TREE_OPERAND (t, 0));
5591 break;
5592 }
5593
5594 case CALL_EXPR:
5595 switch (builtin_mathfn_code (t))
5596 {
5597 case BUILT_IN_CEIL:
5598 case BUILT_IN_CEILF:
5599 case BUILT_IN_CEILL:
5600 case BUILT_IN_FLOOR:
5601 case BUILT_IN_FLOORF:
5602 case BUILT_IN_FLOORL:
5603 case BUILT_IN_NEARBYINT:
5604 case BUILT_IN_NEARBYINTF:
5605 case BUILT_IN_NEARBYINTL:
5606 case BUILT_IN_ROUND:
5607 case BUILT_IN_ROUNDF:
5608 case BUILT_IN_ROUNDL:
5609 case BUILT_IN_TRUNC:
5610 case BUILT_IN_TRUNCF:
5611 case BUILT_IN_TRUNCL:
5612 return true;
5613
5614 default:
5615 break;
5616 }
5617 break;
5618
5619 default:
5620 break;
5621 }
5622 return false;
5623}
5624
5625/* EXP is assumed to be builtin call where truncation can be propagated
6528f4f4 5626 across (for instance floor((double)f) == (double)floorf (f).
5627 Do the transformation. */
277f8dd2 5628
6528f4f4 5629static tree
aecda0d6 5630fold_trunc_transparent_mathfn (tree exp)
6528f4f4 5631{
c6e6ecb1 5632 tree fndecl = get_callee_fndecl (exp);
6528f4f4 5633 tree arglist = TREE_OPERAND (exp, 1);
5634 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
277f8dd2 5635 tree arg;
5636
5637 if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5638 return 0;
6528f4f4 5639
277f8dd2 5640 arg = TREE_VALUE (arglist);
5641 /* Integer rounding functions are idempotent. */
5642 if (fcode == builtin_mathfn_code (arg))
5643 return arg;
5644
5645 /* If argument is already integer valued, and we don't need to worry
5646 about setting errno, there's no need to perform rounding. */
5647 if (! flag_errno_math && integer_valued_real_p (arg))
5648 return arg;
5649
5650 if (optimize)
6528f4f4 5651 {
277f8dd2 5652 tree arg0 = strip_float_extensions (arg);
6528f4f4 5653 tree ftype = TREE_TYPE (exp);
5654 tree newtype = TREE_TYPE (arg0);
5655 tree decl;
5656
5657 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
5658 && (decl = mathfn_built_in (newtype, fcode)))
5659 {
5660 arglist =
5661 build_tree_list (NULL_TREE, fold (convert (newtype, arg0)));
5662 return convert (ftype,
5663 build_function_call_expr (decl, arglist));
5664 }
5665 }
5666 return 0;
5667}
5668
c63f4ad3 5669/* Fold function call to builtin cabs, cabsf or cabsl. FNDECL is the
5670 function's DECL, ARGLIST is the argument list and TYPE is the return
5671 type. Return NULL_TREE if no simplification can be made. */
5672
5673static tree
aecda0d6 5674fold_builtin_cabs (tree fndecl, tree arglist, tree type)
c63f4ad3 5675{
5676 tree arg;
5677
5678 if (!arglist || TREE_CHAIN (arglist))
5679 return NULL_TREE;
5680
5681 arg = TREE_VALUE (arglist);
5682 if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
5683 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
5684 return NULL_TREE;
5685
5686 /* Evaluate cabs of a constant at compile-time. */
5687 if (flag_unsafe_math_optimizations
5688 && TREE_CODE (arg) == COMPLEX_CST
5689 && TREE_CODE (TREE_REALPART (arg)) == REAL_CST
5690 && TREE_CODE (TREE_IMAGPART (arg)) == REAL_CST
5691 && ! TREE_CONSTANT_OVERFLOW (TREE_REALPART (arg))
5692 && ! TREE_CONSTANT_OVERFLOW (TREE_IMAGPART (arg)))
5693 {
5694 REAL_VALUE_TYPE r, i;
5695
5696 r = TREE_REAL_CST (TREE_REALPART (arg));
5697 i = TREE_REAL_CST (TREE_IMAGPART (arg));
5698
5699 real_arithmetic (&r, MULT_EXPR, &r, &r);
5700 real_arithmetic (&i, MULT_EXPR, &i, &i);
5701 real_arithmetic (&r, PLUS_EXPR, &r, &i);
5702 if (real_sqrt (&r, TYPE_MODE (type), &r)
5703 || ! flag_trapping_math)
5704 return build_real (type, r);
5705 }
5706
5707 /* If either part is zero, cabs is fabs of the other. */
5708 if (TREE_CODE (arg) == COMPLEX_EXPR
5709 && real_zerop (TREE_OPERAND (arg, 0)))
5710 return fold (build1 (ABS_EXPR, type, TREE_OPERAND (arg, 1)));
5711 if (TREE_CODE (arg) == COMPLEX_EXPR
5712 && real_zerop (TREE_OPERAND (arg, 1)))
5713 return fold (build1 (ABS_EXPR, type, TREE_OPERAND (arg, 0)));
5714
5715 if (flag_unsafe_math_optimizations)
5716 {
5717 enum built_in_function fcode;
5718 tree sqrtfn;
5719
5720 fcode = DECL_FUNCTION_CODE (fndecl);
5721 if (fcode == BUILT_IN_CABS)
5722 sqrtfn = implicit_built_in_decls[BUILT_IN_SQRT];
5723 else if (fcode == BUILT_IN_CABSF)
5724 sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTF];
5725 else if (fcode == BUILT_IN_CABSL)
5726 sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTL];
5727 else
5728 sqrtfn = NULL_TREE;
5729
5730 if (sqrtfn != NULL_TREE)
5731 {
5732 tree rpart, ipart, result, arglist;
5733
29a6518e 5734 arg = save_expr (arg);
5735
c63f4ad3 5736 rpart = fold (build1 (REALPART_EXPR, type, arg));
5737 ipart = fold (build1 (IMAGPART_EXPR, type, arg));
5738
5739 rpart = save_expr (rpart);
5740 ipart = save_expr (ipart);
5741
5742 result = fold (build (PLUS_EXPR, type,
5743 fold (build (MULT_EXPR, type,
5744 rpart, rpart)),
5745 fold (build (MULT_EXPR, type,
5746 ipart, ipart))));
5747
5748 arglist = build_tree_list (NULL_TREE, result);
5749 return build_function_call_expr (sqrtfn, arglist);
5750 }
5751 }
5752
5753 return NULL_TREE;
5754}
5755
277f8dd2 5756/* Fold function call to builtin trunc, truncf or truncl. Return
5757 NULL_TREE if no simplification can be made. */
5758
5759static tree
5760fold_builtin_trunc (tree exp)
5761{
5762 tree arglist = TREE_OPERAND (exp, 1);
5763 tree arg;
5764
5765 if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5766 return 0;
5767
5768 /* Optimize trunc of constant value. */
5769 arg = TREE_VALUE (arglist);
5770 if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
5771 {
5772 REAL_VALUE_TYPE r, x;
5773 tree type = TREE_TYPE (exp);
5774
5775 x = TREE_REAL_CST (arg);
5776 real_trunc (&r, TYPE_MODE (type), &x);
5777 return build_real (type, r);
5778 }
5779
5780 return fold_trunc_transparent_mathfn (exp);
5781}
5782
5783/* Fold function call to builtin floor, floorf or floorl. Return
5784 NULL_TREE if no simplification can be made. */
5785
5786static tree
5787fold_builtin_floor (tree exp)
5788{
5789 tree arglist = TREE_OPERAND (exp, 1);
5790 tree arg;
5791
5792 if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5793 return 0;
5794
5795 /* Optimize floor of constant value. */
5796 arg = TREE_VALUE (arglist);
5797 if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
5798 {
5799 REAL_VALUE_TYPE x;
5800
5801 x = TREE_REAL_CST (arg);
5802 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
5803 {
5804 tree type = TREE_TYPE (exp);
5805 REAL_VALUE_TYPE r;
5806
5807 real_floor (&r, TYPE_MODE (type), &x);
5808 return build_real (type, r);
5809 }
5810 }
5811
5812 return fold_trunc_transparent_mathfn (exp);
5813}
5814
5815/* Fold function call to builtin ceil, ceilf or ceill. Return
5816 NULL_TREE if no simplification can be made. */
5817
5818static tree
5819fold_builtin_ceil (tree exp)
5820{
5821 tree arglist = TREE_OPERAND (exp, 1);
5822 tree arg;
5823
5824 if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5825 return 0;
5826
5827 /* Optimize ceil of constant value. */
5828 arg = TREE_VALUE (arglist);
5829 if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
5830 {
5831 REAL_VALUE_TYPE x;
5832
5833 x = TREE_REAL_CST (arg);
5834 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
5835 {
5836 tree type = TREE_TYPE (exp);
5837 REAL_VALUE_TYPE r;
5838
5839 real_ceil (&r, TYPE_MODE (type), &x);
5840 return build_real (type, r);
5841 }
5842 }
5843
5844 return fold_trunc_transparent_mathfn (exp);
5845}
5846
70fb4c07 5847/* Fold function call to builtin ffs, clz, ctz, popcount and parity
5848 and their long and long long variants (i.e. ffsl and ffsll).
5849 Return NULL_TREE if no simplification can be made. */
5850
5851static tree
5852fold_builtin_bitop (tree exp)
5853{
5854 tree fndecl = get_callee_fndecl (exp);
5855 tree arglist = TREE_OPERAND (exp, 1);
5856 tree arg;
5857
5858 if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
5859 return NULL_TREE;
5860
5861 /* Optimize for constant argument. */
5862 arg = TREE_VALUE (arglist);
5863 if (TREE_CODE (arg) == INTEGER_CST && ! TREE_CONSTANT_OVERFLOW (arg))
5864 {
5865 HOST_WIDE_INT hi, width, result;
5866 unsigned HOST_WIDE_INT lo;
5867 tree type, t;
5868
5869 type = TREE_TYPE (arg);
5870 width = TYPE_PRECISION (type);
5871 lo = TREE_INT_CST_LOW (arg);
5872
5873 /* Clear all the bits that are beyond the type's precision. */
5874 if (width > HOST_BITS_PER_WIDE_INT)
5875 {
5876 hi = TREE_INT_CST_HIGH (arg);
5877 if (width < 2 * HOST_BITS_PER_WIDE_INT)
5878 hi &= ~((HOST_WIDE_INT) (-1) >> (width - HOST_BITS_PER_WIDE_INT));
5879 }
5880 else
5881 {
5882 hi = 0;
5883 if (width < HOST_BITS_PER_WIDE_INT)
5884 lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
5885 }
5886
5887 switch (DECL_FUNCTION_CODE (fndecl))
5888 {
5889 case BUILT_IN_FFS:
5890 case BUILT_IN_FFSL:
5891 case BUILT_IN_FFSLL:
5892 if (lo != 0)
5893 result = exact_log2 (lo & -lo) + 1;
5894 else if (hi != 0)
5895 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi) + 1;
5896 else
5897 result = 0;
5898 break;
5899
5900 case BUILT_IN_CLZ:
5901 case BUILT_IN_CLZL:
5902 case BUILT_IN_CLZLL:
5903 if (hi != 0)
5904 result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
5905 else if (lo != 0)
5906 result = width - floor_log2 (lo) - 1;
5907 else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
5908 result = width;
5909 break;
5910
5911 case BUILT_IN_CTZ:
5912 case BUILT_IN_CTZL:
5913 case BUILT_IN_CTZLL:
5914 if (lo != 0)
5915 result = exact_log2 (lo & -lo);
5916 else if (hi != 0)
5917 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi);
5918 else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
5919 result = width;
5920 break;
5921
5922 case BUILT_IN_POPCOUNT:
5923 case BUILT_IN_POPCOUNTL:
5924 case BUILT_IN_POPCOUNTLL:
5925 result = 0;
5926 while (lo)
5927 result++, lo &= lo - 1;
5928 while (hi)
5929 result++, hi &= hi - 1;
5930 break;
5931
5932 case BUILT_IN_PARITY:
5933 case BUILT_IN_PARITYL:
5934 case BUILT_IN_PARITYLL:
5935 result = 0;
5936 while (lo)
5937 result++, lo &= lo - 1;
5938 while (hi)
5939 result++, hi &= hi - 1;
5940 result &= 1;
5941 break;
5942
5943 default:
5944 abort();
5945 }
5946
5947 t = build_int_2 (result, 0);
5948 TREE_TYPE (t) = TREE_TYPE (exp);
5949 return t;
5950 }
5951
5952 return NULL_TREE;
5953}
5954
8918c507 5955/* Return true if EXPR is the real constant contained in VALUE. */
5956
5957static bool
5958real_dconstp (tree expr, const REAL_VALUE_TYPE *value)
5959{
5960 STRIP_NOPS (expr);
5961
5962 return ((TREE_CODE (expr) == REAL_CST
5963 && ! TREE_CONSTANT_OVERFLOW (expr)
5964 && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), *value))
5965 || (TREE_CODE (expr) == COMPLEX_CST
5966 && real_dconstp (TREE_REALPART (expr), value)
5967 && real_zerop (TREE_IMAGPART (expr))));
5968}
5969
5970/* A subroutine of fold_builtin to fold the various logarithmic
5971 functions. EXP is the CALL_EXPR of a call to a builtin log*
5972 function. VALUE is the base of the log* function. */
5973
5974static tree
5975fold_builtin_logarithm (tree exp, const REAL_VALUE_TYPE *value)
5976{
5977 tree arglist = TREE_OPERAND (exp, 1);
5978
5979 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5980 {
5981 tree fndecl = get_callee_fndecl (exp);
5982 tree type = TREE_TYPE (TREE_TYPE (fndecl));
5983 tree arg = TREE_VALUE (arglist);
5984 const enum built_in_function fcode = builtin_mathfn_code (arg);
8918c507 5985
5986 /* Optimize log*(1.0) = 0.0. */
5987 if (real_onep (arg))
5988 return build_real (type, dconst0);
5989
1f5cb383 5990 /* Optimize logN(N) = 1.0. If N can't be truncated to MODE
5991 exactly, then only do this if flag_unsafe_math_optimizations. */
5992 if (exact_real_truncate (TYPE_MODE (type), value)
5993 || flag_unsafe_math_optimizations)
5994 {
5995 const REAL_VALUE_TYPE value_truncate =
5996 real_value_truncate (TYPE_MODE (type), *value);
5997 if (real_dconstp (arg, &value_truncate))
5998 return build_real (type, dconst1);
5999 }
8918c507 6000
6001 /* Special case, optimize logN(expN(x)) = x. */
6002 if (flag_unsafe_math_optimizations
6003 && ((value == &dconste
6004 && (fcode == BUILT_IN_EXP
6005 || fcode == BUILT_IN_EXPF
6006 || fcode == BUILT_IN_EXPL))
6007 || (value == &dconst2
6008 && (fcode == BUILT_IN_EXP2
6009 || fcode == BUILT_IN_EXP2F
6010 || fcode == BUILT_IN_EXP2L))
6011 || (value == &dconst10
6012 && (fcode == BUILT_IN_EXP10
6013 || fcode == BUILT_IN_EXP10F
6014 || fcode == BUILT_IN_EXP10L))))
6015 return convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
6016
6017 /* Optimize log*(func()) for various exponential functions. We
6018 want to determine the value "x" and the power "exponent" in
6019 order to transform logN(x**exponent) into exponent*logN(x). */
6020 if (flag_unsafe_math_optimizations)
6021 {
6022 tree exponent = 0, x = 0;
6023
6024 switch (fcode)
6025 {
6026 case BUILT_IN_EXP:
6027 case BUILT_IN_EXPF:
6028 case BUILT_IN_EXPL:
6029 /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
8918c507 6030 x = build_real (type,
6031 real_value_truncate (TYPE_MODE (type), dconste));
6032 exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
6033 break;
6034 case BUILT_IN_EXP2:
6035 case BUILT_IN_EXP2F:
6036 case BUILT_IN_EXP2L:
6037 /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */
6038 x = build_real (type, dconst2);
6039 exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
6040 break;
6041 case BUILT_IN_EXP10:
6042 case BUILT_IN_EXP10F:
6043 case BUILT_IN_EXP10L:
6044 case BUILT_IN_POW10:
6045 case BUILT_IN_POW10F:
6046 case BUILT_IN_POW10L:
6047 /* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */
6048 x = build_real (type, dconst10);
6049 exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
6050 break;
6051 case BUILT_IN_SQRT:
6052 case BUILT_IN_SQRTF:
6053 case BUILT_IN_SQRTL:
6054 /* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */
6055 x = TREE_VALUE (TREE_OPERAND (arg, 1));
6056 exponent = build_real (type, dconsthalf);
6057 break;
6058 case BUILT_IN_CBRT:
6059 case BUILT_IN_CBRTF:
6060 case BUILT_IN_CBRTL:
6061 /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */
6062 x = TREE_VALUE (TREE_OPERAND (arg, 1));
6063 exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
6064 dconstthird));
6065 break;
6066 case BUILT_IN_POW:
6067 case BUILT_IN_POWF:
6068 case BUILT_IN_POWL:
6069 /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x). */
6070 x = TREE_VALUE (TREE_OPERAND (arg, 1));
6071 exponent = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
6072 break;
6073 default:
6074 break;
6075 }
6076
6077 /* Now perform the optimization. */
6078 if (x && exponent)
6079 {
6080 tree logfn;
6081 arglist = build_tree_list (NULL_TREE, x);
6082 logfn = build_function_call_expr (fndecl, arglist);
6083 return fold (build (MULT_EXPR, type, exponent, logfn));
6084 }
6085 }
6086 }
6087
6088 return 0;
6089}
6090
6091/* A subroutine of fold_builtin to fold the various exponent
6092 functions. EXP is the CALL_EXPR of a call to a builtin function.
6093 VALUE is the value which will be raised to a power. */
6094
6095static tree
6096fold_builtin_exponent (tree exp, const REAL_VALUE_TYPE *value)
6097{
6098 tree arglist = TREE_OPERAND (exp, 1);
6099
6100 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6101 {
6102 tree fndecl = get_callee_fndecl (exp);
6103 tree type = TREE_TYPE (TREE_TYPE (fndecl));
6104 tree arg = TREE_VALUE (arglist);
6105
6106 /* Optimize exp*(0.0) = 1.0. */
6107 if (real_zerop (arg))
6108 return build_real (type, dconst1);
6109
6110 /* Optimize expN(1.0) = N. */
6111 if (real_onep (arg))
6112 {
6113 REAL_VALUE_TYPE cst;
6114
6115 real_convert (&cst, TYPE_MODE (type), value);
6116 return build_real (type, cst);
6117 }
6118
6119 /* Attempt to evaluate expN(integer) at compile-time. */
6120 if (flag_unsafe_math_optimizations
6121 && TREE_CODE (arg) == REAL_CST
6122 && ! TREE_CONSTANT_OVERFLOW (arg))
6123 {
6124 REAL_VALUE_TYPE cint;
6125 REAL_VALUE_TYPE c;
6126 HOST_WIDE_INT n;
6127
6128 c = TREE_REAL_CST (arg);
6129 n = real_to_integer (&c);
6130 real_from_integer (&cint, VOIDmode, n,
6131 n < 0 ? -1 : 0, 0);
6132 if (real_identical (&c, &cint))
6133 {
6134 REAL_VALUE_TYPE x;
6135
6136 real_powi (&x, TYPE_MODE (type), value, n);
6137 return build_real (type, x);
6138 }
6139 }
6140
6141 /* Optimize expN(logN(x)) = x. */
6142 if (flag_unsafe_math_optimizations)
6143 {
6144 const enum built_in_function fcode = builtin_mathfn_code (arg);
6145
6146 if ((value == &dconste
6147 && (fcode == BUILT_IN_LOG
6148 || fcode == BUILT_IN_LOGF
6149 || fcode == BUILT_IN_LOGL))
6150 || (value == &dconst2
6151 && (fcode == BUILT_IN_LOG2
6152 || fcode == BUILT_IN_LOG2F
6153 || fcode == BUILT_IN_LOG2L))
6154 || (value == &dconst10
6155 && (fcode == BUILT_IN_LOG10
6156 || fcode == BUILT_IN_LOG10F
6157 || fcode == BUILT_IN_LOG10L)))
6158 return convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
6159 }
6160 }
6161
6162 return 0;
6163}
6164
650e4c94 6165/* Used by constant folding to eliminate some builtin calls early. EXP is
6166 the CALL_EXPR of a call to a builtin function. */
6167
6168tree
aecda0d6 6169fold_builtin (tree exp)
650e4c94 6170{
c6e6ecb1 6171 tree fndecl = get_callee_fndecl (exp);
650e4c94 6172 tree arglist = TREE_OPERAND (exp, 1);
e9f80ff5 6173 tree type = TREE_TYPE (TREE_TYPE (fndecl));
650e4c94 6174
6175 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
6176 return 0;
6177
2643011a 6178 switch (DECL_FUNCTION_CODE (fndecl))
650e4c94 6179 {
6180 case BUILT_IN_CONSTANT_P:
6181 return fold_builtin_constant_p (arglist);
6182
539a3a92 6183 case BUILT_IN_CLASSIFY_TYPE:
6184 return fold_builtin_classify_type (arglist);
6185
650e4c94 6186 case BUILT_IN_STRLEN:
0eb671f7 6187 if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
650e4c94 6188 {
681fab1e 6189 tree len = c_strlen (TREE_VALUE (arglist), 0);
654ef926 6190 if (len)
6191 {
6192 /* Convert from the internal "sizetype" type to "size_t". */
6193 if (size_type_node)
6194 len = convert (size_type_node, len);
6195 return len;
6196 }
650e4c94 6197 }
6198 break;
6199
c63f4ad3 6200 case BUILT_IN_FABS:
6201 case BUILT_IN_FABSF:
6202 case BUILT_IN_FABSL:
6203 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6204 return fold (build1 (ABS_EXPR, type, TREE_VALUE (arglist)));
6205 break;
6206
6207 case BUILT_IN_CABS:
6208 case BUILT_IN_CABSF:
6209 case BUILT_IN_CABSL:
6210 return fold_builtin_cabs (fndecl, arglist, type);
6211
805e22b2 6212 case BUILT_IN_SQRT:
6213 case BUILT_IN_SQRTF:
6214 case BUILT_IN_SQRTL:
6215 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6216 {
6217 enum built_in_function fcode;
6218 tree arg = TREE_VALUE (arglist);
6219
6220 /* Optimize sqrt of constant value. */
6221 if (TREE_CODE (arg) == REAL_CST
6222 && ! TREE_CONSTANT_OVERFLOW (arg))
6223 {
805e22b2 6224 REAL_VALUE_TYPE r, x;
6225
6226 x = TREE_REAL_CST (arg);
3be04962 6227 if (real_sqrt (&r, TYPE_MODE (type), &x)
61f1dccc 6228 || (!flag_trapping_math && !flag_errno_math))
e9f80ff5 6229 return build_real (type, r);
805e22b2 6230 }
6231
2643011a 6232 /* Optimize sqrt(exp(x)) = exp(x*0.5). */
805e22b2 6233 fcode = builtin_mathfn_code (arg);
6234 if (flag_unsafe_math_optimizations
6235 && (fcode == BUILT_IN_EXP
6236 || fcode == BUILT_IN_EXPF
6237 || fcode == BUILT_IN_EXPL))
6238 {
6239 tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
2643011a 6240 arg = fold (build (MULT_EXPR, type,
77e89269 6241 TREE_VALUE (TREE_OPERAND (arg, 1)),
2643011a 6242 build_real (type, dconsthalf)));
805e22b2 6243 arglist = build_tree_list (NULL_TREE, arg);
6244 return build_function_call_expr (expfn, arglist);
6245 }
2643011a 6246
6247 /* Optimize sqrt(pow(x,y)) = pow(x,y*0.5). */
6248 if (flag_unsafe_math_optimizations
6249 && (fcode == BUILT_IN_POW
6250 || fcode == BUILT_IN_POWF
6251 || fcode == BUILT_IN_POWL))
6252 {
6253 tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
6254 tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
6255 tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
6256 tree narg1 = fold (build (MULT_EXPR, type, arg1,
6257 build_real (type, dconsthalf)));
6258 arglist = tree_cons (NULL_TREE, arg0,
6259 build_tree_list (NULL_TREE, narg1));
6260 return build_function_call_expr (powfn, arglist);
6261 }
805e22b2 6262 }
6263 break;
6264
77e89269 6265 case BUILT_IN_SIN:
6266 case BUILT_IN_SINF:
6267 case BUILT_IN_SINL:
6268 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6269 {
6270 tree arg = TREE_VALUE (arglist);
6271
6272 /* Optimize sin(0.0) = 0.0. */
6273 if (real_zerop (arg))
98b40778 6274 return arg;
77e89269 6275 }
6276 break;
6277
6278 case BUILT_IN_COS:
6279 case BUILT_IN_COSF:
6280 case BUILT_IN_COSL:
6281 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6282 {
6283 tree arg = TREE_VALUE (arglist);
6284
6285 /* Optimize cos(0.0) = 1.0. */
6286 if (real_zerop (arg))
6287 return build_real (type, dconst1);
a4a686a7 6288
6289 /* Optimize cos(-x) into cos(x). */
6290 if (TREE_CODE (arg) == NEGATE_EXPR)
6291 {
6292 tree arglist = build_tree_list (NULL_TREE,
6293 TREE_OPERAND (arg, 0));
6294 return build_function_call_expr (fndecl, arglist);
6295 }
77e89269 6296 }
6297 break;
6298
805e22b2 6299 case BUILT_IN_EXP:
6300 case BUILT_IN_EXPF:
6301 case BUILT_IN_EXPL:
8918c507 6302 return fold_builtin_exponent (exp, &dconste);
6303 case BUILT_IN_EXP2:
6304 case BUILT_IN_EXP2F:
6305 case BUILT_IN_EXP2L:
6306 return fold_builtin_exponent (exp, &dconst2);
6307 case BUILT_IN_EXP10:
6308 case BUILT_IN_EXP10F:
6309 case BUILT_IN_EXP10L:
6310 case BUILT_IN_POW10:
6311 case BUILT_IN_POW10F:
6312 case BUILT_IN_POW10L:
6313 return fold_builtin_exponent (exp, &dconst10);
805e22b2 6314 case BUILT_IN_LOG:
6315 case BUILT_IN_LOGF:
6316 case BUILT_IN_LOGL:
8918c507 6317 return fold_builtin_logarithm (exp, &dconste);
6318 break;
6319 case BUILT_IN_LOG2:
6320 case BUILT_IN_LOG2F:
6321 case BUILT_IN_LOG2L:
6322 return fold_builtin_logarithm (exp, &dconst2);
6323 break;
6324 case BUILT_IN_LOG10:
6325 case BUILT_IN_LOG10F:
6326 case BUILT_IN_LOG10L:
6327 return fold_builtin_logarithm (exp, &dconst10);
805e22b2 6328 break;
6329
98b40778 6330 case BUILT_IN_TAN:
6331 case BUILT_IN_TANF:
6332 case BUILT_IN_TANL:
6333 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6334 {
6335 enum built_in_function fcode;
6336 tree arg = TREE_VALUE (arglist);
6337
6338 /* Optimize tan(0.0) = 0.0. */
6339 if (real_zerop (arg))
6340 return arg;
6341
6342 /* Optimize tan(atan(x)) = x. */
6343 fcode = builtin_mathfn_code (arg);
6344 if (flag_unsafe_math_optimizations
6345 && (fcode == BUILT_IN_ATAN
6346 || fcode == BUILT_IN_ATANF
6347 || fcode == BUILT_IN_ATANL))
6348 return TREE_VALUE (TREE_OPERAND (arg, 1));
6349 }
6350 break;
6351
6352 case BUILT_IN_ATAN:
6353 case BUILT_IN_ATANF:
6354 case BUILT_IN_ATANL:
6355 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6356 {
6357 tree arg = TREE_VALUE (arglist);
6358
6359 /* Optimize atan(0.0) = 0.0. */
6360 if (real_zerop (arg))
6361 return arg;
6362
6363 /* Optimize atan(1.0) = pi/4. */
6364 if (real_onep (arg))
6365 {
6366 REAL_VALUE_TYPE cst;
6367
98b40778 6368 real_convert (&cst, TYPE_MODE (type), &dconstpi);
6369 cst.exp -= 2;
6370 return build_real (type, cst);
6371 }
6372 }
6373 break;
6374
e9f80ff5 6375 case BUILT_IN_POW:
6376 case BUILT_IN_POWF:
6377 case BUILT_IN_POWL:
6378 if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
6379 {
2643011a 6380 enum built_in_function fcode;
e9f80ff5 6381 tree arg0 = TREE_VALUE (arglist);
6382 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
6383
e9f80ff5 6384 /* Optimize pow(1.0,y) = 1.0. */
6385 if (real_onep (arg0))
6386 return omit_one_operand (type, build_real (type, dconst1), arg1);
77e89269 6387
6388 if (TREE_CODE (arg1) == REAL_CST
6389 && ! TREE_CONSTANT_OVERFLOW (arg1))
6390 {
6391 REAL_VALUE_TYPE c;
6392 c = TREE_REAL_CST (arg1);
6393
6394 /* Optimize pow(x,0.0) = 1.0. */
6395 if (REAL_VALUES_EQUAL (c, dconst0))
6396 return omit_one_operand (type, build_real (type, dconst1),
6397 arg0);
6398
6399 /* Optimize pow(x,1.0) = x. */
6400 if (REAL_VALUES_EQUAL (c, dconst1))
6401 return arg0;
6402
6403 /* Optimize pow(x,-1.0) = 1.0/x. */
6404 if (REAL_VALUES_EQUAL (c, dconstm1))
6405 return fold (build (RDIV_EXPR, type,
6406 build_real (type, dconst1),
6407 arg0));
6408
77e89269 6409 /* Optimize pow(x,0.5) = sqrt(x). */
6410 if (flag_unsafe_math_optimizations
6411 && REAL_VALUES_EQUAL (c, dconsthalf))
6412 {
6413 tree sqrtfn;
6414
2643011a 6415 fcode = DECL_FUNCTION_CODE (fndecl);
77e89269 6416 if (fcode == BUILT_IN_POW)
6417 sqrtfn = implicit_built_in_decls[BUILT_IN_SQRT];
6418 else if (fcode == BUILT_IN_POWF)
6419 sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTF];
6420 else if (fcode == BUILT_IN_POWL)
6421 sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTL];
6422 else
6423 sqrtfn = NULL_TREE;
6424
6425 if (sqrtfn != NULL_TREE)
6426 {
6427 tree arglist = build_tree_list (NULL_TREE, arg0);
6428 return build_function_call_expr (sqrtfn, arglist);
6429 }
6430 }
3be04962 6431
6432 /* Attempt to evaluate pow at compile-time. */
6433 if (TREE_CODE (arg0) == REAL_CST
6434 && ! TREE_CONSTANT_OVERFLOW (arg0))
6435 {
6436 REAL_VALUE_TYPE cint;
6437 HOST_WIDE_INT n;
6438
98b40778 6439 n = real_to_integer (&c);
3be04962 6440 real_from_integer (&cint, VOIDmode, n,
6441 n < 0 ? -1 : 0, 0);
6442 if (real_identical (&c, &cint))
6443 {
6444 REAL_VALUE_TYPE x;
6445 bool inexact;
6446
6447 x = TREE_REAL_CST (arg0);
6448 inexact = real_powi (&x, TYPE_MODE (type), &x, n);
6449 if (flag_unsafe_math_optimizations || !inexact)
6450 return build_real (type, x);
6451 }
6452 }
77e89269 6453 }
2643011a 6454
6455 /* Optimize pow(exp(x),y) = exp(x*y). */
6456 fcode = builtin_mathfn_code (arg0);
6457 if (flag_unsafe_math_optimizations
6458 && (fcode == BUILT_IN_EXP
6459 || fcode == BUILT_IN_EXPF
6460 || fcode == BUILT_IN_EXPL))
6461 {
6462 tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
6463 tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
6464 arg = fold (build (MULT_EXPR, type, arg, arg1));
6465 arglist = build_tree_list (NULL_TREE, arg);
6466 return build_function_call_expr (expfn, arglist);
6467 }
6468
6469 /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
6470 if (flag_unsafe_math_optimizations
6471 && (fcode == BUILT_IN_SQRT
6472 || fcode == BUILT_IN_SQRTF
6473 || fcode == BUILT_IN_SQRTL))
6474 {
6475 tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
6476 tree narg1 = fold (build (MULT_EXPR, type, arg1,
6477 build_real (type, dconsthalf)));
6478
6479 arglist = tree_cons (NULL_TREE, narg0,
6480 build_tree_list (NULL_TREE, narg1));
6481 return build_function_call_expr (fndecl, arglist);
6482 }
6483
6484 /* Optimize pow(pow(x,y),z) = pow(x,y*z). */
6485 if (flag_unsafe_math_optimizations
6486 && (fcode == BUILT_IN_POW
6487 || fcode == BUILT_IN_POWF
6488 || fcode == BUILT_IN_POWL))
6489 {
6490 tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
6491 tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
6492 tree narg1 = fold (build (MULT_EXPR, type, arg01, arg1));
6493 arglist = tree_cons (NULL_TREE, arg00,
6494 build_tree_list (NULL_TREE, narg1));
6495 return build_function_call_expr (fndecl, arglist);
6496 }
e9f80ff5 6497 }
6498 break;
6499
92c43e3c 6500 case BUILT_IN_INF:
6501 case BUILT_IN_INFF:
6502 case BUILT_IN_INFL:
e9f80ff5 6503 return fold_builtin_inf (type, true);
92c43e3c 6504
6505 case BUILT_IN_HUGE_VAL:
6506 case BUILT_IN_HUGE_VALF:
6507 case BUILT_IN_HUGE_VALL:
e9f80ff5 6508 return fold_builtin_inf (type, false);
92c43e3c 6509
b0db7939 6510 case BUILT_IN_NAN:
6511 case BUILT_IN_NANF:
6512 case BUILT_IN_NANL:
e9f80ff5 6513 return fold_builtin_nan (arglist, type, true);
b0db7939 6514
6515 case BUILT_IN_NANS:
6516 case BUILT_IN_NANSF:
6517 case BUILT_IN_NANSL:
e9f80ff5 6518 return fold_builtin_nan (arglist, type, false);
b0db7939 6519
6528f4f4 6520 case BUILT_IN_FLOOR:
6521 case BUILT_IN_FLOORF:
6522 case BUILT_IN_FLOORL:
277f8dd2 6523 return fold_builtin_floor (exp);
6524
6528f4f4 6525 case BUILT_IN_CEIL:
6526 case BUILT_IN_CEILF:
6527 case BUILT_IN_CEILL:
277f8dd2 6528 return fold_builtin_ceil (exp);
6529
6528f4f4 6530 case BUILT_IN_TRUNC:
6531 case BUILT_IN_TRUNCF:
6532 case BUILT_IN_TRUNCL:
277f8dd2 6533 return fold_builtin_trunc (exp);
6534
6528f4f4 6535 case BUILT_IN_ROUND:
6536 case BUILT_IN_ROUNDF:
6537 case BUILT_IN_ROUNDL:
6538 case BUILT_IN_NEARBYINT:
6539 case BUILT_IN_NEARBYINTF:
6540 case BUILT_IN_NEARBYINTL:
6541 return fold_trunc_transparent_mathfn (exp);
6542
70fb4c07 6543 case BUILT_IN_FFS:
6544 case BUILT_IN_FFSL:
6545 case BUILT_IN_FFSLL:
6546 case BUILT_IN_CLZ:
6547 case BUILT_IN_CLZL:
6548 case BUILT_IN_CLZLL:
6549 case BUILT_IN_CTZ:
6550 case BUILT_IN_CTZL:
6551 case BUILT_IN_CTZLL:
6552 case BUILT_IN_POPCOUNT:
6553 case BUILT_IN_POPCOUNTL:
6554 case BUILT_IN_POPCOUNTLL:
6555 case BUILT_IN_PARITY:
6556 case BUILT_IN_PARITYL:
6557 case BUILT_IN_PARITYLL:
6558 return fold_builtin_bitop (exp);
6559
650e4c94 6560 default:
6561 break;
6562 }
6563
6564 return 0;
6565}
7e15618b 6566
805e22b2 6567/* Conveniently construct a function call expression. */
6568
6569tree
aecda0d6 6570build_function_call_expr (tree fn, tree arglist)
7e15618b 6571{
6572 tree call_expr;
6573
6574 call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
6575 call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
6576 call_expr, arglist);
7e15618b 6577 return fold (call_expr);
6578}
0eb671f7 6579
6580/* This function validates the types of a function call argument list
6581 represented as a tree chain of parameters against a specified list
6582 of tree_codes. If the last specifier is a 0, that represents an
6583 ellipses, otherwise the last specifier must be a VOID_TYPE. */
27d0c333 6584
0eb671f7 6585static int
ee582a61 6586validate_arglist (tree arglist, ...)
0eb671f7 6587{
0eb671f7 6588 enum tree_code code;
0903457a 6589 int res = 0;
ee582a61 6590 va_list ap;
aecda0d6 6591
ee582a61 6592 va_start (ap, arglist);
0eb671f7 6593
f0ce3b1f 6594 do
0eb671f7 6595 {
f0ce3b1f 6596 code = va_arg (ap, enum tree_code);
6597 switch (code)
6598 {
6599 case 0:
6600 /* This signifies an ellipses, any further arguments are all ok. */
6601 res = 1;
6602 goto end;
6603 case VOID_TYPE:
6604 /* This signifies an endlink, if no arguments remain, return
6605 true, otherwise return false. */
6606 res = arglist == 0;
6607 goto end;
6608 default:
6609 /* If no parameters remain or the parameter's code does not
6610 match the specified code, return false. Otherwise continue
6611 checking any remaining arguments. */
6612 if (arglist == 0
6613 || code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
6614 goto end;
6615 break;
6616 }
6617 arglist = TREE_CHAIN (arglist);
0eb671f7 6618 }
f0ce3b1f 6619 while (1);
0903457a 6620
6621 /* We need gotos here since we can only have one VA_CLOSE in a
6622 function. */
6623 end: ;
ee582a61 6624 va_end (ap);
0903457a 6625
6626 return res;
0eb671f7 6627}
fc2a2dcb 6628
fc2a2dcb 6629/* Default target-specific builtin expander that does nothing. */
6630
6631rtx
aecda0d6 6632default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
6633 rtx target ATTRIBUTE_UNUSED,
6634 rtx subtarget ATTRIBUTE_UNUSED,
6635 enum machine_mode mode ATTRIBUTE_UNUSED,
6636 int ignore ATTRIBUTE_UNUSED)
fc2a2dcb 6637{
6638 return NULL_RTX;
6639}
c7926a82 6640
6641/* Instantiate all remaining CONSTANT_P_RTX nodes. */
6642
6643void
aecda0d6 6644purge_builtin_constant_p (void)
c7926a82 6645{
ea06a334 6646 rtx insn, set, arg, new, note;
c7926a82 6647
ea06a334 6648 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
6649 if (INSN_P (insn)
6650 && (set = single_set (insn)) != NULL_RTX
26d64224 6651 && (GET_CODE (arg = SET_SRC (set)) == CONSTANT_P_RTX
6652 || (GET_CODE (arg) == SUBREG
6653 && (GET_CODE (arg = SUBREG_REG (arg))
6654 == CONSTANT_P_RTX))))
ea06a334 6655 {
26d64224 6656 arg = XEXP (arg, 0);
ea06a334 6657 new = CONSTANT_P (arg) ? const1_rtx : const0_rtx;
6658 validate_change (insn, &SET_SRC (set), new, 0);
c7926a82 6659
ea06a334 6660 /* Remove the REG_EQUAL note from the insn. */
6661 if ((note = find_reg_note (insn, REG_EQUAL, NULL_RTX)) != 0)
6662 remove_note (insn, note);
6663 }
c7926a82 6664}
6665
01537105 6666/* Returns true is EXP represents data that would potentially reside
6667 in a readonly section. */
6668
6669static bool
6670readonly_data_expr (tree exp)
6671{
6672 STRIP_NOPS (exp);
6673
6674 if (TREE_CODE (exp) == ADDR_EXPR)
6675 return decl_readonly_section (TREE_OPERAND (exp, 0), 0);
6676 else
6677 return false;
6678}