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