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