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