]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/builtins.c
Daily bump.
[thirdparty/gcc.git] / gcc / builtins.c
CommitLineData
53800dbe 1/* Expand builtin functions.
61f1dccc 2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
062b4460 3 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
f96bd2bf 4 Free Software Foundation, Inc.
53800dbe 5
f12b58b3 6This file is part of GCC.
53800dbe 7
f12b58b3 8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
8c4c00c1 10Software Foundation; either version 3, or (at your option) any later
f12b58b3 11version.
53800dbe 12
f12b58b3 13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
53800dbe 17
18You should have received a copy of the GNU General Public License
8c4c00c1 19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
53800dbe 21
22#include "config.h"
23#include "system.h"
805e22b2 24#include "coretypes.h"
25#include "tm.h"
53800dbe 26#include "machmode.h"
ef258422 27#include "real.h"
53800dbe 28#include "rtl.h"
29#include "tree.h"
75a70cf9 30#include "gimple.h"
53800dbe 31#include "flags.h"
32#include "regs.h"
33#include "hard-reg-set.h"
34#include "except.h"
35#include "function.h"
53800dbe 36#include "insn-config.h"
37#include "expr.h"
d8fc4d0b 38#include "optabs.h"
39#include "libfuncs.h"
53800dbe 40#include "recog.h"
41#include "output.h"
42#include "typeclass.h"
53800dbe 43#include "toplev.h"
689df48e 44#include "predict.h"
1dd6c958 45#include "tm_p.h"
fc2a2dcb 46#include "target.h"
63c62881 47#include "langhooks.h"
0ec80471 48#include "basic-block.h"
fd62c19a 49#include "tree-mudflap.h"
5a84fdd6 50#include "tree-flow.h"
162719b3 51#include "value-prof.h"
07311427 52#include "diagnostic.h"
53800dbe 53
5383fb56 54#ifndef SLOW_UNALIGNED_ACCESS
55#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
56#endif
57
726e2588 58#ifndef PAD_VARARGS_DOWN
59#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
60#endif
239d491a 61static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_rnd_t));
726e2588 62
ab7943b9 63/* Define the names of the builtin function types and codes. */
8934cb0c 64const char *const built_in_class_names[4]
ab7943b9 65 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
66
9cfddb70 67#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
0dfc45b5 68const char * built_in_names[(int) END_BUILTINS] =
4e9d90c7 69{
70#include "builtins.def"
71};
72#undef DEF_BUILTIN
ab7943b9 73
df94cd3b 74/* Setup an array of _DECL trees, make sure each element is
75 initialized to NULL_TREE. */
d2d4bdde 76tree built_in_decls[(int) END_BUILTINS];
0a68165a 77/* Declarations used when constructing the builtin implicitly in the compiler.
78 It may be NULL_TREE when this is invalid (for instance runtime is not
4ee9c684 79 required to implement the function call in all cases). */
0a68165a 80tree implicit_built_in_decls[(int) END_BUILTINS];
df94cd3b 81
aecda0d6 82static const char *c_getstr (tree);
83static rtx c_readstr (const char *, enum machine_mode);
84static int target_char_cast (tree, char *);
d8ae1baa 85static rtx get_memory_rtx (tree, tree);
aecda0d6 86static int apply_args_size (void);
87static int apply_result_size (void);
d8c9779c 88#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
aecda0d6 89static rtx result_vector (int, rtx);
d8c9779c 90#endif
843d08a9 91static void expand_builtin_update_setjmp_buf (rtx);
aecda0d6 92static void expand_builtin_prefetch (tree);
93static rtx expand_builtin_apply_args (void);
94static rtx expand_builtin_apply_args_1 (void);
95static rtx expand_builtin_apply (rtx, rtx, rtx);
96static void expand_builtin_return (rtx);
97static enum type_class type_to_class (tree);
98static rtx expand_builtin_classify_type (tree);
99static void expand_errno_check (tree, rtx);
100static rtx expand_builtin_mathfn (tree, rtx, rtx);
101static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
6b43bae4 102static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
a67a90e5 103static rtx expand_builtin_interclass_mathfn (tree, rtx, rtx);
c3147c1a 104static rtx expand_builtin_sincos (tree);
d735c391 105static rtx expand_builtin_cexpi (tree, rtx, rtx);
ff1b14e4 106static rtx expand_builtin_int_roundingfn (tree, rtx);
107static rtx expand_builtin_int_roundingfn_2 (tree, rtx);
aecda0d6 108static rtx expand_builtin_args_info (tree);
79012a9d 109static rtx expand_builtin_next_arg (void);
aecda0d6 110static rtx expand_builtin_va_start (tree);
111static rtx expand_builtin_va_end (tree);
112static rtx expand_builtin_va_copy (tree);
c2f47e15 113static rtx expand_builtin_memcmp (tree, rtx, enum machine_mode);
a65c4d64 114static rtx expand_builtin_strcmp (tree, rtx);
aecda0d6 115static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
116static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
a65c4d64 117static rtx expand_builtin_memcpy (tree, rtx);
c2f47e15 118static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode);
48e1416a 119static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx,
c2f47e15 120 enum machine_mode, int);
a65c4d64 121static rtx expand_builtin_strcpy (tree, rtx);
122static rtx expand_builtin_strcpy_args (tree, tree, rtx);
aecda0d6 123static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
a65c4d64 124static rtx expand_builtin_strncpy (tree, rtx);
aecda0d6 125static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
c2f47e15 126static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
127static rtx expand_builtin_memset_args (tree, tree, tree, rtx, enum machine_mode, tree);
aecda0d6 128static rtx expand_builtin_bzero (tree);
129static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
aecda0d6 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);
389dd41b 133static tree stabilize_va_list_loc (location_t, tree, int);
aecda0d6 134static rtx expand_builtin_expect (tree, rtx);
135static tree fold_builtin_constant_p (tree);
389dd41b 136static tree fold_builtin_expect (location_t, tree, tree);
aecda0d6 137static tree fold_builtin_classify_type (tree);
389dd41b 138static tree fold_builtin_strlen (location_t, tree);
139static tree fold_builtin_inf (location_t, tree, int);
aecda0d6 140static tree fold_builtin_nan (tree, tree, int);
389dd41b 141static tree rewrite_call_expr (location_t, tree, int, tree, int, ...);
b7bf20db 142static bool validate_arg (const_tree, enum tree_code code);
277f8dd2 143static bool integer_valued_real_p (tree);
389dd41b 144static tree fold_trunc_transparent_mathfn (location_t, tree, tree);
aecda0d6 145static bool readonly_data_expr (tree);
146static rtx expand_builtin_fabs (tree, rtx, rtx);
27f261ef 147static rtx expand_builtin_signbit (tree, rtx);
389dd41b 148static tree fold_builtin_sqrt (location_t, tree, tree);
149static tree fold_builtin_cbrt (location_t, tree, tree);
150static tree fold_builtin_pow (location_t, tree, tree, tree, tree);
151static tree fold_builtin_powi (location_t, tree, tree, tree, tree);
152static tree fold_builtin_cos (location_t, tree, tree, tree);
153static tree fold_builtin_cosh (location_t, tree, tree, tree);
bffb7645 154static tree fold_builtin_tan (tree, tree);
389dd41b 155static tree fold_builtin_trunc (location_t, tree, tree);
156static tree fold_builtin_floor (location_t, tree, tree);
157static tree fold_builtin_ceil (location_t, tree, tree);
158static tree fold_builtin_round (location_t, tree, tree);
159static tree fold_builtin_int_roundingfn (location_t, tree, tree);
10b9666f 160static tree fold_builtin_bitop (tree, tree);
389dd41b 161static tree fold_builtin_memory_op (location_t, tree, tree, tree, tree, bool, int);
162static tree fold_builtin_strchr (location_t, tree, tree, tree);
163static tree fold_builtin_memchr (location_t, tree, tree, tree, tree);
164static tree fold_builtin_memcmp (location_t, tree, tree, tree);
165static tree fold_builtin_strcmp (location_t, tree, tree);
166static tree fold_builtin_strncmp (location_t, tree, tree, tree);
167static tree fold_builtin_signbit (location_t, tree, tree);
168static tree fold_builtin_copysign (location_t, tree, tree, tree, tree);
169static tree fold_builtin_isascii (location_t, tree);
170static tree fold_builtin_toascii (location_t, tree);
171static tree fold_builtin_isdigit (location_t, tree);
172static tree fold_builtin_fabs (location_t, tree, tree);
173static tree fold_builtin_abs (location_t, tree, tree);
174static tree fold_builtin_unordered_cmp (location_t, tree, tree, tree, enum tree_code,
d5019fe8 175 enum tree_code);
389dd41b 176static tree fold_builtin_n (location_t, tree, tree *, int, bool);
177static tree fold_builtin_0 (location_t, tree, bool);
178static tree fold_builtin_1 (location_t, tree, tree, bool);
179static tree fold_builtin_2 (location_t, tree, tree, tree, bool);
180static tree fold_builtin_3 (location_t, tree, tree, tree, tree, bool);
181static tree fold_builtin_4 (location_t, tree, tree, tree, tree, tree, bool);
182static tree fold_builtin_varargs (location_t, tree, tree, bool);
183
184static tree fold_builtin_strpbrk (location_t, tree, tree, tree);
185static tree fold_builtin_strstr (location_t, tree, tree, tree);
186static tree fold_builtin_strrchr (location_t, tree, tree, tree);
187static tree fold_builtin_strcat (location_t, tree, tree);
188static tree fold_builtin_strncat (location_t, tree, tree, tree);
189static tree fold_builtin_strspn (location_t, tree, tree);
190static tree fold_builtin_strcspn (location_t, tree, tree);
191static tree fold_builtin_sprintf (location_t, tree, tree, tree, int);
4ee9c684 192
0a39fd54 193static rtx expand_builtin_object_size (tree);
194static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
195 enum built_in_function);
196static void maybe_emit_chk_warning (tree, enum built_in_function);
197static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
2c281b15 198static void maybe_emit_free_warning (tree);
c2f47e15 199static tree fold_builtin_object_size (tree, tree);
389dd41b 200static tree fold_builtin_strcat_chk (location_t, tree, tree, tree, tree);
201static tree fold_builtin_strncat_chk (location_t, tree, tree, tree, tree, tree);
202static tree fold_builtin_sprintf_chk (location_t, tree, enum built_in_function);
203static tree fold_builtin_printf (location_t, tree, tree, tree, bool, enum built_in_function);
204static tree fold_builtin_fprintf (location_t, tree, tree, tree, tree, bool,
c2f47e15 205 enum built_in_function);
99eabcc1 206static bool init_target_chars (void);
207
208static unsigned HOST_WIDE_INT target_newline;
209static unsigned HOST_WIDE_INT target_percent;
210static unsigned HOST_WIDE_INT target_c;
211static unsigned HOST_WIDE_INT target_s;
212static char target_percent_c[3];
213static char target_percent_s[3];
214static char target_percent_s_newline[4];
728bac60 215static tree do_mpfr_arg1 (tree, tree, int (*)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
216 const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, bool);
f0c477f2 217static tree do_mpfr_arg2 (tree, tree, tree,
218 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
9917422b 219static tree do_mpfr_arg3 (tree, tree, tree, tree,
220 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
d92f994c 221static tree do_mpfr_sincos (tree, tree, tree);
65dd1378 222static tree do_mpfr_bessel_n (tree, tree, tree,
223 int (*)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
224 const REAL_VALUE_TYPE *, bool);
e5407ca6 225static tree do_mpfr_remquo (tree, tree, tree);
e84da7c1 226static tree do_mpfr_lgamma_r (tree, tree, tree);
0a39fd54 227
7bfefa9d 228/* Return true if NAME starts with __builtin_ or __sync_. */
229
1c47b3e8 230bool
231is_builtin_name (const char *name)
b6a5fc45 232{
b6a5fc45 233 if (strncmp (name, "__builtin_", 10) == 0)
234 return true;
235 if (strncmp (name, "__sync_", 7) == 0)
236 return true;
237 return false;
238}
4ee9c684 239
7bfefa9d 240
241/* Return true if DECL is a function symbol representing a built-in. */
242
243bool
244is_builtin_fn (tree decl)
245{
246 return TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl);
247}
248
249
1c47b3e8 250/* Return true if NODE should be considered for inline expansion regardless
251 of the optimization level. This means whenever a function is invoked with
252 its "internal" name, which normally contains the prefix "__builtin". */
253
254static bool
255called_as_built_in (tree node)
256{
257 /* Note that we must use DECL_NAME, not DECL_ASSEMBLER_NAME_SET_P since
258 we want the name used to call the function, not the name it
259 will have. */
260 const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
261 return is_builtin_name (name);
262}
263
698537d1 264/* Return the alignment in bits of EXP, an object.
265 Don't return more than MAX_ALIGN no matter what, ALIGN is the inital
266 guessed alignment e.g. from type alignment. */
267
268int
269get_object_alignment (tree exp, unsigned int align, unsigned int max_align)
270{
271 unsigned int inner;
272
273 inner = max_align;
274 if (handled_component_p (exp))
275 {
276 HOST_WIDE_INT bitsize, bitpos;
277 tree offset;
48e1416a 278 enum machine_mode mode;
698537d1 279 int unsignedp, volatilep;
280
281 exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
282 &mode, &unsignedp, &volatilep, true);
283 if (bitpos)
284 inner = MIN (inner, (unsigned) (bitpos & -bitpos));
285 while (offset)
286 {
287 tree next_offset;
288
289 if (TREE_CODE (offset) == PLUS_EXPR)
290 {
291 next_offset = TREE_OPERAND (offset, 0);
292 offset = TREE_OPERAND (offset, 1);
293 }
294 else
295 next_offset = NULL;
296 if (host_integerp (offset, 1))
297 {
298 /* Any overflow in calculating offset_bits won't change
299 the alignment. */
300 unsigned offset_bits
301 = ((unsigned) tree_low_cst (offset, 1) * BITS_PER_UNIT);
302
303 if (offset_bits)
304 inner = MIN (inner, (offset_bits & -offset_bits));
305 }
306 else if (TREE_CODE (offset) == MULT_EXPR
307 && host_integerp (TREE_OPERAND (offset, 1), 1))
308 {
309 /* Any overflow in calculating offset_factor won't change
310 the alignment. */
311 unsigned offset_factor
312 = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
313 * BITS_PER_UNIT);
314
315 if (offset_factor)
316 inner = MIN (inner, (offset_factor & -offset_factor));
317 }
318 else
319 {
320 inner = MIN (inner, BITS_PER_UNIT);
321 break;
322 }
323 offset = next_offset;
324 }
325 }
326 if (DECL_P (exp))
327 align = MIN (inner, DECL_ALIGN (exp));
328#ifdef CONSTANT_ALIGNMENT
329 else if (CONSTANT_CLASS_P (exp))
330 align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align));
331#endif
332 else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR
333 || TREE_CODE (exp) == INDIRECT_REF)
334 align = MIN (TYPE_ALIGN (TREE_TYPE (exp)), inner);
335 else
336 align = MIN (align, inner);
337 return MIN (align, max_align);
338}
339
7abca321 340/* Returns true iff we can trust that alignment information has been
341 calculated properly. */
342
343bool
344can_trust_pointer_alignment (void)
345{
346 /* We rely on TER to compute accurate alignment information. */
347 return (optimize && flag_tree_ter);
348}
349
53800dbe 350/* Return the alignment in bits of EXP, a pointer valued expression.
351 But don't return more than MAX_ALIGN no matter what.
352 The alignment returned is, by default, the alignment of the thing that
27d0c333 353 EXP points to. If it is not a POINTER_TYPE, 0 is returned.
53800dbe 354
355 Otherwise, look at the expression to see if we can do better, i.e., if the
356 expression is actually pointing at an object whose alignment is tighter. */
357
f656b751 358int
aecda0d6 359get_pointer_alignment (tree exp, unsigned int max_align)
53800dbe 360{
27d0c333 361 unsigned int align, inner;
53800dbe 362
7abca321 363 if (!can_trust_pointer_alignment ())
189575ff 364 return 0;
365
535e2026 366 if (!POINTER_TYPE_P (TREE_TYPE (exp)))
367 return 0;
368
53800dbe 369 align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
370 align = MIN (align, max_align);
371
372 while (1)
373 {
374 switch (TREE_CODE (exp))
375 {
72dd6141 376 CASE_CONVERT:
53800dbe 377 exp = TREE_OPERAND (exp, 0);
552752f7 378 if (! POINTER_TYPE_P (TREE_TYPE (exp)))
53800dbe 379 return align;
325d1c45 380
53800dbe 381 inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
382 align = MIN (inner, max_align);
383 break;
384
0de36bdb 385 case POINTER_PLUS_EXPR:
53800dbe 386 /* If sum of pointer + int, restrict our maximum alignment to that
387 imposed by the integer. If not, we can't do any better than
388 ALIGN. */
325d1c45 389 if (! host_integerp (TREE_OPERAND (exp, 1), 1))
53800dbe 390 return align;
391
0994d2ed 392 while (((tree_low_cst (TREE_OPERAND (exp, 1), 1))
393 & (max_align / BITS_PER_UNIT - 1))
53800dbe 394 != 0)
395 max_align >>= 1;
396
397 exp = TREE_OPERAND (exp, 0);
398 break;
399
400 case ADDR_EXPR:
401 /* See what we are pointing at and look at its alignment. */
698537d1 402 return get_object_alignment (TREE_OPERAND (exp, 0), align, max_align);
53800dbe 403
404 default:
405 return align;
406 }
407 }
408}
409
410/* Compute the length of a C string. TREE_STRING_LENGTH is not the right
411 way, because it could contain a zero byte in the middle.
412 TREE_STRING_LENGTH is the size of the character array, not the string.
413
4172d65e 414 ONLY_VALUE should be nonzero if the result is not going to be emitted
c09841f6 415 into the instruction stream and zero if it is going to be expanded.
4172d65e 416 E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
681fab1e 417 is returned, otherwise NULL, since
418 len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
419 evaluate the side-effects.
420
902de8ed 421 The value returned is of type `ssizetype'.
422
53800dbe 423 Unfortunately, string_constant can't access the values of const char
424 arrays with initializers, so neither can we do so here. */
425
4ee9c684 426tree
681fab1e 427c_strlen (tree src, int only_value)
53800dbe 428{
429 tree offset_node;
27d0c333 430 HOST_WIDE_INT offset;
431 int max;
44acf429 432 const char *ptr;
53800dbe 433
681fab1e 434 STRIP_NOPS (src);
435 if (TREE_CODE (src) == COND_EXPR
436 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
437 {
438 tree len1, len2;
439
440 len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
441 len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
0862b7e9 442 if (tree_int_cst_equal (len1, len2))
681fab1e 443 return len1;
444 }
445
446 if (TREE_CODE (src) == COMPOUND_EXPR
447 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
448 return c_strlen (TREE_OPERAND (src, 1), only_value);
449
53800dbe 450 src = string_constant (src, &offset_node);
451 if (src == 0)
c2f47e15 452 return NULL_TREE;
902de8ed 453
83d79705 454 max = TREE_STRING_LENGTH (src) - 1;
53800dbe 455 ptr = TREE_STRING_POINTER (src);
902de8ed 456
53800dbe 457 if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
458 {
459 /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
460 compute the offset to the following null if we don't know where to
461 start searching for it. */
462 int i;
902de8ed 463
53800dbe 464 for (i = 0; i < max; i++)
465 if (ptr[i] == 0)
c2f47e15 466 return NULL_TREE;
902de8ed 467
53800dbe 468 /* We don't know the starting offset, but we do know that the string
469 has no internal zero bytes. We can assume that the offset falls
470 within the bounds of the string; otherwise, the programmer deserves
471 what he gets. Subtract the offset from the length of the string,
902de8ed 472 and return that. This would perhaps not be valid if we were dealing
473 with named arrays in addition to literal string constants. */
474
389dd41b 475 return size_diffop_loc (input_location, size_int (max), offset_node);
53800dbe 476 }
477
478 /* We have a known offset into the string. Start searching there for
27d0c333 479 a null character if we can represent it as a single HOST_WIDE_INT. */
dabc4084 480 if (offset_node == 0)
53800dbe 481 offset = 0;
dabc4084 482 else if (! host_integerp (offset_node, 0))
483 offset = -1;
53800dbe 484 else
27d0c333 485 offset = tree_low_cst (offset_node, 0);
902de8ed 486
1f63a7d6 487 /* If the offset is known to be out of bounds, warn, and call strlen at
488 runtime. */
53800dbe 489 if (offset < 0 || offset > max)
490 {
1f63a7d6 491 /* Suppress multiple warnings for propagated constant strings. */
492 if (! TREE_NO_WARNING (src))
493 {
494 warning (0, "offset outside bounds of constant string");
495 TREE_NO_WARNING (src) = 1;
496 }
c2f47e15 497 return NULL_TREE;
53800dbe 498 }
902de8ed 499
53800dbe 500 /* Use strlen to search for the first zero byte. Since any strings
501 constructed with build_string will have nulls appended, we win even
502 if we get handed something like (char[4])"abcd".
503
504 Since OFFSET is our starting index into the string, no further
505 calculation is needed. */
902de8ed 506 return ssize_int (strlen (ptr + offset));
53800dbe 507}
508
83d79705 509/* Return a char pointer for a C string if it is a string constant
510 or sum of string constant and integer constant. */
511
512static const char *
aecda0d6 513c_getstr (tree src)
83d79705 514{
515 tree offset_node;
83d79705 516
517 src = string_constant (src, &offset_node);
518 if (src == 0)
519 return 0;
520
8c85fcb7 521 if (offset_node == 0)
522 return TREE_STRING_POINTER (src);
523 else if (!host_integerp (offset_node, 1)
524 || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
83d79705 525 return 0;
83d79705 526
8c85fcb7 527 return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
83d79705 528}
529
8c85fcb7 530/* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
531 GET_MODE_BITSIZE (MODE) bits from string constant STR. */
ecc318ff 532
6840589f 533static rtx
aecda0d6 534c_readstr (const char *str, enum machine_mode mode)
6840589f 535{
536 HOST_WIDE_INT c[2];
537 HOST_WIDE_INT ch;
538 unsigned int i, j;
539
64db345d 540 gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
7d3f6cc7 541
6840589f 542 c[0] = 0;
543 c[1] = 0;
544 ch = 1;
545 for (i = 0; i < GET_MODE_SIZE (mode); i++)
546 {
547 j = i;
548 if (WORDS_BIG_ENDIAN)
549 j = GET_MODE_SIZE (mode) - i - 1;
550 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
551 && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
552 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
553 j *= BITS_PER_UNIT;
64db345d 554 gcc_assert (j <= 2 * HOST_BITS_PER_WIDE_INT);
7d3f6cc7 555
6840589f 556 if (ch)
557 ch = (unsigned char) str[i];
558 c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
559 }
560 return immed_double_const (c[0], c[1], mode);
561}
562
ecc318ff 563/* Cast a target constant CST to target CHAR and if that value fits into
5206b159 564 host char type, return zero and put that value into variable pointed to by
ecc318ff 565 P. */
566
567static int
aecda0d6 568target_char_cast (tree cst, char *p)
ecc318ff 569{
570 unsigned HOST_WIDE_INT val, hostval;
571
27d0c333 572 if (!host_integerp (cst, 1)
ecc318ff 573 || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
574 return 1;
575
27d0c333 576 val = tree_low_cst (cst, 1);
ecc318ff 577 if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
578 val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
579
580 hostval = val;
581 if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
582 hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
583
584 if (val != hostval)
585 return 1;
586
587 *p = hostval;
588 return 0;
589}
590
4ee9c684 591/* Similar to save_expr, but assumes that arbitrary code is not executed
592 in between the multiple evaluations. In particular, we assume that a
593 non-addressable local variable will not be modified. */
594
595static tree
596builtin_save_expr (tree exp)
597{
598 if (TREE_ADDRESSABLE (exp) == 0
599 && (TREE_CODE (exp) == PARM_DECL
600 || (TREE_CODE (exp) == VAR_DECL && !TREE_STATIC (exp))))
601 return exp;
602
603 return save_expr (exp);
604}
605
53800dbe 606/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
607 times to get the address of either a higher stack frame, or a return
608 address located within it (depending on FNDECL_CODE). */
902de8ed 609
c626df3d 610static rtx
869d0ef0 611expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
53800dbe 612{
613 int i;
614
869d0ef0 615#ifdef INITIAL_FRAME_ADDRESS_RTX
616 rtx tem = INITIAL_FRAME_ADDRESS_RTX;
617#else
e3e15c50 618 rtx tem;
619
1b74fde7 620 /* For a zero count with __builtin_return_address, we don't care what
621 frame address we return, because target-specific definitions will
622 override us. Therefore frame pointer elimination is OK, and using
623 the soft frame pointer is OK.
624
fa7637bd 625 For a nonzero count, or a zero count with __builtin_frame_address,
1b74fde7 626 we require a stable offset from the current frame pointer to the
627 previous one, so we must use the hard frame pointer, and
e3e15c50 628 we must disable frame pointer elimination. */
1b74fde7 629 if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
e3e15c50 630 tem = frame_pointer_rtx;
a0c938f0 631 else
e3e15c50 632 {
633 tem = hard_frame_pointer_rtx;
634
635 /* Tell reload not to eliminate the frame pointer. */
18d50ae6 636 crtl->accesses_prior_frames = 1;
e3e15c50 637 }
869d0ef0 638#endif
639
53800dbe 640 /* Some machines need special handling before we can access
3a69c60c 641 arbitrary frames. For example, on the SPARC, we must first flush
53800dbe 642 all register windows to the stack. */
643#ifdef SETUP_FRAME_ADDRESSES
644 if (count > 0)
645 SETUP_FRAME_ADDRESSES ();
646#endif
647
3a69c60c 648 /* On the SPARC, the return address is not in the frame, it is in a
53800dbe 649 register. There is no way to access it off of the current frame
650 pointer, but it can be accessed off the previous frame pointer by
651 reading the value from the register window save area. */
652#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
653 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
654 count--;
655#endif
656
657 /* Scan back COUNT frames to the specified frame. */
658 for (i = 0; i < count; i++)
659 {
660 /* Assume the dynamic chain pointer is in the word that the
661 frame address points to, unless otherwise specified. */
662#ifdef DYNAMIC_CHAIN_ADDRESS
663 tem = DYNAMIC_CHAIN_ADDRESS (tem);
664#endif
665 tem = memory_address (Pmode, tem);
00060fc2 666 tem = gen_frame_mem (Pmode, tem);
83fc1478 667 tem = copy_to_reg (tem);
53800dbe 668 }
669
3a69c60c 670 /* For __builtin_frame_address, return what we've got. But, on
671 the SPARC for example, we may have to add a bias. */
53800dbe 672 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
3a69c60c 673#ifdef FRAME_ADDR_RTX
674 return FRAME_ADDR_RTX (tem);
675#else
53800dbe 676 return tem;
3a69c60c 677#endif
53800dbe 678
3a69c60c 679 /* For __builtin_return_address, get the return address from that frame. */
53800dbe 680#ifdef RETURN_ADDR_RTX
681 tem = RETURN_ADDR_RTX (count, tem);
682#else
683 tem = memory_address (Pmode,
684 plus_constant (tem, GET_MODE_SIZE (Pmode)));
00060fc2 685 tem = gen_frame_mem (Pmode, tem);
53800dbe 686#endif
687 return tem;
688}
689
f7c44134 690/* Alias set used for setjmp buffer. */
32c2fdea 691static alias_set_type setjmp_alias_set = -1;
f7c44134 692
6b7f6858 693/* Construct the leading half of a __builtin_setjmp call. Control will
2c8a1497 694 return to RECEIVER_LABEL. This is also called directly by the SJLJ
695 exception handling code. */
53800dbe 696
6b7f6858 697void
aecda0d6 698expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
53800dbe 699{
53800dbe 700 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
53800dbe 701 rtx stack_save;
f7c44134 702 rtx mem;
53800dbe 703
f7c44134 704 if (setjmp_alias_set == -1)
705 setjmp_alias_set = new_alias_set ();
706
85d654dd 707 buf_addr = convert_memory_address (Pmode, buf_addr);
53800dbe 708
37ae8504 709 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
53800dbe 710
6b7f6858 711 /* We store the frame pointer and the address of receiver_label in
712 the buffer and use the rest of it for the stack save area, which
713 is machine-dependent. */
53800dbe 714
f7c44134 715 mem = gen_rtx_MEM (Pmode, buf_addr);
ab6ab77e 716 set_mem_alias_set (mem, setjmp_alias_set);
e3e026e8 717 emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
f7c44134 718
719 mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
ab6ab77e 720 set_mem_alias_set (mem, setjmp_alias_set);
f7c44134 721
722 emit_move_insn (validize_mem (mem),
6b7f6858 723 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
53800dbe 724
725 stack_save = gen_rtx_MEM (sa_mode,
726 plus_constant (buf_addr,
727 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 728 set_mem_alias_set (stack_save, setjmp_alias_set);
53800dbe 729 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
730
731 /* If there is further processing to do, do it. */
732#ifdef HAVE_builtin_setjmp_setup
733 if (HAVE_builtin_setjmp_setup)
734 emit_insn (gen_builtin_setjmp_setup (buf_addr));
735#endif
736
6b7f6858 737 /* Tell optimize_save_area_alloca that extra work is going to
738 need to go on during alloca. */
18d50ae6 739 cfun->calls_setjmp = 1;
80ab81b9 740
29f09705 741 /* We have a nonlocal label. */
18d50ae6 742 cfun->has_nonlocal_label = 1;
6b7f6858 743}
53800dbe 744
2c8a1497 745/* Construct the trailing part of a __builtin_setjmp call. This is
746 also called directly by the SJLJ exception handling code. */
6b7f6858 747
748void
aecda0d6 749expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
6b7f6858 750{
82c7907c 751 rtx chain;
752
53800dbe 753 /* Clobber the FP when we get here, so we have to make sure it's
754 marked as used by this function. */
18b42941 755 emit_use (hard_frame_pointer_rtx);
53800dbe 756
757 /* Mark the static chain as clobbered here so life information
758 doesn't get messed up for it. */
82c7907c 759 chain = targetm.calls.static_chain (current_function_decl, true);
760 if (chain && REG_P (chain))
761 emit_clobber (chain);
53800dbe 762
763 /* Now put in the code to restore the frame pointer, and argument
491e04ef 764 pointer, if needed. */
53800dbe 765#ifdef HAVE_nonlocal_goto
766 if (! HAVE_nonlocal_goto)
767#endif
5a1c3f40 768 {
769 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
770 /* This might change the hard frame pointer in ways that aren't
771 apparent to early optimization passes, so force a clobber. */
18b42941 772 emit_clobber (hard_frame_pointer_rtx);
5a1c3f40 773 }
53800dbe 774
775#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
776 if (fixed_regs[ARG_POINTER_REGNUM])
777 {
778#ifdef ELIMINABLE_REGS
779 size_t i;
e99c3a1d 780 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
53800dbe 781
3098b2d3 782 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
53800dbe 783 if (elim_regs[i].from == ARG_POINTER_REGNUM
784 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
785 break;
786
3098b2d3 787 if (i == ARRAY_SIZE (elim_regs))
53800dbe 788#endif
789 {
790 /* Now restore our arg pointer from the address at which it
05927e40 791 was saved in our stack frame. */
27a7a23a 792 emit_move_insn (crtl->args.internal_arg_pointer,
b079a207 793 copy_to_reg (get_arg_pointer_save_area ()));
53800dbe 794 }
795 }
796#endif
797
798#ifdef HAVE_builtin_setjmp_receiver
799 if (HAVE_builtin_setjmp_receiver)
6b7f6858 800 emit_insn (gen_builtin_setjmp_receiver (receiver_label));
53800dbe 801 else
802#endif
803#ifdef HAVE_nonlocal_goto_receiver
804 if (HAVE_nonlocal_goto_receiver)
805 emit_insn (gen_nonlocal_goto_receiver ());
806 else
807#endif
6b7f6858 808 { /* Nothing */ }
57f6bb94 809
3072d30e 810 /* We must not allow the code we just generated to be reordered by
811 scheduling. Specifically, the update of the frame pointer must
812 happen immediately, not later. */
813 emit_insn (gen_blockage ());
6b7f6858 814}
53800dbe 815
53800dbe 816/* __builtin_longjmp is passed a pointer to an array of five words (not
817 all will be used on all machines). It operates similarly to the C
818 library function of the same name, but is more efficient. Much of
2c8a1497 819 the code below is copied from the handling of non-local gotos. */
53800dbe 820
c626df3d 821static void
aecda0d6 822expand_builtin_longjmp (rtx buf_addr, rtx value)
53800dbe 823{
4712c7d6 824 rtx fp, lab, stack, insn, last;
53800dbe 825 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
826
48e1416a 827 /* DRAP is needed for stack realign if longjmp is expanded to current
27a7a23a 828 function */
829 if (SUPPORTS_STACK_ALIGNMENT)
830 crtl->need_drap = true;
831
f7c44134 832 if (setjmp_alias_set == -1)
833 setjmp_alias_set = new_alias_set ();
834
85d654dd 835 buf_addr = convert_memory_address (Pmode, buf_addr);
479e4d5e 836
53800dbe 837 buf_addr = force_reg (Pmode, buf_addr);
838
82c7907c 839 /* We require that the user must pass a second argument of 1, because
840 that is what builtin_setjmp will return. */
64db345d 841 gcc_assert (value == const1_rtx);
53800dbe 842
4712c7d6 843 last = get_last_insn ();
53800dbe 844#ifdef HAVE_builtin_longjmp
845 if (HAVE_builtin_longjmp)
846 emit_insn (gen_builtin_longjmp (buf_addr));
847 else
848#endif
849 {
850 fp = gen_rtx_MEM (Pmode, buf_addr);
851 lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
852 GET_MODE_SIZE (Pmode)));
853
854 stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
855 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 856 set_mem_alias_set (fp, setjmp_alias_set);
857 set_mem_alias_set (lab, setjmp_alias_set);
858 set_mem_alias_set (stack, setjmp_alias_set);
53800dbe 859
860 /* Pick up FP, label, and SP from the block and jump. This code is
861 from expand_goto in stmt.c; see there for detailed comments. */
03fd9d2c 862#ifdef HAVE_nonlocal_goto
53800dbe 863 if (HAVE_nonlocal_goto)
864 /* We have to pass a value to the nonlocal_goto pattern that will
865 get copied into the static_chain pointer, but it does not matter
866 what that value is, because builtin_setjmp does not use it. */
28d202a8 867 emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
53800dbe 868 else
869#endif
870 {
871 lab = copy_to_reg (lab);
872
18b42941 873 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
874 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
2a871ad1 875
53800dbe 876 emit_move_insn (hard_frame_pointer_rtx, fp);
877 emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
878
18b42941 879 emit_use (hard_frame_pointer_rtx);
880 emit_use (stack_pointer_rtx);
53800dbe 881 emit_indirect_jump (lab);
882 }
883 }
615166bb 884
885 /* Search backwards and mark the jump insn as a non-local goto.
886 Note that this precludes the use of __builtin_longjmp to a
887 __builtin_setjmp target in the same function. However, we've
888 already cautioned the user that these functions are for
889 internal exception handling use only. */
449c0509 890 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
891 {
64db345d 892 gcc_assert (insn != last);
7d3f6cc7 893
6d7dc5b9 894 if (JUMP_P (insn))
449c0509 895 {
a1ddb869 896 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
449c0509 897 break;
898 }
6d7dc5b9 899 else if (CALL_P (insn))
9342ee68 900 break;
449c0509 901 }
53800dbe 902}
903
4ee9c684 904/* Expand a call to __builtin_nonlocal_goto. We're passed the target label
905 and the address of the save area. */
906
907static rtx
c2f47e15 908expand_builtin_nonlocal_goto (tree exp)
4ee9c684 909{
910 tree t_label, t_save_area;
911 rtx r_label, r_save_area, r_fp, r_sp, insn;
912
c2f47e15 913 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4ee9c684 914 return NULL_RTX;
915
c2f47e15 916 t_label = CALL_EXPR_ARG (exp, 0);
917 t_save_area = CALL_EXPR_ARG (exp, 1);
4ee9c684 918
8ec3c5c2 919 r_label = expand_normal (t_label);
3dce56cc 920 r_label = convert_memory_address (Pmode, r_label);
8ec3c5c2 921 r_save_area = expand_normal (t_save_area);
3dce56cc 922 r_save_area = convert_memory_address (Pmode, r_save_area);
51adbc8a 923 /* Copy the address of the save location to a register just in case it was based
924 on the frame pointer. */
925 r_save_area = copy_to_reg (r_save_area);
4ee9c684 926 r_fp = gen_rtx_MEM (Pmode, r_save_area);
927 r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
928 plus_constant (r_save_area, GET_MODE_SIZE (Pmode)));
929
18d50ae6 930 crtl->has_nonlocal_goto = 1;
4ee9c684 931
03fd9d2c 932#ifdef HAVE_nonlocal_goto
4ee9c684 933 /* ??? We no longer need to pass the static chain value, afaik. */
934 if (HAVE_nonlocal_goto)
935 emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
936 else
937#endif
938 {
939 r_label = copy_to_reg (r_label);
940
18b42941 941 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
942 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
491e04ef 943
4ee9c684 944 /* Restore frame pointer for containing function.
945 This sets the actual hard register used for the frame pointer
946 to the location of the function's incoming static chain info.
947 The non-local goto handler will then adjust it to contain the
948 proper value and reload the argument pointer, if needed. */
949 emit_move_insn (hard_frame_pointer_rtx, r_fp);
950 emit_stack_restore (SAVE_NONLOCAL, r_sp, NULL_RTX);
491e04ef 951
4ee9c684 952 /* USE of hard_frame_pointer_rtx added for consistency;
953 not clear if really needed. */
18b42941 954 emit_use (hard_frame_pointer_rtx);
955 emit_use (stack_pointer_rtx);
ad0d0af8 956
957 /* If the architecture is using a GP register, we must
958 conservatively assume that the target function makes use of it.
959 The prologue of functions with nonlocal gotos must therefore
960 initialize the GP register to the appropriate value, and we
961 must then make sure that this value is live at the point
962 of the jump. (Note that this doesn't necessarily apply
963 to targets with a nonlocal_goto pattern; they are free
964 to implement it in their own way. Note also that this is
965 a no-op if the GP register is a global invariant.) */
966 if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
967 && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
18b42941 968 emit_use (pic_offset_table_rtx);
ad0d0af8 969
4ee9c684 970 emit_indirect_jump (r_label);
971 }
491e04ef 972
4ee9c684 973 /* Search backwards to the jump insn and mark it as a
974 non-local goto. */
975 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
976 {
6d7dc5b9 977 if (JUMP_P (insn))
4ee9c684 978 {
a1ddb869 979 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
4ee9c684 980 break;
981 }
6d7dc5b9 982 else if (CALL_P (insn))
4ee9c684 983 break;
984 }
985
986 return const0_rtx;
987}
988
843d08a9 989/* __builtin_update_setjmp_buf is passed a pointer to an array of five words
990 (not all will be used on all machines) that was passed to __builtin_setjmp.
991 It updates the stack pointer in that block to correspond to the current
992 stack pointer. */
993
994static void
995expand_builtin_update_setjmp_buf (rtx buf_addr)
996{
997 enum machine_mode sa_mode = Pmode;
998 rtx stack_save;
999
1000
1001#ifdef HAVE_save_stack_nonlocal
1002 if (HAVE_save_stack_nonlocal)
1003 sa_mode = insn_data[(int) CODE_FOR_save_stack_nonlocal].operand[0].mode;
1004#endif
1005#ifdef STACK_SAVEAREA_MODE
1006 sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
1007#endif
1008
1009 stack_save
1010 = gen_rtx_MEM (sa_mode,
1011 memory_address
1012 (sa_mode,
1013 plus_constant (buf_addr, 2 * GET_MODE_SIZE (Pmode))));
1014
1015#ifdef HAVE_setjmp
1016 if (HAVE_setjmp)
1017 emit_insn (gen_setjmp ());
1018#endif
1019
1020 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
1021}
1022
5e3608d8 1023/* Expand a call to __builtin_prefetch. For a target that does not support
1024 data prefetch, evaluate the memory address argument in case it has side
1025 effects. */
1026
1027static void
c2f47e15 1028expand_builtin_prefetch (tree exp)
5e3608d8 1029{
1030 tree arg0, arg1, arg2;
c2f47e15 1031 int nargs;
5e3608d8 1032 rtx op0, op1, op2;
1033
c2f47e15 1034 if (!validate_arglist (exp, POINTER_TYPE, 0))
26a5cadb 1035 return;
1036
c2f47e15 1037 arg0 = CALL_EXPR_ARG (exp, 0);
1038
26a5cadb 1039 /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
1040 zero (read) and argument 2 (locality) defaults to 3 (high degree of
1041 locality). */
c2f47e15 1042 nargs = call_expr_nargs (exp);
1043 if (nargs > 1)
1044 arg1 = CALL_EXPR_ARG (exp, 1);
26a5cadb 1045 else
c2f47e15 1046 arg1 = integer_zero_node;
1047 if (nargs > 2)
1048 arg2 = CALL_EXPR_ARG (exp, 2);
1049 else
1050 arg2 = build_int_cst (NULL_TREE, 3);
5e3608d8 1051
1052 /* Argument 0 is an address. */
1053 op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
1054
1055 /* Argument 1 (read/write flag) must be a compile-time constant int. */
1056 if (TREE_CODE (arg1) != INTEGER_CST)
1057 {
07e3a3d2 1058 error ("second argument to %<__builtin_prefetch%> must be a constant");
9342ee68 1059 arg1 = integer_zero_node;
5e3608d8 1060 }
8ec3c5c2 1061 op1 = expand_normal (arg1);
5e3608d8 1062 /* Argument 1 must be either zero or one. */
1063 if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
1064 {
c3ceba8e 1065 warning (0, "invalid second argument to %<__builtin_prefetch%>;"
07e3a3d2 1066 " using zero");
5e3608d8 1067 op1 = const0_rtx;
1068 }
1069
1070 /* Argument 2 (locality) must be a compile-time constant int. */
1071 if (TREE_CODE (arg2) != INTEGER_CST)
1072 {
07e3a3d2 1073 error ("third argument to %<__builtin_prefetch%> must be a constant");
5e3608d8 1074 arg2 = integer_zero_node;
1075 }
8ec3c5c2 1076 op2 = expand_normal (arg2);
5e3608d8 1077 /* Argument 2 must be 0, 1, 2, or 3. */
1078 if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
1079 {
c3ceba8e 1080 warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
5e3608d8 1081 op2 = const0_rtx;
1082 }
1083
1084#ifdef HAVE_prefetch
1085 if (HAVE_prefetch)
1086 {
f0ce3b1f 1087 if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate)
4cd21437 1088 (op0,
f0ce3b1f 1089 insn_data[(int) CODE_FOR_prefetch].operand[0].mode))
19bf118a 1090 || (GET_MODE (op0) != Pmode))
9342ee68 1091 {
85d654dd 1092 op0 = convert_memory_address (Pmode, op0);
9342ee68 1093 op0 = force_reg (Pmode, op0);
1094 }
5e3608d8 1095 emit_insn (gen_prefetch (op0, op1, op2));
1096 }
5e3608d8 1097#endif
0a534ba7 1098
f0ce3b1f 1099 /* Don't do anything with direct references to volatile memory, but
1100 generate code to handle other side effects. */
e16ceb8e 1101 if (!MEM_P (op0) && side_effects_p (op0))
f0ce3b1f 1102 emit_insn (op0);
5e3608d8 1103}
1104
f7c44134 1105/* Get a MEM rtx for expression EXP which is the address of an operand
d8ae1baa 1106 to be used in a string instruction (cmpstrsi, movmemsi, ..). LEN is
1107 the maximum length of the block of memory that might be accessed or
1108 NULL if unknown. */
f7c44134 1109
53800dbe 1110static rtx
d8ae1baa 1111get_memory_rtx (tree exp, tree len)
53800dbe 1112{
ad0a178f 1113 tree orig_exp = exp;
1114 rtx addr, mem;
1115 HOST_WIDE_INT off;
1116
1117 /* When EXP is not resolved SAVE_EXPR, MEM_ATTRS can be still derived
1118 from its expression, for expr->a.b only <variable>.a.b is recorded. */
1119 if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp))
1120 exp = TREE_OPERAND (exp, 0);
1121
1122 addr = expand_expr (orig_exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
1123 mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
2a631e19 1124
f7c44134 1125 /* Get an expression we can use to find the attributes to assign to MEM.
1126 If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
1127 we can. First remove any nops. */
72dd6141 1128 while (CONVERT_EXPR_P (exp)
f7c44134 1129 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
1130 exp = TREE_OPERAND (exp, 0);
1131
ad0a178f 1132 off = 0;
1133 if (TREE_CODE (exp) == POINTER_PLUS_EXPR
1134 && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
1135 && host_integerp (TREE_OPERAND (exp, 1), 0)
1136 && (off = tree_low_cst (TREE_OPERAND (exp, 1), 0)) > 0)
1137 exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
1138 else if (TREE_CODE (exp) == ADDR_EXPR)
a1a25d19 1139 exp = TREE_OPERAND (exp, 0);
f7c44134 1140 else if (POINTER_TYPE_P (TREE_TYPE (exp)))
a1a25d19 1141 exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
1142 else
1143 exp = NULL;
1144
1145 /* Honor attributes derived from exp, except for the alias set
1146 (as builtin stringops may alias with anything) and the size
1147 (as stringops may access multiple array elements). */
1148 if (exp)
eec8e941 1149 {
a1a25d19 1150 set_mem_attributes (mem, exp, 0);
d8ae1baa 1151
ad0a178f 1152 if (off)
1153 mem = adjust_automodify_address_nv (mem, BLKmode, NULL, off);
1154
d8ae1baa 1155 /* Allow the string and memory builtins to overflow from one
1156 field into another, see http://gcc.gnu.org/PR23561.
1157 Thus avoid COMPONENT_REFs in MEM_EXPR unless we know the whole
1158 memory accessed by the string or memory builtin will fit
1159 within the field. */
1160 if (MEM_EXPR (mem) && TREE_CODE (MEM_EXPR (mem)) == COMPONENT_REF)
1161 {
1162 tree mem_expr = MEM_EXPR (mem);
1163 HOST_WIDE_INT offset = -1, length = -1;
1164 tree inner = exp;
1165
1166 while (TREE_CODE (inner) == ARRAY_REF
72dd6141 1167 || CONVERT_EXPR_P (inner)
d8ae1baa 1168 || TREE_CODE (inner) == VIEW_CONVERT_EXPR
1169 || TREE_CODE (inner) == SAVE_EXPR)
1170 inner = TREE_OPERAND (inner, 0);
1171
1172 gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
1173
1174 if (MEM_OFFSET (mem)
971ba038 1175 && CONST_INT_P (MEM_OFFSET (mem)))
d8ae1baa 1176 offset = INTVAL (MEM_OFFSET (mem));
1177
1178 if (offset >= 0 && len && host_integerp (len, 0))
1179 length = tree_low_cst (len, 0);
1180
1181 while (TREE_CODE (inner) == COMPONENT_REF)
1182 {
1183 tree field = TREE_OPERAND (inner, 1);
d8ae1baa 1184 gcc_assert (TREE_CODE (mem_expr) == COMPONENT_REF);
1185 gcc_assert (field == TREE_OPERAND (mem_expr, 1));
1186
6933ebec 1187 /* Bitfields are generally not byte-addressable. */
1188 gcc_assert (!DECL_BIT_FIELD (field)
1189 || ((tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
1190 % BITS_PER_UNIT) == 0
1191 && host_integerp (DECL_SIZE (field), 0)
1192 && (TREE_INT_CST_LOW (DECL_SIZE (field))
1193 % BITS_PER_UNIT) == 0));
1194
b2f0b2a3 1195 /* If we can prove that the memory starting at XEXP (mem, 0) and
1196 ending at XEXP (mem, 0) + LENGTH will fit into this field, we
1197 can keep the COMPONENT_REF in MEM_EXPR. But be careful with
1198 fields without DECL_SIZE_UNIT like flexible array members. */
d8ae1baa 1199 if (length >= 0
b2f0b2a3 1200 && DECL_SIZE_UNIT (field)
6933ebec 1201 && host_integerp (DECL_SIZE_UNIT (field), 0))
d8ae1baa 1202 {
1203 HOST_WIDE_INT size
6933ebec 1204 = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
d8ae1baa 1205 if (offset <= size
1206 && length <= size
1207 && offset + length <= size)
1208 break;
1209 }
1210
1211 if (offset >= 0
1212 && host_integerp (DECL_FIELD_OFFSET (field), 0))
6933ebec 1213 offset += TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
d8ae1baa 1214 + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
1215 / BITS_PER_UNIT;
1216 else
1217 {
1218 offset = -1;
1219 length = -1;
1220 }
1221
1222 mem_expr = TREE_OPERAND (mem_expr, 0);
1223 inner = TREE_OPERAND (inner, 0);
d8ae1baa 1224 }
1225
1226 if (mem_expr == NULL)
1227 offset = -1;
1228 if (mem_expr != MEM_EXPR (mem))
1229 {
1230 set_mem_expr (mem, mem_expr);
1231 set_mem_offset (mem, offset >= 0 ? GEN_INT (offset) : NULL_RTX);
1232 }
1233 }
eec8e941 1234 set_mem_alias_set (mem, 0);
a1a25d19 1235 set_mem_size (mem, NULL_RTX);
eec8e941 1236 }
53800dbe 1237
53800dbe 1238 return mem;
1239}
1240\f
1241/* Built-in functions to perform an untyped call and return. */
1242
1243/* For each register that may be used for calling a function, this
1244 gives a mode used to copy the register's value. VOIDmode indicates
1245 the register is not used for calling a function. If the machine
1246 has register windows, this gives only the outbound registers.
1247 INCOMING_REGNO gives the corresponding inbound register. */
1248static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
1249
1250/* For each register that may be used for returning values, this gives
1251 a mode used to copy the register's value. VOIDmode indicates the
1252 register is not used for returning values. If the machine has
1253 register windows, this gives only the outbound registers.
1254 INCOMING_REGNO gives the corresponding inbound register. */
1255static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
1256
53800dbe 1257/* Return the size required for the block returned by __builtin_apply_args,
1258 and initialize apply_args_mode. */
1259
1260static int
aecda0d6 1261apply_args_size (void)
53800dbe 1262{
1263 static int size = -1;
58e9ce8f 1264 int align;
1265 unsigned int regno;
53800dbe 1266 enum machine_mode mode;
1267
1268 /* The values computed by this function never change. */
1269 if (size < 0)
1270 {
1271 /* The first value is the incoming arg-pointer. */
1272 size = GET_MODE_SIZE (Pmode);
1273
1274 /* The second value is the structure value address unless this is
1275 passed as an "invisible" first argument. */
6812c89e 1276 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1277 size += GET_MODE_SIZE (Pmode);
1278
1279 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1280 if (FUNCTION_ARG_REGNO_P (regno))
1281 {
0862b7e9 1282 mode = reg_raw_mode[regno];
1283
64db345d 1284 gcc_assert (mode != VOIDmode);
53800dbe 1285
1286 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1287 if (size % align != 0)
1288 size = CEIL (size, align) * align;
53800dbe 1289 size += GET_MODE_SIZE (mode);
1290 apply_args_mode[regno] = mode;
1291 }
1292 else
1293 {
1294 apply_args_mode[regno] = VOIDmode;
53800dbe 1295 }
1296 }
1297 return size;
1298}
1299
1300/* Return the size required for the block returned by __builtin_apply,
1301 and initialize apply_result_mode. */
1302
1303static int
aecda0d6 1304apply_result_size (void)
53800dbe 1305{
1306 static int size = -1;
1307 int align, regno;
1308 enum machine_mode mode;
1309
1310 /* The values computed by this function never change. */
1311 if (size < 0)
1312 {
1313 size = 0;
1314
1315 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1316 if (FUNCTION_VALUE_REGNO_P (regno))
1317 {
0862b7e9 1318 mode = reg_raw_mode[regno];
1319
64db345d 1320 gcc_assert (mode != VOIDmode);
53800dbe 1321
1322 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1323 if (size % align != 0)
1324 size = CEIL (size, align) * align;
1325 size += GET_MODE_SIZE (mode);
1326 apply_result_mode[regno] = mode;
1327 }
1328 else
1329 apply_result_mode[regno] = VOIDmode;
1330
1331 /* Allow targets that use untyped_call and untyped_return to override
1332 the size so that machine-specific information can be stored here. */
1333#ifdef APPLY_RESULT_SIZE
1334 size = APPLY_RESULT_SIZE;
1335#endif
1336 }
1337 return size;
1338}
1339
1340#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1341/* Create a vector describing the result block RESULT. If SAVEP is true,
1342 the result block is used to save the values; otherwise it is used to
1343 restore the values. */
1344
1345static rtx
aecda0d6 1346result_vector (int savep, rtx result)
53800dbe 1347{
1348 int regno, size, align, nelts;
1349 enum machine_mode mode;
1350 rtx reg, mem;
364c0c59 1351 rtx *savevec = XALLOCAVEC (rtx, FIRST_PSEUDO_REGISTER);
bf8e3599 1352
53800dbe 1353 size = nelts = 0;
1354 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1355 if ((mode = apply_result_mode[regno]) != VOIDmode)
1356 {
1357 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1358 if (size % align != 0)
1359 size = CEIL (size, align) * align;
1360 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
e513d163 1361 mem = adjust_address (result, mode, size);
53800dbe 1362 savevec[nelts++] = (savep
1363 ? gen_rtx_SET (VOIDmode, mem, reg)
1364 : gen_rtx_SET (VOIDmode, reg, mem));
1365 size += GET_MODE_SIZE (mode);
1366 }
1367 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1368}
1369#endif /* HAVE_untyped_call or HAVE_untyped_return */
1370
1371/* Save the state required to perform an untyped call with the same
1372 arguments as were passed to the current function. */
1373
1374static rtx
aecda0d6 1375expand_builtin_apply_args_1 (void)
53800dbe 1376{
1c7e61a7 1377 rtx registers, tem;
53800dbe 1378 int size, align, regno;
1379 enum machine_mode mode;
6812c89e 1380 rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
53800dbe 1381
1382 /* Create a block where the arg-pointer, structure value address,
1383 and argument registers can be saved. */
1384 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1385
1386 /* Walk past the arg-pointer and structure value address. */
1387 size = GET_MODE_SIZE (Pmode);
6812c89e 1388 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1389 size += GET_MODE_SIZE (Pmode);
1390
1391 /* Save each register used in calling a function to the block. */
1392 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1393 if ((mode = apply_args_mode[regno]) != VOIDmode)
1394 {
53800dbe 1395 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1396 if (size % align != 0)
1397 size = CEIL (size, align) * align;
1398
1399 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1400
e513d163 1401 emit_move_insn (adjust_address (registers, mode, size), tem);
53800dbe 1402 size += GET_MODE_SIZE (mode);
1403 }
1404
1405 /* Save the arg pointer to the block. */
27a7a23a 1406 tem = copy_to_reg (crtl->args.internal_arg_pointer);
f083a92b 1407#ifdef STACK_GROWS_DOWNWARD
1c7e61a7 1408 /* We need the pointer as the caller actually passed them to us, not
9d4b544c 1409 as we might have pretended they were passed. Make sure it's a valid
1410 operand, as emit_move_insn isn't expected to handle a PLUS. */
1411 tem
abe32cce 1412 = force_operand (plus_constant (tem, crtl->args.pretend_args_size),
9d4b544c 1413 NULL_RTX);
1c7e61a7 1414#endif
1415 emit_move_insn (adjust_address (registers, Pmode, 0), tem);
0862b7e9 1416
53800dbe 1417 size = GET_MODE_SIZE (Pmode);
1418
1419 /* Save the structure value address unless this is passed as an
1420 "invisible" first argument. */
45550790 1421 if (struct_incoming_value)
53800dbe 1422 {
e513d163 1423 emit_move_insn (adjust_address (registers, Pmode, size),
45550790 1424 copy_to_reg (struct_incoming_value));
53800dbe 1425 size += GET_MODE_SIZE (Pmode);
1426 }
1427
1428 /* Return the address of the block. */
1429 return copy_addr_to_reg (XEXP (registers, 0));
1430}
1431
1432/* __builtin_apply_args returns block of memory allocated on
1433 the stack into which is stored the arg pointer, structure
1434 value address, static chain, and all the registers that might
1435 possibly be used in performing a function call. The code is
1436 moved to the start of the function so the incoming values are
1437 saved. */
27d0c333 1438
53800dbe 1439static rtx
aecda0d6 1440expand_builtin_apply_args (void)
53800dbe 1441{
1442 /* Don't do __builtin_apply_args more than once in a function.
1443 Save the result of the first call and reuse it. */
1444 if (apply_args_value != 0)
1445 return apply_args_value;
1446 {
1447 /* When this function is called, it means that registers must be
1448 saved on entry to this function. So we migrate the
1449 call to the first insn of this function. */
1450 rtx temp;
1451 rtx seq;
1452
1453 start_sequence ();
1454 temp = expand_builtin_apply_args_1 ();
1455 seq = get_insns ();
1456 end_sequence ();
1457
1458 apply_args_value = temp;
1459
31d3e01c 1460 /* Put the insns after the NOTE that starts the function.
1461 If this is inside a start_sequence, make the outer-level insn
53800dbe 1462 chain current, so the code is placed at the start of the
0ef1a651 1463 function. If internal_arg_pointer is a non-virtual pseudo,
1464 it needs to be placed after the function that initializes
1465 that pseudo. */
53800dbe 1466 push_topmost_sequence ();
0ef1a651 1467 if (REG_P (crtl->args.internal_arg_pointer)
1468 && REGNO (crtl->args.internal_arg_pointer) > LAST_VIRTUAL_REGISTER)
1469 emit_insn_before (seq, parm_birth_insn);
1470 else
1471 emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
53800dbe 1472 pop_topmost_sequence ();
1473 return temp;
1474 }
1475}
1476
1477/* Perform an untyped call and save the state required to perform an
1478 untyped return of whatever value was returned by the given function. */
1479
1480static rtx
aecda0d6 1481expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
53800dbe 1482{
1483 int size, align, regno;
1484 enum machine_mode mode;
2a631e19 1485 rtx incoming_args, result, reg, dest, src, call_insn;
53800dbe 1486 rtx old_stack_level = 0;
1487 rtx call_fusage = 0;
6812c89e 1488 rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
53800dbe 1489
85d654dd 1490 arguments = convert_memory_address (Pmode, arguments);
726ec87c 1491
53800dbe 1492 /* Create a block where the return registers can be saved. */
1493 result = assign_stack_local (BLKmode, apply_result_size (), -1);
1494
53800dbe 1495 /* Fetch the arg pointer from the ARGUMENTS block. */
1496 incoming_args = gen_reg_rtx (Pmode);
726ec87c 1497 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
53800dbe 1498#ifndef STACK_GROWS_DOWNWARD
ad99e708 1499 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1500 incoming_args, 0, OPTAB_LIB_WIDEN);
53800dbe 1501#endif
1502
04a46d40 1503 /* Push a new argument block and copy the arguments. Do not allow
1504 the (potential) memcpy call below to interfere with our stack
1505 manipulations. */
53800dbe 1506 do_pending_stack_adjust ();
04a46d40 1507 NO_DEFER_POP;
53800dbe 1508
2358393e 1509 /* Save the stack with nonlocal if available. */
53800dbe 1510#ifdef HAVE_save_stack_nonlocal
1511 if (HAVE_save_stack_nonlocal)
1512 emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
1513 else
1514#endif
1515 emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
1516
59647703 1517 /* Allocate a block of memory onto the stack and copy the memory
1518 arguments to the outgoing arguments address. */
1519 allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
27a7a23a 1520
1521 /* Set DRAP flag to true, even though allocate_dynamic_stack_space
1522 may have already set current_function_calls_alloca to true.
1523 current_function_calls_alloca won't be set if argsize is zero,
1524 so we have to guarantee need_drap is true here. */
1525 if (SUPPORTS_STACK_ALIGNMENT)
1526 crtl->need_drap = true;
1527
59647703 1528 dest = virtual_outgoing_args_rtx;
1529#ifndef STACK_GROWS_DOWNWARD
971ba038 1530 if (CONST_INT_P (argsize))
59647703 1531 dest = plus_constant (dest, -INTVAL (argsize));
1532 else
1533 dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1534#endif
2a631e19 1535 dest = gen_rtx_MEM (BLKmode, dest);
1536 set_mem_align (dest, PARM_BOUNDARY);
1537 src = gen_rtx_MEM (BLKmode, incoming_args);
1538 set_mem_align (src, PARM_BOUNDARY);
0378dbdc 1539 emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
53800dbe 1540
1541 /* Refer to the argument block. */
1542 apply_args_size ();
1543 arguments = gen_rtx_MEM (BLKmode, arguments);
2a631e19 1544 set_mem_align (arguments, PARM_BOUNDARY);
53800dbe 1545
1546 /* Walk past the arg-pointer and structure value address. */
1547 size = GET_MODE_SIZE (Pmode);
45550790 1548 if (struct_value)
53800dbe 1549 size += GET_MODE_SIZE (Pmode);
1550
1551 /* Restore each of the registers previously saved. Make USE insns
1552 for each of these registers for use in making the call. */
1553 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1554 if ((mode = apply_args_mode[regno]) != VOIDmode)
1555 {
1556 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1557 if (size % align != 0)
1558 size = CEIL (size, align) * align;
1559 reg = gen_rtx_REG (mode, regno);
e513d163 1560 emit_move_insn (reg, adjust_address (arguments, mode, size));
53800dbe 1561 use_reg (&call_fusage, reg);
1562 size += GET_MODE_SIZE (mode);
1563 }
1564
1565 /* Restore the structure value address unless this is passed as an
1566 "invisible" first argument. */
1567 size = GET_MODE_SIZE (Pmode);
45550790 1568 if (struct_value)
53800dbe 1569 {
1570 rtx value = gen_reg_rtx (Pmode);
e513d163 1571 emit_move_insn (value, adjust_address (arguments, Pmode, size));
45550790 1572 emit_move_insn (struct_value, value);
8ad4c111 1573 if (REG_P (struct_value))
45550790 1574 use_reg (&call_fusage, struct_value);
53800dbe 1575 size += GET_MODE_SIZE (Pmode);
1576 }
1577
1578 /* All arguments and registers used for the call are set up by now! */
82c7907c 1579 function = prepare_call_address (NULL, function, NULL, &call_fusage, 0, 0);
53800dbe 1580
1581 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1582 and we don't want to load it into a register as an optimization,
1583 because prepare_call_address already did it if it should be done. */
1584 if (GET_CODE (function) != SYMBOL_REF)
1585 function = memory_address (FUNCTION_MODE, function);
1586
1587 /* Generate the actual call instruction and save the return value. */
1588#ifdef HAVE_untyped_call
1589 if (HAVE_untyped_call)
1590 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1591 result, result_vector (1, result)));
1592 else
1593#endif
1594#ifdef HAVE_call_value
1595 if (HAVE_call_value)
1596 {
1597 rtx valreg = 0;
1598
1599 /* Locate the unique return register. It is not possible to
1600 express a call that sets more than one return register using
1601 call_value; use untyped_call for that. In fact, untyped_call
1602 only needs to save the return registers in the given block. */
1603 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1604 if ((mode = apply_result_mode[regno]) != VOIDmode)
1605 {
64db345d 1606 gcc_assert (!valreg); /* HAVE_untyped_call required. */
7d3f6cc7 1607
53800dbe 1608 valreg = gen_rtx_REG (mode, regno);
1609 }
1610
2ed6c343 1611 emit_call_insn (GEN_CALL_VALUE (valreg,
53800dbe 1612 gen_rtx_MEM (FUNCTION_MODE, function),
1613 const0_rtx, NULL_RTX, const0_rtx));
1614
e513d163 1615 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
53800dbe 1616 }
1617 else
1618#endif
64db345d 1619 gcc_unreachable ();
53800dbe 1620
d5f9786f 1621 /* Find the CALL insn we just emitted, and attach the register usage
1622 information. */
1623 call_insn = last_call_insn ();
1624 add_function_usage_to (call_insn, call_fusage);
53800dbe 1625
1626 /* Restore the stack. */
1627#ifdef HAVE_save_stack_nonlocal
1628 if (HAVE_save_stack_nonlocal)
1629 emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1630 else
1631#endif
1632 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1633
04a46d40 1634 OK_DEFER_POP;
1635
53800dbe 1636 /* Return the address of the result block. */
85d654dd 1637 result = copy_addr_to_reg (XEXP (result, 0));
1638 return convert_memory_address (ptr_mode, result);
53800dbe 1639}
1640
1641/* Perform an untyped return. */
1642
1643static void
aecda0d6 1644expand_builtin_return (rtx result)
53800dbe 1645{
1646 int size, align, regno;
1647 enum machine_mode mode;
1648 rtx reg;
1649 rtx call_fusage = 0;
1650
85d654dd 1651 result = convert_memory_address (Pmode, result);
726ec87c 1652
53800dbe 1653 apply_result_size ();
1654 result = gen_rtx_MEM (BLKmode, result);
1655
1656#ifdef HAVE_untyped_return
1657 if (HAVE_untyped_return)
1658 {
1659 emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1660 emit_barrier ();
1661 return;
1662 }
1663#endif
1664
1665 /* Restore the return value and note that each value is used. */
1666 size = 0;
1667 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1668 if ((mode = apply_result_mode[regno]) != VOIDmode)
1669 {
1670 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1671 if (size % align != 0)
1672 size = CEIL (size, align) * align;
1673 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
e513d163 1674 emit_move_insn (reg, adjust_address (result, mode, size));
53800dbe 1675
1676 push_to_sequence (call_fusage);
18b42941 1677 emit_use (reg);
53800dbe 1678 call_fusage = get_insns ();
1679 end_sequence ();
1680 size += GET_MODE_SIZE (mode);
1681 }
1682
1683 /* Put the USE insns before the return. */
31d3e01c 1684 emit_insn (call_fusage);
53800dbe 1685
1686 /* Return whatever values was restored by jumping directly to the end
1687 of the function. */
62380d2d 1688 expand_naked_return ();
53800dbe 1689}
1690
539a3a92 1691/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
27d0c333 1692
539a3a92 1693static enum type_class
aecda0d6 1694type_to_class (tree type)
539a3a92 1695{
1696 switch (TREE_CODE (type))
1697 {
1698 case VOID_TYPE: return void_type_class;
1699 case INTEGER_TYPE: return integer_type_class;
539a3a92 1700 case ENUMERAL_TYPE: return enumeral_type_class;
1701 case BOOLEAN_TYPE: return boolean_type_class;
1702 case POINTER_TYPE: return pointer_type_class;
1703 case REFERENCE_TYPE: return reference_type_class;
1704 case OFFSET_TYPE: return offset_type_class;
1705 case REAL_TYPE: return real_type_class;
1706 case COMPLEX_TYPE: return complex_type_class;
1707 case FUNCTION_TYPE: return function_type_class;
1708 case METHOD_TYPE: return method_type_class;
1709 case RECORD_TYPE: return record_type_class;
1710 case UNION_TYPE:
1711 case QUAL_UNION_TYPE: return union_type_class;
1712 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1713 ? string_type_class : array_type_class);
539a3a92 1714 case LANG_TYPE: return lang_type_class;
1715 default: return no_type_class;
1716 }
1717}
bf8e3599 1718
c2f47e15 1719/* Expand a call EXP to __builtin_classify_type. */
27d0c333 1720
53800dbe 1721static rtx
c2f47e15 1722expand_builtin_classify_type (tree exp)
53800dbe 1723{
c2f47e15 1724 if (call_expr_nargs (exp))
1725 return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0))));
53800dbe 1726 return GEN_INT (no_type_class);
1727}
1728
07976da7 1729/* This helper macro, meant to be used in mathfn_built_in below,
1730 determines which among a set of three builtin math functions is
1731 appropriate for a given type mode. The `F' and `L' cases are
1732 automatically generated from the `double' case. */
1733#define CASE_MATHFN(BUILT_IN_MATHFN) \
1734 case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1735 fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1736 fcodel = BUILT_IN_MATHFN##L ; break;
cd2656b0 1737/* Similar to above, but appends _R after any F/L suffix. */
1738#define CASE_MATHFN_REENT(BUILT_IN_MATHFN) \
1739 case BUILT_IN_MATHFN##_R: case BUILT_IN_MATHFN##F_R: case BUILT_IN_MATHFN##L_R: \
1740 fcode = BUILT_IN_MATHFN##_R; fcodef = BUILT_IN_MATHFN##F_R ; \
1741 fcodel = BUILT_IN_MATHFN##L_R ; break;
07976da7 1742
1743/* Return mathematic function equivalent to FN but operating directly
c319d56a 1744 on TYPE, if available. If IMPLICIT is true find the function in
1745 implicit_built_in_decls[], otherwise use built_in_decls[]. If we
1746 can't do the conversion, return zero. */
1747
1748static tree
1749mathfn_built_in_1 (tree type, enum built_in_function fn, bool implicit)
0a68165a 1750{
c319d56a 1751 tree const *const fn_arr
1752 = implicit ? implicit_built_in_decls : built_in_decls;
07976da7 1753 enum built_in_function fcode, fcodef, fcodel;
1754
1755 switch (fn)
1756 {
746114e8 1757 CASE_MATHFN (BUILT_IN_ACOS)
1758 CASE_MATHFN (BUILT_IN_ACOSH)
1759 CASE_MATHFN (BUILT_IN_ASIN)
1760 CASE_MATHFN (BUILT_IN_ASINH)
07976da7 1761 CASE_MATHFN (BUILT_IN_ATAN)
746114e8 1762 CASE_MATHFN (BUILT_IN_ATAN2)
1763 CASE_MATHFN (BUILT_IN_ATANH)
1764 CASE_MATHFN (BUILT_IN_CBRT)
07976da7 1765 CASE_MATHFN (BUILT_IN_CEIL)
d735c391 1766 CASE_MATHFN (BUILT_IN_CEXPI)
746114e8 1767 CASE_MATHFN (BUILT_IN_COPYSIGN)
07976da7 1768 CASE_MATHFN (BUILT_IN_COS)
746114e8 1769 CASE_MATHFN (BUILT_IN_COSH)
1770 CASE_MATHFN (BUILT_IN_DREM)
1771 CASE_MATHFN (BUILT_IN_ERF)
1772 CASE_MATHFN (BUILT_IN_ERFC)
07976da7 1773 CASE_MATHFN (BUILT_IN_EXP)
746114e8 1774 CASE_MATHFN (BUILT_IN_EXP10)
1775 CASE_MATHFN (BUILT_IN_EXP2)
1776 CASE_MATHFN (BUILT_IN_EXPM1)
1777 CASE_MATHFN (BUILT_IN_FABS)
1778 CASE_MATHFN (BUILT_IN_FDIM)
07976da7 1779 CASE_MATHFN (BUILT_IN_FLOOR)
746114e8 1780 CASE_MATHFN (BUILT_IN_FMA)
1781 CASE_MATHFN (BUILT_IN_FMAX)
1782 CASE_MATHFN (BUILT_IN_FMIN)
1783 CASE_MATHFN (BUILT_IN_FMOD)
1784 CASE_MATHFN (BUILT_IN_FREXP)
1785 CASE_MATHFN (BUILT_IN_GAMMA)
cd2656b0 1786 CASE_MATHFN_REENT (BUILT_IN_GAMMA) /* GAMMA_R */
746114e8 1787 CASE_MATHFN (BUILT_IN_HUGE_VAL)
1788 CASE_MATHFN (BUILT_IN_HYPOT)
1789 CASE_MATHFN (BUILT_IN_ILOGB)
1790 CASE_MATHFN (BUILT_IN_INF)
69b779ea 1791 CASE_MATHFN (BUILT_IN_ISINF)
746114e8 1792 CASE_MATHFN (BUILT_IN_J0)
1793 CASE_MATHFN (BUILT_IN_J1)
1794 CASE_MATHFN (BUILT_IN_JN)
ac148751 1795 CASE_MATHFN (BUILT_IN_LCEIL)
746114e8 1796 CASE_MATHFN (BUILT_IN_LDEXP)
ad52b9b7 1797 CASE_MATHFN (BUILT_IN_LFLOOR)
746114e8 1798 CASE_MATHFN (BUILT_IN_LGAMMA)
cd2656b0 1799 CASE_MATHFN_REENT (BUILT_IN_LGAMMA) /* LGAMMA_R */
ac148751 1800 CASE_MATHFN (BUILT_IN_LLCEIL)
ad52b9b7 1801 CASE_MATHFN (BUILT_IN_LLFLOOR)
746114e8 1802 CASE_MATHFN (BUILT_IN_LLRINT)
1803 CASE_MATHFN (BUILT_IN_LLROUND)
07976da7 1804 CASE_MATHFN (BUILT_IN_LOG)
746114e8 1805 CASE_MATHFN (BUILT_IN_LOG10)
1806 CASE_MATHFN (BUILT_IN_LOG1P)
1807 CASE_MATHFN (BUILT_IN_LOG2)
1808 CASE_MATHFN (BUILT_IN_LOGB)
1809 CASE_MATHFN (BUILT_IN_LRINT)
1810 CASE_MATHFN (BUILT_IN_LROUND)
1811 CASE_MATHFN (BUILT_IN_MODF)
1812 CASE_MATHFN (BUILT_IN_NAN)
1813 CASE_MATHFN (BUILT_IN_NANS)
07976da7 1814 CASE_MATHFN (BUILT_IN_NEARBYINT)
746114e8 1815 CASE_MATHFN (BUILT_IN_NEXTAFTER)
1816 CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1817 CASE_MATHFN (BUILT_IN_POW)
757c219d 1818 CASE_MATHFN (BUILT_IN_POWI)
746114e8 1819 CASE_MATHFN (BUILT_IN_POW10)
1820 CASE_MATHFN (BUILT_IN_REMAINDER)
1821 CASE_MATHFN (BUILT_IN_REMQUO)
1822 CASE_MATHFN (BUILT_IN_RINT)
07976da7 1823 CASE_MATHFN (BUILT_IN_ROUND)
746114e8 1824 CASE_MATHFN (BUILT_IN_SCALB)
1825 CASE_MATHFN (BUILT_IN_SCALBLN)
1826 CASE_MATHFN (BUILT_IN_SCALBN)
c319d56a 1827 CASE_MATHFN (BUILT_IN_SIGNBIT)
746114e8 1828 CASE_MATHFN (BUILT_IN_SIGNIFICAND)
07976da7 1829 CASE_MATHFN (BUILT_IN_SIN)
746114e8 1830 CASE_MATHFN (BUILT_IN_SINCOS)
1831 CASE_MATHFN (BUILT_IN_SINH)
07976da7 1832 CASE_MATHFN (BUILT_IN_SQRT)
1833 CASE_MATHFN (BUILT_IN_TAN)
746114e8 1834 CASE_MATHFN (BUILT_IN_TANH)
1835 CASE_MATHFN (BUILT_IN_TGAMMA)
07976da7 1836 CASE_MATHFN (BUILT_IN_TRUNC)
746114e8 1837 CASE_MATHFN (BUILT_IN_Y0)
1838 CASE_MATHFN (BUILT_IN_Y1)
1839 CASE_MATHFN (BUILT_IN_YN)
07976da7 1840
0a68165a 1841 default:
c2f47e15 1842 return NULL_TREE;
0a68165a 1843 }
07976da7 1844
96b9f485 1845 if (TYPE_MAIN_VARIANT (type) == double_type_node)
c319d56a 1846 return fn_arr[fcode];
96b9f485 1847 else if (TYPE_MAIN_VARIANT (type) == float_type_node)
c319d56a 1848 return fn_arr[fcodef];
96b9f485 1849 else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
c319d56a 1850 return fn_arr[fcodel];
07976da7 1851 else
c2f47e15 1852 return NULL_TREE;
0a68165a 1853}
1854
c319d56a 1855/* Like mathfn_built_in_1(), but always use the implicit array. */
1856
1857tree
1858mathfn_built_in (tree type, enum built_in_function fn)
1859{
1860 return mathfn_built_in_1 (type, fn, /*implicit=*/ 1);
1861}
1862
0fd605a5 1863/* If errno must be maintained, expand the RTL to check if the result,
1864 TARGET, of a built-in function call, EXP, is NaN, and if so set
1865 errno to EDOM. */
1866
1867static void
aecda0d6 1868expand_errno_check (tree exp, rtx target)
0fd605a5 1869{
7f05340e 1870 rtx lab = gen_label_rtx ();
0fd605a5 1871
7f05340e 1872 /* Test the result; if it is NaN, set errno=EDOM because
1873 the argument was not in the domain. */
3fcf767f 1874 do_compare_rtx_and_jump (target, target, EQ, 0, GET_MODE (target),
1875 NULL_RTX, NULL_RTX, lab);
0fd605a5 1876
1877#ifdef TARGET_EDOM
7f05340e 1878 /* If this built-in doesn't throw an exception, set errno directly. */
c2f47e15 1879 if (TREE_NOTHROW (TREE_OPERAND (CALL_EXPR_FN (exp), 0)))
7f05340e 1880 {
0fd605a5 1881#ifdef GEN_ERRNO_RTX
7f05340e 1882 rtx errno_rtx = GEN_ERRNO_RTX;
0fd605a5 1883#else
7f05340e 1884 rtx errno_rtx
0fd605a5 1885 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1886#endif
7f05340e 1887 emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
0fd605a5 1888 emit_label (lab);
7f05340e 1889 return;
0fd605a5 1890 }
7f05340e 1891#endif
1892
08491912 1893 /* Make sure the library call isn't expanded as a tail call. */
1894 CALL_EXPR_TAILCALL (exp) = 0;
1895
7f05340e 1896 /* We can't set errno=EDOM directly; let the library call do it.
1897 Pop the arguments right away in case the call gets deleted. */
1898 NO_DEFER_POP;
1899 expand_call (exp, target, 0);
1900 OK_DEFER_POP;
1901 emit_label (lab);
0fd605a5 1902}
1903
6b43bae4 1904/* Expand a call to one of the builtin math functions (sqrt, exp, or log).
c2f47e15 1905 Return NULL_RTX if a normal call should be emitted rather than expanding
1906 the function in-line. EXP is the expression that is a call to the builtin
53800dbe 1907 function; if convenient, the result should be placed in TARGET.
1908 SUBTARGET may be used as the target for computing one of EXP's operands. */
27d0c333 1909
53800dbe 1910static rtx
aecda0d6 1911expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
53800dbe 1912{
bf8e3599 1913 optab builtin_optab;
1e4adcfc 1914 rtx op0, insns;
c6e6ecb1 1915 tree fndecl = get_callee_fndecl (exp);
7f05340e 1916 enum machine_mode mode;
528ee710 1917 bool errno_set = false;
abfea505 1918 tree arg;
53800dbe 1919
c2f47e15 1920 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
1921 return NULL_RTX;
53800dbe 1922
c2f47e15 1923 arg = CALL_EXPR_ARG (exp, 0);
53800dbe 1924
1925 switch (DECL_FUNCTION_CODE (fndecl))
1926 {
4f35b1fc 1927 CASE_FLT_FN (BUILT_IN_SQRT):
7f05340e 1928 errno_set = ! tree_expr_nonnegative_p (arg);
1929 builtin_optab = sqrt_optab;
1930 break;
4f35b1fc 1931 CASE_FLT_FN (BUILT_IN_EXP):
528ee710 1932 errno_set = true; builtin_optab = exp_optab; break;
4f35b1fc 1933 CASE_FLT_FN (BUILT_IN_EXP10):
1934 CASE_FLT_FN (BUILT_IN_POW10):
750ef9f5 1935 errno_set = true; builtin_optab = exp10_optab; break;
4f35b1fc 1936 CASE_FLT_FN (BUILT_IN_EXP2):
750ef9f5 1937 errno_set = true; builtin_optab = exp2_optab; break;
4f35b1fc 1938 CASE_FLT_FN (BUILT_IN_EXPM1):
a6b4eed2 1939 errno_set = true; builtin_optab = expm1_optab; break;
4f35b1fc 1940 CASE_FLT_FN (BUILT_IN_LOGB):
4efbc641 1941 errno_set = true; builtin_optab = logb_optab; break;
4f35b1fc 1942 CASE_FLT_FN (BUILT_IN_LOG):
528ee710 1943 errno_set = true; builtin_optab = log_optab; break;
4f35b1fc 1944 CASE_FLT_FN (BUILT_IN_LOG10):
d3cd9bde 1945 errno_set = true; builtin_optab = log10_optab; break;
4f35b1fc 1946 CASE_FLT_FN (BUILT_IN_LOG2):
d3cd9bde 1947 errno_set = true; builtin_optab = log2_optab; break;
4f35b1fc 1948 CASE_FLT_FN (BUILT_IN_LOG1P):
f474cd93 1949 errno_set = true; builtin_optab = log1p_optab; break;
4f35b1fc 1950 CASE_FLT_FN (BUILT_IN_ASIN):
8de2f465 1951 builtin_optab = asin_optab; break;
4f35b1fc 1952 CASE_FLT_FN (BUILT_IN_ACOS):
8de2f465 1953 builtin_optab = acos_optab; break;
4f35b1fc 1954 CASE_FLT_FN (BUILT_IN_TAN):
528ee710 1955 builtin_optab = tan_optab; break;
4f35b1fc 1956 CASE_FLT_FN (BUILT_IN_ATAN):
528ee710 1957 builtin_optab = atan_optab; break;
4f35b1fc 1958 CASE_FLT_FN (BUILT_IN_FLOOR):
528ee710 1959 builtin_optab = floor_optab; break;
4f35b1fc 1960 CASE_FLT_FN (BUILT_IN_CEIL):
528ee710 1961 builtin_optab = ceil_optab; break;
4f35b1fc 1962 CASE_FLT_FN (BUILT_IN_TRUNC):
a7cc195f 1963 builtin_optab = btrunc_optab; break;
4f35b1fc 1964 CASE_FLT_FN (BUILT_IN_ROUND):
528ee710 1965 builtin_optab = round_optab; break;
4f35b1fc 1966 CASE_FLT_FN (BUILT_IN_NEARBYINT):
0ddf4ad9 1967 builtin_optab = nearbyint_optab;
1968 if (flag_trapping_math)
1969 break;
1970 /* Else fallthrough and expand as rint. */
4f35b1fc 1971 CASE_FLT_FN (BUILT_IN_RINT):
aef94a0f 1972 builtin_optab = rint_optab; break;
b3154a1f 1973 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
1974 builtin_optab = significand_optab; break;
42721db0 1975 default:
64db345d 1976 gcc_unreachable ();
53800dbe 1977 }
1978
7f05340e 1979 /* Make a suitable register to place result in. */
1980 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 1981
7f05340e 1982 if (! flag_errno_math || ! HONOR_NANS (mode))
1983 errno_set = false;
1984
bd421108 1985 /* Before working hard, check whether the instruction is available. */
99bdde56 1986 if (optab_handler (builtin_optab, mode)->insn_code != CODE_FOR_nothing)
68e6cb9d 1987 {
bd421108 1988 target = gen_reg_rtx (mode);
7f05340e 1989
bd421108 1990 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
1991 need to expand the argument again. This way, we will not perform
1992 side-effects more the once. */
abfea505 1993 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7f05340e 1994
1db6d067 1995 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
7f05340e 1996
bd421108 1997 start_sequence ();
53800dbe 1998
bd421108 1999 /* Compute into TARGET.
2000 Set TARGET to wherever the result comes back. */
2001 target = expand_unop (mode, builtin_optab, op0, target, 0);
2002
2003 if (target != 0)
2004 {
2005 if (errno_set)
2006 expand_errno_check (exp, target);
2007
2008 /* Output the entire sequence. */
2009 insns = get_insns ();
2010 end_sequence ();
2011 emit_insn (insns);
2012 return target;
2013 }
2014
2015 /* If we were unable to expand via the builtin, stop the sequence
2016 (without outputting the insns) and call to the library function
2017 with the stabilized argument list. */
53800dbe 2018 end_sequence ();
53800dbe 2019 }
2020
1e5b92fa 2021 return expand_call (exp, target, target == const0_rtx);
0fd605a5 2022}
2023
2024/* Expand a call to the builtin binary math functions (pow and atan2).
c2f47e15 2025 Return NULL_RTX if a normal call should be emitted rather than expanding the
0fd605a5 2026 function in-line. EXP is the expression that is a call to the builtin
2027 function; if convenient, the result should be placed in TARGET.
2028 SUBTARGET may be used as the target for computing one of EXP's
2029 operands. */
2030
2031static rtx
aecda0d6 2032expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
0fd605a5 2033{
2034 optab builtin_optab;
2035 rtx op0, op1, insns;
4737caf2 2036 int op1_type = REAL_TYPE;
c6e6ecb1 2037 tree fndecl = get_callee_fndecl (exp);
abfea505 2038 tree arg0, arg1;
7f05340e 2039 enum machine_mode mode;
0fd605a5 2040 bool errno_set = true;
0fd605a5 2041
73a954a1 2042 switch (DECL_FUNCTION_CODE (fndecl))
2043 {
2044 CASE_FLT_FN (BUILT_IN_SCALBN):
2045 CASE_FLT_FN (BUILT_IN_SCALBLN):
2046 CASE_FLT_FN (BUILT_IN_LDEXP):
2047 op1_type = INTEGER_TYPE;
2048 default:
2049 break;
2050 }
4737caf2 2051
c2f47e15 2052 if (!validate_arglist (exp, REAL_TYPE, op1_type, VOID_TYPE))
2053 return NULL_RTX;
0fd605a5 2054
c2f47e15 2055 arg0 = CALL_EXPR_ARG (exp, 0);
2056 arg1 = CALL_EXPR_ARG (exp, 1);
0fd605a5 2057
0fd605a5 2058 switch (DECL_FUNCTION_CODE (fndecl))
2059 {
4f35b1fc 2060 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 2061 builtin_optab = pow_optab; break;
4f35b1fc 2062 CASE_FLT_FN (BUILT_IN_ATAN2):
0fd605a5 2063 builtin_optab = atan2_optab; break;
73a954a1 2064 CASE_FLT_FN (BUILT_IN_SCALB):
2065 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2066 return 0;
2067 builtin_optab = scalb_optab; break;
2068 CASE_FLT_FN (BUILT_IN_SCALBN):
2069 CASE_FLT_FN (BUILT_IN_SCALBLN):
2070 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2071 return 0;
2072 /* Fall through... */
4f35b1fc 2073 CASE_FLT_FN (BUILT_IN_LDEXP):
4737caf2 2074 builtin_optab = ldexp_optab; break;
4f35b1fc 2075 CASE_FLT_FN (BUILT_IN_FMOD):
80ed5c06 2076 builtin_optab = fmod_optab; break;
ef722005 2077 CASE_FLT_FN (BUILT_IN_REMAINDER):
4f35b1fc 2078 CASE_FLT_FN (BUILT_IN_DREM):
ef722005 2079 builtin_optab = remainder_optab; break;
0fd605a5 2080 default:
64db345d 2081 gcc_unreachable ();
0fd605a5 2082 }
2083
7f05340e 2084 /* Make a suitable register to place result in. */
2085 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2086
2087 /* Before working hard, check whether the instruction is available. */
99bdde56 2088 if (optab_handler (builtin_optab, mode)->insn_code == CODE_FOR_nothing)
c2f47e15 2089 return NULL_RTX;
fc4eef90 2090
7f05340e 2091 target = gen_reg_rtx (mode);
2092
2093 if (! flag_errno_math || ! HONOR_NANS (mode))
2094 errno_set = false;
2095
4ee9c684 2096 /* Always stabilize the argument list. */
abfea505 2097 CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
2098 CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
7f05340e 2099
8ec3c5c2 2100 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2101 op1 = expand_normal (arg1);
7f05340e 2102
7f05340e 2103 start_sequence ();
2104
0fd605a5 2105 /* Compute into TARGET.
2106 Set TARGET to wherever the result comes back. */
7f05340e 2107 target = expand_binop (mode, builtin_optab, op0, op1,
0fd605a5 2108 target, 0, OPTAB_DIRECT);
53800dbe 2109
68e6cb9d 2110 /* If we were unable to expand via the builtin, stop the sequence
2111 (without outputting the insns) and call to the library function
2112 with the stabilized argument list. */
0fd605a5 2113 if (target == 0)
2114 {
2115 end_sequence ();
68e6cb9d 2116 return expand_call (exp, target, target == const0_rtx);
53800dbe 2117 }
2118
a4356fb9 2119 if (errno_set)
2120 expand_errno_check (exp, target);
0fd605a5 2121
53800dbe 2122 /* Output the entire sequence. */
2123 insns = get_insns ();
2124 end_sequence ();
31d3e01c 2125 emit_insn (insns);
bf8e3599 2126
53800dbe 2127 return target;
2128}
2129
6b43bae4 2130/* Expand a call to the builtin sin and cos math functions.
c2f47e15 2131 Return NULL_RTX if a normal call should be emitted rather than expanding the
6b43bae4 2132 function in-line. EXP is the expression that is a call to the builtin
2133 function; if convenient, the result should be placed in TARGET.
2134 SUBTARGET may be used as the target for computing one of EXP's
2135 operands. */
2136
2137static rtx
2138expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
2139{
2140 optab builtin_optab;
7511b819 2141 rtx op0, insns;
6b43bae4 2142 tree fndecl = get_callee_fndecl (exp);
6b43bae4 2143 enum machine_mode mode;
abfea505 2144 tree arg;
6b43bae4 2145
c2f47e15 2146 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2147 return NULL_RTX;
6b43bae4 2148
c2f47e15 2149 arg = CALL_EXPR_ARG (exp, 0);
6b43bae4 2150
2151 switch (DECL_FUNCTION_CODE (fndecl))
2152 {
4f35b1fc 2153 CASE_FLT_FN (BUILT_IN_SIN):
2154 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2155 builtin_optab = sincos_optab; break;
2156 default:
64db345d 2157 gcc_unreachable ();
6b43bae4 2158 }
2159
2160 /* Make a suitable register to place result in. */
2161 mode = TYPE_MODE (TREE_TYPE (exp));
2162
6b43bae4 2163 /* Check if sincos insn is available, otherwise fallback
0bed3869 2164 to sin or cos insn. */
99bdde56 2165 if (optab_handler (builtin_optab, mode)->insn_code == CODE_FOR_nothing)
6b43bae4 2166 switch (DECL_FUNCTION_CODE (fndecl))
2167 {
4f35b1fc 2168 CASE_FLT_FN (BUILT_IN_SIN):
6b43bae4 2169 builtin_optab = sin_optab; break;
4f35b1fc 2170 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2171 builtin_optab = cos_optab; break;
2172 default:
64db345d 2173 gcc_unreachable ();
6b43bae4 2174 }
6b43bae4 2175
2176 /* Before working hard, check whether the instruction is available. */
99bdde56 2177 if (optab_handler (builtin_optab, mode)->insn_code != CODE_FOR_nothing)
6b43bae4 2178 {
2179 target = gen_reg_rtx (mode);
2180
2181 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2182 need to expand the argument again. This way, we will not perform
2183 side-effects more the once. */
abfea505 2184 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
6b43bae4 2185
1db6d067 2186 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
6b43bae4 2187
6b43bae4 2188 start_sequence ();
2189
2190 /* Compute into TARGET.
2191 Set TARGET to wherever the result comes back. */
2192 if (builtin_optab == sincos_optab)
2193 {
64db345d 2194 int result;
7d3f6cc7 2195
6b43bae4 2196 switch (DECL_FUNCTION_CODE (fndecl))
2197 {
4f35b1fc 2198 CASE_FLT_FN (BUILT_IN_SIN):
64db345d 2199 result = expand_twoval_unop (builtin_optab, op0, 0, target, 0);
6b43bae4 2200 break;
4f35b1fc 2201 CASE_FLT_FN (BUILT_IN_COS):
64db345d 2202 result = expand_twoval_unop (builtin_optab, op0, target, 0, 0);
6b43bae4 2203 break;
2204 default:
64db345d 2205 gcc_unreachable ();
6b43bae4 2206 }
64db345d 2207 gcc_assert (result);
6b43bae4 2208 }
2209 else
2210 {
2211 target = expand_unop (mode, builtin_optab, op0, target, 0);
2212 }
2213
2214 if (target != 0)
2215 {
6b43bae4 2216 /* Output the entire sequence. */
2217 insns = get_insns ();
2218 end_sequence ();
2219 emit_insn (insns);
2220 return target;
2221 }
2222
2223 /* If we were unable to expand via the builtin, stop the sequence
2224 (without outputting the insns) and call to the library function
2225 with the stabilized argument list. */
2226 end_sequence ();
2227 }
2228
6b43bae4 2229 target = expand_call (exp, target, target == const0_rtx);
2230
2231 return target;
2232}
2233
a65c4d64 2234/* Given an interclass math builtin decl FNDECL and it's argument ARG
2235 return an RTL instruction code that implements the functionality.
2236 If that isn't possible or available return CODE_FOR_nothing. */
a67a90e5 2237
a65c4d64 2238static enum insn_code
2239interclass_mathfn_icode (tree arg, tree fndecl)
a67a90e5 2240{
a65c4d64 2241 bool errno_set = false;
cde061c1 2242 optab builtin_optab = 0;
a67a90e5 2243 enum machine_mode mode;
a67a90e5 2244
2245 switch (DECL_FUNCTION_CODE (fndecl))
2246 {
2247 CASE_FLT_FN (BUILT_IN_ILOGB):
2248 errno_set = true; builtin_optab = ilogb_optab; break;
69b779ea 2249 CASE_FLT_FN (BUILT_IN_ISINF):
2250 builtin_optab = isinf_optab; break;
8a1a9cb7 2251 case BUILT_IN_ISNORMAL:
cde061c1 2252 case BUILT_IN_ISFINITE:
2253 CASE_FLT_FN (BUILT_IN_FINITE):
a65c4d64 2254 case BUILT_IN_FINITED32:
2255 case BUILT_IN_FINITED64:
2256 case BUILT_IN_FINITED128:
2257 case BUILT_IN_ISINFD32:
2258 case BUILT_IN_ISINFD64:
2259 case BUILT_IN_ISINFD128:
cde061c1 2260 /* These builtins have no optabs (yet). */
2261 break;
a67a90e5 2262 default:
2263 gcc_unreachable ();
2264 }
2265
2266 /* There's no easy way to detect the case we need to set EDOM. */
2267 if (flag_errno_math && errno_set)
a65c4d64 2268 return CODE_FOR_nothing;
a67a90e5 2269
2270 /* Optab mode depends on the mode of the input argument. */
2271 mode = TYPE_MODE (TREE_TYPE (arg));
2272
cde061c1 2273 if (builtin_optab)
a65c4d64 2274 return optab_handler (builtin_optab, mode)->insn_code;
2275 return CODE_FOR_nothing;
2276}
2277
2278/* Expand a call to one of the builtin math functions that operate on
2279 floating point argument and output an integer result (ilogb, isinf,
2280 isnan, etc).
2281 Return 0 if a normal call should be emitted rather than expanding the
2282 function in-line. EXP is the expression that is a call to the builtin
2283 function; if convenient, the result should be placed in TARGET.
2284 SUBTARGET may be used as the target for computing one of EXP's operands. */
2285
2286static rtx
2287expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
2288{
2289 enum insn_code icode = CODE_FOR_nothing;
2290 rtx op0;
2291 tree fndecl = get_callee_fndecl (exp);
2292 enum machine_mode mode;
2293 tree arg;
2294
2295 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2296 return NULL_RTX;
2297
2298 arg = CALL_EXPR_ARG (exp, 0);
2299 icode = interclass_mathfn_icode (arg, fndecl);
2300 mode = TYPE_MODE (TREE_TYPE (arg));
2301
a67a90e5 2302 if (icode != CODE_FOR_nothing)
2303 {
2304 /* Make a suitable register to place result in. */
2305 if (!target
2306 || GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
2307 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
2308
2309 gcc_assert (insn_data[icode].operand[0].predicate
2310 (target, GET_MODE (target)));
2311
2312 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2313 need to expand the argument again. This way, we will not perform
2314 side-effects more the once. */
abfea505 2315 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
a67a90e5 2316
1db6d067 2317 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
a67a90e5 2318
2319 if (mode != GET_MODE (op0))
2320 op0 = convert_to_mode (mode, op0, 0);
2321
2322 /* Compute into TARGET.
2323 Set TARGET to wherever the result comes back. */
2324 emit_unop_insn (icode, target, op0, UNKNOWN);
2325 return target;
2326 }
2327
a65c4d64 2328 return NULL_RTX;
a67a90e5 2329}
2330
c3147c1a 2331/* Expand a call to the builtin sincos math function.
c2f47e15 2332 Return NULL_RTX if a normal call should be emitted rather than expanding the
c3147c1a 2333 function in-line. EXP is the expression that is a call to the builtin
2334 function. */
2335
2336static rtx
2337expand_builtin_sincos (tree exp)
2338{
2339 rtx op0, op1, op2, target1, target2;
c3147c1a 2340 enum machine_mode mode;
2341 tree arg, sinp, cosp;
2342 int result;
389dd41b 2343 location_t loc = EXPR_LOCATION (exp);
c3147c1a 2344
c2f47e15 2345 if (!validate_arglist (exp, REAL_TYPE,
2346 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2347 return NULL_RTX;
c3147c1a 2348
c2f47e15 2349 arg = CALL_EXPR_ARG (exp, 0);
2350 sinp = CALL_EXPR_ARG (exp, 1);
2351 cosp = CALL_EXPR_ARG (exp, 2);
c3147c1a 2352
2353 /* Make a suitable register to place result in. */
2354 mode = TYPE_MODE (TREE_TYPE (arg));
2355
2356 /* Check if sincos insn is available, otherwise emit the call. */
99bdde56 2357 if (optab_handler (sincos_optab, mode)->insn_code == CODE_FOR_nothing)
c3147c1a 2358 return NULL_RTX;
2359
2360 target1 = gen_reg_rtx (mode);
2361 target2 = gen_reg_rtx (mode);
2362
8ec3c5c2 2363 op0 = expand_normal (arg);
389dd41b 2364 op1 = expand_normal (build_fold_indirect_ref_loc (loc, sinp));
2365 op2 = expand_normal (build_fold_indirect_ref_loc (loc, cosp));
c3147c1a 2366
2367 /* Compute into target1 and target2.
2368 Set TARGET to wherever the result comes back. */
2369 result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
2370 gcc_assert (result);
2371
2372 /* Move target1 and target2 to the memory locations indicated
2373 by op1 and op2. */
2374 emit_move_insn (op1, target1);
2375 emit_move_insn (op2, target2);
2376
2377 return const0_rtx;
2378}
2379
d735c391 2380/* Expand a call to the internal cexpi builtin to the sincos math function.
2381 EXP is the expression that is a call to the builtin function; if convenient,
2382 the result should be placed in TARGET. SUBTARGET may be used as the target
2383 for computing one of EXP's operands. */
2384
2385static rtx
2386expand_builtin_cexpi (tree exp, rtx target, rtx subtarget)
2387{
2388 tree fndecl = get_callee_fndecl (exp);
d735c391 2389 tree arg, type;
c2f47e15 2390 enum machine_mode mode;
d735c391 2391 rtx op0, op1, op2;
389dd41b 2392 location_t loc = EXPR_LOCATION (exp);
d735c391 2393
c2f47e15 2394 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2395 return NULL_RTX;
d735c391 2396
c2f47e15 2397 arg = CALL_EXPR_ARG (exp, 0);
d735c391 2398 type = TREE_TYPE (arg);
2399 mode = TYPE_MODE (TREE_TYPE (arg));
2400
2401 /* Try expanding via a sincos optab, fall back to emitting a libcall
18b8d8ae 2402 to sincos or cexp. We are sure we have sincos or cexp because cexpi
2403 is only generated from sincos, cexp or if we have either of them. */
99bdde56 2404 if (optab_handler (sincos_optab, mode)->insn_code != CODE_FOR_nothing)
d735c391 2405 {
2406 op1 = gen_reg_rtx (mode);
2407 op2 = gen_reg_rtx (mode);
2408
1db6d067 2409 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
d735c391 2410
2411 /* Compute into op1 and op2. */
2412 expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
2413 }
18b8d8ae 2414 else if (TARGET_HAS_SINCOS)
d735c391 2415 {
c2f47e15 2416 tree call, fn = NULL_TREE;
d735c391 2417 tree top1, top2;
2418 rtx op1a, op2a;
2419
2420 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2421 fn = built_in_decls[BUILT_IN_SINCOSF];
2422 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2423 fn = built_in_decls[BUILT_IN_SINCOS];
2424 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2425 fn = built_in_decls[BUILT_IN_SINCOSL];
c2f47e15 2426 else
2427 gcc_unreachable ();
48e1416a 2428
d735c391 2429 op1 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
2430 op2 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
2431 op1a = copy_to_mode_reg (Pmode, XEXP (op1, 0));
2432 op2a = copy_to_mode_reg (Pmode, XEXP (op2, 0));
2433 top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
2434 top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
2435
d735c391 2436 /* Make sure not to fold the sincos call again. */
2437 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
c2f47e15 2438 expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
2439 call, 3, arg, top1, top2));
d735c391 2440 }
18b8d8ae 2441 else
2442 {
0ecbc158 2443 tree call, fn = NULL_TREE, narg;
18b8d8ae 2444 tree ctype = build_complex_type (type);
2445
0ecbc158 2446 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2447 fn = built_in_decls[BUILT_IN_CEXPF];
2448 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2449 fn = built_in_decls[BUILT_IN_CEXP];
2450 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2451 fn = built_in_decls[BUILT_IN_CEXPL];
c2f47e15 2452 else
2453 gcc_unreachable ();
fc0dfa6e 2454
2455 /* If we don't have a decl for cexp create one. This is the
2456 friendliest fallback if the user calls __builtin_cexpi
2457 without full target C99 function support. */
2458 if (fn == NULL_TREE)
2459 {
2460 tree fntype;
2461 const char *name = NULL;
2462
2463 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2464 name = "cexpf";
2465 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2466 name = "cexp";
2467 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2468 name = "cexpl";
2469
2470 fntype = build_function_type_list (ctype, ctype, NULL_TREE);
2471 fn = build_fn_decl (name, fntype);
2472 }
2473
389dd41b 2474 narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype,
18b8d8ae 2475 build_real (type, dconst0), arg);
2476
2477 /* Make sure not to fold the cexp call again. */
2478 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
48e1416a 2479 return expand_expr (build_call_nary (ctype, call, 1, narg),
1db6d067 2480 target, VOIDmode, EXPAND_NORMAL);
18b8d8ae 2481 }
d735c391 2482
2483 /* Now build the proper return type. */
2484 return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
2485 make_tree (TREE_TYPE (arg), op2),
2486 make_tree (TREE_TYPE (arg), op1)),
1db6d067 2487 target, VOIDmode, EXPAND_NORMAL);
d735c391 2488}
2489
a65c4d64 2490/* Conveniently construct a function call expression. FNDECL names the
2491 function to be called, N is the number of arguments, and the "..."
2492 parameters are the argument expressions. Unlike build_call_exr
2493 this doesn't fold the call, hence it will always return a CALL_EXPR. */
2494
2495static tree
2496build_call_nofold_loc (location_t loc, tree fndecl, int n, ...)
2497{
2498 va_list ap;
2499 tree fntype = TREE_TYPE (fndecl);
2500 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
2501
2502 va_start (ap, n);
2503 fn = build_call_valist (TREE_TYPE (fntype), fn, n, ap);
2504 va_end (ap);
2505 SET_EXPR_LOCATION (fn, loc);
2506 return fn;
2507}
2508#define build_call_nofold(...) \
2509 build_call_nofold_loc (UNKNOWN_LOCATION, __VA_ARGS__)
2510
7d3afc77 2511/* Expand a call to one of the builtin rounding functions gcc defines
2512 as an extension (lfloor and lceil). As these are gcc extensions we
2513 do not need to worry about setting errno to EDOM.
ad52b9b7 2514 If expanding via optab fails, lower expression to (int)(floor(x)).
2515 EXP is the expression that is a call to the builtin function;
ff1b14e4 2516 if convenient, the result should be placed in TARGET. */
ad52b9b7 2517
2518static rtx
ff1b14e4 2519expand_builtin_int_roundingfn (tree exp, rtx target)
ad52b9b7 2520{
9c42dd28 2521 convert_optab builtin_optab;
ad52b9b7 2522 rtx op0, insns, tmp;
2523 tree fndecl = get_callee_fndecl (exp);
ad52b9b7 2524 enum built_in_function fallback_fn;
2525 tree fallback_fndecl;
2526 enum machine_mode mode;
4de0924f 2527 tree arg;
ad52b9b7 2528
c2f47e15 2529 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
ad52b9b7 2530 gcc_unreachable ();
2531
c2f47e15 2532 arg = CALL_EXPR_ARG (exp, 0);
ad52b9b7 2533
2534 switch (DECL_FUNCTION_CODE (fndecl))
2535 {
4f35b1fc 2536 CASE_FLT_FN (BUILT_IN_LCEIL):
2537 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 2538 builtin_optab = lceil_optab;
2539 fallback_fn = BUILT_IN_CEIL;
2540 break;
2541
4f35b1fc 2542 CASE_FLT_FN (BUILT_IN_LFLOOR):
2543 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 2544 builtin_optab = lfloor_optab;
2545 fallback_fn = BUILT_IN_FLOOR;
2546 break;
2547
2548 default:
2549 gcc_unreachable ();
2550 }
2551
2552 /* Make a suitable register to place result in. */
2553 mode = TYPE_MODE (TREE_TYPE (exp));
2554
9c42dd28 2555 target = gen_reg_rtx (mode);
ad52b9b7 2556
9c42dd28 2557 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2558 need to expand the argument again. This way, we will not perform
2559 side-effects more the once. */
abfea505 2560 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
ad52b9b7 2561
ff1b14e4 2562 op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
ad52b9b7 2563
9c42dd28 2564 start_sequence ();
ad52b9b7 2565
9c42dd28 2566 /* Compute into TARGET. */
2567 if (expand_sfix_optab (target, op0, builtin_optab))
2568 {
2569 /* Output the entire sequence. */
2570 insns = get_insns ();
ad52b9b7 2571 end_sequence ();
9c42dd28 2572 emit_insn (insns);
2573 return target;
ad52b9b7 2574 }
2575
9c42dd28 2576 /* If we were unable to expand via the builtin, stop the sequence
2577 (without outputting the insns). */
2578 end_sequence ();
2579
ad52b9b7 2580 /* Fall back to floating point rounding optab. */
2581 fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
fc0dfa6e 2582
2583 /* For non-C99 targets we may end up without a fallback fndecl here
2584 if the user called __builtin_lfloor directly. In this case emit
2585 a call to the floor/ceil variants nevertheless. This should result
2586 in the best user experience for not full C99 targets. */
2587 if (fallback_fndecl == NULL_TREE)
2588 {
2589 tree fntype;
2590 const char *name = NULL;
2591
2592 switch (DECL_FUNCTION_CODE (fndecl))
2593 {
2594 case BUILT_IN_LCEIL:
2595 case BUILT_IN_LLCEIL:
2596 name = "ceil";
2597 break;
2598 case BUILT_IN_LCEILF:
2599 case BUILT_IN_LLCEILF:
2600 name = "ceilf";
2601 break;
2602 case BUILT_IN_LCEILL:
2603 case BUILT_IN_LLCEILL:
2604 name = "ceill";
2605 break;
2606 case BUILT_IN_LFLOOR:
2607 case BUILT_IN_LLFLOOR:
2608 name = "floor";
2609 break;
2610 case BUILT_IN_LFLOORF:
2611 case BUILT_IN_LLFLOORF:
2612 name = "floorf";
2613 break;
2614 case BUILT_IN_LFLOORL:
2615 case BUILT_IN_LLFLOORL:
2616 name = "floorl";
2617 break;
2618 default:
2619 gcc_unreachable ();
2620 }
2621
2622 fntype = build_function_type_list (TREE_TYPE (arg),
2623 TREE_TYPE (arg), NULL_TREE);
2624 fallback_fndecl = build_fn_decl (name, fntype);
2625 }
2626
a65c4d64 2627 exp = build_call_nofold (fallback_fndecl, 1, arg);
ad52b9b7 2628
d4c690af 2629 tmp = expand_normal (exp);
ad52b9b7 2630
2631 /* Truncate the result of floating point optab to integer
2632 via expand_fix (). */
2633 target = gen_reg_rtx (mode);
2634 expand_fix (target, tmp, 0);
2635
2636 return target;
2637}
2638
7d3afc77 2639/* Expand a call to one of the builtin math functions doing integer
2640 conversion (lrint).
2641 Return 0 if a normal call should be emitted rather than expanding the
2642 function in-line. EXP is the expression that is a call to the builtin
ff1b14e4 2643 function; if convenient, the result should be placed in TARGET. */
7d3afc77 2644
2645static rtx
ff1b14e4 2646expand_builtin_int_roundingfn_2 (tree exp, rtx target)
7d3afc77 2647{
5f51ee59 2648 convert_optab builtin_optab;
7d3afc77 2649 rtx op0, insns;
2650 tree fndecl = get_callee_fndecl (exp);
4de0924f 2651 tree arg;
c2f47e15 2652 enum machine_mode mode;
7d3afc77 2653
2654 /* There's no easy way to detect the case we need to set EDOM. */
2655 if (flag_errno_math)
2656 return NULL_RTX;
2657
c2f47e15 2658 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2659 gcc_unreachable ();
48e1416a 2660
c2f47e15 2661 arg = CALL_EXPR_ARG (exp, 0);
7d3afc77 2662
2663 switch (DECL_FUNCTION_CODE (fndecl))
2664 {
2665 CASE_FLT_FN (BUILT_IN_LRINT):
2666 CASE_FLT_FN (BUILT_IN_LLRINT):
2667 builtin_optab = lrint_optab; break;
ef2f1a10 2668 CASE_FLT_FN (BUILT_IN_LROUND):
2669 CASE_FLT_FN (BUILT_IN_LLROUND):
2670 builtin_optab = lround_optab; break;
7d3afc77 2671 default:
2672 gcc_unreachable ();
2673 }
2674
2675 /* Make a suitable register to place result in. */
2676 mode = TYPE_MODE (TREE_TYPE (exp));
2677
5f51ee59 2678 target = gen_reg_rtx (mode);
7d3afc77 2679
5f51ee59 2680 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2681 need to expand the argument again. This way, we will not perform
2682 side-effects more the once. */
abfea505 2683 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7d3afc77 2684
ff1b14e4 2685 op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
7d3afc77 2686
5f51ee59 2687 start_sequence ();
7d3afc77 2688
5f51ee59 2689 if (expand_sfix_optab (target, op0, builtin_optab))
2690 {
2691 /* Output the entire sequence. */
2692 insns = get_insns ();
7d3afc77 2693 end_sequence ();
5f51ee59 2694 emit_insn (insns);
2695 return target;
7d3afc77 2696 }
2697
5f51ee59 2698 /* If we were unable to expand via the builtin, stop the sequence
2699 (without outputting the insns) and call to the library function
2700 with the stabilized argument list. */
2701 end_sequence ();
2702
7d3afc77 2703 target = expand_call (exp, target, target == const0_rtx);
2704
2705 return target;
2706}
2707
f1b844c6 2708/* To evaluate powi(x,n), the floating point value x raised to the
2709 constant integer exponent n, we use a hybrid algorithm that
2710 combines the "window method" with look-up tables. For an
2711 introduction to exponentiation algorithms and "addition chains",
2712 see section 4.6.3, "Evaluation of Powers" of Donald E. Knuth,
2713 "Seminumerical Algorithms", Vol. 2, "The Art of Computer Programming",
2714 3rd Edition, 1998, and Daniel M. Gordon, "A Survey of Fast Exponentiation
2715 Methods", Journal of Algorithms, Vol. 27, pp. 129-146, 1998. */
2716
2717/* Provide a default value for POWI_MAX_MULTS, the maximum number of
2718 multiplications to inline before calling the system library's pow
2719 function. powi(x,n) requires at worst 2*bits(n)-2 multiplications,
2720 so this default never requires calling pow, powf or powl. */
0862b7e9 2721
f1b844c6 2722#ifndef POWI_MAX_MULTS
2723#define POWI_MAX_MULTS (2*HOST_BITS_PER_WIDE_INT-2)
2724#endif
2725
2726/* The size of the "optimal power tree" lookup table. All
2727 exponents less than this value are simply looked up in the
2728 powi_table below. This threshold is also used to size the
2729 cache of pseudo registers that hold intermediate results. */
2730#define POWI_TABLE_SIZE 256
2731
2732/* The size, in bits of the window, used in the "window method"
2733 exponentiation algorithm. This is equivalent to a radix of
2734 (1<<POWI_WINDOW_SIZE) in the corresponding "m-ary method". */
2735#define POWI_WINDOW_SIZE 3
2736
2737/* The following table is an efficient representation of an
2738 "optimal power tree". For each value, i, the corresponding
2739 value, j, in the table states than an optimal evaluation
2740 sequence for calculating pow(x,i) can be found by evaluating
2741 pow(x,j)*pow(x,i-j). An optimal power tree for the first
2742 100 integers is given in Knuth's "Seminumerical algorithms". */
2743
2744static const unsigned char powi_table[POWI_TABLE_SIZE] =
2745 {
2746 0, 1, 1, 2, 2, 3, 3, 4, /* 0 - 7 */
2747 4, 6, 5, 6, 6, 10, 7, 9, /* 8 - 15 */
2748 8, 16, 9, 16, 10, 12, 11, 13, /* 16 - 23 */
2749 12, 17, 13, 18, 14, 24, 15, 26, /* 24 - 31 */
2750 16, 17, 17, 19, 18, 33, 19, 26, /* 32 - 39 */
2751 20, 25, 21, 40, 22, 27, 23, 44, /* 40 - 47 */
2752 24, 32, 25, 34, 26, 29, 27, 44, /* 48 - 55 */
2753 28, 31, 29, 34, 30, 60, 31, 36, /* 56 - 63 */
2754 32, 64, 33, 34, 34, 46, 35, 37, /* 64 - 71 */
2755 36, 65, 37, 50, 38, 48, 39, 69, /* 72 - 79 */
2756 40, 49, 41, 43, 42, 51, 43, 58, /* 80 - 87 */
2757 44, 64, 45, 47, 46, 59, 47, 76, /* 88 - 95 */
2758 48, 65, 49, 66, 50, 67, 51, 66, /* 96 - 103 */
2759 52, 70, 53, 74, 54, 104, 55, 74, /* 104 - 111 */
2760 56, 64, 57, 69, 58, 78, 59, 68, /* 112 - 119 */
2761 60, 61, 61, 80, 62, 75, 63, 68, /* 120 - 127 */
2762 64, 65, 65, 128, 66, 129, 67, 90, /* 128 - 135 */
2763 68, 73, 69, 131, 70, 94, 71, 88, /* 136 - 143 */
2764 72, 128, 73, 98, 74, 132, 75, 121, /* 144 - 151 */
2765 76, 102, 77, 124, 78, 132, 79, 106, /* 152 - 159 */
2766 80, 97, 81, 160, 82, 99, 83, 134, /* 160 - 167 */
2767 84, 86, 85, 95, 86, 160, 87, 100, /* 168 - 175 */
2768 88, 113, 89, 98, 90, 107, 91, 122, /* 176 - 183 */
2769 92, 111, 93, 102, 94, 126, 95, 150, /* 184 - 191 */
2770 96, 128, 97, 130, 98, 133, 99, 195, /* 192 - 199 */
2771 100, 128, 101, 123, 102, 164, 103, 138, /* 200 - 207 */
2772 104, 145, 105, 146, 106, 109, 107, 149, /* 208 - 215 */
2773 108, 200, 109, 146, 110, 170, 111, 157, /* 216 - 223 */
2774 112, 128, 113, 130, 114, 182, 115, 132, /* 224 - 231 */
2775 116, 200, 117, 132, 118, 158, 119, 206, /* 232 - 239 */
2776 120, 240, 121, 162, 122, 147, 123, 152, /* 240 - 247 */
2777 124, 166, 125, 214, 126, 138, 127, 153, /* 248 - 255 */
2778 };
2779
2780
2781/* Return the number of multiplications required to calculate
2782 powi(x,n) where n is less than POWI_TABLE_SIZE. This is a
2783 subroutine of powi_cost. CACHE is an array indicating
2784 which exponents have already been calculated. */
2785
2786static int
2787powi_lookup_cost (unsigned HOST_WIDE_INT n, bool *cache)
2788{
2789 /* If we've already calculated this exponent, then this evaluation
2790 doesn't require any additional multiplications. */
2791 if (cache[n])
2792 return 0;
2793
2794 cache[n] = true;
2795 return powi_lookup_cost (n - powi_table[n], cache)
2796 + powi_lookup_cost (powi_table[n], cache) + 1;
2797}
2798
2799/* Return the number of multiplications required to calculate
2800 powi(x,n) for an arbitrary x, given the exponent N. This
2801 function needs to be kept in sync with expand_powi below. */
2802
2803static int
2804powi_cost (HOST_WIDE_INT n)
2805{
2806 bool cache[POWI_TABLE_SIZE];
2807 unsigned HOST_WIDE_INT digit;
2808 unsigned HOST_WIDE_INT val;
2809 int result;
2810
2811 if (n == 0)
2812 return 0;
2813
2814 /* Ignore the reciprocal when calculating the cost. */
2815 val = (n < 0) ? -n : n;
2816
2817 /* Initialize the exponent cache. */
2818 memset (cache, 0, POWI_TABLE_SIZE * sizeof (bool));
2819 cache[1] = true;
2820
2821 result = 0;
2822
2823 while (val >= POWI_TABLE_SIZE)
2824 {
2825 if (val & 1)
2826 {
2827 digit = val & ((1 << POWI_WINDOW_SIZE) - 1);
2828 result += powi_lookup_cost (digit, cache)
2829 + POWI_WINDOW_SIZE + 1;
2830 val >>= POWI_WINDOW_SIZE;
2831 }
2832 else
2833 {
2834 val >>= 1;
2835 result++;
2836 }
2837 }
0862b7e9 2838
6881dbab 2839 return result + powi_lookup_cost (val, cache);
f1b844c6 2840}
2841
2842/* Recursive subroutine of expand_powi. This function takes the array,
2843 CACHE, of already calculated exponents and an exponent N and returns
2844 an RTX that corresponds to CACHE[1]**N, as calculated in mode MODE. */
2845
2846static rtx
2847expand_powi_1 (enum machine_mode mode, unsigned HOST_WIDE_INT n, rtx *cache)
2848{
2849 unsigned HOST_WIDE_INT digit;
2850 rtx target, result;
2851 rtx op0, op1;
2852
2853 if (n < POWI_TABLE_SIZE)
2854 {
2855 if (cache[n])
a0c938f0 2856 return cache[n];
f1b844c6 2857
2858 target = gen_reg_rtx (mode);
2859 cache[n] = target;
2860
2861 op0 = expand_powi_1 (mode, n - powi_table[n], cache);
2862 op1 = expand_powi_1 (mode, powi_table[n], cache);
2863 }
2864 else if (n & 1)
2865 {
2866 target = gen_reg_rtx (mode);
2867 digit = n & ((1 << POWI_WINDOW_SIZE) - 1);
2868 op0 = expand_powi_1 (mode, n - digit, cache);
2869 op1 = expand_powi_1 (mode, digit, cache);
2870 }
2871 else
2872 {
2873 target = gen_reg_rtx (mode);
2874 op0 = expand_powi_1 (mode, n >> 1, cache);
2875 op1 = op0;
2876 }
2877
2878 result = expand_mult (mode, op0, op1, target, 0);
2879 if (result != target)
2880 emit_move_insn (target, result);
2881 return target;
2882}
2883
2884/* Expand the RTL to evaluate powi(x,n) in mode MODE. X is the
2885 floating point operand in mode MODE, and N is the exponent. This
2886 function needs to be kept in sync with powi_cost above. */
0862b7e9 2887
f1b844c6 2888static rtx
2889expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n)
2890{
f1b844c6 2891 rtx cache[POWI_TABLE_SIZE];
2892 rtx result;
2893
2894 if (n == 0)
2895 return CONST1_RTX (mode);
2896
19bf118a 2897 memset (cache, 0, sizeof (cache));
f1b844c6 2898 cache[1] = x;
2899
2900 result = expand_powi_1 (mode, (n < 0) ? -n : n, cache);
2901
2902 /* If the original exponent was negative, reciprocate the result. */
2903 if (n < 0)
2904 result = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2905 result, NULL_RTX, 0, OPTAB_LIB_WIDEN);
2906
2907 return result;
2908}
2909
c2f47e15 2910/* Expand a call to the pow built-in mathematical function. Return NULL_RTX if
f1b844c6 2911 a normal call should be emitted rather than expanding the function
2912 in-line. EXP is the expression that is a call to the builtin
2913 function; if convenient, the result should be placed in TARGET. */
2914
2915static rtx
2916expand_builtin_pow (tree exp, rtx target, rtx subtarget)
2917{
c2f47e15 2918 tree arg0, arg1;
2919 tree fn, narg0;
1c4709b4 2920 tree type = TREE_TYPE (exp);
2921 REAL_VALUE_TYPE cint, c, c2;
2922 HOST_WIDE_INT n;
2923 rtx op, op2;
2924 enum machine_mode mode = TYPE_MODE (type);
f1b844c6 2925
c2f47e15 2926 if (! validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2927 return NULL_RTX;
f1b844c6 2928
c2f47e15 2929 arg0 = CALL_EXPR_ARG (exp, 0);
2930 arg1 = CALL_EXPR_ARG (exp, 1);
f1b844c6 2931
1c4709b4 2932 if (TREE_CODE (arg1) != REAL_CST
f96bd2bf 2933 || TREE_OVERFLOW (arg1))
1c4709b4 2934 return expand_builtin_mathfn_2 (exp, target, subtarget);
2935
2936 /* Handle constant exponents. */
2937
2938 /* For integer valued exponents we can expand to an optimal multiplication
2939 sequence using expand_powi. */
2940 c = TREE_REAL_CST (arg1);
2941 n = real_to_integer (&c);
2942 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
2943 if (real_identical (&c, &cint)
2944 && ((n >= -1 && n <= 2)
2945 || (flag_unsafe_math_optimizations
a0d18cec 2946 && optimize_insn_for_speed_p ()
1c4709b4 2947 && powi_cost (n) <= POWI_MAX_MULTS)))
f1b844c6 2948 {
1db6d067 2949 op = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 2950 if (n != 1)
2951 {
2952 op = force_reg (mode, op);
2953 op = expand_powi (op, mode, n);
2954 }
2955 return op;
2956 }
2957
2958 narg0 = builtin_save_expr (arg0);
f1b844c6 2959
1c4709b4 2960 /* If the exponent is not integer valued, check if it is half of an integer.
2961 In this case we can expand to sqrt (x) * x**(n/2). */
2962 fn = mathfn_built_in (type, BUILT_IN_SQRT);
2963 if (fn != NULL_TREE)
2964 {
2965 real_arithmetic (&c2, MULT_EXPR, &c, &dconst2);
2966 n = real_to_integer (&c2);
f1b844c6 2967 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
1c4709b4 2968 if (real_identical (&c2, &cint)
2969 && ((flag_unsafe_math_optimizations
a0d18cec 2970 && optimize_insn_for_speed_p ()
1c4709b4 2971 && powi_cost (n/2) <= POWI_MAX_MULTS)
2972 || n == 1))
f1b844c6 2973 {
a65c4d64 2974 tree call_expr = build_call_nofold (fn, 1, narg0);
8697cf4d 2975 /* Use expand_expr in case the newly built call expression
2976 was folded to a non-call. */
2977 op = expand_expr (call_expr, subtarget, mode, EXPAND_NORMAL);
1c4709b4 2978 if (n != 1)
8c5cac78 2979 {
1db6d067 2980 op2 = expand_expr (narg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 2981 op2 = force_reg (mode, op2);
2982 op2 = expand_powi (op2, mode, abs (n / 2));
2983 op = expand_simple_binop (mode, MULT, op, op2, NULL_RTX,
2984 0, OPTAB_LIB_WIDEN);
2985 /* If the original exponent was negative, reciprocate the
2986 result. */
2987 if (n < 0)
2988 op = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2989 op, NULL_RTX, 0, OPTAB_LIB_WIDEN);
8c5cac78 2990 }
1c4709b4 2991 return op;
f1b844c6 2992 }
2993 }
b613c2a6 2994
1c4709b4 2995 /* Try if the exponent is a third of an integer. In this case
5a84ba55 2996 we can expand to x**(n/3) * cbrt(x)**(n%3). As cbrt (x) is
2997 different from pow (x, 1./3.) due to rounding and behavior
2998 with negative x we need to constrain this transformation to
2999 unsafe math and positive x or finite math. */
1c4709b4 3000 fn = mathfn_built_in (type, BUILT_IN_CBRT);
5a84ba55 3001 if (fn != NULL_TREE
3002 && flag_unsafe_math_optimizations
3003 && (tree_expr_nonnegative_p (arg0)
3004 || !HONOR_NANS (mode)))
1c4709b4 3005 {
3fa759a9 3006 REAL_VALUE_TYPE dconst3;
3007 real_from_integer (&dconst3, VOIDmode, 3, 0, 0);
1c4709b4 3008 real_arithmetic (&c2, MULT_EXPR, &c, &dconst3);
3009 real_round (&c2, mode, &c2);
3010 n = real_to_integer (&c2);
3011 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
3012 real_arithmetic (&c2, RDIV_EXPR, &cint, &dconst3);
3013 real_convert (&c2, mode, &c2);
3014 if (real_identical (&c2, &c)
a0d18cec 3015 && ((optimize_insn_for_speed_p ()
1c4709b4 3016 && powi_cost (n/3) <= POWI_MAX_MULTS)
3017 || n == 1))
3018 {
a65c4d64 3019 tree call_expr = build_call_nofold (fn, 1,narg0);
1c4709b4 3020 op = expand_builtin (call_expr, NULL_RTX, subtarget, mode, 0);
3021 if (abs (n) % 3 == 2)
3022 op = expand_simple_binop (mode, MULT, op, op, op,
3023 0, OPTAB_LIB_WIDEN);
3024 if (n != 1)
3025 {
1db6d067 3026 op2 = expand_expr (narg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 3027 op2 = force_reg (mode, op2);
3028 op2 = expand_powi (op2, mode, abs (n / 3));
3029 op = expand_simple_binop (mode, MULT, op, op2, NULL_RTX,
3030 0, OPTAB_LIB_WIDEN);
3031 /* If the original exponent was negative, reciprocate the
3032 result. */
3033 if (n < 0)
3034 op = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
3035 op, NULL_RTX, 0, OPTAB_LIB_WIDEN);
3036 }
3037 return op;
3038 }
3039 }
3040
3041 /* Fall back to optab expansion. */
b613c2a6 3042 return expand_builtin_mathfn_2 (exp, target, subtarget);
f1b844c6 3043}
3044
c2f47e15 3045/* Expand a call to the powi built-in mathematical function. Return NULL_RTX if
757c219d 3046 a normal call should be emitted rather than expanding the function
3047 in-line. EXP is the expression that is a call to the builtin
3048 function; if convenient, the result should be placed in TARGET. */
3049
3050static rtx
3051expand_builtin_powi (tree exp, rtx target, rtx subtarget)
3052{
757c219d 3053 tree arg0, arg1;
3054 rtx op0, op1;
3055 enum machine_mode mode;
d0405f40 3056 enum machine_mode mode2;
757c219d 3057
c2f47e15 3058 if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
3059 return NULL_RTX;
757c219d 3060
c2f47e15 3061 arg0 = CALL_EXPR_ARG (exp, 0);
3062 arg1 = CALL_EXPR_ARG (exp, 1);
757c219d 3063 mode = TYPE_MODE (TREE_TYPE (exp));
3064
3065 /* Handle constant power. */
3066
3067 if (TREE_CODE (arg1) == INTEGER_CST
f96bd2bf 3068 && !TREE_OVERFLOW (arg1))
757c219d 3069 {
3070 HOST_WIDE_INT n = TREE_INT_CST_LOW (arg1);
3071
3072 /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
3073 Otherwise, check the number of multiplications required. */
3074 if ((TREE_INT_CST_HIGH (arg1) == 0
3075 || TREE_INT_CST_HIGH (arg1) == -1)
3076 && ((n >= -1 && n <= 2)
a0d18cec 3077 || (optimize_insn_for_speed_p ()
757c219d 3078 && powi_cost (n) <= POWI_MAX_MULTS)))
3079 {
1db6d067 3080 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
757c219d 3081 op0 = force_reg (mode, op0);
3082 return expand_powi (op0, mode, n);
3083 }
3084 }
3085
3086 /* Emit a libcall to libgcc. */
3087
c2f47e15 3088 /* Mode of the 2nd argument must match that of an int. */
d0405f40 3089 mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
3090
757c219d 3091 if (target == NULL_RTX)
3092 target = gen_reg_rtx (mode);
3093
1db6d067 3094 op0 = expand_expr (arg0, subtarget, mode, EXPAND_NORMAL);
757c219d 3095 if (GET_MODE (op0) != mode)
3096 op0 = convert_to_mode (mode, op0, 0);
1db6d067 3097 op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
d0405f40 3098 if (GET_MODE (op1) != mode2)
3099 op1 = convert_to_mode (mode2, op1, 0);
757c219d 3100
f36b9f69 3101 target = emit_library_call_value (optab_libfunc (powi_optab, mode),
2dd6f9ed 3102 target, LCT_CONST, mode, 2,
d0405f40 3103 op0, mode, op1, mode2);
757c219d 3104
3105 return target;
3106}
3107
48e1416a 3108/* Expand expression EXP which is a call to the strlen builtin. Return
c2f47e15 3109 NULL_RTX if we failed the caller should emit a normal call, otherwise
aed0bd19 3110 try to get the result in TARGET, if convenient. */
f7c44134 3111
53800dbe 3112static rtx
c2f47e15 3113expand_builtin_strlen (tree exp, rtx target,
aecda0d6 3114 enum machine_mode target_mode)
53800dbe 3115{
c2f47e15 3116 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
3117 return NULL_RTX;
53800dbe 3118 else
3119 {
911c0150 3120 rtx pat;
c2f47e15 3121 tree len;
3122 tree src = CALL_EXPR_ARG (exp, 0);
911c0150 3123 rtx result, src_reg, char_rtx, before_strlen;
80cd7a5e 3124 enum machine_mode insn_mode = target_mode, char_mode;
ef2c4a29 3125 enum insn_code icode = CODE_FOR_nothing;
6248e345 3126 int align;
3127
3128 /* If the length can be computed at compile-time, return it. */
681fab1e 3129 len = c_strlen (src, 0);
6248e345 3130 if (len)
80cd7a5e 3131 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
6248e345 3132
681fab1e 3133 /* If the length can be computed at compile-time and is constant
3134 integer, but there are side-effects in src, evaluate
3135 src for side-effects, then return len.
3136 E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
3137 can be optimized into: i++; x = 3; */
3138 len = c_strlen (src, 1);
3139 if (len && TREE_CODE (len) == INTEGER_CST)
3140 {
3141 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
3142 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
3143 }
3144
6248e345 3145 align = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
53800dbe 3146
53800dbe 3147 /* If SRC is not a pointer type, don't do this operation inline. */
3148 if (align == 0)
c2f47e15 3149 return NULL_RTX;
53800dbe 3150
911c0150 3151 /* Bail out if we can't compute strlen in the right mode. */
53800dbe 3152 while (insn_mode != VOIDmode)
3153 {
99bdde56 3154 icode = optab_handler (strlen_optab, insn_mode)->insn_code;
53800dbe 3155 if (icode != CODE_FOR_nothing)
c28ae87f 3156 break;
53800dbe 3157
3158 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
3159 }
3160 if (insn_mode == VOIDmode)
c2f47e15 3161 return NULL_RTX;
53800dbe 3162
3163 /* Make a place to write the result of the instruction. */
3164 result = target;
3165 if (! (result != 0
8ad4c111 3166 && REG_P (result)
53800dbe 3167 && GET_MODE (result) == insn_mode
3168 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3169 result = gen_reg_rtx (insn_mode);
3170
911c0150 3171 /* Make a place to hold the source address. We will not expand
3172 the actual source until we are sure that the expansion will
3173 not fail -- there are trees that cannot be expanded twice. */
3174 src_reg = gen_reg_rtx (Pmode);
53800dbe 3175
911c0150 3176 /* Mark the beginning of the strlen sequence so we can emit the
3177 source operand later. */
f0ce3b1f 3178 before_strlen = get_last_insn ();
53800dbe 3179
53800dbe 3180 char_rtx = const0_rtx;
f7c44134 3181 char_mode = insn_data[(int) icode].operand[2].mode;
3182 if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
3183 char_mode))
53800dbe 3184 char_rtx = copy_to_mode_reg (char_mode, char_rtx);
3185
911c0150 3186 pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
3187 char_rtx, GEN_INT (align));
3188 if (! pat)
c2f47e15 3189 return NULL_RTX;
911c0150 3190 emit_insn (pat);
3191
3192 /* Now that we are assured of success, expand the source. */
3193 start_sequence ();
c5aba89c 3194 pat = expand_expr (src, src_reg, ptr_mode, EXPAND_NORMAL);
911c0150 3195 if (pat != src_reg)
3196 emit_move_insn (src_reg, pat);
31d3e01c 3197 pat = get_insns ();
911c0150 3198 end_sequence ();
bceb0d1f 3199
3200 if (before_strlen)
3201 emit_insn_after (pat, before_strlen);
3202 else
3203 emit_insn_before (pat, get_insns ());
53800dbe 3204
3205 /* Return the value in the proper mode for this function. */
80cd7a5e 3206 if (GET_MODE (result) == target_mode)
911c0150 3207 target = result;
53800dbe 3208 else if (target != 0)
911c0150 3209 convert_move (target, result, 0);
53800dbe 3210 else
80cd7a5e 3211 target = convert_to_mode (target_mode, result, 0);
911c0150 3212
3213 return target;
53800dbe 3214 }
3215}
3216
6840589f 3217/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3218 bytes from constant string DATA + OFFSET and return it as target
3219 constant. */
3220
3221static rtx
aecda0d6 3222builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
3223 enum machine_mode mode)
6840589f 3224{
3225 const char *str = (const char *) data;
3226
64db345d 3227 gcc_assert (offset >= 0
3228 && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
3229 <= strlen (str) + 1));
6840589f 3230
3231 return c_readstr (str + offset, mode);
3232}
3233
c2f47e15 3234/* Expand a call EXP to the memcpy builtin.
3235 Return NULL_RTX if we failed, the caller should emit a normal call,
3b824fa6 3236 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3237 mode MODE if that's convenient). */
c2f47e15 3238
53800dbe 3239static rtx
a65c4d64 3240expand_builtin_memcpy (tree exp, rtx target)
53800dbe 3241{
c2f47e15 3242 if (!validate_arglist (exp,
3243 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3244 return NULL_RTX;
53800dbe 3245 else
3246 {
c2f47e15 3247 tree dest = CALL_EXPR_ARG (exp, 0);
3248 tree src = CALL_EXPR_ARG (exp, 1);
3249 tree len = CALL_EXPR_ARG (exp, 2);
6840589f 3250 const char *src_str;
27d0c333 3251 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3252 unsigned int dest_align
3253 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
53800dbe 3254 rtx dest_mem, src_mem, dest_addr, len_rtx;
162719b3 3255 HOST_WIDE_INT expected_size = -1;
3256 unsigned int expected_align = 0;
5a0de151 3257
6f428e8b 3258 /* If DEST is not a pointer type, call the normal function. */
3259 if (dest_align == 0)
c2f47e15 3260 return NULL_RTX;
6f428e8b 3261
6f428e8b 3262 /* If either SRC is not a pointer type, don't do this
a0c938f0 3263 operation in-line. */
6f428e8b 3264 if (src_align == 0)
c2f47e15 3265 return NULL_RTX;
48e1416a 3266
8cee8dc0 3267 if (currently_expanding_gimple_stmt)
3268 stringop_block_profile (currently_expanding_gimple_stmt,
3269 &expected_align, &expected_size);
75a70cf9 3270
162719b3 3271 if (expected_align < dest_align)
3272 expected_align = dest_align;
d8ae1baa 3273 dest_mem = get_memory_rtx (dest, len);
2a631e19 3274 set_mem_align (dest_mem, dest_align);
8ec3c5c2 3275 len_rtx = expand_normal (len);
6840589f 3276 src_str = c_getstr (src);
3277
3278 /* If SRC is a string constant and block move would be done
3279 by pieces, we can avoid loading the string from memory
3280 and only stored the computed constants. */
3281 if (src_str
971ba038 3282 && CONST_INT_P (len_rtx)
6840589f 3283 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3284 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3285 CONST_CAST (char *, src_str),
3286 dest_align, false))
6840589f 3287 {
9fe0e1b8 3288 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3289 builtin_memcpy_read_str,
364c0c59 3290 CONST_CAST (char *, src_str),
3291 dest_align, false, 0);
a65c4d64 3292 dest_mem = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3293 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3294 return dest_mem;
6840589f 3295 }
3296
d8ae1baa 3297 src_mem = get_memory_rtx (src, len);
2a631e19 3298 set_mem_align (src_mem, src_align);
53800dbe 3299
53800dbe 3300 /* Copy word part most expediently. */
162719b3 3301 dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
3302 CALL_EXPR_TAILCALL (exp)
3303 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3304 expected_align, expected_size);
53800dbe 3305
3306 if (dest_addr == 0)
e5716f7e 3307 {
a65c4d64 3308 dest_addr = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3309 dest_addr = convert_memory_address (ptr_mode, dest_addr);
e5716f7e 3310 }
9fe0e1b8 3311 return dest_addr;
53800dbe 3312 }
3313}
3314
c2f47e15 3315/* Expand a call EXP to the mempcpy builtin.
3316 Return NULL_RTX if we failed; the caller should emit a normal call,
647661c6 3317 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3318 mode MODE if that's convenient). If ENDP is 0 return the
3319 destination pointer, if ENDP is 1 return the end pointer ala
3320 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3321 stpcpy. */
647661c6 3322
3323static rtx
c8b17b2e 3324expand_builtin_mempcpy (tree exp, rtx target, enum machine_mode mode)
647661c6 3325{
c2f47e15 3326 if (!validate_arglist (exp,
3327 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3328 return NULL_RTX;
3329 else
3330 {
3331 tree dest = CALL_EXPR_ARG (exp, 0);
3332 tree src = CALL_EXPR_ARG (exp, 1);
3333 tree len = CALL_EXPR_ARG (exp, 2);
3334 return expand_builtin_mempcpy_args (dest, src, len,
c2f47e15 3335 target, mode, /*endp=*/ 1);
3336 }
3337}
3338
3339/* Helper function to do the actual work for expand_builtin_mempcpy. The
3340 arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out
3341 so that this can also be called without constructing an actual CALL_EXPR.
a65c4d64 3342 The other arguments and return value are the same as for
3343 expand_builtin_mempcpy. */
c2f47e15 3344
3345static rtx
a65c4d64 3346expand_builtin_mempcpy_args (tree dest, tree src, tree len,
c2f47e15 3347 rtx target, enum machine_mode mode, int endp)
3348{
3349 /* If return value is ignored, transform mempcpy into memcpy. */
c8b17b2e 3350 if (target == const0_rtx && implicit_built_in_decls[BUILT_IN_MEMCPY])
9fe0e1b8 3351 {
3352 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
a65c4d64 3353 tree result = build_call_nofold (fn, 3, dest, src, len);
c8b17b2e 3354 return expand_expr (result, target, mode, EXPAND_NORMAL);
9fe0e1b8 3355 }
647661c6 3356 else
3357 {
9fe0e1b8 3358 const char *src_str;
3359 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3360 unsigned int dest_align
3361 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3362 rtx dest_mem, src_mem, len_rtx;
a0c938f0 3363
7da1412b 3364 /* If either SRC or DEST is not a pointer type, don't do this
a0c938f0 3365 operation in-line. */
7da1412b 3366 if (dest_align == 0 || src_align == 0)
c2f47e15 3367 return NULL_RTX;
9fe0e1b8 3368
6217c238 3369 /* If LEN is not constant, call the normal function. */
3370 if (! host_integerp (len, 1))
c2f47e15 3371 return NULL_RTX;
0862b7e9 3372
8ec3c5c2 3373 len_rtx = expand_normal (len);
9fe0e1b8 3374 src_str = c_getstr (src);
647661c6 3375
9fe0e1b8 3376 /* If SRC is a string constant and block move would be done
3377 by pieces, we can avoid loading the string from memory
3378 and only stored the computed constants. */
3379 if (src_str
971ba038 3380 && CONST_INT_P (len_rtx)
9fe0e1b8 3381 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3382 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3383 CONST_CAST (char *, src_str),
3384 dest_align, false))
9fe0e1b8 3385 {
d8ae1baa 3386 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3387 set_mem_align (dest_mem, dest_align);
3388 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3389 builtin_memcpy_read_str,
364c0c59 3390 CONST_CAST (char *, src_str),
3391 dest_align, false, endp);
9fe0e1b8 3392 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3393 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3394 return dest_mem;
647661c6 3395 }
3396
971ba038 3397 if (CONST_INT_P (len_rtx)
9fe0e1b8 3398 && can_move_by_pieces (INTVAL (len_rtx),
3399 MIN (dest_align, src_align)))
3400 {
d8ae1baa 3401 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3402 set_mem_align (dest_mem, dest_align);
d8ae1baa 3403 src_mem = get_memory_rtx (src, len);
9fe0e1b8 3404 set_mem_align (src_mem, src_align);
3405 dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
3406 MIN (dest_align, src_align), endp);
3407 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3408 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3409 return dest_mem;
3410 }
3411
c2f47e15 3412 return NULL_RTX;
647661c6 3413 }
3414}
3415
727c62dd 3416#ifndef HAVE_movstr
3417# define HAVE_movstr 0
3418# define CODE_FOR_movstr CODE_FOR_nothing
3419#endif
3420
c2f47e15 3421/* Expand into a movstr instruction, if one is available. Return NULL_RTX if
727c62dd 3422 we failed, the caller should emit a normal call, otherwise try to
3423 get the result in TARGET, if convenient. If ENDP is 0 return the
3424 destination pointer, if ENDP is 1 return the end pointer ala
3425 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3426 stpcpy. */
3427
3428static rtx
3429expand_movstr (tree dest, tree src, rtx target, int endp)
3430{
3431 rtx end;
3432 rtx dest_mem;
3433 rtx src_mem;
3434 rtx insn;
3435 const struct insn_data * data;
3436
3437 if (!HAVE_movstr)
c2f47e15 3438 return NULL_RTX;
727c62dd 3439
d8ae1baa 3440 dest_mem = get_memory_rtx (dest, NULL);
3441 src_mem = get_memory_rtx (src, NULL);
727c62dd 3442 if (!endp)
3443 {
3444 target = force_reg (Pmode, XEXP (dest_mem, 0));
3445 dest_mem = replace_equiv_address (dest_mem, target);
3446 end = gen_reg_rtx (Pmode);
3447 }
3448 else
3449 {
3450 if (target == 0 || target == const0_rtx)
3451 {
3452 end = gen_reg_rtx (Pmode);
3453 if (target == 0)
3454 target = end;
3455 }
3456 else
3457 end = target;
3458 }
3459
3460 data = insn_data + CODE_FOR_movstr;
3461
3462 if (data->operand[0].mode != VOIDmode)
3463 end = gen_lowpart (data->operand[0].mode, end);
3464
3465 insn = data->genfun (end, dest_mem, src_mem);
3466
64db345d 3467 gcc_assert (insn);
727c62dd 3468
3469 emit_insn (insn);
3470
3471 /* movstr is supposed to set end to the address of the NUL
3472 terminator. If the caller requested a mempcpy-like return value,
3473 adjust it. */
3474 if (endp == 1 && target != const0_rtx)
c5aba89c 3475 {
3476 rtx tem = plus_constant (gen_lowpart (GET_MODE (target), end), 1);
3477 emit_move_insn (target, force_operand (tem, NULL_RTX));
3478 }
727c62dd 3479
3480 return target;
3481}
3482
48e1416a 3483/* Expand expression EXP, which is a call to the strcpy builtin. Return
3484 NULL_RTX if we failed the caller should emit a normal call, otherwise
c2f47e15 3485 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3486 convenient). */
902de8ed 3487
53800dbe 3488static rtx
a65c4d64 3489expand_builtin_strcpy (tree exp, rtx target)
53800dbe 3490{
c2f47e15 3491 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3492 {
3493 tree dest = CALL_EXPR_ARG (exp, 0);
3494 tree src = CALL_EXPR_ARG (exp, 1);
a65c4d64 3495 return expand_builtin_strcpy_args (dest, src, target);
c2f47e15 3496 }
3497 return NULL_RTX;
3498}
3499
3500/* Helper function to do the actual work for expand_builtin_strcpy. The
3501 arguments to the builtin_strcpy call DEST and SRC are broken out
3502 so that this can also be called without constructing an actual CALL_EXPR.
3503 The other arguments and return value are the same as for
3504 expand_builtin_strcpy. */
3505
3506static rtx
a65c4d64 3507expand_builtin_strcpy_args (tree dest, tree src, rtx target)
c2f47e15 3508{
c2f47e15 3509 return expand_movstr (dest, src, target, /*endp=*/0);
53800dbe 3510}
3511
c2f47e15 3512/* Expand a call EXP to the stpcpy builtin.
3513 Return NULL_RTX if we failed the caller should emit a normal call,
3b824fa6 3514 otherwise try to get the result in TARGET, if convenient (and in
3515 mode MODE if that's convenient). */
3516
3517static rtx
dc369150 3518expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
3b824fa6 3519{
c2f47e15 3520 tree dst, src;
389dd41b 3521 location_t loc = EXPR_LOCATION (exp);
c2f47e15 3522
3523 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3524 return NULL_RTX;
3525
3526 dst = CALL_EXPR_ARG (exp, 0);
3527 src = CALL_EXPR_ARG (exp, 1);
3528
727c62dd 3529 /* If return value is ignored, transform stpcpy into strcpy. */
c8b17b2e 3530 if (target == const0_rtx && implicit_built_in_decls[BUILT_IN_STRCPY])
978836e5 3531 {
3532 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
a65c4d64 3533 tree result = build_call_nofold (fn, 2, dst, src);
c8b17b2e 3534 return expand_expr (result, target, mode, EXPAND_NORMAL);
978836e5 3535 }
3b824fa6 3536 else
3537 {
c2f47e15 3538 tree len, lenp1;
727c62dd 3539 rtx ret;
647661c6 3540
9fe0e1b8 3541 /* Ensure we get an actual string whose length can be evaluated at
a0c938f0 3542 compile-time, not an expression containing a string. This is
3543 because the latter will potentially produce pessimized code
3544 when used to produce the return value. */
681fab1e 3545 if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
c2f47e15 3546 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3547
389dd41b 3548 lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
a65c4d64 3549 ret = expand_builtin_mempcpy_args (dst, src, lenp1,
c2f47e15 3550 target, mode, /*endp=*/2);
727c62dd 3551
3552 if (ret)
3553 return ret;
3554
3555 if (TREE_CODE (len) == INTEGER_CST)
3556 {
8ec3c5c2 3557 rtx len_rtx = expand_normal (len);
727c62dd 3558
971ba038 3559 if (CONST_INT_P (len_rtx))
727c62dd 3560 {
a65c4d64 3561 ret = expand_builtin_strcpy_args (dst, src, target);
727c62dd 3562
3563 if (ret)
3564 {
3565 if (! target)
7ac87324 3566 {
3567 if (mode != VOIDmode)
3568 target = gen_reg_rtx (mode);
3569 else
3570 target = gen_reg_rtx (GET_MODE (ret));
3571 }
727c62dd 3572 if (GET_MODE (target) != GET_MODE (ret))
3573 ret = gen_lowpart (GET_MODE (target), ret);
3574
c5aba89c 3575 ret = plus_constant (ret, INTVAL (len_rtx));
3576 ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
64db345d 3577 gcc_assert (ret);
727c62dd 3578
3579 return target;
3580 }
3581 }
3582 }
3583
c2f47e15 3584 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3585 }
3586}
3587
6840589f 3588/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3589 bytes from constant string DATA + OFFSET and return it as target
3590 constant. */
3591
09879952 3592rtx
aecda0d6 3593builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
3594 enum machine_mode mode)
6840589f 3595{
3596 const char *str = (const char *) data;
3597
3598 if ((unsigned HOST_WIDE_INT) offset > strlen (str))
3599 return const0_rtx;
3600
3601 return c_readstr (str + offset, mode);
3602}
3603
48e1416a 3604/* Expand expression EXP, which is a call to the strncpy builtin. Return
c2f47e15 3605 NULL_RTX if we failed the caller should emit a normal call. */
ed09096d 3606
3607static rtx
a65c4d64 3608expand_builtin_strncpy (tree exp, rtx target)
ed09096d 3609{
389dd41b 3610 location_t loc = EXPR_LOCATION (exp);
c2f47e15 3611
3612 if (validate_arglist (exp,
3613 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
ed09096d 3614 {
c2f47e15 3615 tree dest = CALL_EXPR_ARG (exp, 0);
3616 tree src = CALL_EXPR_ARG (exp, 1);
3617 tree len = CALL_EXPR_ARG (exp, 2);
3618 tree slen = c_strlen (src, 1);
6840589f 3619
8ff6a5cd 3620 /* We must be passed a constant len and src parameter. */
3621 if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
c2f47e15 3622 return NULL_RTX;
ed09096d 3623
389dd41b 3624 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
ed09096d 3625
3626 /* We're required to pad with trailing zeros if the requested
a0c938f0 3627 len is greater than strlen(s2)+1. In that case try to
6840589f 3628 use store_by_pieces, if it fails, punt. */
ed09096d 3629 if (tree_int_cst_lt (slen, len))
6840589f 3630 {
27d0c333 3631 unsigned int dest_align
3632 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
c2f47e15 3633 const char *p = c_getstr (src);
6840589f 3634 rtx dest_mem;
3635
27d0c333 3636 if (!p || dest_align == 0 || !host_integerp (len, 1)
3637 || !can_store_by_pieces (tree_low_cst (len, 1),
6840589f 3638 builtin_strncpy_read_str,
364c0c59 3639 CONST_CAST (char *, p),
3640 dest_align, false))
c2f47e15 3641 return NULL_RTX;
6840589f 3642
d8ae1baa 3643 dest_mem = get_memory_rtx (dest, len);
27d0c333 3644 store_by_pieces (dest_mem, tree_low_cst (len, 1),
6840589f 3645 builtin_strncpy_read_str,
364c0c59 3646 CONST_CAST (char *, p), dest_align, false, 0);
a65c4d64 3647 dest_mem = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3648 dest_mem = convert_memory_address (ptr_mode, dest_mem);
e5716f7e 3649 return dest_mem;
6840589f 3650 }
ed09096d 3651 }
c2f47e15 3652 return NULL_RTX;
ed09096d 3653}
3654
ecc318ff 3655/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3656 bytes from constant string DATA + OFFSET and return it as target
3657 constant. */
3658
f656b751 3659rtx
aecda0d6 3660builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3661 enum machine_mode mode)
ecc318ff 3662{
3663 const char *c = (const char *) data;
364c0c59 3664 char *p = XALLOCAVEC (char, GET_MODE_SIZE (mode));
ecc318ff 3665
3666 memset (p, *c, GET_MODE_SIZE (mode));
3667
3668 return c_readstr (p, mode);
3669}
3670
a7ec6974 3671/* Callback routine for store_by_pieces. Return the RTL of a register
3672 containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
3673 char value given in the RTL register data. For example, if mode is
3674 4 bytes wide, return the RTL for 0x01010101*data. */
3675
3676static rtx
aecda0d6 3677builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3678 enum machine_mode mode)
a7ec6974 3679{
3680 rtx target, coeff;
3681 size_t size;
3682 char *p;
3683
3684 size = GET_MODE_SIZE (mode);
f0ce3b1f 3685 if (size == 1)
3686 return (rtx) data;
a7ec6974 3687
364c0c59 3688 p = XALLOCAVEC (char, size);
a7ec6974 3689 memset (p, 1, size);
3690 coeff = c_readstr (p, mode);
3691
f0ce3b1f 3692 target = convert_to_mode (mode, (rtx) data, 1);
a7ec6974 3693 target = expand_mult (mode, target, coeff, NULL_RTX, 1);
3694 return force_reg (mode, target);
3695}
3696
48e1416a 3697/* Expand expression EXP, which is a call to the memset builtin. Return
3698 NULL_RTX if we failed the caller should emit a normal call, otherwise
c2f47e15 3699 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3700 convenient). */
902de8ed 3701
53800dbe 3702static rtx
c2f47e15 3703expand_builtin_memset (tree exp, rtx target, enum machine_mode mode)
53800dbe 3704{
c2f47e15 3705 if (!validate_arglist (exp,
3706 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
3707 return NULL_RTX;
53800dbe 3708 else
3709 {
c2f47e15 3710 tree dest = CALL_EXPR_ARG (exp, 0);
3711 tree val = CALL_EXPR_ARG (exp, 1);
3712 tree len = CALL_EXPR_ARG (exp, 2);
3713 return expand_builtin_memset_args (dest, val, len, target, mode, exp);
3714 }
3715}
53800dbe 3716
c2f47e15 3717/* Helper function to do the actual work for expand_builtin_memset. The
3718 arguments to the builtin_memset call DEST, VAL, and LEN are broken out
3719 so that this can also be called without constructing an actual CALL_EXPR.
3720 The other arguments and return value are the same as for
3721 expand_builtin_memset. */
6b961939 3722
c2f47e15 3723static rtx
3724expand_builtin_memset_args (tree dest, tree val, tree len,
3725 rtx target, enum machine_mode mode, tree orig_exp)
3726{
3727 tree fndecl, fn;
3728 enum built_in_function fcode;
3729 char c;
3730 unsigned int dest_align;
3731 rtx dest_mem, dest_addr, len_rtx;
3732 HOST_WIDE_INT expected_size = -1;
3733 unsigned int expected_align = 0;
53800dbe 3734
c2f47e15 3735 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
162719b3 3736
c2f47e15 3737 /* If DEST is not a pointer type, don't do this operation in-line. */
3738 if (dest_align == 0)
3739 return NULL_RTX;
6f428e8b 3740
8cee8dc0 3741 if (currently_expanding_gimple_stmt)
3742 stringop_block_profile (currently_expanding_gimple_stmt,
3743 &expected_align, &expected_size);
75a70cf9 3744
c2f47e15 3745 if (expected_align < dest_align)
3746 expected_align = dest_align;
6b961939 3747
c2f47e15 3748 /* If the LEN parameter is zero, return DEST. */
3749 if (integer_zerop (len))
3750 {
3751 /* Evaluate and ignore VAL in case it has side-effects. */
3752 expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
3753 return expand_expr (dest, target, mode, EXPAND_NORMAL);
3754 }
7a3e5564 3755
c2f47e15 3756 /* Stabilize the arguments in case we fail. */
3757 dest = builtin_save_expr (dest);
3758 val = builtin_save_expr (val);
3759 len = builtin_save_expr (len);
a7ec6974 3760
c2f47e15 3761 len_rtx = expand_normal (len);
3762 dest_mem = get_memory_rtx (dest, len);
a7ec6974 3763
c2f47e15 3764 if (TREE_CODE (val) != INTEGER_CST)
3765 {
3766 rtx val_rtx;
a7ec6974 3767
c2f47e15 3768 val_rtx = expand_normal (val);
3769 val_rtx = convert_to_mode (TYPE_MODE (unsigned_char_type_node),
3770 val_rtx, 0);
53800dbe 3771
c2f47e15 3772 /* Assume that we can memset by pieces if we can store
3773 * the coefficients by pieces (in the required modes).
3774 * We can't pass builtin_memset_gen_str as that emits RTL. */
3775 c = 1;
3776 if (host_integerp (len, 1)
c2f47e15 3777 && can_store_by_pieces (tree_low_cst (len, 1),
4b297e2e 3778 builtin_memset_read_str, &c, dest_align,
3779 true))
c2f47e15 3780 {
3781 val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
3782 val_rtx);
3783 store_by_pieces (dest_mem, tree_low_cst (len, 1),
4b297e2e 3784 builtin_memset_gen_str, val_rtx, dest_align,
3785 true, 0);
c2f47e15 3786 }
3787 else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
3788 dest_align, expected_align,
3789 expected_size))
6b961939 3790 goto do_libcall;
48e1416a 3791
c2f47e15 3792 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3793 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3794 return dest_mem;
3795 }
53800dbe 3796
c2f47e15 3797 if (target_char_cast (val, &c))
3798 goto do_libcall;
ecc318ff 3799
c2f47e15 3800 if (c)
3801 {
3802 if (host_integerp (len, 1)
c2f47e15 3803 && can_store_by_pieces (tree_low_cst (len, 1),
4b297e2e 3804 builtin_memset_read_str, &c, dest_align,
3805 true))
c2f47e15 3806 store_by_pieces (dest_mem, tree_low_cst (len, 1),
4b297e2e 3807 builtin_memset_read_str, &c, dest_align, true, 0);
c2f47e15 3808 else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
3809 dest_align, expected_align,
3810 expected_size))
3811 goto do_libcall;
48e1416a 3812
c2f47e15 3813 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3814 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3815 return dest_mem;
3816 }
ecc318ff 3817
c2f47e15 3818 set_mem_align (dest_mem, dest_align);
3819 dest_addr = clear_storage_hints (dest_mem, len_rtx,
3820 CALL_EXPR_TAILCALL (orig_exp)
3821 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3822 expected_align, expected_size);
53800dbe 3823
c2f47e15 3824 if (dest_addr == 0)
3825 {
3826 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3827 dest_addr = convert_memory_address (ptr_mode, dest_addr);
3828 }
53800dbe 3829
c2f47e15 3830 return dest_addr;
6b961939 3831
c2f47e15 3832 do_libcall:
3833 fndecl = get_callee_fndecl (orig_exp);
3834 fcode = DECL_FUNCTION_CODE (fndecl);
3835 if (fcode == BUILT_IN_MEMSET)
a65c4d64 3836 fn = build_call_nofold (fndecl, 3, dest, val, len);
c2f47e15 3837 else if (fcode == BUILT_IN_BZERO)
a65c4d64 3838 fn = build_call_nofold (fndecl, 2, dest, len);
c2f47e15 3839 else
3840 gcc_unreachable ();
a65c4d64 3841 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
3842 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
c2f47e15 3843 return expand_call (fn, target, target == const0_rtx);
53800dbe 3844}
3845
48e1416a 3846/* Expand expression EXP, which is a call to the bzero builtin. Return
c2f47e15 3847 NULL_RTX if we failed the caller should emit a normal call. */
27d0c333 3848
ffc83088 3849static rtx
0b25db21 3850expand_builtin_bzero (tree exp)
ffc83088 3851{
c2f47e15 3852 tree dest, size;
389dd41b 3853 location_t loc = EXPR_LOCATION (exp);
ffc83088 3854
c2f47e15 3855 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
7369e7ba 3856 return NULL_RTX;
ffc83088 3857
c2f47e15 3858 dest = CALL_EXPR_ARG (exp, 0);
3859 size = CALL_EXPR_ARG (exp, 1);
bf8e3599 3860
7369e7ba 3861 /* New argument list transforming bzero(ptr x, int y) to
6f428e8b 3862 memset(ptr x, int 0, size_t y). This is done this way
3863 so that if it isn't expanded inline, we fallback to
3864 calling bzero instead of memset. */
bf8e3599 3865
c2f47e15 3866 return expand_builtin_memset_args (dest, integer_zero_node,
389dd41b 3867 fold_convert_loc (loc, sizetype, size),
c2f47e15 3868 const0_rtx, VOIDmode, exp);
ffc83088 3869}
3870
7a3f89b5 3871/* Expand expression EXP, which is a call to the memcmp built-in function.
c2f47e15 3872 Return NULL_RTX if we failed and the
53800dbe 3873 caller should emit a normal call, otherwise try to get the result in
6f428e8b 3874 TARGET, if convenient (and in mode MODE, if that's convenient). */
27d0c333 3875
53800dbe 3876static rtx
a65c4d64 3877expand_builtin_memcmp (tree exp, ATTRIBUTE_UNUSED rtx target,
3878 ATTRIBUTE_UNUSED enum machine_mode mode)
53800dbe 3879{
a65c4d64 3880 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
389dd41b 3881
c2f47e15 3882 if (!validate_arglist (exp,
3883 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3884 return NULL_RTX;
6f428e8b 3885
6ac5504b 3886#if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi
53800dbe 3887 {
0cd832f0 3888 rtx arg1_rtx, arg2_rtx, arg3_rtx;
53800dbe 3889 rtx result;
0cd832f0 3890 rtx insn;
c2f47e15 3891 tree arg1 = CALL_EXPR_ARG (exp, 0);
3892 tree arg2 = CALL_EXPR_ARG (exp, 1);
3893 tree len = CALL_EXPR_ARG (exp, 2);
53800dbe 3894
3895 int arg1_align
3896 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3897 int arg2_align
3898 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
b428c0a5 3899 enum machine_mode insn_mode;
3900
3901#ifdef HAVE_cmpmemsi
3902 if (HAVE_cmpmemsi)
3903 insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
3904 else
3905#endif
6ac5504b 3906#ifdef HAVE_cmpstrnsi
3907 if (HAVE_cmpstrnsi)
3908 insn_mode = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
b428c0a5 3909 else
3910#endif
c2f47e15 3911 return NULL_RTX;
53800dbe 3912
3913 /* If we don't have POINTER_TYPE, call the function. */
3914 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 3915 return NULL_RTX;
53800dbe 3916
3917 /* Make a place to write the result of the instruction. */
3918 result = target;
3919 if (! (result != 0
8ad4c111 3920 && REG_P (result) && GET_MODE (result) == insn_mode
53800dbe 3921 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3922 result = gen_reg_rtx (insn_mode);
3923
d8ae1baa 3924 arg1_rtx = get_memory_rtx (arg1, len);
3925 arg2_rtx = get_memory_rtx (arg2, len);
389dd41b 3926 arg3_rtx = expand_normal (fold_convert_loc (loc, sizetype, len));
83f88f8e 3927
3928 /* Set MEM_SIZE as appropriate. */
971ba038 3929 if (CONST_INT_P (arg3_rtx))
83f88f8e 3930 {
3931 set_mem_size (arg1_rtx, arg3_rtx);
3932 set_mem_size (arg2_rtx, arg3_rtx);
3933 }
3934
b428c0a5 3935#ifdef HAVE_cmpmemsi
3936 if (HAVE_cmpmemsi)
3937 insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3938 GEN_INT (MIN (arg1_align, arg2_align)));
0cd832f0 3939 else
b428c0a5 3940#endif
6ac5504b 3941#ifdef HAVE_cmpstrnsi
3942 if (HAVE_cmpstrnsi)
3943 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3944 GEN_INT (MIN (arg1_align, arg2_align)));
b428c0a5 3945 else
3946#endif
64db345d 3947 gcc_unreachable ();
0cd832f0 3948
3949 if (insn)
3950 emit_insn (insn);
3951 else
2dd6f9ed 3952 emit_library_call_value (memcmp_libfunc, result, LCT_PURE,
0cd832f0 3953 TYPE_MODE (integer_type_node), 3,
3954 XEXP (arg1_rtx, 0), Pmode,
3955 XEXP (arg2_rtx, 0), Pmode,
3956 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
78a8ed03 3957 TYPE_UNSIGNED (sizetype)),
0cd832f0 3958 TYPE_MODE (sizetype));
53800dbe 3959
3960 /* Return the value in the proper mode for this function. */
3961 mode = TYPE_MODE (TREE_TYPE (exp));
3962 if (GET_MODE (result) == mode)
3963 return result;
3964 else if (target != 0)
3965 {
3966 convert_move (target, result, 0);
3967 return target;
3968 }
3969 else
3970 return convert_to_mode (mode, result, 0);
3971 }
83d79705 3972#endif
53800dbe 3973
c2f47e15 3974 return NULL_RTX;
6f428e8b 3975}
3976
c2f47e15 3977/* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX
53800dbe 3978 if we failed the caller should emit a normal call, otherwise try to get
3979 the result in TARGET, if convenient. */
902de8ed 3980
53800dbe 3981static rtx
a65c4d64 3982expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
53800dbe 3983{
c2f47e15 3984 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3985 return NULL_RTX;
bf8e3599 3986
6ac5504b 3987#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
3988 if (cmpstr_optab[SImode] != CODE_FOR_nothing
3989 || cmpstrn_optab[SImode] != CODE_FOR_nothing)
3990 {
3991 rtx arg1_rtx, arg2_rtx;
3992 rtx result, insn = NULL_RTX;
3993 tree fndecl, fn;
c2f47e15 3994 tree arg1 = CALL_EXPR_ARG (exp, 0);
3995 tree arg2 = CALL_EXPR_ARG (exp, 1);
a0c938f0 3996
6ac5504b 3997 int arg1_align
3998 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3999 int arg2_align
4000 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4001
4002 /* If we don't have POINTER_TYPE, call the function. */
4003 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4004 return NULL_RTX;
7a3f89b5 4005
6ac5504b 4006 /* Stabilize the arguments in case gen_cmpstr(n)si fail. */
4007 arg1 = builtin_save_expr (arg1);
4008 arg2 = builtin_save_expr (arg2);
7a3f89b5 4009
d8ae1baa 4010 arg1_rtx = get_memory_rtx (arg1, NULL);
4011 arg2_rtx = get_memory_rtx (arg2, NULL);
53800dbe 4012
6ac5504b 4013#ifdef HAVE_cmpstrsi
4014 /* Try to call cmpstrsi. */
4015 if (HAVE_cmpstrsi)
4016 {
a0c938f0 4017 enum machine_mode insn_mode
6ac5504b 4018 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
4019
4020 /* Make a place to write the result of the instruction. */
4021 result = target;
4022 if (! (result != 0
4023 && REG_P (result) && GET_MODE (result) == insn_mode
4024 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4025 result = gen_reg_rtx (insn_mode);
4026
4027 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
4028 GEN_INT (MIN (arg1_align, arg2_align)));
4029 }
4030#endif
03fd9d2c 4031#ifdef HAVE_cmpstrnsi
6ac5504b 4032 /* Try to determine at least one length and call cmpstrnsi. */
a0c938f0 4033 if (!insn && HAVE_cmpstrnsi)
6ac5504b 4034 {
4035 tree len;
4036 rtx arg3_rtx;
4037
a0c938f0 4038 enum machine_mode insn_mode
6ac5504b 4039 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
4040 tree len1 = c_strlen (arg1, 1);
4041 tree len2 = c_strlen (arg2, 1);
4042
4043 if (len1)
4044 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
4045 if (len2)
4046 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
4047
4048 /* If we don't have a constant length for the first, use the length
4049 of the second, if we know it. We don't require a constant for
4050 this case; some cost analysis could be done if both are available
4051 but neither is constant. For now, assume they're equally cheap,
4052 unless one has side effects. If both strings have constant lengths,
4053 use the smaller. */
4054
4055 if (!len1)
4056 len = len2;
4057 else if (!len2)
4058 len = len1;
4059 else if (TREE_SIDE_EFFECTS (len1))
4060 len = len2;
4061 else if (TREE_SIDE_EFFECTS (len2))
4062 len = len1;
4063 else if (TREE_CODE (len1) != INTEGER_CST)
4064 len = len2;
4065 else if (TREE_CODE (len2) != INTEGER_CST)
4066 len = len1;
4067 else if (tree_int_cst_lt (len1, len2))
4068 len = len1;
4069 else
4070 len = len2;
4071
4072 /* If both arguments have side effects, we cannot optimize. */
4073 if (!len || TREE_SIDE_EFFECTS (len))
6b961939 4074 goto do_libcall;
53800dbe 4075
8ec3c5c2 4076 arg3_rtx = expand_normal (len);
902de8ed 4077
6ac5504b 4078 /* Make a place to write the result of the instruction. */
4079 result = target;
4080 if (! (result != 0
4081 && REG_P (result) && GET_MODE (result) == insn_mode
4082 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4083 result = gen_reg_rtx (insn_mode);
53800dbe 4084
6ac5504b 4085 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4086 GEN_INT (MIN (arg1_align, arg2_align)));
4087 }
4088#endif
3f8aefe2 4089
6ac5504b 4090 if (insn)
4091 {
a65c4d64 4092 enum machine_mode mode;
6ac5504b 4093 emit_insn (insn);
3f8aefe2 4094
6ac5504b 4095 /* Return the value in the proper mode for this function. */
4096 mode = TYPE_MODE (TREE_TYPE (exp));
4097 if (GET_MODE (result) == mode)
4098 return result;
4099 if (target == 0)
4100 return convert_to_mode (mode, result, 0);
4101 convert_move (target, result, 0);
4102 return target;
4103 }
902de8ed 4104
6ac5504b 4105 /* Expand the library call ourselves using a stabilized argument
4106 list to avoid re-evaluating the function's arguments twice. */
2694880e 4107#ifdef HAVE_cmpstrnsi
6b961939 4108 do_libcall:
2694880e 4109#endif
6ac5504b 4110 fndecl = get_callee_fndecl (exp);
a65c4d64 4111 fn = build_call_nofold (fndecl, 2, arg1, arg2);
4112 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
4113 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
6ac5504b 4114 return expand_call (fn, target, target == const0_rtx);
4115 }
7a3f89b5 4116#endif
c2f47e15 4117 return NULL_RTX;
83d79705 4118}
53800dbe 4119
48e1416a 4120/* Expand expression EXP, which is a call to the strncmp builtin. Return
c2f47e15 4121 NULL_RTX if we failed the caller should emit a normal call, otherwise try to get
ed09096d 4122 the result in TARGET, if convenient. */
27d0c333 4123
ed09096d 4124static rtx
a65c4d64 4125expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
4126 ATTRIBUTE_UNUSED enum machine_mode mode)
ed09096d 4127{
a65c4d64 4128 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
389dd41b 4129
c2f47e15 4130 if (!validate_arglist (exp,
4131 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4132 return NULL_RTX;
ed09096d 4133
6e34e617 4134 /* If c_strlen can determine an expression for one of the string
6ac5504b 4135 lengths, and it doesn't have side effects, then emit cmpstrnsi
7a3f89b5 4136 using length MIN(strlen(string)+1, arg3). */
6ac5504b 4137#ifdef HAVE_cmpstrnsi
4138 if (HAVE_cmpstrnsi)
7a3f89b5 4139 {
4140 tree len, len1, len2;
4141 rtx arg1_rtx, arg2_rtx, arg3_rtx;
4142 rtx result, insn;
0b25db21 4143 tree fndecl, fn;
c2f47e15 4144 tree arg1 = CALL_EXPR_ARG (exp, 0);
4145 tree arg2 = CALL_EXPR_ARG (exp, 1);
4146 tree arg3 = CALL_EXPR_ARG (exp, 2);
6f428e8b 4147
7a3f89b5 4148 int arg1_align
4149 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4150 int arg2_align
4151 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4152 enum machine_mode insn_mode
6ac5504b 4153 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
bf8e3599 4154
681fab1e 4155 len1 = c_strlen (arg1, 1);
4156 len2 = c_strlen (arg2, 1);
7a3f89b5 4157
4158 if (len1)
389dd41b 4159 len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1);
7a3f89b5 4160 if (len2)
389dd41b 4161 len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2);
7a3f89b5 4162
4163 /* If we don't have a constant length for the first, use the length
4164 of the second, if we know it. We don't require a constant for
4165 this case; some cost analysis could be done if both are available
4166 but neither is constant. For now, assume they're equally cheap,
4167 unless one has side effects. If both strings have constant lengths,
4168 use the smaller. */
4169
4170 if (!len1)
4171 len = len2;
4172 else if (!len2)
4173 len = len1;
4174 else if (TREE_SIDE_EFFECTS (len1))
4175 len = len2;
4176 else if (TREE_SIDE_EFFECTS (len2))
4177 len = len1;
4178 else if (TREE_CODE (len1) != INTEGER_CST)
4179 len = len2;
4180 else if (TREE_CODE (len2) != INTEGER_CST)
4181 len = len1;
4182 else if (tree_int_cst_lt (len1, len2))
4183 len = len1;
4184 else
4185 len = len2;
6e34e617 4186
7a3f89b5 4187 /* If both arguments have side effects, we cannot optimize. */
4188 if (!len || TREE_SIDE_EFFECTS (len))
c2f47e15 4189 return NULL_RTX;
bf8e3599 4190
7a3f89b5 4191 /* The actual new length parameter is MIN(len,arg3). */
389dd41b 4192 len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len,
4193 fold_convert_loc (loc, TREE_TYPE (len), arg3));
7a3f89b5 4194
4195 /* If we don't have POINTER_TYPE, call the function. */
4196 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4197 return NULL_RTX;
7a3f89b5 4198
4199 /* Make a place to write the result of the instruction. */
4200 result = target;
4201 if (! (result != 0
8ad4c111 4202 && REG_P (result) && GET_MODE (result) == insn_mode
7a3f89b5 4203 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4204 result = gen_reg_rtx (insn_mode);
4205
a65c4d64 4206 /* Stabilize the arguments in case gen_cmpstrnsi fails. */
4207 arg1 = builtin_save_expr (arg1);
4208 arg2 = builtin_save_expr (arg2);
4209 len = builtin_save_expr (len);
27d0c333 4210
a65c4d64 4211 arg1_rtx = get_memory_rtx (arg1, len);
4212 arg2_rtx = get_memory_rtx (arg2, len);
4213 arg3_rtx = expand_normal (len);
4214 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4215 GEN_INT (MIN (arg1_align, arg2_align)));
4216 if (insn)
4217 {
4218 emit_insn (insn);
49f0327b 4219
a65c4d64 4220 /* Return the value in the proper mode for this function. */
4221 mode = TYPE_MODE (TREE_TYPE (exp));
4222 if (GET_MODE (result) == mode)
4223 return result;
4224 if (target == 0)
4225 return convert_to_mode (mode, result, 0);
4226 convert_move (target, result, 0);
4227 return target;
4228 }
27d0c333 4229
a65c4d64 4230 /* Expand the library call ourselves using a stabilized argument
4231 list to avoid re-evaluating the function's arguments twice. */
4232 fndecl = get_callee_fndecl (exp);
4233 fn = build_call_nofold (fndecl, 3, arg1, arg2, len);
4234 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
4235 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4236 return expand_call (fn, target, target == const0_rtx);
4237 }
4238#endif
c2f47e15 4239 return NULL_RTX;
49f0327b 4240}
4241
a66c9326 4242/* Expand a call to __builtin_saveregs, generating the result in TARGET,
4243 if that's convenient. */
902de8ed 4244
a66c9326 4245rtx
aecda0d6 4246expand_builtin_saveregs (void)
53800dbe 4247{
a66c9326 4248 rtx val, seq;
53800dbe 4249
4250 /* Don't do __builtin_saveregs more than once in a function.
4251 Save the result of the first call and reuse it. */
4252 if (saveregs_value != 0)
4253 return saveregs_value;
53800dbe 4254
a66c9326 4255 /* When this function is called, it means that registers must be
4256 saved on entry to this function. So we migrate the call to the
4257 first insn of this function. */
4258
4259 start_sequence ();
53800dbe 4260
a66c9326 4261 /* Do whatever the machine needs done in this case. */
45550790 4262 val = targetm.calls.expand_builtin_saveregs ();
53800dbe 4263
a66c9326 4264 seq = get_insns ();
4265 end_sequence ();
53800dbe 4266
a66c9326 4267 saveregs_value = val;
53800dbe 4268
31d3e01c 4269 /* Put the insns after the NOTE that starts the function. If this
4270 is inside a start_sequence, make the outer-level insn chain current, so
a66c9326 4271 the code is placed at the start of the function. */
4272 push_topmost_sequence ();
0ec80471 4273 emit_insn_after (seq, entry_of_function ());
a66c9326 4274 pop_topmost_sequence ();
4275
4276 return val;
53800dbe 4277}
4278
4279/* __builtin_args_info (N) returns word N of the arg space info
4280 for the current function. The number and meanings of words
4281 is controlled by the definition of CUMULATIVE_ARGS. */
f7c44134 4282
53800dbe 4283static rtx
c2f47e15 4284expand_builtin_args_info (tree exp)
53800dbe 4285{
53800dbe 4286 int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
abe32cce 4287 int *word_ptr = (int *) &crtl->args.info;
53800dbe 4288
64db345d 4289 gcc_assert (sizeof (CUMULATIVE_ARGS) % sizeof (int) == 0);
53800dbe 4290
c2f47e15 4291 if (call_expr_nargs (exp) != 0)
53800dbe 4292 {
c2f47e15 4293 if (!host_integerp (CALL_EXPR_ARG (exp, 0), 0))
eb586f2c 4294 error ("argument of %<__builtin_args_info%> must be constant");
53800dbe 4295 else
4296 {
c2f47e15 4297 HOST_WIDE_INT wordnum = tree_low_cst (CALL_EXPR_ARG (exp, 0), 0);
53800dbe 4298
27d0c333 4299 if (wordnum < 0 || wordnum >= nwords)
eb586f2c 4300 error ("argument of %<__builtin_args_info%> out of range");
53800dbe 4301 else
4302 return GEN_INT (word_ptr[wordnum]);
4303 }
4304 }
4305 else
eb586f2c 4306 error ("missing argument in %<__builtin_args_info%>");
53800dbe 4307
4308 return const0_rtx;
53800dbe 4309}
4310
79012a9d 4311/* Expand a call to __builtin_next_arg. */
27d0c333 4312
53800dbe 4313static rtx
79012a9d 4314expand_builtin_next_arg (void)
53800dbe 4315{
79012a9d 4316 /* Checking arguments is already done in fold_builtin_next_arg
4317 that must be called before this function. */
940ddc5c 4318 return expand_binop (ptr_mode, add_optab,
abe32cce 4319 crtl->args.internal_arg_pointer,
4320 crtl->args.arg_offset_rtx,
53800dbe 4321 NULL_RTX, 0, OPTAB_LIB_WIDEN);
4322}
4323
a66c9326 4324/* Make it easier for the backends by protecting the valist argument
4325 from multiple evaluations. */
4326
4327static tree
389dd41b 4328stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
a66c9326 4329{
5f57a8b1 4330 tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
4331
4332 gcc_assert (vatype != NULL_TREE);
4333
4334 if (TREE_CODE (vatype) == ARRAY_TYPE)
a66c9326 4335 {
2d47cc32 4336 if (TREE_SIDE_EFFECTS (valist))
4337 valist = save_expr (valist);
11a61dea 4338
2d47cc32 4339 /* For this case, the backends will be expecting a pointer to
5f57a8b1 4340 vatype, but it's possible we've actually been given an array
4341 (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)).
2d47cc32 4342 So fix it. */
4343 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
8a15c04a 4344 {
5f57a8b1 4345 tree p1 = build_pointer_type (TREE_TYPE (vatype));
389dd41b 4346 valist = build_fold_addr_expr_with_type_loc (loc, valist, p1);
8a15c04a 4347 }
a66c9326 4348 }
11a61dea 4349 else
a66c9326 4350 {
2d47cc32 4351 tree pt;
11a61dea 4352
2d47cc32 4353 if (! needs_lvalue)
4354 {
11a61dea 4355 if (! TREE_SIDE_EFFECTS (valist))
4356 return valist;
bf8e3599 4357
5f57a8b1 4358 pt = build_pointer_type (vatype);
389dd41b 4359 valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist);
a66c9326 4360 TREE_SIDE_EFFECTS (valist) = 1;
a66c9326 4361 }
2d47cc32 4362
11a61dea 4363 if (TREE_SIDE_EFFECTS (valist))
2d47cc32 4364 valist = save_expr (valist);
389dd41b 4365 valist = build_fold_indirect_ref_loc (loc, valist);
a66c9326 4366 }
4367
4368 return valist;
4369}
4370
2e15d750 4371/* The "standard" definition of va_list is void*. */
4372
4373tree
4374std_build_builtin_va_list (void)
4375{
4376 return ptr_type_node;
4377}
4378
5f57a8b1 4379/* The "standard" abi va_list is va_list_type_node. */
4380
4381tree
4382std_fn_abi_va_list (tree fndecl ATTRIBUTE_UNUSED)
4383{
4384 return va_list_type_node;
4385}
4386
4387/* The "standard" type of va_list is va_list_type_node. */
4388
4389tree
4390std_canonical_va_list_type (tree type)
4391{
4392 tree wtype, htype;
4393
4394 if (INDIRECT_REF_P (type))
4395 type = TREE_TYPE (type);
4396 else if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE(type)))
4397 type = TREE_TYPE (type);
5f57a8b1 4398 wtype = va_list_type_node;
4399 htype = type;
7b36f9ab 4400 /* Treat structure va_list types. */
4401 if (TREE_CODE (wtype) == RECORD_TYPE && POINTER_TYPE_P (htype))
4402 htype = TREE_TYPE (htype);
4403 else if (TREE_CODE (wtype) == ARRAY_TYPE)
5f57a8b1 4404 {
4405 /* If va_list is an array type, the argument may have decayed
4406 to a pointer type, e.g. by being passed to another function.
4407 In that case, unwrap both types so that we can compare the
4408 underlying records. */
4409 if (TREE_CODE (htype) == ARRAY_TYPE
4410 || POINTER_TYPE_P (htype))
4411 {
4412 wtype = TREE_TYPE (wtype);
4413 htype = TREE_TYPE (htype);
4414 }
4415 }
4416 if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype))
4417 return va_list_type_node;
4418
4419 return NULL_TREE;
4420}
4421
a66c9326 4422/* The "standard" implementation of va_start: just assign `nextarg' to
4423 the variable. */
27d0c333 4424
a66c9326 4425void
aecda0d6 4426std_expand_builtin_va_start (tree valist, rtx nextarg)
a66c9326 4427{
f03c17bc 4428 rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
4429 convert_move (va_r, nextarg, 0);
a66c9326 4430}
4431
c2f47e15 4432/* Expand EXP, a call to __builtin_va_start. */
27d0c333 4433
a66c9326 4434static rtx
c2f47e15 4435expand_builtin_va_start (tree exp)
a66c9326 4436{
4437 rtx nextarg;
c2f47e15 4438 tree valist;
389dd41b 4439 location_t loc = EXPR_LOCATION (exp);
a66c9326 4440
c2f47e15 4441 if (call_expr_nargs (exp) < 2)
cb166087 4442 {
389dd41b 4443 error_at (loc, "too few arguments to function %<va_start%>");
cb166087 4444 return const0_rtx;
4445 }
a66c9326 4446
c2f47e15 4447 if (fold_builtin_next_arg (exp, true))
79012a9d 4448 return const0_rtx;
7c2f0500 4449
79012a9d 4450 nextarg = expand_builtin_next_arg ();
389dd41b 4451 valist = stabilize_va_list_loc (loc, CALL_EXPR_ARG (exp, 0), 1);
a66c9326 4452
8a58ed0a 4453 if (targetm.expand_builtin_va_start)
4454 targetm.expand_builtin_va_start (valist, nextarg);
4455 else
4456 std_expand_builtin_va_start (valist, nextarg);
a66c9326 4457
4458 return const0_rtx;
4459}
4460
a66c9326 4461/* The "standard" implementation of va_arg: read the value from the
4462 current (padded) address and increment by the (padded) size. */
f7c44134 4463
e0eca1fa 4464tree
75a70cf9 4465std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
4466 gimple_seq *post_p)
fcdd3ab3 4467{
52cc2eeb 4468 tree addr, t, type_size, rounded_size, valist_tmp;
b8e8e485 4469 unsigned HOST_WIDE_INT align, boundary;
bef380a4 4470 bool indirect;
52cc2eeb 4471
4472#ifdef ARGS_GROW_DOWNWARD
4473 /* All of the alignment and movement below is for args-grow-up machines.
4474 As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
4475 implement their own specialized gimplify_va_arg_expr routines. */
64db345d 4476 gcc_unreachable ();
52cc2eeb 4477#endif
fcdd3ab3 4478
bef380a4 4479 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
4480 if (indirect)
4481 type = build_pointer_type (type);
4482
52cc2eeb 4483 align = PARM_BOUNDARY / BITS_PER_UNIT;
c8b779eb 4484 boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type);
4485
4486 /* When we align parameter on stack for caller, if the parameter
befa808c 4487 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
4488 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
c8b779eb 4489 here with caller. */
befa808c 4490 if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
4491 boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
c8b779eb 4492
4493 boundary /= BITS_PER_UNIT;
fcdd3ab3 4494
52cc2eeb 4495 /* Hoist the valist value into a temporary for the moment. */
ecdeeb37 4496 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
4497
fcdd3ab3 4498 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
4499 requires greater alignment, we must perform dynamic alignment. */
85c1f587 4500 if (boundary > align
4501 && !integer_zerop (TYPE_SIZE (type)))
fcdd3ab3 4502 {
41076ef6 4503 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
389dd41b 4504 fold_build2 (POINTER_PLUS_EXPR,
4505 TREE_TYPE (valist),
0de36bdb 4506 valist_tmp, size_int (boundary - 1)));
52cc2eeb 4507 gimplify_and_add (t, pre_p);
4508
0de36bdb 4509 t = fold_convert (sizetype, valist_tmp);
41076ef6 4510 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
0de36bdb 4511 fold_convert (TREE_TYPE (valist),
4512 fold_build2 (BIT_AND_EXPR, sizetype, t,
4513 size_int (-boundary))));
ecdeeb37 4514 gimplify_and_add (t, pre_p);
fcdd3ab3 4515 }
c5dc0c32 4516 else
4517 boundary = align;
4518
4519 /* If the actual alignment is less than the alignment of the type,
4520 adjust the type accordingly so that we don't assume strict alignment
f0b5f617 4521 when dereferencing the pointer. */
c5dc0c32 4522 boundary *= BITS_PER_UNIT;
4523 if (boundary < TYPE_ALIGN (type))
4524 {
4525 type = build_variant_type_copy (type);
4526 TYPE_ALIGN (type) = boundary;
4527 }
fcdd3ab3 4528
bcff3604 4529 /* Compute the rounded size of the type. */
52cc2eeb 4530 type_size = size_in_bytes (type);
4531 rounded_size = round_up (type_size, align);
4532
fcdd3ab3 4533 /* Reduce rounded_size so it's sharable with the postqueue. */
4534 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
4535
4536 /* Get AP. */
ecdeeb37 4537 addr = valist_tmp;
52cc2eeb 4538 if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
fcdd3ab3 4539 {
4540 /* Small args are padded downward. */
389dd41b 4541 t = fold_build2_loc (input_location, GT_EXPR, sizetype,
4542 rounded_size, size_int (align));
49d00087 4543 t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
4544 size_binop (MINUS_EXPR, rounded_size, type_size));
389dd41b 4545 addr = fold_build2 (POINTER_PLUS_EXPR,
4546 TREE_TYPE (addr), addr, t);
fcdd3ab3 4547 }
4548
fcdd3ab3 4549 /* Compute new value for AP. */
0de36bdb 4550 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (valist), valist_tmp, rounded_size);
41076ef6 4551 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
ecdeeb37 4552 gimplify_and_add (t, pre_p);
e0eca1fa 4553
4554 addr = fold_convert (build_pointer_type (type), addr);
fcdd3ab3 4555
bef380a4 4556 if (indirect)
f2462d6c 4557 addr = build_va_arg_indirect_ref (addr);
4558
4559 return build_va_arg_indirect_ref (addr);
4560}
a0930a69 4561
f2462d6c 4562/* Build an indirect-ref expression over the given TREE, which represents a
4563 piece of a va_arg() expansion. */
4564tree
4565build_va_arg_indirect_ref (tree addr)
4566{
389dd41b 4567 addr = build_fold_indirect_ref_loc (EXPR_LOCATION (addr), addr);
f2462d6c 4568
a0930a69 4569 if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */
4570 mf_mark (addr);
bef380a4 4571
a0930a69 4572 return addr;
433006a9 4573}
4574
fcdd3ab3 4575/* Return a dummy expression of type TYPE in order to keep going after an
4576 error. */
4577
4578static tree
4579dummy_object (tree type)
4580{
535664e3 4581 tree t = build_int_cst (build_pointer_type (type), 0);
fcdd3ab3 4582 return build1 (INDIRECT_REF, type, t);
4583}
4584
2799a2b7 4585/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
4586 builtin function, but a very special sort of operator. */
fcdd3ab3 4587
4588enum gimplify_status
75a70cf9 4589gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
fcdd3ab3 4590{
5f57a8b1 4591 tree promoted_type, have_va_type;
fcdd3ab3 4592 tree valist = TREE_OPERAND (*expr_p, 0);
4593 tree type = TREE_TYPE (*expr_p);
4594 tree t;
389dd41b 4595 location_t loc = EXPR_LOCATION (*expr_p);
fcdd3ab3 4596
4597 /* Verify that valist is of the proper type. */
fcdd3ab3 4598 have_va_type = TREE_TYPE (valist);
f43dda35 4599 if (have_va_type == error_mark_node)
4600 return GS_ERROR;
5f57a8b1 4601 have_va_type = targetm.canonical_va_list_type (have_va_type);
f43dda35 4602
5f57a8b1 4603 if (have_va_type == NULL_TREE)
fcdd3ab3 4604 {
e60a6f7b 4605 error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>");
e0eca1fa 4606 return GS_ERROR;
fcdd3ab3 4607 }
4608
4609 /* Generate a diagnostic for requesting data of a type that cannot
4610 be passed through `...' due to type promotion at the call site. */
5f57a8b1 4611 if ((promoted_type = lang_hooks.types.type_promotes_to (type))
fcdd3ab3 4612 != type)
4613 {
4614 static bool gave_help;
a52d5726 4615 bool warned;
fcdd3ab3 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. */
e60a6f7b 4620 warned = warning_at (loc, 0,
4621 "%qT is promoted to %qT when passed through %<...%>",
4622 type, promoted_type);
a52d5726 4623 if (!gave_help && warned)
fcdd3ab3 4624 {
4625 gave_help = true;
e60a6f7b 4626 inform (loc, "(so you should pass %qT not %qT to %<va_arg%>)",
4627 promoted_type, type);
fcdd3ab3 4628 }
4629
4630 /* We can, however, treat "undefined" any way we please.
4631 Call abort to encourage the user to fix the program. */
a52d5726 4632 if (warned)
e60a6f7b 4633 inform (loc, "if this code is reached, the program will abort");
ad0e7a06 4634 /* Before the abort, allow the evaluation of the va_list
4635 expression to exit or longjmp. */
4636 gimplify_and_add (valist, pre_p);
389dd41b 4637 t = build_call_expr_loc (loc,
4638 implicit_built_in_decls[BUILT_IN_TRAP], 0);
75a70cf9 4639 gimplify_and_add (t, pre_p);
fcdd3ab3 4640
4641 /* This is dead code, but go ahead and finish so that the
4642 mode of the result comes out right. */
4643 *expr_p = dummy_object (type);
4644 return GS_ALL_DONE;
4645 }
4646 else
4647 {
4648 /* Make it easier for the backends by protecting the valist argument
a0c938f0 4649 from multiple evaluations. */
5f57a8b1 4650 if (TREE_CODE (have_va_type) == ARRAY_TYPE)
e0eca1fa 4651 {
4652 /* For this case, the backends will be expecting a pointer to
5f57a8b1 4653 TREE_TYPE (abi), but it's possible we've
4654 actually been given an array (an actual TARGET_FN_ABI_VA_LIST).
e0eca1fa 4655 So fix it. */
4656 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
4657 {
5f57a8b1 4658 tree p1 = build_pointer_type (TREE_TYPE (have_va_type));
389dd41b 4659 valist = fold_convert_loc (loc, p1,
4660 build_fold_addr_expr_loc (loc, valist));
e0eca1fa 4661 }
75a70cf9 4662
e0eca1fa 4663 gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
4664 }
4665 else
4666 gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
fcdd3ab3 4667
17a6380d 4668 if (!targetm.gimplify_va_arg_expr)
75a70cf9 4669 /* FIXME: Once most targets are converted we should merely
89f18f73 4670 assert this is non-null. */
fcdd3ab3 4671 return GS_ALL_DONE;
4672
17a6380d 4673 *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
fcdd3ab3 4674 return GS_OK;
4675 }
4676}
4677
c2f47e15 4678/* Expand EXP, a call to __builtin_va_end. */
f7c44134 4679
a66c9326 4680static rtx
c2f47e15 4681expand_builtin_va_end (tree exp)
a66c9326 4682{
c2f47e15 4683 tree valist = CALL_EXPR_ARG (exp, 0);
8a15c04a 4684
8a15c04a 4685 /* Evaluate for side effects, if needed. I hate macros that don't
4686 do that. */
4687 if (TREE_SIDE_EFFECTS (valist))
4688 expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
a66c9326 4689
4690 return const0_rtx;
4691}
4692
c2f47e15 4693/* Expand EXP, a call to __builtin_va_copy. We do this as a
a66c9326 4694 builtin rather than just as an assignment in stdarg.h because of the
4695 nastiness of array-type va_list types. */
f7c44134 4696
a66c9326 4697static rtx
c2f47e15 4698expand_builtin_va_copy (tree exp)
a66c9326 4699{
4700 tree dst, src, t;
389dd41b 4701 location_t loc = EXPR_LOCATION (exp);
a66c9326 4702
c2f47e15 4703 dst = CALL_EXPR_ARG (exp, 0);
4704 src = CALL_EXPR_ARG (exp, 1);
a66c9326 4705
389dd41b 4706 dst = stabilize_va_list_loc (loc, dst, 1);
4707 src = stabilize_va_list_loc (loc, src, 0);
a66c9326 4708
5f57a8b1 4709 gcc_assert (cfun != NULL && cfun->decl != NULL_TREE);
4710
4711 if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE)
a66c9326 4712 {
5f57a8b1 4713 t = build2 (MODIFY_EXPR, targetm.fn_abi_va_list (cfun->decl), dst, src);
a66c9326 4714 TREE_SIDE_EFFECTS (t) = 1;
4715 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4716 }
4717 else
4718 {
11a61dea 4719 rtx dstb, srcb, size;
4720
4721 /* Evaluate to pointers. */
4722 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
4723 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
5f57a8b1 4724 size = expand_expr (TYPE_SIZE_UNIT (targetm.fn_abi_va_list (cfun->decl)),
4725 NULL_RTX, VOIDmode, EXPAND_NORMAL);
11a61dea 4726
85d654dd 4727 dstb = convert_memory_address (Pmode, dstb);
4728 srcb = convert_memory_address (Pmode, srcb);
726ec87c 4729
11a61dea 4730 /* "Dereference" to BLKmode memories. */
4731 dstb = gen_rtx_MEM (BLKmode, dstb);
ab6ab77e 4732 set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
5f57a8b1 4733 set_mem_align (dstb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 4734 srcb = gen_rtx_MEM (BLKmode, srcb);
ab6ab77e 4735 set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
5f57a8b1 4736 set_mem_align (srcb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 4737
4738 /* Copy. */
0378dbdc 4739 emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
a66c9326 4740 }
4741
4742 return const0_rtx;
4743}
4744
53800dbe 4745/* Expand a call to one of the builtin functions __builtin_frame_address or
4746 __builtin_return_address. */
27d0c333 4747
53800dbe 4748static rtx
c2f47e15 4749expand_builtin_frame_address (tree fndecl, tree exp)
53800dbe 4750{
53800dbe 4751 /* The argument must be a nonnegative integer constant.
4752 It counts the number of frames to scan up the stack.
4753 The value is the return address saved in that frame. */
c2f47e15 4754 if (call_expr_nargs (exp) == 0)
53800dbe 4755 /* Warning about missing arg was already issued. */
4756 return const0_rtx;
c2f47e15 4757 else if (! host_integerp (CALL_EXPR_ARG (exp, 0), 1))
53800dbe 4758 {
4759 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
07e3a3d2 4760 error ("invalid argument to %<__builtin_frame_address%>");
53800dbe 4761 else
07e3a3d2 4762 error ("invalid argument to %<__builtin_return_address%>");
53800dbe 4763 return const0_rtx;
4764 }
4765 else
4766 {
27d0c333 4767 rtx tem
4768 = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
c2f47e15 4769 tree_low_cst (CALL_EXPR_ARG (exp, 0), 1));
53800dbe 4770
4771 /* Some ports cannot access arbitrary stack frames. */
4772 if (tem == NULL)
4773 {
4774 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
c3ceba8e 4775 warning (0, "unsupported argument to %<__builtin_frame_address%>");
53800dbe 4776 else
c3ceba8e 4777 warning (0, "unsupported argument to %<__builtin_return_address%>");
53800dbe 4778 return const0_rtx;
4779 }
4780
4781 /* For __builtin_frame_address, return what we've got. */
4782 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4783 return tem;
4784
8ad4c111 4785 if (!REG_P (tem)
53800dbe 4786 && ! CONSTANT_P (tem))
4787 tem = copy_to_mode_reg (Pmode, tem);
4788 return tem;
4789 }
4790}
4791
c2f47e15 4792/* Expand EXP, a call to the alloca builtin. Return NULL_RTX if
53800dbe 4793 we failed and the caller should emit a normal call, otherwise try to get
4794 the result in TARGET, if convenient. */
15c6cf6b 4795
53800dbe 4796static rtx
c2f47e15 4797expand_builtin_alloca (tree exp, rtx target)
53800dbe 4798{
4799 rtx op0;
15c6cf6b 4800 rtx result;
53800dbe 4801
f9fa0459 4802 /* Emit normal call if marked not-inlineable. */
48e1416a 4803 if (CALL_CANNOT_INLINE_P (exp))
c2f47e15 4804 return NULL_RTX;
4ee9c684 4805
c2f47e15 4806 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4807 return NULL_RTX;
53800dbe 4808
4809 /* Compute the argument. */
c2f47e15 4810 op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
53800dbe 4811
4812 /* Allocate the desired space. */
15c6cf6b 4813 result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
85d654dd 4814 result = convert_memory_address (ptr_mode, result);
15c6cf6b 4815
4816 return result;
53800dbe 4817}
4818
c2f47e15 4819/* Expand a call to a bswap builtin with argument ARG0. MODE
42791117 4820 is the mode to expand with. */
4821
4822static rtx
c2f47e15 4823expand_builtin_bswap (tree exp, rtx target, rtx subtarget)
42791117 4824{
4825 enum machine_mode mode;
4826 tree arg;
4827 rtx op0;
4828
c2f47e15 4829 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4830 return NULL_RTX;
42791117 4831
c2f47e15 4832 arg = CALL_EXPR_ARG (exp, 0);
42791117 4833 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 4834 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
42791117 4835
4836 target = expand_unop (mode, bswap_optab, op0, target, 1);
4837
4838 gcc_assert (target);
4839
4840 return convert_to_mode (mode, target, 0);
4841}
4842
c2f47e15 4843/* Expand a call to a unary builtin in EXP.
4844 Return NULL_RTX if a normal call should be emitted rather than expanding the
53800dbe 4845 function in-line. If convenient, the result should be placed in TARGET.
4846 SUBTARGET may be used as the target for computing one of EXP's operands. */
15c6cf6b 4847
53800dbe 4848static rtx
c2f47e15 4849expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target,
aecda0d6 4850 rtx subtarget, optab op_optab)
53800dbe 4851{
4852 rtx op0;
c2f47e15 4853
4854 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4855 return NULL_RTX;
53800dbe 4856
4857 /* Compute the argument. */
1db6d067 4858 op0 = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
4859 VOIDmode, EXPAND_NORMAL);
6a08d0ab 4860 /* Compute op, into TARGET if possible.
53800dbe 4861 Set TARGET to wherever the result comes back. */
c2f47e15 4862 target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
6a08d0ab 4863 op_optab, op0, target, 1);
64db345d 4864 gcc_assert (target);
7d3f6cc7 4865
efb070c8 4866 return convert_to_mode (target_mode, target, 0);
53800dbe 4867}
89cfe6e5 4868
48e1416a 4869/* Expand a call to __builtin_expect. We just return our argument
5a74f77e 4870 as the builtin_expect semantic should've been already executed by
4871 tree branch prediction pass. */
89cfe6e5 4872
4873static rtx
c2f47e15 4874expand_builtin_expect (tree exp, rtx target)
89cfe6e5 4875{
1e4adcfc 4876 tree arg;
89cfe6e5 4877
c2f47e15 4878 if (call_expr_nargs (exp) < 2)
89cfe6e5 4879 return const0_rtx;
c2f47e15 4880 arg = CALL_EXPR_ARG (exp, 0);
89cfe6e5 4881
c2f47e15 4882 target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5a74f77e 4883 /* When guessing was done, the hints should be already stripped away. */
07311427 4884 gcc_assert (!flag_guess_branch_prob
4885 || optimize == 0 || errorcount || sorrycount);
89cfe6e5 4886 return target;
4887}
689df48e 4888
c22de3f0 4889void
aecda0d6 4890expand_builtin_trap (void)
a0ef1725 4891{
4892#ifdef HAVE_trap
4893 if (HAVE_trap)
4894 emit_insn (gen_trap ());
4895 else
4896#endif
4897 emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
4898 emit_barrier ();
4899}
78a74442 4900
d2b48f0c 4901/* Expand a call to __builtin_unreachable. We do nothing except emit
4902 a barrier saying that control flow will not pass here.
4903
4904 It is the responsibility of the program being compiled to ensure
4905 that control flow does never reach __builtin_unreachable. */
4906static void
4907expand_builtin_unreachable (void)
4908{
4909 emit_barrier ();
4910}
4911
c2f47e15 4912/* Expand EXP, a call to fabs, fabsf or fabsl.
4913 Return NULL_RTX if a normal call should be emitted rather than expanding
78a74442 4914 the function inline. If convenient, the result should be placed
4915 in TARGET. SUBTARGET may be used as the target for computing
4916 the operand. */
4917
4918static rtx
c2f47e15 4919expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
78a74442 4920{
4921 enum machine_mode mode;
4922 tree arg;
4923 rtx op0;
4924
c2f47e15 4925 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
4926 return NULL_RTX;
78a74442 4927
c2f47e15 4928 arg = CALL_EXPR_ARG (exp, 0);
c7f617c2 4929 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
78a74442 4930 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 4931 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
78a74442 4932 return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
4933}
4934
c2f47e15 4935/* Expand EXP, a call to copysign, copysignf, or copysignl.
270436f3 4936 Return NULL is a normal call should be emitted rather than expanding the
4937 function inline. If convenient, the result should be placed in TARGET.
4938 SUBTARGET may be used as the target for computing the operand. */
4939
4940static rtx
c2f47e15 4941expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
270436f3 4942{
4943 rtx op0, op1;
4944 tree arg;
4945
c2f47e15 4946 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
4947 return NULL_RTX;
270436f3 4948
c2f47e15 4949 arg = CALL_EXPR_ARG (exp, 0);
8ec3c5c2 4950 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
270436f3 4951
c2f47e15 4952 arg = CALL_EXPR_ARG (exp, 1);
8ec3c5c2 4953 op1 = expand_normal (arg);
270436f3 4954
4955 return expand_copysign (op0, op1, target);
4956}
4957
19bf118a 4958/* Create a new constant string literal and return a char* pointer to it.
4959 The STRING_CST value is the LEN characters at STR. */
1e8e9920 4960tree
19bf118a 4961build_string_literal (int len, const char *str)
4962{
4963 tree t, elem, index, type;
4964
4965 t = build_string (len, str);
4966 elem = build_type_variant (char_type_node, 1, 0);
40238f64 4967 index = build_index_type (size_int (len - 1));
19bf118a 4968 type = build_array_type (elem, index);
4969 TREE_TYPE (t) = type;
4970 TREE_CONSTANT (t) = 1;
4971 TREE_READONLY (t) = 1;
4972 TREE_STATIC (t) = 1;
4973
19bf118a 4974 type = build_pointer_type (elem);
40238f64 4975 t = build1 (ADDR_EXPR, type,
4976 build4 (ARRAY_REF, elem,
4977 t, integer_zero_node, NULL_TREE, NULL_TREE));
19bf118a 4978 return t;
4979}
4980
4ee9c684 4981/* Expand a call to either the entry or exit function profiler. */
4982
4983static rtx
4984expand_builtin_profile_func (bool exitp)
4985{
f4e36c33 4986 rtx this_rtx, which;
4ee9c684 4987
f4e36c33 4988 this_rtx = DECL_RTL (current_function_decl);
4989 gcc_assert (MEM_P (this_rtx));
4990 this_rtx = XEXP (this_rtx, 0);
4ee9c684 4991
4992 if (exitp)
4993 which = profile_function_exit_libfunc;
4994 else
4995 which = profile_function_entry_libfunc;
4996
f4e36c33 4997 emit_library_call (which, LCT_NORMAL, VOIDmode, 2, this_rtx, Pmode,
4ee9c684 4998 expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
869d0ef0 4999 0),
4ee9c684 5000 Pmode);
5001
5002 return const0_rtx;
5003}
5004
ac8fb6db 5005/* Expand a call to __builtin___clear_cache. */
5006
5007static rtx
5008expand_builtin___clear_cache (tree exp ATTRIBUTE_UNUSED)
5009{
5010#ifndef HAVE_clear_cache
5011#ifdef CLEAR_INSN_CACHE
5012 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
5013 does something. Just do the default expansion to a call to
5014 __clear_cache(). */
5015 return NULL_RTX;
5016#else
5017 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
5018 does nothing. There is no need to call it. Do nothing. */
5019 return const0_rtx;
5020#endif /* CLEAR_INSN_CACHE */
5021#else
5022 /* We have a "clear_cache" insn, and it will handle everything. */
5023 tree begin, end;
5024 rtx begin_rtx, end_rtx;
5025 enum insn_code icode;
5026
5027 /* We must not expand to a library call. If we did, any
5028 fallback library function in libgcc that might contain a call to
5029 __builtin___clear_cache() would recurse infinitely. */
5030 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
5031 {
5032 error ("both arguments to %<__builtin___clear_cache%> must be pointers");
5033 return const0_rtx;
5034 }
5035
5036 if (HAVE_clear_cache)
5037 {
5038 icode = CODE_FOR_clear_cache;
5039
5040 begin = CALL_EXPR_ARG (exp, 0);
5041 begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
5042 begin_rtx = convert_memory_address (Pmode, begin_rtx);
5043 if (!insn_data[icode].operand[0].predicate (begin_rtx, Pmode))
5044 begin_rtx = copy_to_mode_reg (Pmode, begin_rtx);
5045
5046 end = CALL_EXPR_ARG (exp, 1);
5047 end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
5048 end_rtx = convert_memory_address (Pmode, end_rtx);
5049 if (!insn_data[icode].operand[1].predicate (end_rtx, Pmode))
5050 end_rtx = copy_to_mode_reg (Pmode, end_rtx);
5051
5052 emit_insn (gen_clear_cache (begin_rtx, end_rtx));
5053 }
5054 return const0_rtx;
5055#endif /* HAVE_clear_cache */
5056}
5057
4ee9c684 5058/* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
5059
5060static rtx
5061round_trampoline_addr (rtx tramp)
5062{
5063 rtx temp, addend, mask;
5064
5065 /* If we don't need too much alignment, we'll have been guaranteed
5066 proper alignment by get_trampoline_type. */
5067 if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
5068 return tramp;
5069
5070 /* Round address up to desired boundary. */
5071 temp = gen_reg_rtx (Pmode);
5072 addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
5073 mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
5074
5075 temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
5076 temp, 0, OPTAB_LIB_WIDEN);
5077 tramp = expand_simple_binop (Pmode, AND, temp, mask,
5078 temp, 0, OPTAB_LIB_WIDEN);
5079
5080 return tramp;
5081}
5082
5083static rtx
c2f47e15 5084expand_builtin_init_trampoline (tree exp)
4ee9c684 5085{
5086 tree t_tramp, t_func, t_chain;
82c7907c 5087 rtx m_tramp, r_tramp, r_chain, tmp;
4ee9c684 5088
c2f47e15 5089 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
4ee9c684 5090 POINTER_TYPE, VOID_TYPE))
5091 return NULL_RTX;
5092
c2f47e15 5093 t_tramp = CALL_EXPR_ARG (exp, 0);
5094 t_func = CALL_EXPR_ARG (exp, 1);
5095 t_chain = CALL_EXPR_ARG (exp, 2);
4ee9c684 5096
8ec3c5c2 5097 r_tramp = expand_normal (t_tramp);
82c7907c 5098 m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
5099 MEM_NOTRAP_P (m_tramp) = 1;
5100
5101 /* The TRAMP argument should be the address of a field within the
5102 local function's FRAME decl. Let's see if we can fill in the
5103 to fill in the MEM_ATTRs for this memory. */
5104 if (TREE_CODE (t_tramp) == ADDR_EXPR)
5105 set_mem_attributes_minus_bitpos (m_tramp, TREE_OPERAND (t_tramp, 0),
5106 true, 0);
5107
5108 tmp = round_trampoline_addr (r_tramp);
5109 if (tmp != r_tramp)
5110 {
5111 m_tramp = change_address (m_tramp, BLKmode, tmp);
5112 set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
5113 set_mem_size (m_tramp, GEN_INT (TRAMPOLINE_SIZE));
5114 }
5115
5116 /* The FUNC argument should be the address of the nested function.
5117 Extract the actual function decl to pass to the hook. */
5118 gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
5119 t_func = TREE_OPERAND (t_func, 0);
5120 gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
5121
8ec3c5c2 5122 r_chain = expand_normal (t_chain);
4ee9c684 5123
5124 /* Generate insns to initialize the trampoline. */
82c7907c 5125 targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
4ee9c684 5126
82c7907c 5127 trampolines_created = 1;
4ee9c684 5128 return const0_rtx;
5129}
5130
5131static rtx
c2f47e15 5132expand_builtin_adjust_trampoline (tree exp)
4ee9c684 5133{
5134 rtx tramp;
5135
c2f47e15 5136 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
4ee9c684 5137 return NULL_RTX;
5138
c2f47e15 5139 tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
4ee9c684 5140 tramp = round_trampoline_addr (tramp);
82c7907c 5141 if (targetm.calls.trampoline_adjust_address)
5142 tramp = targetm.calls.trampoline_adjust_address (tramp);
4ee9c684 5143
5144 return tramp;
5145}
5146
93f564d6 5147/* Expand the call EXP to the built-in signbit, signbitf or signbitl
5148 function. The function first checks whether the back end provides
5149 an insn to implement signbit for the respective mode. If not, it
5150 checks whether the floating point format of the value is such that
5151 the sign bit can be extracted. If that is not the case, the
5152 function returns NULL_RTX to indicate that a normal call should be
5153 emitted rather than expanding the function in-line. EXP is the
5154 expression that is a call to the builtin function; if convenient,
5155 the result should be placed in TARGET. */
27f261ef 5156static rtx
5157expand_builtin_signbit (tree exp, rtx target)
5158{
5159 const struct real_format *fmt;
5160 enum machine_mode fmode, imode, rmode;
5161 HOST_WIDE_INT hi, lo;
c2f47e15 5162 tree arg;
ca4f1f5b 5163 int word, bitpos;
27eda240 5164 enum insn_code icode;
27f261ef 5165 rtx temp;
389dd41b 5166 location_t loc = EXPR_LOCATION (exp);
27f261ef 5167
c2f47e15 5168 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
5169 return NULL_RTX;
27f261ef 5170
c2f47e15 5171 arg = CALL_EXPR_ARG (exp, 0);
27f261ef 5172 fmode = TYPE_MODE (TREE_TYPE (arg));
5173 rmode = TYPE_MODE (TREE_TYPE (exp));
5174 fmt = REAL_MODE_FORMAT (fmode);
5175
93f564d6 5176 arg = builtin_save_expr (arg);
5177
5178 /* Expand the argument yielding a RTX expression. */
5179 temp = expand_normal (arg);
5180
5181 /* Check if the back end provides an insn that handles signbit for the
5182 argument's mode. */
27eda240 5183 icode = signbit_optab->handlers [(int) fmode].insn_code;
5184 if (icode != CODE_FOR_nothing)
93f564d6 5185 {
5186 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
27eda240 5187 emit_unop_insn (icode, target, temp, UNKNOWN);
93f564d6 5188 return target;
5189 }
5190
27f261ef 5191 /* For floating point formats without a sign bit, implement signbit
5192 as "ARG < 0.0". */
8d564692 5193 bitpos = fmt->signbit_ro;
ca4f1f5b 5194 if (bitpos < 0)
27f261ef 5195 {
5196 /* But we can't do this if the format supports signed zero. */
5197 if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
c2f47e15 5198 return NULL_RTX;
27f261ef 5199
389dd41b 5200 arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
49d00087 5201 build_real (TREE_TYPE (arg), dconst0));
27f261ef 5202 return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5203 }
5204
ca4f1f5b 5205 if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
27f261ef 5206 {
ca4f1f5b 5207 imode = int_mode_for_mode (fmode);
5208 if (imode == BLKmode)
c2f47e15 5209 return NULL_RTX;
ca4f1f5b 5210 temp = gen_lowpart (imode, temp);
24fd4260 5211 }
5212 else
5213 {
ca4f1f5b 5214 imode = word_mode;
5215 /* Handle targets with different FP word orders. */
5216 if (FLOAT_WORDS_BIG_ENDIAN)
a0c938f0 5217 word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
ca4f1f5b 5218 else
a0c938f0 5219 word = bitpos / BITS_PER_WORD;
ca4f1f5b 5220 temp = operand_subword_force (temp, word, fmode);
5221 bitpos = bitpos % BITS_PER_WORD;
5222 }
5223
44b0f1d0 5224 /* Force the intermediate word_mode (or narrower) result into a
5225 register. This avoids attempting to create paradoxical SUBREGs
5226 of floating point modes below. */
5227 temp = force_reg (imode, temp);
5228
ca4f1f5b 5229 /* If the bitpos is within the "result mode" lowpart, the operation
5230 can be implement with a single bitwise AND. Otherwise, we need
5231 a right shift and an AND. */
5232
5233 if (bitpos < GET_MODE_BITSIZE (rmode))
5234 {
24fd4260 5235 if (bitpos < HOST_BITS_PER_WIDE_INT)
27f261ef 5236 {
24fd4260 5237 hi = 0;
5238 lo = (HOST_WIDE_INT) 1 << bitpos;
27f261ef 5239 }
5240 else
24fd4260 5241 {
5242 hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
5243 lo = 0;
5244 }
27f261ef 5245
4a46f016 5246 if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
ca4f1f5b 5247 temp = gen_lowpart (rmode, temp);
24fd4260 5248 temp = expand_binop (rmode, and_optab, temp,
5249 immed_double_const (lo, hi, rmode),
ca4f1f5b 5250 NULL_RTX, 1, OPTAB_LIB_WIDEN);
27f261ef 5251 }
ca4f1f5b 5252 else
5253 {
5254 /* Perform a logical right shift to place the signbit in the least
a0c938f0 5255 significant bit, then truncate the result to the desired mode
ca4f1f5b 5256 and mask just this bit. */
5257 temp = expand_shift (RSHIFT_EXPR, imode, temp,
5258 build_int_cst (NULL_TREE, bitpos), NULL_RTX, 1);
5259 temp = gen_lowpart (rmode, temp);
5260 temp = expand_binop (rmode, and_optab, temp, const1_rtx,
5261 NULL_RTX, 1, OPTAB_LIB_WIDEN);
5262 }
5263
27f261ef 5264 return temp;
5265}
73673831 5266
5267/* Expand fork or exec calls. TARGET is the desired target of the
c2f47e15 5268 call. EXP is the call. FN is the
73673831 5269 identificator of the actual function. IGNORE is nonzero if the
5270 value is to be ignored. */
5271
5272static rtx
c2f47e15 5273expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
73673831 5274{
5275 tree id, decl;
5276 tree call;
5277
5278 /* If we are not profiling, just call the function. */
5279 if (!profile_arc_flag)
5280 return NULL_RTX;
5281
5282 /* Otherwise call the wrapper. This should be equivalent for the rest of
5283 compiler, so the code does not diverge, and the wrapper may run the
9c9bad97 5284 code necessary for keeping the profiling sane. */
73673831 5285
5286 switch (DECL_FUNCTION_CODE (fn))
5287 {
5288 case BUILT_IN_FORK:
5289 id = get_identifier ("__gcov_fork");
5290 break;
5291
5292 case BUILT_IN_EXECL:
5293 id = get_identifier ("__gcov_execl");
5294 break;
5295
5296 case BUILT_IN_EXECV:
5297 id = get_identifier ("__gcov_execv");
5298 break;
5299
5300 case BUILT_IN_EXECLP:
5301 id = get_identifier ("__gcov_execlp");
5302 break;
5303
5304 case BUILT_IN_EXECLE:
5305 id = get_identifier ("__gcov_execle");
5306 break;
5307
5308 case BUILT_IN_EXECVP:
5309 id = get_identifier ("__gcov_execvp");
5310 break;
5311
5312 case BUILT_IN_EXECVE:
5313 id = get_identifier ("__gcov_execve");
5314 break;
5315
5316 default:
64db345d 5317 gcc_unreachable ();
73673831 5318 }
5319
e60a6f7b 5320 decl = build_decl (DECL_SOURCE_LOCATION (fn),
5321 FUNCTION_DECL, id, TREE_TYPE (fn));
73673831 5322 DECL_EXTERNAL (decl) = 1;
5323 TREE_PUBLIC (decl) = 1;
5324 DECL_ARTIFICIAL (decl) = 1;
5325 TREE_NOTHROW (decl) = 1;
e82d310b 5326 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
5327 DECL_VISIBILITY_SPECIFIED (decl) = 1;
389dd41b 5328 call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0);
73673831 5329 return expand_call (call, target, ignore);
c2f47e15 5330 }
48e1416a 5331
b6a5fc45 5332
5333\f
3e272de8 5334/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
5335 the pointer in these functions is void*, the tree optimizers may remove
5336 casts. The mode computed in expand_builtin isn't reliable either, due
5337 to __sync_bool_compare_and_swap.
5338
5339 FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
5340 group of builtins. This gives us log2 of the mode size. */
5341
5342static inline enum machine_mode
5343get_builtin_sync_mode (int fcode_diff)
5344{
ad3a13b5 5345 /* The size is not negotiable, so ask not to get BLKmode in return
5346 if the target indicates that a smaller size would be better. */
5347 return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
3e272de8 5348}
5349
041e0215 5350/* Expand the memory expression LOC and return the appropriate memory operand
5351 for the builtin_sync operations. */
5352
5353static rtx
5354get_builtin_sync_mem (tree loc, enum machine_mode mode)
5355{
5356 rtx addr, mem;
5357
7f4d56ad 5358 addr = expand_expr (loc, NULL_RTX, ptr_mode, EXPAND_SUM);
5359 addr = convert_memory_address (Pmode, addr);
041e0215 5360
5361 /* Note that we explicitly do not want any alias information for this
5362 memory, so that we kill all other live memories. Otherwise we don't
5363 satisfy the full barrier semantics of the intrinsic. */
5364 mem = validize_mem (gen_rtx_MEM (mode, addr));
5365
5366 set_mem_align (mem, get_pointer_alignment (loc, BIGGEST_ALIGNMENT));
c94cfd1c 5367 set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
041e0215 5368 MEM_VOLATILE_P (mem) = 1;
5369
5370 return mem;
5371}
5372
b6a5fc45 5373/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
c2f47e15 5374 EXP is the CALL_EXPR. CODE is the rtx code
b6a5fc45 5375 that corresponds to the arithmetic or logical operation from the name;
5376 an exception here is that NOT actually means NAND. TARGET is an optional
5377 place for us to store the results; AFTER is true if this is the
5378 fetch_and_xxx form. IGNORE is true if we don't actually care about
5379 the result of the operation at all. */
5380
5381static rtx
c2f47e15 5382expand_builtin_sync_operation (enum machine_mode mode, tree exp,
3e272de8 5383 enum rtx_code code, bool after,
b6a5fc45 5384 rtx target, bool ignore)
5385{
041e0215 5386 rtx val, mem;
a8bb7059 5387 enum machine_mode old_mode;
e60a6f7b 5388 location_t loc = EXPR_LOCATION (exp);
b6a5fc45 5389
cf73e559 5390 if (code == NOT && warn_sync_nand)
5391 {
5392 tree fndecl = get_callee_fndecl (exp);
5393 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
5394
5395 static bool warned_f_a_n, warned_n_a_f;
5396
5397 switch (fcode)
5398 {
5399 case BUILT_IN_FETCH_AND_NAND_1:
5400 case BUILT_IN_FETCH_AND_NAND_2:
5401 case BUILT_IN_FETCH_AND_NAND_4:
5402 case BUILT_IN_FETCH_AND_NAND_8:
5403 case BUILT_IN_FETCH_AND_NAND_16:
5404
5405 if (warned_f_a_n)
5406 break;
5407
5408 fndecl = implicit_built_in_decls[BUILT_IN_FETCH_AND_NAND_N];
e60a6f7b 5409 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
cf73e559 5410 warned_f_a_n = true;
5411 break;
5412
5413 case BUILT_IN_NAND_AND_FETCH_1:
5414 case BUILT_IN_NAND_AND_FETCH_2:
5415 case BUILT_IN_NAND_AND_FETCH_4:
5416 case BUILT_IN_NAND_AND_FETCH_8:
5417 case BUILT_IN_NAND_AND_FETCH_16:
5418
5419 if (warned_n_a_f)
5420 break;
5421
5422 fndecl = implicit_built_in_decls[BUILT_IN_NAND_AND_FETCH_N];
e60a6f7b 5423 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
cf73e559 5424 warned_n_a_f = true;
5425 break;
5426
5427 default:
5428 gcc_unreachable ();
5429 }
5430 }
5431
b6a5fc45 5432 /* Expand the operands. */
c2f47e15 5433 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5434
1db6d067 5435 val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
a8bb7059 5436 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5437 of CONST_INTs, where we know the old_mode only from the call argument. */
5438 old_mode = GET_MODE (val);
5439 if (old_mode == VOIDmode)
5440 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5441 val = convert_modes (mode, old_mode, val, 1);
b6a5fc45 5442
b6a5fc45 5443 if (ignore)
5444 return expand_sync_operation (mem, val, code);
5445 else
5446 return expand_sync_fetch_operation (mem, val, code, after, target);
5447}
5448
5449/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
c2f47e15 5450 intrinsics. EXP is the CALL_EXPR. IS_BOOL is
b6a5fc45 5451 true if this is the boolean form. TARGET is a place for us to store the
5452 results; this is NOT optional if IS_BOOL is true. */
5453
5454static rtx
c2f47e15 5455expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
3e272de8 5456 bool is_bool, rtx target)
b6a5fc45 5457{
041e0215 5458 rtx old_val, new_val, mem;
a8bb7059 5459 enum machine_mode old_mode;
b6a5fc45 5460
5461 /* Expand the operands. */
c2f47e15 5462 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5463
c2f47e15 5464
1db6d067 5465 old_val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX,
5466 mode, EXPAND_NORMAL);
a8bb7059 5467 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5468 of CONST_INTs, where we know the old_mode only from the call argument. */
5469 old_mode = GET_MODE (old_val);
5470 if (old_mode == VOIDmode)
5471 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5472 old_val = convert_modes (mode, old_mode, old_val, 1);
b6a5fc45 5473
1db6d067 5474 new_val = expand_expr (CALL_EXPR_ARG (exp, 2), NULL_RTX,
5475 mode, EXPAND_NORMAL);
a8bb7059 5476 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5477 of CONST_INTs, where we know the old_mode only from the call argument. */
5478 old_mode = GET_MODE (new_val);
5479 if (old_mode == VOIDmode)
5480 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2)));
5481 new_val = convert_modes (mode, old_mode, new_val, 1);
b6a5fc45 5482
b6a5fc45 5483 if (is_bool)
5484 return expand_bool_compare_and_swap (mem, old_val, new_val, target);
5485 else
5486 return expand_val_compare_and_swap (mem, old_val, new_val, target);
5487}
5488
5489/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
5490 general form is actually an atomic exchange, and some targets only
5491 support a reduced form with the second argument being a constant 1.
48e1416a 5492 EXP is the CALL_EXPR; TARGET is an optional place for us to store
c2f47e15 5493 the results. */
b6a5fc45 5494
5495static rtx
c2f47e15 5496expand_builtin_lock_test_and_set (enum machine_mode mode, tree exp,
3e272de8 5497 rtx target)
b6a5fc45 5498{
041e0215 5499 rtx val, mem;
a8bb7059 5500 enum machine_mode old_mode;
b6a5fc45 5501
5502 /* Expand the operands. */
c2f47e15 5503 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1db6d067 5504 val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
a8bb7059 5505 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5506 of CONST_INTs, where we know the old_mode only from the call argument. */
5507 old_mode = GET_MODE (val);
5508 if (old_mode == VOIDmode)
5509 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5510 val = convert_modes (mode, old_mode, val, 1);
b6a5fc45 5511
b6a5fc45 5512 return expand_sync_lock_test_and_set (mem, val, target);
5513}
5514
5515/* Expand the __sync_synchronize intrinsic. */
5516
5517static void
5518expand_builtin_synchronize (void)
5519{
16c9337c 5520 gimple x;
78f55ca8 5521 VEC (tree, gc) *v_clobbers;
b6a5fc45 5522
5523#ifdef HAVE_memory_barrier
5524 if (HAVE_memory_barrier)
5525 {
5526 emit_insn (gen_memory_barrier ());
5527 return;
5528 }
5529#endif
5530
047a7e40 5531 if (synchronize_libfunc != NULL_RTX)
5532 {
5533 emit_library_call (synchronize_libfunc, LCT_NORMAL, VOIDmode, 0);
5534 return;
5535 }
5536
82e58396 5537 /* If no explicit memory barrier instruction is available, create an
5538 empty asm stmt with a memory clobber. */
78f55ca8 5539 v_clobbers = VEC_alloc (tree, gc, 1);
5540 VEC_quick_push (tree, v_clobbers,
5541 tree_cons (NULL, build_string (6, "memory"), NULL));
5542 x = gimple_build_asm_vec ("", NULL, NULL, v_clobbers, NULL);
16c9337c 5543 gimple_asm_set_volatile (x, true);
5544 expand_asm_stmt (x);
b6a5fc45 5545}
5546
c2f47e15 5547/* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */
b6a5fc45 5548
5549static void
c2f47e15 5550expand_builtin_lock_release (enum machine_mode mode, tree exp)
b6a5fc45 5551{
b6a5fc45 5552 enum insn_code icode;
041e0215 5553 rtx mem, insn;
3e272de8 5554 rtx val = const0_rtx;
b6a5fc45 5555
5556 /* Expand the operands. */
c2f47e15 5557 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5558
5559 /* If there is an explicit operation in the md file, use it. */
5560 icode = sync_lock_release[mode];
5561 if (icode != CODE_FOR_nothing)
5562 {
5563 if (!insn_data[icode].operand[1].predicate (val, mode))
5564 val = force_reg (mode, val);
5565
5566 insn = GEN_FCN (icode) (mem, val);
5567 if (insn)
5568 {
5569 emit_insn (insn);
5570 return;
5571 }
5572 }
5573
5574 /* Otherwise we can implement this operation by emitting a barrier
5575 followed by a store of zero. */
5576 expand_builtin_synchronize ();
5577 emit_move_insn (mem, val);
5578}
53800dbe 5579\f
5580/* Expand an expression EXP that calls a built-in function,
5581 with result going to TARGET if that's convenient
5582 (and in mode MODE if that's convenient).
5583 SUBTARGET may be used as the target for computing one of EXP's operands.
5584 IGNORE is nonzero if the value is to be ignored. */
5585
5586rtx
aecda0d6 5587expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
5588 int ignore)
53800dbe 5589{
c6e6ecb1 5590 tree fndecl = get_callee_fndecl (exp);
53800dbe 5591 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
efb070c8 5592 enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
53800dbe 5593
8305149e 5594 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
883b2e73 5595 return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
bf8e3599 5596
53800dbe 5597 /* When not optimizing, generate calls to library functions for a certain
5598 set of builtins. */
cd9ff771 5599 if (!optimize
b6a5fc45 5600 && !called_as_built_in (fndecl)
cd9ff771 5601 && DECL_ASSEMBLER_NAME_SET_P (fndecl)
2c281b15 5602 && fcode != BUILT_IN_ALLOCA
5603 && fcode != BUILT_IN_FREE)
cd9ff771 5604 return expand_call (exp, target, ignore);
53800dbe 5605
8d6d7930 5606 /* The built-in function expanders test for target == const0_rtx
5607 to determine whether the function's result will be ignored. */
5608 if (ignore)
5609 target = const0_rtx;
5610
5611 /* If the result of a pure or const built-in function is ignored, and
5612 none of its arguments are volatile, we can avoid expanding the
5613 built-in call and just evaluate the arguments for side-effects. */
5614 if (target == const0_rtx
9c2a0c05 5615 && (DECL_PURE_P (fndecl) || TREE_READONLY (fndecl)))
8d6d7930 5616 {
5617 bool volatilep = false;
5618 tree arg;
c2f47e15 5619 call_expr_arg_iterator iter;
8d6d7930 5620
c2f47e15 5621 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5622 if (TREE_THIS_VOLATILE (arg))
8d6d7930 5623 {
5624 volatilep = true;
5625 break;
5626 }
5627
5628 if (! volatilep)
5629 {
c2f47e15 5630 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5631 expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
8d6d7930 5632 return const0_rtx;
5633 }
5634 }
5635
53800dbe 5636 switch (fcode)
5637 {
4f35b1fc 5638 CASE_FLT_FN (BUILT_IN_FABS):
c2f47e15 5639 target = expand_builtin_fabs (exp, target, subtarget);
78a74442 5640 if (target)
a0c938f0 5641 return target;
78a74442 5642 break;
5643
4f35b1fc 5644 CASE_FLT_FN (BUILT_IN_COPYSIGN):
c2f47e15 5645 target = expand_builtin_copysign (exp, target, subtarget);
270436f3 5646 if (target)
5647 return target;
5648 break;
5649
7d3f6cc7 5650 /* Just do a normal library call if we were unable to fold
5651 the values. */
4f35b1fc 5652 CASE_FLT_FN (BUILT_IN_CABS):
78a74442 5653 break;
53800dbe 5654
4f35b1fc 5655 CASE_FLT_FN (BUILT_IN_EXP):
5656 CASE_FLT_FN (BUILT_IN_EXP10):
5657 CASE_FLT_FN (BUILT_IN_POW10):
5658 CASE_FLT_FN (BUILT_IN_EXP2):
5659 CASE_FLT_FN (BUILT_IN_EXPM1):
5660 CASE_FLT_FN (BUILT_IN_LOGB):
4f35b1fc 5661 CASE_FLT_FN (BUILT_IN_LOG):
5662 CASE_FLT_FN (BUILT_IN_LOG10):
5663 CASE_FLT_FN (BUILT_IN_LOG2):
5664 CASE_FLT_FN (BUILT_IN_LOG1P):
5665 CASE_FLT_FN (BUILT_IN_TAN):
5666 CASE_FLT_FN (BUILT_IN_ASIN):
5667 CASE_FLT_FN (BUILT_IN_ACOS):
5668 CASE_FLT_FN (BUILT_IN_ATAN):
b3154a1f 5669 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
7f3be425 5670 /* Treat these like sqrt only if unsafe math optimizations are allowed,
5671 because of possible accuracy problems. */
5672 if (! flag_unsafe_math_optimizations)
53800dbe 5673 break;
4f35b1fc 5674 CASE_FLT_FN (BUILT_IN_SQRT):
5675 CASE_FLT_FN (BUILT_IN_FLOOR):
5676 CASE_FLT_FN (BUILT_IN_CEIL):
5677 CASE_FLT_FN (BUILT_IN_TRUNC):
5678 CASE_FLT_FN (BUILT_IN_ROUND):
5679 CASE_FLT_FN (BUILT_IN_NEARBYINT):
5680 CASE_FLT_FN (BUILT_IN_RINT):
53800dbe 5681 target = expand_builtin_mathfn (exp, target, subtarget);
5682 if (target)
5683 return target;
5684 break;
5685
a67a90e5 5686 CASE_FLT_FN (BUILT_IN_ILOGB):
5687 if (! flag_unsafe_math_optimizations)
5688 break;
69b779ea 5689 CASE_FLT_FN (BUILT_IN_ISINF):
cde061c1 5690 CASE_FLT_FN (BUILT_IN_FINITE):
5691 case BUILT_IN_ISFINITE:
8a1a9cb7 5692 case BUILT_IN_ISNORMAL:
a67a90e5 5693 target = expand_builtin_interclass_mathfn (exp, target, subtarget);
5694 if (target)
5695 return target;
5696 break;
5697
4f35b1fc 5698 CASE_FLT_FN (BUILT_IN_LCEIL):
5699 CASE_FLT_FN (BUILT_IN_LLCEIL):
5700 CASE_FLT_FN (BUILT_IN_LFLOOR):
5701 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ff1b14e4 5702 target = expand_builtin_int_roundingfn (exp, target);
ad52b9b7 5703 if (target)
5704 return target;
5705 break;
5706
7d3afc77 5707 CASE_FLT_FN (BUILT_IN_LRINT):
5708 CASE_FLT_FN (BUILT_IN_LLRINT):
ef2f1a10 5709 CASE_FLT_FN (BUILT_IN_LROUND):
5710 CASE_FLT_FN (BUILT_IN_LLROUND):
ff1b14e4 5711 target = expand_builtin_int_roundingfn_2 (exp, target);
7d3afc77 5712 if (target)
5713 return target;
5714 break;
5715
4f35b1fc 5716 CASE_FLT_FN (BUILT_IN_POW):
f1b844c6 5717 target = expand_builtin_pow (exp, target, subtarget);
5718 if (target)
5719 return target;
5720 break;
5721
4f35b1fc 5722 CASE_FLT_FN (BUILT_IN_POWI):
757c219d 5723 target = expand_builtin_powi (exp, target, subtarget);
5724 if (target)
5725 return target;
5726 break;
5727
4f35b1fc 5728 CASE_FLT_FN (BUILT_IN_ATAN2):
5729 CASE_FLT_FN (BUILT_IN_LDEXP):
73a954a1 5730 CASE_FLT_FN (BUILT_IN_SCALB):
5731 CASE_FLT_FN (BUILT_IN_SCALBN):
5732 CASE_FLT_FN (BUILT_IN_SCALBLN):
0fd605a5 5733 if (! flag_unsafe_math_optimizations)
5734 break;
ef722005 5735
5736 CASE_FLT_FN (BUILT_IN_FMOD):
5737 CASE_FLT_FN (BUILT_IN_REMAINDER):
5738 CASE_FLT_FN (BUILT_IN_DREM):
0fd605a5 5739 target = expand_builtin_mathfn_2 (exp, target, subtarget);
5740 if (target)
5741 return target;
5742 break;
5743
d735c391 5744 CASE_FLT_FN (BUILT_IN_CEXPI):
5745 target = expand_builtin_cexpi (exp, target, subtarget);
5746 gcc_assert (target);
5747 return target;
5748
4f35b1fc 5749 CASE_FLT_FN (BUILT_IN_SIN):
5750 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 5751 if (! flag_unsafe_math_optimizations)
5752 break;
5753 target = expand_builtin_mathfn_3 (exp, target, subtarget);
5754 if (target)
5755 return target;
5756 break;
5757
c3147c1a 5758 CASE_FLT_FN (BUILT_IN_SINCOS):
5759 if (! flag_unsafe_math_optimizations)
5760 break;
5761 target = expand_builtin_sincos (exp);
5762 if (target)
5763 return target;
5764 break;
5765
53800dbe 5766 case BUILT_IN_APPLY_ARGS:
5767 return expand_builtin_apply_args ();
5768
5769 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
5770 FUNCTION with a copy of the parameters described by
5771 ARGUMENTS, and ARGSIZE. It returns a block of memory
5772 allocated on the stack into which is stored all the registers
5773 that might possibly be used for returning the result of a
5774 function. ARGUMENTS is the value returned by
5775 __builtin_apply_args. ARGSIZE is the number of bytes of
5776 arguments that must be copied. ??? How should this value be
5777 computed? We'll also need a safe worst case value for varargs
5778 functions. */
5779 case BUILT_IN_APPLY:
c2f47e15 5780 if (!validate_arglist (exp, POINTER_TYPE,
0eb671f7 5781 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
c2f47e15 5782 && !validate_arglist (exp, REFERENCE_TYPE,
0eb671f7 5783 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 5784 return const0_rtx;
5785 else
5786 {
53800dbe 5787 rtx ops[3];
5788
c2f47e15 5789 ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
5790 ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
5791 ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
53800dbe 5792
5793 return expand_builtin_apply (ops[0], ops[1], ops[2]);
5794 }
5795
5796 /* __builtin_return (RESULT) causes the function to return the
5797 value described by RESULT. RESULT is address of the block of
5798 memory returned by __builtin_apply. */
5799 case BUILT_IN_RETURN:
c2f47e15 5800 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
5801 expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
53800dbe 5802 return const0_rtx;
5803
5804 case BUILT_IN_SAVEREGS:
a66c9326 5805 return expand_builtin_saveregs ();
53800dbe 5806
5807 case BUILT_IN_ARGS_INFO:
c2f47e15 5808 return expand_builtin_args_info (exp);
53800dbe 5809
48dc2227 5810 case BUILT_IN_VA_ARG_PACK:
5811 /* All valid uses of __builtin_va_arg_pack () are removed during
5812 inlining. */
b8c23db3 5813 error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
48dc2227 5814 return const0_rtx;
5815
4e1d7ea4 5816 case BUILT_IN_VA_ARG_PACK_LEN:
5817 /* All valid uses of __builtin_va_arg_pack_len () are removed during
5818 inlining. */
b8c23db3 5819 error ("%Kinvalid use of %<__builtin_va_arg_pack_len ()%>", exp);
4e1d7ea4 5820 return const0_rtx;
5821
53800dbe 5822 /* Return the address of the first anonymous stack arg. */
5823 case BUILT_IN_NEXT_ARG:
c2f47e15 5824 if (fold_builtin_next_arg (exp, false))
a0c938f0 5825 return const0_rtx;
79012a9d 5826 return expand_builtin_next_arg ();
53800dbe 5827
ac8fb6db 5828 case BUILT_IN_CLEAR_CACHE:
5829 target = expand_builtin___clear_cache (exp);
5830 if (target)
5831 return target;
5832 break;
5833
53800dbe 5834 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 5835 return expand_builtin_classify_type (exp);
53800dbe 5836
5837 case BUILT_IN_CONSTANT_P:
4ee9c684 5838 return const0_rtx;
53800dbe 5839
5840 case BUILT_IN_FRAME_ADDRESS:
5841 case BUILT_IN_RETURN_ADDRESS:
c2f47e15 5842 return expand_builtin_frame_address (fndecl, exp);
53800dbe 5843
5844 /* Returns the address of the area where the structure is returned.
5845 0 otherwise. */
5846 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
c2f47e15 5847 if (call_expr_nargs (exp) != 0
9342ee68 5848 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
e16ceb8e 5849 || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
9342ee68 5850 return const0_rtx;
53800dbe 5851 else
9342ee68 5852 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
53800dbe 5853
5854 case BUILT_IN_ALLOCA:
c2f47e15 5855 target = expand_builtin_alloca (exp, target);
53800dbe 5856 if (target)
5857 return target;
5858 break;
5859
4ee9c684 5860 case BUILT_IN_STACK_SAVE:
5861 return expand_stack_save ();
5862
5863 case BUILT_IN_STACK_RESTORE:
c2f47e15 5864 expand_stack_restore (CALL_EXPR_ARG (exp, 0));
4ee9c684 5865 return const0_rtx;
5866
42791117 5867 case BUILT_IN_BSWAP32:
5868 case BUILT_IN_BSWAP64:
c2f47e15 5869 target = expand_builtin_bswap (exp, target, subtarget);
42791117 5870
5871 if (target)
5872 return target;
5873 break;
5874
4f35b1fc 5875 CASE_INT_FN (BUILT_IN_FFS):
5053259b 5876 case BUILT_IN_FFSIMAX:
c2f47e15 5877 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 5878 subtarget, ffs_optab);
6a08d0ab 5879 if (target)
5880 return target;
5881 break;
5882
4f35b1fc 5883 CASE_INT_FN (BUILT_IN_CLZ):
5053259b 5884 case BUILT_IN_CLZIMAX:
c2f47e15 5885 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 5886 subtarget, clz_optab);
6a08d0ab 5887 if (target)
5888 return target;
5889 break;
5890
4f35b1fc 5891 CASE_INT_FN (BUILT_IN_CTZ):
5053259b 5892 case BUILT_IN_CTZIMAX:
c2f47e15 5893 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 5894 subtarget, ctz_optab);
6a08d0ab 5895 if (target)
5896 return target;
5897 break;
5898
4f35b1fc 5899 CASE_INT_FN (BUILT_IN_POPCOUNT):
5053259b 5900 case BUILT_IN_POPCOUNTIMAX:
c2f47e15 5901 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 5902 subtarget, popcount_optab);
6a08d0ab 5903 if (target)
5904 return target;
5905 break;
5906
4f35b1fc 5907 CASE_INT_FN (BUILT_IN_PARITY):
5053259b 5908 case BUILT_IN_PARITYIMAX:
c2f47e15 5909 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 5910 subtarget, parity_optab);
53800dbe 5911 if (target)
5912 return target;
5913 break;
5914
5915 case BUILT_IN_STRLEN:
c2f47e15 5916 target = expand_builtin_strlen (exp, target, target_mode);
53800dbe 5917 if (target)
5918 return target;
5919 break;
5920
5921 case BUILT_IN_STRCPY:
a65c4d64 5922 target = expand_builtin_strcpy (exp, target);
53800dbe 5923 if (target)
5924 return target;
5925 break;
bf8e3599 5926
ed09096d 5927 case BUILT_IN_STRNCPY:
a65c4d64 5928 target = expand_builtin_strncpy (exp, target);
ed09096d 5929 if (target)
5930 return target;
5931 break;
bf8e3599 5932
3b824fa6 5933 case BUILT_IN_STPCPY:
dc369150 5934 target = expand_builtin_stpcpy (exp, target, mode);
3b824fa6 5935 if (target)
5936 return target;
5937 break;
5938
53800dbe 5939 case BUILT_IN_MEMCPY:
a65c4d64 5940 target = expand_builtin_memcpy (exp, target);
3b824fa6 5941 if (target)
5942 return target;
5943 break;
5944
5945 case BUILT_IN_MEMPCPY:
c2f47e15 5946 target = expand_builtin_mempcpy (exp, target, mode);
53800dbe 5947 if (target)
5948 return target;
5949 break;
5950
5951 case BUILT_IN_MEMSET:
c2f47e15 5952 target = expand_builtin_memset (exp, target, mode);
53800dbe 5953 if (target)
5954 return target;
5955 break;
5956
ffc83088 5957 case BUILT_IN_BZERO:
0b25db21 5958 target = expand_builtin_bzero (exp);
ffc83088 5959 if (target)
5960 return target;
5961 break;
5962
53800dbe 5963 case BUILT_IN_STRCMP:
a65c4d64 5964 target = expand_builtin_strcmp (exp, target);
53800dbe 5965 if (target)
5966 return target;
5967 break;
5968
ed09096d 5969 case BUILT_IN_STRNCMP:
5970 target = expand_builtin_strncmp (exp, target, mode);
5971 if (target)
5972 return target;
5973 break;
5974
071f1696 5975 case BUILT_IN_BCMP:
53800dbe 5976 case BUILT_IN_MEMCMP:
c2f47e15 5977 target = expand_builtin_memcmp (exp, target, mode);
53800dbe 5978 if (target)
5979 return target;
5980 break;
53800dbe 5981
5982 case BUILT_IN_SETJMP:
2c8a1497 5983 /* This should have been lowered to the builtins below. */
5984 gcc_unreachable ();
5985
5986 case BUILT_IN_SETJMP_SETUP:
5987 /* __builtin_setjmp_setup is passed a pointer to an array of five words
5988 and the receiver label. */
c2f47e15 5989 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2c8a1497 5990 {
c2f47e15 5991 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
2c8a1497 5992 VOIDmode, EXPAND_NORMAL);
c2f47e15 5993 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
2c8a1497 5994 rtx label_r = label_rtx (label);
5995
5996 /* This is copied from the handling of non-local gotos. */
5997 expand_builtin_setjmp_setup (buf_addr, label_r);
5998 nonlocal_goto_handler_labels
5999 = gen_rtx_EXPR_LIST (VOIDmode, label_r,
6000 nonlocal_goto_handler_labels);
6001 /* ??? Do not let expand_label treat us as such since we would
6002 not want to be both on the list of non-local labels and on
6003 the list of forced labels. */
6004 FORCED_LABEL (label) = 0;
6005 return const0_rtx;
6006 }
6007 break;
6008
6009 case BUILT_IN_SETJMP_DISPATCHER:
6010 /* __builtin_setjmp_dispatcher is passed the dispatcher label. */
c2f47e15 6011 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6012 {
c2f47e15 6013 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6014 rtx label_r = label_rtx (label);
6015
6016 /* Remove the dispatcher label from the list of non-local labels
6017 since the receiver labels have been added to it above. */
6018 remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels);
6019 return const0_rtx;
6020 }
6021 break;
6022
6023 case BUILT_IN_SETJMP_RECEIVER:
6024 /* __builtin_setjmp_receiver is passed the receiver label. */
c2f47e15 6025 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6026 {
c2f47e15 6027 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6028 rtx label_r = label_rtx (label);
6029
6030 expand_builtin_setjmp_receiver (label_r);
6031 return const0_rtx;
6032 }
6b7f6858 6033 break;
53800dbe 6034
6035 /* __builtin_longjmp is passed a pointer to an array of five words.
6036 It's similar to the C library longjmp function but works with
6037 __builtin_setjmp above. */
6038 case BUILT_IN_LONGJMP:
c2f47e15 6039 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 6040 {
c2f47e15 6041 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
8ec3c5c2 6042 VOIDmode, EXPAND_NORMAL);
c2f47e15 6043 rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
53800dbe 6044
6045 if (value != const1_rtx)
6046 {
1e5fcbe2 6047 error ("%<__builtin_longjmp%> second argument must be 1");
53800dbe 6048 return const0_rtx;
6049 }
6050
6051 expand_builtin_longjmp (buf_addr, value);
6052 return const0_rtx;
6053 }
2c8a1497 6054 break;
53800dbe 6055
4ee9c684 6056 case BUILT_IN_NONLOCAL_GOTO:
c2f47e15 6057 target = expand_builtin_nonlocal_goto (exp);
4ee9c684 6058 if (target)
6059 return target;
6060 break;
6061
843d08a9 6062 /* This updates the setjmp buffer that is its argument with the value
6063 of the current stack pointer. */
6064 case BUILT_IN_UPDATE_SETJMP_BUF:
c2f47e15 6065 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
843d08a9 6066 {
6067 rtx buf_addr
c2f47e15 6068 = expand_normal (CALL_EXPR_ARG (exp, 0));
843d08a9 6069
6070 expand_builtin_update_setjmp_buf (buf_addr);
6071 return const0_rtx;
6072 }
6073 break;
6074
53800dbe 6075 case BUILT_IN_TRAP:
a0ef1725 6076 expand_builtin_trap ();
53800dbe 6077 return const0_rtx;
6078
d2b48f0c 6079 case BUILT_IN_UNREACHABLE:
6080 expand_builtin_unreachable ();
6081 return const0_rtx;
6082
4f35b1fc 6083 CASE_FLT_FN (BUILT_IN_SIGNBIT):
004e23c4 6084 case BUILT_IN_SIGNBITD32:
6085 case BUILT_IN_SIGNBITD64:
6086 case BUILT_IN_SIGNBITD128:
27f261ef 6087 target = expand_builtin_signbit (exp, target);
6088 if (target)
6089 return target;
6090 break;
6091
53800dbe 6092 /* Various hooks for the DWARF 2 __throw routine. */
6093 case BUILT_IN_UNWIND_INIT:
6094 expand_builtin_unwind_init ();
6095 return const0_rtx;
6096 case BUILT_IN_DWARF_CFA:
6097 return virtual_cfa_rtx;
6098#ifdef DWARF2_UNWIND_INFO
f8f023a5 6099 case BUILT_IN_DWARF_SP_COLUMN:
6100 return expand_builtin_dwarf_sp_column ();
695e919b 6101 case BUILT_IN_INIT_DWARF_REG_SIZES:
c2f47e15 6102 expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
695e919b 6103 return const0_rtx;
53800dbe 6104#endif
6105 case BUILT_IN_FROB_RETURN_ADDR:
c2f47e15 6106 return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6107 case BUILT_IN_EXTRACT_RETURN_ADDR:
c2f47e15 6108 return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6109 case BUILT_IN_EH_RETURN:
c2f47e15 6110 expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
6111 CALL_EXPR_ARG (exp, 1));
53800dbe 6112 return const0_rtx;
df4b504c 6113#ifdef EH_RETURN_DATA_REGNO
6114 case BUILT_IN_EH_RETURN_DATA_REGNO:
c2f47e15 6115 return expand_builtin_eh_return_data_regno (exp);
df4b504c 6116#endif
26093bf4 6117 case BUILT_IN_EXTEND_POINTER:
c2f47e15 6118 return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
e38def9c 6119 case BUILT_IN_EH_POINTER:
6120 return expand_builtin_eh_pointer (exp);
6121 case BUILT_IN_EH_FILTER:
6122 return expand_builtin_eh_filter (exp);
6123 case BUILT_IN_EH_COPY_VALUES:
6124 return expand_builtin_eh_copy_values (exp);
26093bf4 6125
7ccc713a 6126 case BUILT_IN_VA_START:
c2f47e15 6127 return expand_builtin_va_start (exp);
a66c9326 6128 case BUILT_IN_VA_END:
c2f47e15 6129 return expand_builtin_va_end (exp);
a66c9326 6130 case BUILT_IN_VA_COPY:
c2f47e15 6131 return expand_builtin_va_copy (exp);
89cfe6e5 6132 case BUILT_IN_EXPECT:
c2f47e15 6133 return expand_builtin_expect (exp, target);
5e3608d8 6134 case BUILT_IN_PREFETCH:
c2f47e15 6135 expand_builtin_prefetch (exp);
5e3608d8 6136 return const0_rtx;
6137
4ee9c684 6138 case BUILT_IN_PROFILE_FUNC_ENTER:
6139 return expand_builtin_profile_func (false);
6140 case BUILT_IN_PROFILE_FUNC_EXIT:
6141 return expand_builtin_profile_func (true);
6142
6143 case BUILT_IN_INIT_TRAMPOLINE:
c2f47e15 6144 return expand_builtin_init_trampoline (exp);
4ee9c684 6145 case BUILT_IN_ADJUST_TRAMPOLINE:
c2f47e15 6146 return expand_builtin_adjust_trampoline (exp);
4ee9c684 6147
73673831 6148 case BUILT_IN_FORK:
6149 case BUILT_IN_EXECL:
6150 case BUILT_IN_EXECV:
6151 case BUILT_IN_EXECLP:
6152 case BUILT_IN_EXECLE:
6153 case BUILT_IN_EXECVP:
6154 case BUILT_IN_EXECVE:
c2f47e15 6155 target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
73673831 6156 if (target)
6157 return target;
6158 break;
53800dbe 6159
b6a5fc45 6160 case BUILT_IN_FETCH_AND_ADD_1:
6161 case BUILT_IN_FETCH_AND_ADD_2:
6162 case BUILT_IN_FETCH_AND_ADD_4:
6163 case BUILT_IN_FETCH_AND_ADD_8:
27213ba3 6164 case BUILT_IN_FETCH_AND_ADD_16:
3e272de8 6165 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_ADD_1);
c2f47e15 6166 target = expand_builtin_sync_operation (mode, exp, PLUS,
b6a5fc45 6167 false, target, ignore);
6168 if (target)
6169 return target;
6170 break;
6171
6172 case BUILT_IN_FETCH_AND_SUB_1:
6173 case BUILT_IN_FETCH_AND_SUB_2:
6174 case BUILT_IN_FETCH_AND_SUB_4:
6175 case BUILT_IN_FETCH_AND_SUB_8:
27213ba3 6176 case BUILT_IN_FETCH_AND_SUB_16:
3e272de8 6177 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_SUB_1);
c2f47e15 6178 target = expand_builtin_sync_operation (mode, exp, MINUS,
b6a5fc45 6179 false, target, ignore);
6180 if (target)
6181 return target;
6182 break;
6183
6184 case BUILT_IN_FETCH_AND_OR_1:
6185 case BUILT_IN_FETCH_AND_OR_2:
6186 case BUILT_IN_FETCH_AND_OR_4:
6187 case BUILT_IN_FETCH_AND_OR_8:
27213ba3 6188 case BUILT_IN_FETCH_AND_OR_16:
3e272de8 6189 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_OR_1);
c2f47e15 6190 target = expand_builtin_sync_operation (mode, exp, IOR,
b6a5fc45 6191 false, target, ignore);
6192 if (target)
6193 return target;
6194 break;
6195
6196 case BUILT_IN_FETCH_AND_AND_1:
6197 case BUILT_IN_FETCH_AND_AND_2:
6198 case BUILT_IN_FETCH_AND_AND_4:
6199 case BUILT_IN_FETCH_AND_AND_8:
27213ba3 6200 case BUILT_IN_FETCH_AND_AND_16:
3e272de8 6201 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_AND_1);
c2f47e15 6202 target = expand_builtin_sync_operation (mode, exp, AND,
b6a5fc45 6203 false, target, ignore);
6204 if (target)
6205 return target;
6206 break;
6207
6208 case BUILT_IN_FETCH_AND_XOR_1:
6209 case BUILT_IN_FETCH_AND_XOR_2:
6210 case BUILT_IN_FETCH_AND_XOR_4:
6211 case BUILT_IN_FETCH_AND_XOR_8:
27213ba3 6212 case BUILT_IN_FETCH_AND_XOR_16:
3e272de8 6213 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_XOR_1);
c2f47e15 6214 target = expand_builtin_sync_operation (mode, exp, XOR,
b6a5fc45 6215 false, target, ignore);
6216 if (target)
6217 return target;
6218 break;
6219
6220 case BUILT_IN_FETCH_AND_NAND_1:
6221 case BUILT_IN_FETCH_AND_NAND_2:
6222 case BUILT_IN_FETCH_AND_NAND_4:
6223 case BUILT_IN_FETCH_AND_NAND_8:
27213ba3 6224 case BUILT_IN_FETCH_AND_NAND_16:
3e272de8 6225 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_NAND_1);
c2f47e15 6226 target = expand_builtin_sync_operation (mode, exp, NOT,
b6a5fc45 6227 false, target, ignore);
6228 if (target)
6229 return target;
6230 break;
6231
6232 case BUILT_IN_ADD_AND_FETCH_1:
6233 case BUILT_IN_ADD_AND_FETCH_2:
6234 case BUILT_IN_ADD_AND_FETCH_4:
6235 case BUILT_IN_ADD_AND_FETCH_8:
27213ba3 6236 case BUILT_IN_ADD_AND_FETCH_16:
3e272de8 6237 mode = get_builtin_sync_mode (fcode - BUILT_IN_ADD_AND_FETCH_1);
c2f47e15 6238 target = expand_builtin_sync_operation (mode, exp, PLUS,
b6a5fc45 6239 true, target, ignore);
6240 if (target)
6241 return target;
6242 break;
6243
6244 case BUILT_IN_SUB_AND_FETCH_1:
6245 case BUILT_IN_SUB_AND_FETCH_2:
6246 case BUILT_IN_SUB_AND_FETCH_4:
6247 case BUILT_IN_SUB_AND_FETCH_8:
27213ba3 6248 case BUILT_IN_SUB_AND_FETCH_16:
3e272de8 6249 mode = get_builtin_sync_mode (fcode - BUILT_IN_SUB_AND_FETCH_1);
c2f47e15 6250 target = expand_builtin_sync_operation (mode, exp, MINUS,
b6a5fc45 6251 true, target, ignore);
6252 if (target)
6253 return target;
6254 break;
6255
6256 case BUILT_IN_OR_AND_FETCH_1:
6257 case BUILT_IN_OR_AND_FETCH_2:
6258 case BUILT_IN_OR_AND_FETCH_4:
6259 case BUILT_IN_OR_AND_FETCH_8:
27213ba3 6260 case BUILT_IN_OR_AND_FETCH_16:
3e272de8 6261 mode = get_builtin_sync_mode (fcode - BUILT_IN_OR_AND_FETCH_1);
c2f47e15 6262 target = expand_builtin_sync_operation (mode, exp, IOR,
b6a5fc45 6263 true, target, ignore);
6264 if (target)
6265 return target;
6266 break;
6267
6268 case BUILT_IN_AND_AND_FETCH_1:
6269 case BUILT_IN_AND_AND_FETCH_2:
6270 case BUILT_IN_AND_AND_FETCH_4:
6271 case BUILT_IN_AND_AND_FETCH_8:
27213ba3 6272 case BUILT_IN_AND_AND_FETCH_16:
3e272de8 6273 mode = get_builtin_sync_mode (fcode - BUILT_IN_AND_AND_FETCH_1);
c2f47e15 6274 target = expand_builtin_sync_operation (mode, exp, AND,
b6a5fc45 6275 true, target, ignore);
6276 if (target)
6277 return target;
6278 break;
6279
6280 case BUILT_IN_XOR_AND_FETCH_1:
6281 case BUILT_IN_XOR_AND_FETCH_2:
6282 case BUILT_IN_XOR_AND_FETCH_4:
6283 case BUILT_IN_XOR_AND_FETCH_8:
27213ba3 6284 case BUILT_IN_XOR_AND_FETCH_16:
3e272de8 6285 mode = get_builtin_sync_mode (fcode - BUILT_IN_XOR_AND_FETCH_1);
c2f47e15 6286 target = expand_builtin_sync_operation (mode, exp, XOR,
b6a5fc45 6287 true, target, ignore);
6288 if (target)
6289 return target;
6290 break;
6291
6292 case BUILT_IN_NAND_AND_FETCH_1:
6293 case BUILT_IN_NAND_AND_FETCH_2:
6294 case BUILT_IN_NAND_AND_FETCH_4:
6295 case BUILT_IN_NAND_AND_FETCH_8:
27213ba3 6296 case BUILT_IN_NAND_AND_FETCH_16:
3e272de8 6297 mode = get_builtin_sync_mode (fcode - BUILT_IN_NAND_AND_FETCH_1);
c2f47e15 6298 target = expand_builtin_sync_operation (mode, exp, NOT,
b6a5fc45 6299 true, target, ignore);
6300 if (target)
6301 return target;
6302 break;
6303
6304 case BUILT_IN_BOOL_COMPARE_AND_SWAP_1:
6305 case BUILT_IN_BOOL_COMPARE_AND_SWAP_2:
6306 case BUILT_IN_BOOL_COMPARE_AND_SWAP_4:
6307 case BUILT_IN_BOOL_COMPARE_AND_SWAP_8:
27213ba3 6308 case BUILT_IN_BOOL_COMPARE_AND_SWAP_16:
a601d32a 6309 if (mode == VOIDmode)
6310 mode = TYPE_MODE (boolean_type_node);
b6a5fc45 6311 if (!target || !register_operand (target, mode))
6312 target = gen_reg_rtx (mode);
3e272de8 6313
6314 mode = get_builtin_sync_mode (fcode - BUILT_IN_BOOL_COMPARE_AND_SWAP_1);
c2f47e15 6315 target = expand_builtin_compare_and_swap (mode, exp, true, target);
b6a5fc45 6316 if (target)
6317 return target;
6318 break;
6319
6320 case BUILT_IN_VAL_COMPARE_AND_SWAP_1:
6321 case BUILT_IN_VAL_COMPARE_AND_SWAP_2:
6322 case BUILT_IN_VAL_COMPARE_AND_SWAP_4:
6323 case BUILT_IN_VAL_COMPARE_AND_SWAP_8:
27213ba3 6324 case BUILT_IN_VAL_COMPARE_AND_SWAP_16:
3e272de8 6325 mode = get_builtin_sync_mode (fcode - BUILT_IN_VAL_COMPARE_AND_SWAP_1);
c2f47e15 6326 target = expand_builtin_compare_and_swap (mode, exp, false, target);
b6a5fc45 6327 if (target)
6328 return target;
6329 break;
6330
6331 case BUILT_IN_LOCK_TEST_AND_SET_1:
6332 case BUILT_IN_LOCK_TEST_AND_SET_2:
6333 case BUILT_IN_LOCK_TEST_AND_SET_4:
6334 case BUILT_IN_LOCK_TEST_AND_SET_8:
27213ba3 6335 case BUILT_IN_LOCK_TEST_AND_SET_16:
3e272de8 6336 mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_TEST_AND_SET_1);
c2f47e15 6337 target = expand_builtin_lock_test_and_set (mode, exp, target);
b6a5fc45 6338 if (target)
6339 return target;
6340 break;
6341
6342 case BUILT_IN_LOCK_RELEASE_1:
6343 case BUILT_IN_LOCK_RELEASE_2:
6344 case BUILT_IN_LOCK_RELEASE_4:
6345 case BUILT_IN_LOCK_RELEASE_8:
27213ba3 6346 case BUILT_IN_LOCK_RELEASE_16:
3e272de8 6347 mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_RELEASE_1);
c2f47e15 6348 expand_builtin_lock_release (mode, exp);
b6a5fc45 6349 return const0_rtx;
6350
6351 case BUILT_IN_SYNCHRONIZE:
6352 expand_builtin_synchronize ();
6353 return const0_rtx;
6354
0a39fd54 6355 case BUILT_IN_OBJECT_SIZE:
6356 return expand_builtin_object_size (exp);
6357
6358 case BUILT_IN_MEMCPY_CHK:
6359 case BUILT_IN_MEMPCPY_CHK:
6360 case BUILT_IN_MEMMOVE_CHK:
6361 case BUILT_IN_MEMSET_CHK:
6362 target = expand_builtin_memory_chk (exp, target, mode, fcode);
6363 if (target)
6364 return target;
6365 break;
6366
6367 case BUILT_IN_STRCPY_CHK:
6368 case BUILT_IN_STPCPY_CHK:
6369 case BUILT_IN_STRNCPY_CHK:
6370 case BUILT_IN_STRCAT_CHK:
b356dfef 6371 case BUILT_IN_STRNCAT_CHK:
0a39fd54 6372 case BUILT_IN_SNPRINTF_CHK:
6373 case BUILT_IN_VSNPRINTF_CHK:
6374 maybe_emit_chk_warning (exp, fcode);
6375 break;
6376
6377 case BUILT_IN_SPRINTF_CHK:
6378 case BUILT_IN_VSPRINTF_CHK:
6379 maybe_emit_sprintf_chk_warning (exp, fcode);
6380 break;
6381
2c281b15 6382 case BUILT_IN_FREE:
6383 maybe_emit_free_warning (exp);
6384 break;
6385
92482ee0 6386 default: /* just do library call, if unknown builtin */
146c1b4f 6387 break;
53800dbe 6388 }
6389
6390 /* The switch statement above can drop through to cause the function
6391 to be called normally. */
6392 return expand_call (exp, target, ignore);
6393}
650e4c94 6394
805e22b2 6395/* Determine whether a tree node represents a call to a built-in
52203a9d 6396 function. If the tree T is a call to a built-in function with
6397 the right number of arguments of the appropriate types, return
6398 the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
6399 Otherwise the return value is END_BUILTINS. */
aecda0d6 6400
805e22b2 6401enum built_in_function
b7bf20db 6402builtin_mathfn_code (const_tree t)
805e22b2 6403{
b7bf20db 6404 const_tree fndecl, arg, parmlist;
6405 const_tree argtype, parmtype;
6406 const_call_expr_arg_iterator iter;
805e22b2 6407
6408 if (TREE_CODE (t) != CALL_EXPR
c2f47e15 6409 || TREE_CODE (CALL_EXPR_FN (t)) != ADDR_EXPR)
805e22b2 6410 return END_BUILTINS;
6411
c6e6ecb1 6412 fndecl = get_callee_fndecl (t);
6413 if (fndecl == NULL_TREE
52203a9d 6414 || TREE_CODE (fndecl) != FUNCTION_DECL
805e22b2 6415 || ! DECL_BUILT_IN (fndecl)
6416 || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
6417 return END_BUILTINS;
6418
52203a9d 6419 parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
b7bf20db 6420 init_const_call_expr_arg_iterator (t, &iter);
52203a9d 6421 for (; parmlist; parmlist = TREE_CHAIN (parmlist))
e9f80ff5 6422 {
52203a9d 6423 /* If a function doesn't take a variable number of arguments,
6424 the last element in the list will have type `void'. */
6425 parmtype = TREE_VALUE (parmlist);
6426 if (VOID_TYPE_P (parmtype))
6427 {
b7bf20db 6428 if (more_const_call_expr_args_p (&iter))
52203a9d 6429 return END_BUILTINS;
6430 return DECL_FUNCTION_CODE (fndecl);
6431 }
6432
b7bf20db 6433 if (! more_const_call_expr_args_p (&iter))
e9f80ff5 6434 return END_BUILTINS;
48e1416a 6435
b7bf20db 6436 arg = next_const_call_expr_arg (&iter);
c2f47e15 6437 argtype = TREE_TYPE (arg);
52203a9d 6438
6439 if (SCALAR_FLOAT_TYPE_P (parmtype))
6440 {
6441 if (! SCALAR_FLOAT_TYPE_P (argtype))
6442 return END_BUILTINS;
6443 }
6444 else if (COMPLEX_FLOAT_TYPE_P (parmtype))
6445 {
6446 if (! COMPLEX_FLOAT_TYPE_P (argtype))
6447 return END_BUILTINS;
6448 }
6449 else if (POINTER_TYPE_P (parmtype))
6450 {
6451 if (! POINTER_TYPE_P (argtype))
6452 return END_BUILTINS;
6453 }
6454 else if (INTEGRAL_TYPE_P (parmtype))
6455 {
6456 if (! INTEGRAL_TYPE_P (argtype))
6457 return END_BUILTINS;
6458 }
6459 else
e9f80ff5 6460 return END_BUILTINS;
e9f80ff5 6461 }
6462
52203a9d 6463 /* Variable-length argument list. */
805e22b2 6464 return DECL_FUNCTION_CODE (fndecl);
6465}
6466
c2f47e15 6467/* Fold a call to __builtin_constant_p, if we know its argument ARG will
6468 evaluate to a constant. */
650e4c94 6469
6470static tree
c2f47e15 6471fold_builtin_constant_p (tree arg)
650e4c94 6472{
650e4c94 6473 /* We return 1 for a numeric type that's known to be a constant
6474 value at compile-time or for an aggregate type that's a
6475 literal constant. */
c2f47e15 6476 STRIP_NOPS (arg);
650e4c94 6477
6478 /* If we know this is a constant, emit the constant of one. */
c2f47e15 6479 if (CONSTANT_CLASS_P (arg)
6480 || (TREE_CODE (arg) == CONSTRUCTOR
6481 && TREE_CONSTANT (arg)))
650e4c94 6482 return integer_one_node;
c2f47e15 6483 if (TREE_CODE (arg) == ADDR_EXPR)
adcfa3a3 6484 {
c2f47e15 6485 tree op = TREE_OPERAND (arg, 0);
adcfa3a3 6486 if (TREE_CODE (op) == STRING_CST
6487 || (TREE_CODE (op) == ARRAY_REF
6488 && integer_zerop (TREE_OPERAND (op, 1))
6489 && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
6490 return integer_one_node;
6491 }
650e4c94 6492
1fb4300c 6493 /* If this expression has side effects, show we don't know it to be a
6494 constant. Likewise if it's a pointer or aggregate type since in
6495 those case we only want literals, since those are only optimized
f97c71a1 6496 when generating RTL, not later.
6497 And finally, if we are compiling an initializer, not code, we
6498 need to return a definite result now; there's not going to be any
6499 more optimization done. */
c2f47e15 6500 if (TREE_SIDE_EFFECTS (arg)
6501 || AGGREGATE_TYPE_P (TREE_TYPE (arg))
6502 || POINTER_TYPE_P (TREE_TYPE (arg))
47be647d 6503 || cfun == 0
6504 || folding_initializer)
650e4c94 6505 return integer_zero_node;
6506
c2f47e15 6507 return NULL_TREE;
650e4c94 6508}
6509
76f5a783 6510/* Create builtin_expect with PRED and EXPECTED as its arguments and
6511 return it as a truthvalue. */
4ee9c684 6512
6513static tree
389dd41b 6514build_builtin_expect_predicate (location_t loc, tree pred, tree expected)
4ee9c684 6515{
76f5a783 6516 tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
4ee9c684 6517
76f5a783 6518 fn = built_in_decls[BUILT_IN_EXPECT];
6519 arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
6520 ret_type = TREE_TYPE (TREE_TYPE (fn));
6521 pred_type = TREE_VALUE (arg_types);
6522 expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
6523
389dd41b 6524 pred = fold_convert_loc (loc, pred_type, pred);
6525 expected = fold_convert_loc (loc, expected_type, expected);
6526 call_expr = build_call_expr_loc (loc, fn, 2, pred, expected);
76f5a783 6527
6528 return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
6529 build_int_cst (ret_type, 0));
6530}
6531
6532/* Fold a call to builtin_expect with arguments ARG0 and ARG1. Return
6533 NULL_TREE if no simplification is possible. */
6534
6535static tree
389dd41b 6536fold_builtin_expect (location_t loc, tree arg0, tree arg1)
76f5a783 6537{
6538 tree inner, fndecl;
6539 enum tree_code code;
6540
6541 /* If this is a builtin_expect within a builtin_expect keep the
6542 inner one. See through a comparison against a constant. It
6543 might have been added to create a thruthvalue. */
6544 inner = arg0;
6545 if (COMPARISON_CLASS_P (inner)
6546 && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST)
6547 inner = TREE_OPERAND (inner, 0);
6548
6549 if (TREE_CODE (inner) == CALL_EXPR
6550 && (fndecl = get_callee_fndecl (inner))
6551 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
6552 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT)
6553 return arg0;
6554
6555 /* Distribute the expected value over short-circuiting operators.
6556 See through the cast from truthvalue_type_node to long. */
6557 inner = arg0;
6558 while (TREE_CODE (inner) == NOP_EXPR
6559 && INTEGRAL_TYPE_P (TREE_TYPE (inner))
6560 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner, 0))))
6561 inner = TREE_OPERAND (inner, 0);
6562
6563 code = TREE_CODE (inner);
6564 if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
6565 {
6566 tree op0 = TREE_OPERAND (inner, 0);
6567 tree op1 = TREE_OPERAND (inner, 1);
6568
389dd41b 6569 op0 = build_builtin_expect_predicate (loc, op0, arg1);
6570 op1 = build_builtin_expect_predicate (loc, op1, arg1);
76f5a783 6571 inner = build2 (code, TREE_TYPE (inner), op0, op1);
6572
389dd41b 6573 return fold_convert_loc (loc, TREE_TYPE (arg0), inner);
76f5a783 6574 }
6575
6576 /* If the argument isn't invariant then there's nothing else we can do. */
c7d4e749 6577 if (!TREE_CONSTANT (arg0))
c2f47e15 6578 return NULL_TREE;
4ee9c684 6579
76f5a783 6580 /* If we expect that a comparison against the argument will fold to
6581 a constant return the constant. In practice, this means a true
6582 constant or the address of a non-weak symbol. */
6583 inner = arg0;
4ee9c684 6584 STRIP_NOPS (inner);
6585 if (TREE_CODE (inner) == ADDR_EXPR)
6586 {
6587 do
6588 {
6589 inner = TREE_OPERAND (inner, 0);
6590 }
6591 while (TREE_CODE (inner) == COMPONENT_REF
6592 || TREE_CODE (inner) == ARRAY_REF);
062b4460 6593 if ((TREE_CODE (inner) == VAR_DECL
6594 || TREE_CODE (inner) == FUNCTION_DECL)
6595 && DECL_WEAK (inner))
c2f47e15 6596 return NULL_TREE;
4ee9c684 6597 }
6598
76f5a783 6599 /* Otherwise, ARG0 already has the proper type for the return value. */
6600 return arg0;
4ee9c684 6601}
6602
c2f47e15 6603/* Fold a call to __builtin_classify_type with argument ARG. */
27d0c333 6604
539a3a92 6605static tree
c2f47e15 6606fold_builtin_classify_type (tree arg)
539a3a92 6607{
c2f47e15 6608 if (arg == 0)
7016c612 6609 return build_int_cst (NULL_TREE, no_type_class);
539a3a92 6610
c2f47e15 6611 return build_int_cst (NULL_TREE, type_to_class (TREE_TYPE (arg)));
539a3a92 6612}
6613
c2f47e15 6614/* Fold a call to __builtin_strlen with argument ARG. */
e6e27594 6615
6616static tree
389dd41b 6617fold_builtin_strlen (location_t loc, tree arg)
e6e27594 6618{
c2f47e15 6619 if (!validate_arg (arg, POINTER_TYPE))
e6e27594 6620 return NULL_TREE;
6621 else
6622 {
c2f47e15 6623 tree len = c_strlen (arg, 0);
e6e27594 6624
6625 if (len)
6626 {
6627 /* Convert from the internal "sizetype" type to "size_t". */
6628 if (size_type_node)
389dd41b 6629 len = fold_convert_loc (loc, size_type_node, len);
e6e27594 6630 return len;
6631 }
6632
6633 return NULL_TREE;
6634 }
6635}
6636
92c43e3c 6637/* Fold a call to __builtin_inf or __builtin_huge_val. */
6638
6639static tree
389dd41b 6640fold_builtin_inf (location_t loc, tree type, int warn)
92c43e3c 6641{
aa870c1b 6642 REAL_VALUE_TYPE real;
6643
40f4dbd5 6644 /* __builtin_inff is intended to be usable to define INFINITY on all
6645 targets. If an infinity is not available, INFINITY expands "to a
6646 positive constant of type float that overflows at translation
6647 time", footnote "In this case, using INFINITY will violate the
6648 constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
6649 Thus we pedwarn to ensure this constraint violation is
6650 diagnosed. */
92c43e3c 6651 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
389dd41b 6652 pedwarn (loc, 0, "target format does not support infinity");
92c43e3c 6653
aa870c1b 6654 real_inf (&real);
6655 return build_real (type, real);
92c43e3c 6656}
6657
c2f47e15 6658/* Fold a call to __builtin_nan or __builtin_nans with argument ARG. */
b0db7939 6659
6660static tree
c2f47e15 6661fold_builtin_nan (tree arg, tree type, int quiet)
b0db7939 6662{
6663 REAL_VALUE_TYPE real;
6664 const char *str;
6665
c2f47e15 6666 if (!validate_arg (arg, POINTER_TYPE))
6667 return NULL_TREE;
6668 str = c_getstr (arg);
b0db7939 6669 if (!str)
c2f47e15 6670 return NULL_TREE;
b0db7939 6671
6672 if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
c2f47e15 6673 return NULL_TREE;
b0db7939 6674
6675 return build_real (type, real);
6676}
6677
277f8dd2 6678/* Return true if the floating point expression T has an integer value.
6679 We also allow +Inf, -Inf and NaN to be considered integer values. */
6680
6681static bool
6682integer_valued_real_p (tree t)
6683{
6684 switch (TREE_CODE (t))
6685 {
6686 case FLOAT_EXPR:
6687 return true;
6688
6689 case ABS_EXPR:
6690 case SAVE_EXPR:
277f8dd2 6691 return integer_valued_real_p (TREE_OPERAND (t, 0));
6692
6693 case COMPOUND_EXPR:
41076ef6 6694 case MODIFY_EXPR:
277f8dd2 6695 case BIND_EXPR:
75a70cf9 6696 return integer_valued_real_p (TREE_OPERAND (t, 1));
277f8dd2 6697
6698 case PLUS_EXPR:
6699 case MINUS_EXPR:
6700 case MULT_EXPR:
6701 case MIN_EXPR:
6702 case MAX_EXPR:
6703 return integer_valued_real_p (TREE_OPERAND (t, 0))
6704 && integer_valued_real_p (TREE_OPERAND (t, 1));
6705
6706 case COND_EXPR:
6707 return integer_valued_real_p (TREE_OPERAND (t, 1))
6708 && integer_valued_real_p (TREE_OPERAND (t, 2));
6709
6710 case REAL_CST:
0570334c 6711 return real_isinteger (TREE_REAL_CST_PTR (t), TYPE_MODE (TREE_TYPE (t)));
277f8dd2 6712
6713 case NOP_EXPR:
6714 {
6715 tree type = TREE_TYPE (TREE_OPERAND (t, 0));
6716 if (TREE_CODE (type) == INTEGER_TYPE)
6717 return true;
6718 if (TREE_CODE (type) == REAL_TYPE)
6719 return integer_valued_real_p (TREE_OPERAND (t, 0));
6720 break;
6721 }
6722
6723 case CALL_EXPR:
6724 switch (builtin_mathfn_code (t))
6725 {
4f35b1fc 6726 CASE_FLT_FN (BUILT_IN_CEIL):
6727 CASE_FLT_FN (BUILT_IN_FLOOR):
6728 CASE_FLT_FN (BUILT_IN_NEARBYINT):
6729 CASE_FLT_FN (BUILT_IN_RINT):
6730 CASE_FLT_FN (BUILT_IN_ROUND):
6731 CASE_FLT_FN (BUILT_IN_TRUNC):
277f8dd2 6732 return true;
6733
d4a43a03 6734 CASE_FLT_FN (BUILT_IN_FMIN):
6735 CASE_FLT_FN (BUILT_IN_FMAX):
c2f47e15 6736 return integer_valued_real_p (CALL_EXPR_ARG (t, 0))
6737 && integer_valued_real_p (CALL_EXPR_ARG (t, 1));
d4a43a03 6738
277f8dd2 6739 default:
6740 break;
6741 }
6742 break;
6743
6744 default:
6745 break;
6746 }
6747 return false;
6748}
6749
c2f47e15 6750/* FNDECL is assumed to be a builtin where truncation can be propagated
6528f4f4 6751 across (for instance floor((double)f) == (double)floorf (f).
c2f47e15 6752 Do the transformation for a call with argument ARG. */
277f8dd2 6753
6528f4f4 6754static tree
389dd41b 6755fold_trunc_transparent_mathfn (location_t loc, tree fndecl, tree arg)
6528f4f4 6756{
6528f4f4 6757 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
277f8dd2 6758
c2f47e15 6759 if (!validate_arg (arg, REAL_TYPE))
6760 return NULL_TREE;
6528f4f4 6761
277f8dd2 6762 /* Integer rounding functions are idempotent. */
6763 if (fcode == builtin_mathfn_code (arg))
6764 return arg;
6765
6766 /* If argument is already integer valued, and we don't need to worry
6767 about setting errno, there's no need to perform rounding. */
6768 if (! flag_errno_math && integer_valued_real_p (arg))
6769 return arg;
6770
6771 if (optimize)
6528f4f4 6772 {
277f8dd2 6773 tree arg0 = strip_float_extensions (arg);
2426241c 6774 tree ftype = TREE_TYPE (TREE_TYPE (fndecl));
6528f4f4 6775 tree newtype = TREE_TYPE (arg0);
6776 tree decl;
6777
6778 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
6779 && (decl = mathfn_built_in (newtype, fcode)))
389dd41b 6780 return fold_convert_loc (loc, ftype,
6781 build_call_expr_loc (loc, decl, 1,
6782 fold_convert_loc (loc,
6783 newtype,
6784 arg0)));
6528f4f4 6785 }
c2f47e15 6786 return NULL_TREE;
6528f4f4 6787}
6788
c2f47e15 6789/* FNDECL is assumed to be builtin which can narrow the FP type of
6790 the argument, for instance lround((double)f) -> lroundf (f).
6791 Do the transformation for a call with argument ARG. */
9ed65c7f 6792
6793static tree
389dd41b 6794fold_fixed_mathfn (location_t loc, tree fndecl, tree arg)
9ed65c7f 6795{
9ed65c7f 6796 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9ed65c7f 6797
c2f47e15 6798 if (!validate_arg (arg, REAL_TYPE))
6799 return NULL_TREE;
9ed65c7f 6800
6801 /* If argument is already integer valued, and we don't need to worry
6802 about setting errno, there's no need to perform rounding. */
6803 if (! flag_errno_math && integer_valued_real_p (arg))
389dd41b 6804 return fold_build1_loc (loc, FIX_TRUNC_EXPR,
6805 TREE_TYPE (TREE_TYPE (fndecl)), arg);
9ed65c7f 6806
6807 if (optimize)
6808 {
6809 tree ftype = TREE_TYPE (arg);
6810 tree arg0 = strip_float_extensions (arg);
6811 tree newtype = TREE_TYPE (arg0);
6812 tree decl;
6813
6814 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
6815 && (decl = mathfn_built_in (newtype, fcode)))
389dd41b 6816 return build_call_expr_loc (loc, decl, 1,
6817 fold_convert_loc (loc, newtype, arg0));
9ed65c7f 6818 }
73a0da56 6819
6820 /* Canonicalize llround (x) to lround (x) on LP64 targets where
6821 sizeof (long long) == sizeof (long). */
6822 if (TYPE_PRECISION (long_long_integer_type_node)
6823 == TYPE_PRECISION (long_integer_type_node))
6824 {
6825 tree newfn = NULL_TREE;
6826 switch (fcode)
6827 {
6828 CASE_FLT_FN (BUILT_IN_LLCEIL):
6829 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
6830 break;
6831
6832 CASE_FLT_FN (BUILT_IN_LLFLOOR):
6833 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
6834 break;
6835
6836 CASE_FLT_FN (BUILT_IN_LLROUND):
6837 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
6838 break;
6839
6840 CASE_FLT_FN (BUILT_IN_LLRINT):
6841 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
6842 break;
6843
6844 default:
6845 break;
6846 }
6847
6848 if (newfn)
6849 {
389dd41b 6850 tree newcall = build_call_expr_loc (loc, newfn, 1, arg);
6851 return fold_convert_loc (loc,
6852 TREE_TYPE (TREE_TYPE (fndecl)), newcall);
73a0da56 6853 }
6854 }
6855
c2f47e15 6856 return NULL_TREE;
9ed65c7f 6857}
6858
c2f47e15 6859/* Fold call to builtin cabs, cabsf or cabsl with argument ARG. TYPE is the
6860 return type. Return NULL_TREE if no simplification can be made. */
c63f4ad3 6861
6862static tree
389dd41b 6863fold_builtin_cabs (location_t loc, tree arg, tree type, tree fndecl)
c63f4ad3 6864{
c2f47e15 6865 tree res;
c63f4ad3 6866
b0ce8887 6867 if (!validate_arg (arg, COMPLEX_TYPE)
c63f4ad3 6868 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
6869 return NULL_TREE;
6870
b4725390 6871 /* Calculate the result when the argument is a constant. */
6872 if (TREE_CODE (arg) == COMPLEX_CST
6873 && (res = do_mpfr_arg2 (TREE_REALPART (arg), TREE_IMAGPART (arg),
6874 type, mpfr_hypot)))
6875 return res;
48e1416a 6876
1af0d139 6877 if (TREE_CODE (arg) == COMPLEX_EXPR)
6878 {
6879 tree real = TREE_OPERAND (arg, 0);
6880 tree imag = TREE_OPERAND (arg, 1);
48e1416a 6881
1af0d139 6882 /* If either part is zero, cabs is fabs of the other. */
6883 if (real_zerop (real))
389dd41b 6884 return fold_build1_loc (loc, ABS_EXPR, type, imag);
1af0d139 6885 if (real_zerop (imag))
389dd41b 6886 return fold_build1_loc (loc, ABS_EXPR, type, real);
1af0d139 6887
6888 /* cabs(x+xi) -> fabs(x)*sqrt(2). */
6889 if (flag_unsafe_math_optimizations
6890 && operand_equal_p (real, imag, OEP_PURE_SAME))
6891 {
2e7ca27b 6892 const REAL_VALUE_TYPE sqrt2_trunc
7910b2fb 6893 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
1af0d139 6894 STRIP_NOPS (real);
389dd41b 6895 return fold_build2_loc (loc, MULT_EXPR, type,
6896 fold_build1_loc (loc, ABS_EXPR, type, real),
2e7ca27b 6897 build_real (type, sqrt2_trunc));
1af0d139 6898 }
6899 }
c63f4ad3 6900
749891b2 6901 /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */
6902 if (TREE_CODE (arg) == NEGATE_EXPR
6903 || TREE_CODE (arg) == CONJ_EXPR)
389dd41b 6904 return build_call_expr_loc (loc, fndecl, 1, TREE_OPERAND (arg, 0));
749891b2 6905
7d3f6cc7 6906 /* Don't do this when optimizing for size. */
6907 if (flag_unsafe_math_optimizations
0bfd8d5c 6908 && optimize && optimize_function_for_speed_p (cfun))
c63f4ad3 6909 {
0da0dbfa 6910 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
c63f4ad3 6911
6912 if (sqrtfn != NULL_TREE)
6913 {
c2f47e15 6914 tree rpart, ipart, result;
c63f4ad3 6915
4ee9c684 6916 arg = builtin_save_expr (arg);
29a6518e 6917
389dd41b 6918 rpart = fold_build1_loc (loc, REALPART_EXPR, type, arg);
6919 ipart = fold_build1_loc (loc, IMAGPART_EXPR, type, arg);
c63f4ad3 6920
4ee9c684 6921 rpart = builtin_save_expr (rpart);
6922 ipart = builtin_save_expr (ipart);
c63f4ad3 6923
389dd41b 6924 result = fold_build2_loc (loc, PLUS_EXPR, type,
6925 fold_build2_loc (loc, MULT_EXPR, type,
49d00087 6926 rpart, rpart),
389dd41b 6927 fold_build2_loc (loc, MULT_EXPR, type,
49d00087 6928 ipart, ipart));
c63f4ad3 6929
389dd41b 6930 return build_call_expr_loc (loc, sqrtfn, 1, result);
c63f4ad3 6931 }
6932 }
6933
6934 return NULL_TREE;
6935}
6936
c2f47e15 6937/* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG.
6938 Return NULL_TREE if no simplification can be made. */
e6e27594 6939
6940static tree
389dd41b 6941fold_builtin_sqrt (location_t loc, tree arg, tree type)
e6e27594 6942{
6943
6944 enum built_in_function fcode;
b4e8ab0c 6945 tree res;
c2f47e15 6946
6947 if (!validate_arg (arg, REAL_TYPE))
e6e27594 6948 return NULL_TREE;
6949
b4e8ab0c 6950 /* Calculate the result when the argument is a constant. */
6951 if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
6952 return res;
48e1416a 6953
e6e27594 6954 /* Optimize sqrt(expN(x)) = expN(x*0.5). */
6955 fcode = builtin_mathfn_code (arg);
6956 if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
6957 {
c2f47e15 6958 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
389dd41b 6959 arg = fold_build2_loc (loc, MULT_EXPR, type,
c2f47e15 6960 CALL_EXPR_ARG (arg, 0),
49d00087 6961 build_real (type, dconsthalf));
389dd41b 6962 return build_call_expr_loc (loc, expfn, 1, arg);
e6e27594 6963 }
6964
6965 /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */
6966 if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
6967 {
6968 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
6969
6970 if (powfn)
6971 {
c2f47e15 6972 tree arg0 = CALL_EXPR_ARG (arg, 0);
e6e27594 6973 tree tree_root;
6974 /* The inner root was either sqrt or cbrt. */
57510da6 6975 /* This was a conditional expression but it triggered a bug
18381619 6976 in Sun C 5.5. */
ce6cd837 6977 REAL_VALUE_TYPE dconstroot;
6978 if (BUILTIN_SQRT_P (fcode))
6979 dconstroot = dconsthalf;
6980 else
6981 dconstroot = dconst_third ();
e6e27594 6982
6983 /* Adjust for the outer root. */
6984 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
6985 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
6986 tree_root = build_real (type, dconstroot);
389dd41b 6987 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
e6e27594 6988 }
6989 }
6990
bc33117f 6991 /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
e6e27594 6992 if (flag_unsafe_math_optimizations
6993 && (fcode == BUILT_IN_POW
6994 || fcode == BUILT_IN_POWF
6995 || fcode == BUILT_IN_POWL))
6996 {
c2f47e15 6997 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
6998 tree arg0 = CALL_EXPR_ARG (arg, 0);
6999 tree arg1 = CALL_EXPR_ARG (arg, 1);
bc33117f 7000 tree narg1;
7001 if (!tree_expr_nonnegative_p (arg0))
7002 arg0 = build1 (ABS_EXPR, type, arg0);
389dd41b 7003 narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 7004 build_real (type, dconsthalf));
389dd41b 7005 return build_call_expr_loc (loc, powfn, 2, arg0, narg1);
e6e27594 7006 }
7007
7008 return NULL_TREE;
7009}
7010
c2f47e15 7011/* Fold a builtin function call to cbrt, cbrtf, or cbrtl with argument ARG.
7012 Return NULL_TREE if no simplification can be made. */
7013
e6e27594 7014static tree
389dd41b 7015fold_builtin_cbrt (location_t loc, tree arg, tree type)
e6e27594 7016{
e6e27594 7017 const enum built_in_function fcode = builtin_mathfn_code (arg);
29f4cd78 7018 tree res;
e6e27594 7019
c2f47e15 7020 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7021 return NULL_TREE;
7022
29f4cd78 7023 /* Calculate the result when the argument is a constant. */
7024 if ((res = do_mpfr_arg1 (arg, type, mpfr_cbrt, NULL, NULL, 0)))
7025 return res;
e6e27594 7026
cdfeb715 7027 if (flag_unsafe_math_optimizations)
e6e27594 7028 {
cdfeb715 7029 /* Optimize cbrt(expN(x)) -> expN(x/3). */
7030 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 7031 {
c2f47e15 7032 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7033 const REAL_VALUE_TYPE third_trunc =
7910b2fb 7034 real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 7035 arg = fold_build2_loc (loc, MULT_EXPR, type,
c2f47e15 7036 CALL_EXPR_ARG (arg, 0),
49d00087 7037 build_real (type, third_trunc));
389dd41b 7038 return build_call_expr_loc (loc, expfn, 1, arg);
cdfeb715 7039 }
e6e27594 7040
cdfeb715 7041 /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */
7042 if (BUILTIN_SQRT_P (fcode))
a0c938f0 7043 {
cdfeb715 7044 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
e6e27594 7045
cdfeb715 7046 if (powfn)
7047 {
c2f47e15 7048 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7049 tree tree_root;
7910b2fb 7050 REAL_VALUE_TYPE dconstroot = dconst_third ();
cdfeb715 7051
7052 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7053 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7054 tree_root = build_real (type, dconstroot);
389dd41b 7055 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
cdfeb715 7056 }
e6e27594 7057 }
7058
cdfeb715 7059 /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */
7060 if (BUILTIN_CBRT_P (fcode))
a0c938f0 7061 {
c2f47e15 7062 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7063 if (tree_expr_nonnegative_p (arg0))
7064 {
7065 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7066
7067 if (powfn)
a0c938f0 7068 {
cdfeb715 7069 tree tree_root;
7070 REAL_VALUE_TYPE dconstroot;
a0c938f0 7071
3fa759a9 7072 real_arithmetic (&dconstroot, MULT_EXPR,
7910b2fb 7073 dconst_third_ptr (), dconst_third_ptr ());
cdfeb715 7074 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7075 tree_root = build_real (type, dconstroot);
389dd41b 7076 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
cdfeb715 7077 }
7078 }
7079 }
a0c938f0 7080
cdfeb715 7081 /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */
48e1416a 7082 if (fcode == BUILT_IN_POW
c2f47e15 7083 || fcode == BUILT_IN_POWF
cdfeb715 7084 || fcode == BUILT_IN_POWL)
a0c938f0 7085 {
c2f47e15 7086 tree arg00 = CALL_EXPR_ARG (arg, 0);
7087 tree arg01 = CALL_EXPR_ARG (arg, 1);
cdfeb715 7088 if (tree_expr_nonnegative_p (arg00))
7089 {
c2f47e15 7090 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7091 const REAL_VALUE_TYPE dconstroot
7910b2fb 7092 = real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 7093 tree narg01 = fold_build2_loc (loc, MULT_EXPR, type, arg01,
49d00087 7094 build_real (type, dconstroot));
389dd41b 7095 return build_call_expr_loc (loc, powfn, 2, arg00, narg01);
cdfeb715 7096 }
7097 }
e6e27594 7098 }
7099 return NULL_TREE;
7100}
7101
c2f47e15 7102/* Fold function call to builtin cos, cosf, or cosl with argument ARG.
7103 TYPE is the type of the return value. Return NULL_TREE if no
7104 simplification can be made. */
7105
e6e27594 7106static tree
389dd41b 7107fold_builtin_cos (location_t loc,
7108 tree arg, tree type, tree fndecl)
e6e27594 7109{
e6ab33d8 7110 tree res, narg;
e6e27594 7111
c2f47e15 7112 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7113 return NULL_TREE;
7114
bffb7645 7115 /* Calculate the result when the argument is a constant. */
728bac60 7116 if ((res = do_mpfr_arg1 (arg, type, mpfr_cos, NULL, NULL, 0)))
bffb7645 7117 return res;
48e1416a 7118
e6e27594 7119 /* Optimize cos(-x) into cos (x). */
e6ab33d8 7120 if ((narg = fold_strip_sign_ops (arg)))
389dd41b 7121 return build_call_expr_loc (loc, fndecl, 1, narg);
e6e27594 7122
7123 return NULL_TREE;
7124}
7125
c2f47e15 7126/* Fold function call to builtin cosh, coshf, or coshl with argument ARG.
7127 Return NULL_TREE if no simplification can be made. */
7128
cacdc1af 7129static tree
389dd41b 7130fold_builtin_cosh (location_t loc, tree arg, tree type, tree fndecl)
cacdc1af 7131{
c2f47e15 7132 if (validate_arg (arg, REAL_TYPE))
cacdc1af 7133 {
cacdc1af 7134 tree res, narg;
7135
7136 /* Calculate the result when the argument is a constant. */
7137 if ((res = do_mpfr_arg1 (arg, type, mpfr_cosh, NULL, NULL, 0)))
7138 return res;
48e1416a 7139
cacdc1af 7140 /* Optimize cosh(-x) into cosh (x). */
7141 if ((narg = fold_strip_sign_ops (arg)))
389dd41b 7142 return build_call_expr_loc (loc, fndecl, 1, narg);
cacdc1af 7143 }
48e1416a 7144
cacdc1af 7145 return NULL_TREE;
7146}
7147
239d491a 7148/* Fold function call to builtin ccos (or ccosh if HYPER is TRUE) with
7149 argument ARG. TYPE is the type of the return value. Return
7150 NULL_TREE if no simplification can be made. */
7151
7152static tree
965d0f29 7153fold_builtin_ccos (location_t loc, tree arg, tree type, tree fndecl,
7154 bool hyper)
239d491a 7155{
7156 if (validate_arg (arg, COMPLEX_TYPE)
7157 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
7158 {
7159 tree tmp;
7160
239d491a 7161 /* Calculate the result when the argument is a constant. */
7162 if ((tmp = do_mpc_arg1 (arg, type, (hyper ? mpc_cosh : mpc_cos))))
7163 return tmp;
48e1416a 7164
239d491a 7165 /* Optimize fn(-x) into fn(x). */
7166 if ((tmp = fold_strip_sign_ops (arg)))
389dd41b 7167 return build_call_expr_loc (loc, fndecl, 1, tmp);
239d491a 7168 }
7169
7170 return NULL_TREE;
7171}
7172
c2f47e15 7173/* Fold function call to builtin tan, tanf, or tanl with argument ARG.
7174 Return NULL_TREE if no simplification can be made. */
7175
e6e27594 7176static tree
c2f47e15 7177fold_builtin_tan (tree arg, tree type)
e6e27594 7178{
7179 enum built_in_function fcode;
29f4cd78 7180 tree res;
e6e27594 7181
c2f47e15 7182 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7183 return NULL_TREE;
7184
bffb7645 7185 /* Calculate the result when the argument is a constant. */
728bac60 7186 if ((res = do_mpfr_arg1 (arg, type, mpfr_tan, NULL, NULL, 0)))
bffb7645 7187 return res;
48e1416a 7188
e6e27594 7189 /* Optimize tan(atan(x)) = x. */
7190 fcode = builtin_mathfn_code (arg);
7191 if (flag_unsafe_math_optimizations
7192 && (fcode == BUILT_IN_ATAN
7193 || fcode == BUILT_IN_ATANF
7194 || fcode == BUILT_IN_ATANL))
c2f47e15 7195 return CALL_EXPR_ARG (arg, 0);
e6e27594 7196
7197 return NULL_TREE;
7198}
7199
d735c391 7200/* Fold function call to builtin sincos, sincosf, or sincosl. Return
7201 NULL_TREE if no simplification can be made. */
7202
7203static tree
389dd41b 7204fold_builtin_sincos (location_t loc,
7205 tree arg0, tree arg1, tree arg2)
d735c391 7206{
c2f47e15 7207 tree type;
d735c391 7208 tree res, fn, call;
7209
c2f47e15 7210 if (!validate_arg (arg0, REAL_TYPE)
7211 || !validate_arg (arg1, POINTER_TYPE)
7212 || !validate_arg (arg2, POINTER_TYPE))
d735c391 7213 return NULL_TREE;
7214
d735c391 7215 type = TREE_TYPE (arg0);
d735c391 7216
7217 /* Calculate the result when the argument is a constant. */
7218 if ((res = do_mpfr_sincos (arg0, arg1, arg2)))
7219 return res;
7220
7221 /* Canonicalize sincos to cexpi. */
2a6b4c77 7222 if (!TARGET_C99_FUNCTIONS)
7223 return NULL_TREE;
d735c391 7224 fn = mathfn_built_in (type, BUILT_IN_CEXPI);
7225 if (!fn)
7226 return NULL_TREE;
7227
389dd41b 7228 call = build_call_expr_loc (loc, fn, 1, arg0);
d735c391 7229 call = builtin_save_expr (call);
7230
a75b1c71 7231 return build2 (COMPOUND_EXPR, void_type_node,
d735c391 7232 build2 (MODIFY_EXPR, void_type_node,
389dd41b 7233 build_fold_indirect_ref_loc (loc, arg1),
d735c391 7234 build1 (IMAGPART_EXPR, type, call)),
7235 build2 (MODIFY_EXPR, void_type_node,
389dd41b 7236 build_fold_indirect_ref_loc (loc, arg2),
d735c391 7237 build1 (REALPART_EXPR, type, call)));
7238}
7239
c5bb2c4b 7240/* Fold function call to builtin cexp, cexpf, or cexpl. Return
7241 NULL_TREE if no simplification can be made. */
7242
7243static tree
389dd41b 7244fold_builtin_cexp (location_t loc, tree arg0, tree type)
c5bb2c4b 7245{
c2f47e15 7246 tree rtype;
c5bb2c4b 7247 tree realp, imagp, ifn;
239d491a 7248 tree res;
c5bb2c4b 7249
239d491a 7250 if (!validate_arg (arg0, COMPLEX_TYPE)
b0ce8887 7251 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) != REAL_TYPE)
c5bb2c4b 7252 return NULL_TREE;
7253
239d491a 7254 /* Calculate the result when the argument is a constant. */
7255 if ((res = do_mpc_arg1 (arg0, type, mpc_exp)))
7256 return res;
48e1416a 7257
c5bb2c4b 7258 rtype = TREE_TYPE (TREE_TYPE (arg0));
7259
7260 /* In case we can figure out the real part of arg0 and it is constant zero
7261 fold to cexpi. */
2a6b4c77 7262 if (!TARGET_C99_FUNCTIONS)
7263 return NULL_TREE;
c5bb2c4b 7264 ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI);
7265 if (!ifn)
7266 return NULL_TREE;
7267
389dd41b 7268 if ((realp = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0))
c5bb2c4b 7269 && real_zerop (realp))
7270 {
389dd41b 7271 tree narg = fold_build1_loc (loc, IMAGPART_EXPR, rtype, arg0);
7272 return build_call_expr_loc (loc, ifn, 1, narg);
c5bb2c4b 7273 }
7274
7275 /* In case we can easily decompose real and imaginary parts split cexp
7276 to exp (r) * cexpi (i). */
7277 if (flag_unsafe_math_optimizations
7278 && realp)
7279 {
7280 tree rfn, rcall, icall;
7281
7282 rfn = mathfn_built_in (rtype, BUILT_IN_EXP);
7283 if (!rfn)
7284 return NULL_TREE;
7285
389dd41b 7286 imagp = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
c5bb2c4b 7287 if (!imagp)
7288 return NULL_TREE;
7289
389dd41b 7290 icall = build_call_expr_loc (loc, ifn, 1, imagp);
c5bb2c4b 7291 icall = builtin_save_expr (icall);
389dd41b 7292 rcall = build_call_expr_loc (loc, rfn, 1, realp);
c5bb2c4b 7293 rcall = builtin_save_expr (rcall);
389dd41b 7294 return fold_build2_loc (loc, COMPLEX_EXPR, type,
7295 fold_build2_loc (loc, MULT_EXPR, rtype,
71bf42bb 7296 rcall,
389dd41b 7297 fold_build1_loc (loc, REALPART_EXPR,
7298 rtype, icall)),
7299 fold_build2_loc (loc, MULT_EXPR, rtype,
71bf42bb 7300 rcall,
389dd41b 7301 fold_build1_loc (loc, IMAGPART_EXPR,
7302 rtype, icall)));
c5bb2c4b 7303 }
7304
7305 return NULL_TREE;
7306}
7307
c2f47e15 7308/* Fold function call to builtin trunc, truncf or truncl with argument ARG.
7309 Return NULL_TREE if no simplification can be made. */
277f8dd2 7310
7311static tree
389dd41b 7312fold_builtin_trunc (location_t loc, tree fndecl, tree arg)
277f8dd2 7313{
c2f47e15 7314 if (!validate_arg (arg, REAL_TYPE))
7315 return NULL_TREE;
277f8dd2 7316
7317 /* Optimize trunc of constant value. */
f96bd2bf 7318 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7319 {
7320 REAL_VALUE_TYPE r, x;
2426241c 7321 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7322
7323 x = TREE_REAL_CST (arg);
7324 real_trunc (&r, TYPE_MODE (type), &x);
7325 return build_real (type, r);
7326 }
7327
389dd41b 7328 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7329}
7330
c2f47e15 7331/* Fold function call to builtin floor, floorf or floorl with argument ARG.
7332 Return NULL_TREE if no simplification can be made. */
277f8dd2 7333
7334static tree
389dd41b 7335fold_builtin_floor (location_t loc, tree fndecl, tree arg)
277f8dd2 7336{
c2f47e15 7337 if (!validate_arg (arg, REAL_TYPE))
7338 return NULL_TREE;
277f8dd2 7339
7340 /* Optimize floor of constant value. */
f96bd2bf 7341 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7342 {
7343 REAL_VALUE_TYPE x;
7344
7345 x = TREE_REAL_CST (arg);
7346 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7347 {
2426241c 7348 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7349 REAL_VALUE_TYPE r;
7350
7351 real_floor (&r, TYPE_MODE (type), &x);
7352 return build_real (type, r);
7353 }
7354 }
7355
acc2b92e 7356 /* Fold floor (x) where x is nonnegative to trunc (x). */
7357 if (tree_expr_nonnegative_p (arg))
30fe8286 7358 {
7359 tree truncfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_TRUNC);
7360 if (truncfn)
389dd41b 7361 return build_call_expr_loc (loc, truncfn, 1, arg);
30fe8286 7362 }
acc2b92e 7363
389dd41b 7364 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7365}
7366
c2f47e15 7367/* Fold function call to builtin ceil, ceilf or ceill with argument ARG.
7368 Return NULL_TREE if no simplification can be made. */
277f8dd2 7369
7370static tree
389dd41b 7371fold_builtin_ceil (location_t loc, tree fndecl, tree arg)
277f8dd2 7372{
c2f47e15 7373 if (!validate_arg (arg, REAL_TYPE))
7374 return NULL_TREE;
277f8dd2 7375
7376 /* Optimize ceil of constant value. */
f96bd2bf 7377 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7378 {
7379 REAL_VALUE_TYPE x;
7380
7381 x = TREE_REAL_CST (arg);
7382 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7383 {
2426241c 7384 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7385 REAL_VALUE_TYPE r;
7386
7387 real_ceil (&r, TYPE_MODE (type), &x);
7388 return build_real (type, r);
7389 }
7390 }
7391
389dd41b 7392 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7393}
7394
c2f47e15 7395/* Fold function call to builtin round, roundf or roundl with argument ARG.
7396 Return NULL_TREE if no simplification can be made. */
89ab3887 7397
7398static tree
389dd41b 7399fold_builtin_round (location_t loc, tree fndecl, tree arg)
89ab3887 7400{
c2f47e15 7401 if (!validate_arg (arg, REAL_TYPE))
7402 return NULL_TREE;
89ab3887 7403
34f17811 7404 /* Optimize round of constant value. */
f96bd2bf 7405 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
89ab3887 7406 {
7407 REAL_VALUE_TYPE x;
7408
7409 x = TREE_REAL_CST (arg);
7410 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7411 {
2426241c 7412 tree type = TREE_TYPE (TREE_TYPE (fndecl));
89ab3887 7413 REAL_VALUE_TYPE r;
7414
7415 real_round (&r, TYPE_MODE (type), &x);
7416 return build_real (type, r);
7417 }
7418 }
7419
389dd41b 7420 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
89ab3887 7421}
7422
34f17811 7423/* Fold function call to builtin lround, lroundf or lroundl (or the
c2f47e15 7424 corresponding long long versions) and other rounding functions. ARG
7425 is the argument to the call. Return NULL_TREE if no simplification
7426 can be made. */
34f17811 7427
7428static tree
389dd41b 7429fold_builtin_int_roundingfn (location_t loc, tree fndecl, tree arg)
34f17811 7430{
c2f47e15 7431 if (!validate_arg (arg, REAL_TYPE))
7432 return NULL_TREE;
34f17811 7433
7434 /* Optimize lround of constant value. */
f96bd2bf 7435 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
34f17811 7436 {
7437 const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
7438
776a7bab 7439 if (real_isfinite (&x))
34f17811 7440 {
2426241c 7441 tree itype = TREE_TYPE (TREE_TYPE (fndecl));
ca9b061d 7442 tree ftype = TREE_TYPE (arg);
7443 unsigned HOST_WIDE_INT lo2;
34f17811 7444 HOST_WIDE_INT hi, lo;
7445 REAL_VALUE_TYPE r;
7446
ad52b9b7 7447 switch (DECL_FUNCTION_CODE (fndecl))
7448 {
4f35b1fc 7449 CASE_FLT_FN (BUILT_IN_LFLOOR):
7450 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 7451 real_floor (&r, TYPE_MODE (ftype), &x);
7452 break;
7453
4f35b1fc 7454 CASE_FLT_FN (BUILT_IN_LCEIL):
7455 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 7456 real_ceil (&r, TYPE_MODE (ftype), &x);
7457 break;
7458
4f35b1fc 7459 CASE_FLT_FN (BUILT_IN_LROUND):
7460 CASE_FLT_FN (BUILT_IN_LLROUND):
ad52b9b7 7461 real_round (&r, TYPE_MODE (ftype), &x);
7462 break;
7463
7464 default:
7465 gcc_unreachable ();
7466 }
7467
34f17811 7468 REAL_VALUE_TO_INT (&lo, &hi, r);
ca9b061d 7469 if (!fit_double_type (lo, hi, &lo2, &hi, itype))
7470 return build_int_cst_wide (itype, lo2, hi);
34f17811 7471 }
7472 }
7473
acc2b92e 7474 switch (DECL_FUNCTION_CODE (fndecl))
7475 {
7476 CASE_FLT_FN (BUILT_IN_LFLOOR):
7477 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7478 /* Fold lfloor (x) where x is nonnegative to FIX_TRUNC (x). */
7479 if (tree_expr_nonnegative_p (arg))
389dd41b 7480 return fold_build1_loc (loc, FIX_TRUNC_EXPR,
7481 TREE_TYPE (TREE_TYPE (fndecl)), arg);
acc2b92e 7482 break;
7483 default:;
7484 }
7485
389dd41b 7486 return fold_fixed_mathfn (loc, fndecl, arg);
34f17811 7487}
7488
70fb4c07 7489/* Fold function call to builtin ffs, clz, ctz, popcount and parity
c2f47e15 7490 and their long and long long variants (i.e. ffsl and ffsll). ARG is
7491 the argument to the call. Return NULL_TREE if no simplification can
7492 be made. */
70fb4c07 7493
7494static tree
c2f47e15 7495fold_builtin_bitop (tree fndecl, tree arg)
70fb4c07 7496{
c2f47e15 7497 if (!validate_arg (arg, INTEGER_TYPE))
70fb4c07 7498 return NULL_TREE;
7499
7500 /* Optimize for constant argument. */
f96bd2bf 7501 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
70fb4c07 7502 {
7503 HOST_WIDE_INT hi, width, result;
7504 unsigned HOST_WIDE_INT lo;
7c446c95 7505 tree type;
70fb4c07 7506
7507 type = TREE_TYPE (arg);
7508 width = TYPE_PRECISION (type);
7509 lo = TREE_INT_CST_LOW (arg);
7510
7511 /* Clear all the bits that are beyond the type's precision. */
7512 if (width > HOST_BITS_PER_WIDE_INT)
7513 {
7514 hi = TREE_INT_CST_HIGH (arg);
7515 if (width < 2 * HOST_BITS_PER_WIDE_INT)
7516 hi &= ~((HOST_WIDE_INT) (-1) >> (width - HOST_BITS_PER_WIDE_INT));
7517 }
7518 else
7519 {
7520 hi = 0;
7521 if (width < HOST_BITS_PER_WIDE_INT)
7522 lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
7523 }
7524
7525 switch (DECL_FUNCTION_CODE (fndecl))
7526 {
4f35b1fc 7527 CASE_INT_FN (BUILT_IN_FFS):
70fb4c07 7528 if (lo != 0)
7529 result = exact_log2 (lo & -lo) + 1;
7530 else if (hi != 0)
7531 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi) + 1;
7532 else
7533 result = 0;
7534 break;
7535
4f35b1fc 7536 CASE_INT_FN (BUILT_IN_CLZ):
70fb4c07 7537 if (hi != 0)
7538 result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
7539 else if (lo != 0)
7540 result = width - floor_log2 (lo) - 1;
7541 else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
7542 result = width;
7543 break;
7544
4f35b1fc 7545 CASE_INT_FN (BUILT_IN_CTZ):
70fb4c07 7546 if (lo != 0)
7547 result = exact_log2 (lo & -lo);
7548 else if (hi != 0)
7549 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi);
7550 else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
7551 result = width;
7552 break;
7553
4f35b1fc 7554 CASE_INT_FN (BUILT_IN_POPCOUNT):
70fb4c07 7555 result = 0;
7556 while (lo)
7557 result++, lo &= lo - 1;
7558 while (hi)
7559 result++, hi &= hi - 1;
7560 break;
7561
4f35b1fc 7562 CASE_INT_FN (BUILT_IN_PARITY):
70fb4c07 7563 result = 0;
7564 while (lo)
7565 result++, lo &= lo - 1;
7566 while (hi)
7567 result++, hi &= hi - 1;
7568 result &= 1;
7569 break;
7570
7571 default:
64db345d 7572 gcc_unreachable ();
70fb4c07 7573 }
7574
2426241c 7575 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
70fb4c07 7576 }
7577
7578 return NULL_TREE;
7579}
7580
42791117 7581/* Fold function call to builtin_bswap and the long and long long
7582 variants. Return NULL_TREE if no simplification can be made. */
7583static tree
c2f47e15 7584fold_builtin_bswap (tree fndecl, tree arg)
42791117 7585{
c2f47e15 7586 if (! validate_arg (arg, INTEGER_TYPE))
7587 return NULL_TREE;
42791117 7588
7589 /* Optimize constant value. */
f96bd2bf 7590 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
42791117 7591 {
7592 HOST_WIDE_INT hi, width, r_hi = 0;
7593 unsigned HOST_WIDE_INT lo, r_lo = 0;
7594 tree type;
7595
7596 type = TREE_TYPE (arg);
7597 width = TYPE_PRECISION (type);
7598 lo = TREE_INT_CST_LOW (arg);
7599 hi = TREE_INT_CST_HIGH (arg);
7600
7601 switch (DECL_FUNCTION_CODE (fndecl))
7602 {
7603 case BUILT_IN_BSWAP32:
7604 case BUILT_IN_BSWAP64:
7605 {
7606 int s;
7607
7608 for (s = 0; s < width; s += 8)
7609 {
7610 int d = width - s - 8;
7611 unsigned HOST_WIDE_INT byte;
7612
7613 if (s < HOST_BITS_PER_WIDE_INT)
7614 byte = (lo >> s) & 0xff;
7615 else
7616 byte = (hi >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff;
7617
7618 if (d < HOST_BITS_PER_WIDE_INT)
7619 r_lo |= byte << d;
7620 else
7621 r_hi |= byte << (d - HOST_BITS_PER_WIDE_INT);
7622 }
7623 }
7624
7625 break;
7626
7627 default:
7628 gcc_unreachable ();
7629 }
7630
7631 if (width < HOST_BITS_PER_WIDE_INT)
7632 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), r_lo);
7633 else
7634 return build_int_cst_wide (TREE_TYPE (TREE_TYPE (fndecl)), r_lo, r_hi);
7635 }
7636
7637 return NULL_TREE;
7638}
c2f47e15 7639
8918c507 7640/* A subroutine of fold_builtin to fold the various logarithmic
29f4cd78 7641 functions. Return NULL_TREE if no simplification can me made.
7642 FUNC is the corresponding MPFR logarithm function. */
8918c507 7643
7644static tree
389dd41b 7645fold_builtin_logarithm (location_t loc, tree fndecl, tree arg,
29f4cd78 7646 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 7647{
c2f47e15 7648 if (validate_arg (arg, REAL_TYPE))
8918c507 7649 {
8918c507 7650 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 7651 tree res;
8918c507 7652 const enum built_in_function fcode = builtin_mathfn_code (arg);
0862b7e9 7653
29f4cd78 7654 /* Calculate the result when the argument is a constant. */
7655 if ((res = do_mpfr_arg1 (arg, type, func, &dconst0, NULL, false)))
7656 return res;
7657
8918c507 7658 /* Special case, optimize logN(expN(x)) = x. */
7659 if (flag_unsafe_math_optimizations
29f4cd78 7660 && ((func == mpfr_log
8918c507 7661 && (fcode == BUILT_IN_EXP
7662 || fcode == BUILT_IN_EXPF
7663 || fcode == BUILT_IN_EXPL))
29f4cd78 7664 || (func == mpfr_log2
8918c507 7665 && (fcode == BUILT_IN_EXP2
7666 || fcode == BUILT_IN_EXP2F
7667 || fcode == BUILT_IN_EXP2L))
29f4cd78 7668 || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode)))))
389dd41b 7669 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
8918c507 7670
ca273d4a 7671 /* Optimize logN(func()) for various exponential functions. We
a0c938f0 7672 want to determine the value "x" and the power "exponent" in
7673 order to transform logN(x**exponent) into exponent*logN(x). */
8918c507 7674 if (flag_unsafe_math_optimizations)
a0c938f0 7675 {
8918c507 7676 tree exponent = 0, x = 0;
0862b7e9 7677
8918c507 7678 switch (fcode)
7679 {
4f35b1fc 7680 CASE_FLT_FN (BUILT_IN_EXP):
8918c507 7681 /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
48e1416a 7682 x = build_real (type, real_value_truncate (TYPE_MODE (type),
7910b2fb 7683 dconst_e ()));
c2f47e15 7684 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 7685 break;
4f35b1fc 7686 CASE_FLT_FN (BUILT_IN_EXP2):
8918c507 7687 /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */
7688 x = build_real (type, dconst2);
c2f47e15 7689 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 7690 break;
4f35b1fc 7691 CASE_FLT_FN (BUILT_IN_EXP10):
7692 CASE_FLT_FN (BUILT_IN_POW10):
8918c507 7693 /* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */
3fa759a9 7694 {
7695 REAL_VALUE_TYPE dconst10;
7696 real_from_integer (&dconst10, VOIDmode, 10, 0, 0);
7697 x = build_real (type, dconst10);
7698 }
c2f47e15 7699 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 7700 break;
4f35b1fc 7701 CASE_FLT_FN (BUILT_IN_SQRT):
8918c507 7702 /* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */
c2f47e15 7703 x = CALL_EXPR_ARG (arg, 0);
8918c507 7704 exponent = build_real (type, dconsthalf);
7705 break;
4f35b1fc 7706 CASE_FLT_FN (BUILT_IN_CBRT):
8918c507 7707 /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */
c2f47e15 7708 x = CALL_EXPR_ARG (arg, 0);
8918c507 7709 exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
7910b2fb 7710 dconst_third ()));
8918c507 7711 break;
4f35b1fc 7712 CASE_FLT_FN (BUILT_IN_POW):
8918c507 7713 /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x). */
c2f47e15 7714 x = CALL_EXPR_ARG (arg, 0);
7715 exponent = CALL_EXPR_ARG (arg, 1);
8918c507 7716 break;
7717 default:
7718 break;
7719 }
7720
7721 /* Now perform the optimization. */
7722 if (x && exponent)
7723 {
389dd41b 7724 tree logfn = build_call_expr_loc (loc, fndecl, 1, x);
7725 return fold_build2_loc (loc, MULT_EXPR, type, exponent, logfn);
8918c507 7726 }
7727 }
7728 }
7729
c2f47e15 7730 return NULL_TREE;
8918c507 7731}
0862b7e9 7732
f0c477f2 7733/* Fold a builtin function call to hypot, hypotf, or hypotl. Return
7734 NULL_TREE if no simplification can be made. */
7735
7736static tree
389dd41b 7737fold_builtin_hypot (location_t loc, tree fndecl,
7738 tree arg0, tree arg1, tree type)
f0c477f2 7739{
e6ab33d8 7740 tree res, narg0, narg1;
f0c477f2 7741
c2f47e15 7742 if (!validate_arg (arg0, REAL_TYPE)
7743 || !validate_arg (arg1, REAL_TYPE))
f0c477f2 7744 return NULL_TREE;
7745
7746 /* Calculate the result when the argument is a constant. */
7747 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot)))
7748 return res;
48e1416a 7749
6c95f21c 7750 /* If either argument to hypot has a negate or abs, strip that off.
7751 E.g. hypot(-x,fabs(y)) -> hypot(x,y). */
e6ab33d8 7752 narg0 = fold_strip_sign_ops (arg0);
7753 narg1 = fold_strip_sign_ops (arg1);
7754 if (narg0 || narg1)
7755 {
48e1416a 7756 return build_call_expr_loc (loc, fndecl, 2, narg0 ? narg0 : arg0,
c2f47e15 7757 narg1 ? narg1 : arg1);
6c95f21c 7758 }
48e1416a 7759
f0c477f2 7760 /* If either argument is zero, hypot is fabs of the other. */
7761 if (real_zerop (arg0))
389dd41b 7762 return fold_build1_loc (loc, ABS_EXPR, type, arg1);
f0c477f2 7763 else if (real_zerop (arg1))
389dd41b 7764 return fold_build1_loc (loc, ABS_EXPR, type, arg0);
48e1416a 7765
6c95f21c 7766 /* hypot(x,x) -> fabs(x)*sqrt(2). */
7767 if (flag_unsafe_math_optimizations
7768 && operand_equal_p (arg0, arg1, OEP_PURE_SAME))
f0c477f2 7769 {
2e7ca27b 7770 const REAL_VALUE_TYPE sqrt2_trunc
7910b2fb 7771 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
389dd41b 7772 return fold_build2_loc (loc, MULT_EXPR, type,
7773 fold_build1_loc (loc, ABS_EXPR, type, arg0),
2e7ca27b 7774 build_real (type, sqrt2_trunc));
f0c477f2 7775 }
7776
f0c477f2 7777 return NULL_TREE;
7778}
7779
7780
e6e27594 7781/* Fold a builtin function call to pow, powf, or powl. Return
7782 NULL_TREE if no simplification can be made. */
7783static tree
389dd41b 7784fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
e6e27594 7785{
f0c477f2 7786 tree res;
e6e27594 7787
c2f47e15 7788 if (!validate_arg (arg0, REAL_TYPE)
7789 || !validate_arg (arg1, REAL_TYPE))
e6e27594 7790 return NULL_TREE;
7791
f0c477f2 7792 /* Calculate the result when the argument is a constant. */
7793 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_pow)))
7794 return res;
7795
e6e27594 7796 /* Optimize pow(1.0,y) = 1.0. */
7797 if (real_onep (arg0))
389dd41b 7798 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
e6e27594 7799
7800 if (TREE_CODE (arg1) == REAL_CST
f96bd2bf 7801 && !TREE_OVERFLOW (arg1))
e6e27594 7802 {
198d9bbe 7803 REAL_VALUE_TYPE cint;
e6e27594 7804 REAL_VALUE_TYPE c;
198d9bbe 7805 HOST_WIDE_INT n;
7806
e6e27594 7807 c = TREE_REAL_CST (arg1);
7808
7809 /* Optimize pow(x,0.0) = 1.0. */
7810 if (REAL_VALUES_EQUAL (c, dconst0))
389dd41b 7811 return omit_one_operand_loc (loc, type, build_real (type, dconst1),
e6e27594 7812 arg0);
7813
7814 /* Optimize pow(x,1.0) = x. */
7815 if (REAL_VALUES_EQUAL (c, dconst1))
7816 return arg0;
7817
7818 /* Optimize pow(x,-1.0) = 1.0/x. */
7819 if (REAL_VALUES_EQUAL (c, dconstm1))
389dd41b 7820 return fold_build2_loc (loc, RDIV_EXPR, type,
49d00087 7821 build_real (type, dconst1), arg0);
e6e27594 7822
7823 /* Optimize pow(x,0.5) = sqrt(x). */
7824 if (flag_unsafe_math_optimizations
7825 && REAL_VALUES_EQUAL (c, dconsthalf))
7826 {
7827 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
7828
7829 if (sqrtfn != NULL_TREE)
389dd41b 7830 return build_call_expr_loc (loc, sqrtfn, 1, arg0);
e6e27594 7831 }
7832
feb5b3eb 7833 /* Optimize pow(x,1.0/3.0) = cbrt(x). */
7834 if (flag_unsafe_math_optimizations)
7835 {
7836 const REAL_VALUE_TYPE dconstroot
7910b2fb 7837 = real_value_truncate (TYPE_MODE (type), dconst_third ());
feb5b3eb 7838
7839 if (REAL_VALUES_EQUAL (c, dconstroot))
7840 {
7841 tree cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT);
7842 if (cbrtfn != NULL_TREE)
389dd41b 7843 return build_call_expr_loc (loc, cbrtfn, 1, arg0);
feb5b3eb 7844 }
7845 }
7846
198d9bbe 7847 /* Check for an integer exponent. */
7848 n = real_to_integer (&c);
7849 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
7850 if (real_identical (&c, &cint))
e6e27594 7851 {
a2b30b48 7852 /* Attempt to evaluate pow at compile-time, unless this should
7853 raise an exception. */
198d9bbe 7854 if (TREE_CODE (arg0) == REAL_CST
a2b30b48 7855 && !TREE_OVERFLOW (arg0)
7856 && (n > 0
7857 || (!flag_trapping_math && !flag_errno_math)
7858 || !REAL_VALUES_EQUAL (TREE_REAL_CST (arg0), dconst0)))
e6e27594 7859 {
7860 REAL_VALUE_TYPE x;
7861 bool inexact;
7862
7863 x = TREE_REAL_CST (arg0);
7864 inexact = real_powi (&x, TYPE_MODE (type), &x, n);
7865 if (flag_unsafe_math_optimizations || !inexact)
7866 return build_real (type, x);
7867 }
198d9bbe 7868
7869 /* Strip sign ops from even integer powers. */
7870 if ((n & 1) == 0 && flag_unsafe_math_optimizations)
7871 {
7872 tree narg0 = fold_strip_sign_ops (arg0);
7873 if (narg0)
389dd41b 7874 return build_call_expr_loc (loc, fndecl, 2, narg0, arg1);
198d9bbe 7875 }
e6e27594 7876 }
7877 }
7878
cdfeb715 7879 if (flag_unsafe_math_optimizations)
e6e27594 7880 {
cdfeb715 7881 const enum built_in_function fcode = builtin_mathfn_code (arg0);
e6e27594 7882
cdfeb715 7883 /* Optimize pow(expN(x),y) = expN(x*y). */
7884 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 7885 {
c2f47e15 7886 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
7887 tree arg = CALL_EXPR_ARG (arg0, 0);
389dd41b 7888 arg = fold_build2_loc (loc, MULT_EXPR, type, arg, arg1);
7889 return build_call_expr_loc (loc, expfn, 1, arg);
cdfeb715 7890 }
e6e27594 7891
cdfeb715 7892 /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
7893 if (BUILTIN_SQRT_P (fcode))
a0c938f0 7894 {
c2f47e15 7895 tree narg0 = CALL_EXPR_ARG (arg0, 0);
389dd41b 7896 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 7897 build_real (type, dconsthalf));
389dd41b 7898 return build_call_expr_loc (loc, fndecl, 2, narg0, narg1);
cdfeb715 7899 }
7900
7901 /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */
7902 if (BUILTIN_CBRT_P (fcode))
a0c938f0 7903 {
c2f47e15 7904 tree arg = CALL_EXPR_ARG (arg0, 0);
cdfeb715 7905 if (tree_expr_nonnegative_p (arg))
7906 {
7907 const REAL_VALUE_TYPE dconstroot
7910b2fb 7908 = real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 7909 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 7910 build_real (type, dconstroot));
389dd41b 7911 return build_call_expr_loc (loc, fndecl, 2, arg, narg1);
cdfeb715 7912 }
7913 }
a0c938f0 7914
49e436b5 7915 /* Optimize pow(pow(x,y),z) = pow(x,y*z) iff x is nonnegative. */
c2f47e15 7916 if (fcode == BUILT_IN_POW
7917 || fcode == BUILT_IN_POWF
7918 || fcode == BUILT_IN_POWL)
a0c938f0 7919 {
c2f47e15 7920 tree arg00 = CALL_EXPR_ARG (arg0, 0);
49e436b5 7921 if (tree_expr_nonnegative_p (arg00))
7922 {
7923 tree arg01 = CALL_EXPR_ARG (arg0, 1);
7924 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg01, arg1);
7925 return build_call_expr_loc (loc, fndecl, 2, arg00, narg1);
7926 }
cdfeb715 7927 }
e6e27594 7928 }
cdfeb715 7929
e6e27594 7930 return NULL_TREE;
7931}
7932
c2f47e15 7933/* Fold a builtin function call to powi, powif, or powil with argument ARG.
7934 Return NULL_TREE if no simplification can be made. */
b4d0c20c 7935static tree
389dd41b 7936fold_builtin_powi (location_t loc, tree fndecl ATTRIBUTE_UNUSED,
c2f47e15 7937 tree arg0, tree arg1, tree type)
b4d0c20c 7938{
c2f47e15 7939 if (!validate_arg (arg0, REAL_TYPE)
7940 || !validate_arg (arg1, INTEGER_TYPE))
b4d0c20c 7941 return NULL_TREE;
7942
7943 /* Optimize pow(1.0,y) = 1.0. */
7944 if (real_onep (arg0))
389dd41b 7945 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
b4d0c20c 7946
7947 if (host_integerp (arg1, 0))
7948 {
7949 HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
7950
7951 /* Evaluate powi at compile-time. */
7952 if (TREE_CODE (arg0) == REAL_CST
f96bd2bf 7953 && !TREE_OVERFLOW (arg0))
b4d0c20c 7954 {
7955 REAL_VALUE_TYPE x;
7956 x = TREE_REAL_CST (arg0);
7957 real_powi (&x, TYPE_MODE (type), &x, c);
7958 return build_real (type, x);
7959 }
7960
7961 /* Optimize pow(x,0) = 1.0. */
7962 if (c == 0)
389dd41b 7963 return omit_one_operand_loc (loc, type, build_real (type, dconst1),
b4d0c20c 7964 arg0);
7965
7966 /* Optimize pow(x,1) = x. */
7967 if (c == 1)
7968 return arg0;
7969
7970 /* Optimize pow(x,-1) = 1.0/x. */
7971 if (c == -1)
389dd41b 7972 return fold_build2_loc (loc, RDIV_EXPR, type,
49d00087 7973 build_real (type, dconst1), arg0);
b4d0c20c 7974 }
7975
7976 return NULL_TREE;
7977}
7978
8918c507 7979/* A subroutine of fold_builtin to fold the various exponent
c2f47e15 7980 functions. Return NULL_TREE if no simplification can be made.
debf9994 7981 FUNC is the corresponding MPFR exponent function. */
8918c507 7982
7983static tree
389dd41b 7984fold_builtin_exponent (location_t loc, tree fndecl, tree arg,
debf9994 7985 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 7986{
c2f47e15 7987 if (validate_arg (arg, REAL_TYPE))
8918c507 7988 {
8918c507 7989 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 7990 tree res;
48e1416a 7991
debf9994 7992 /* Calculate the result when the argument is a constant. */
728bac60 7993 if ((res = do_mpfr_arg1 (arg, type, func, NULL, NULL, 0)))
debf9994 7994 return res;
8918c507 7995
7996 /* Optimize expN(logN(x)) = x. */
7997 if (flag_unsafe_math_optimizations)
a0c938f0 7998 {
8918c507 7999 const enum built_in_function fcode = builtin_mathfn_code (arg);
8000
debf9994 8001 if ((func == mpfr_exp
8918c507 8002 && (fcode == BUILT_IN_LOG
8003 || fcode == BUILT_IN_LOGF
8004 || fcode == BUILT_IN_LOGL))
debf9994 8005 || (func == mpfr_exp2
8918c507 8006 && (fcode == BUILT_IN_LOG2
8007 || fcode == BUILT_IN_LOG2F
8008 || fcode == BUILT_IN_LOG2L))
debf9994 8009 || (func == mpfr_exp10
8918c507 8010 && (fcode == BUILT_IN_LOG10
8011 || fcode == BUILT_IN_LOG10F
8012 || fcode == BUILT_IN_LOG10L)))
389dd41b 8013 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
8918c507 8014 }
8015 }
8016
c2f47e15 8017 return NULL_TREE;
8918c507 8018}
8019
e973ffcc 8020/* Return true if VAR is a VAR_DECL or a component thereof. */
8021
8022static bool
8023var_decl_component_p (tree var)
8024{
8025 tree inner = var;
8026 while (handled_component_p (inner))
8027 inner = TREE_OPERAND (inner, 0);
8028 return SSA_VAR_P (inner);
8029}
8030
4f46f2b9 8031/* Fold function call to builtin memset. Return
9c8a1629 8032 NULL_TREE if no simplification can be made. */
8033
8034static tree
389dd41b 8035fold_builtin_memset (location_t loc, tree dest, tree c, tree len,
8036 tree type, bool ignore)
9c8a1629 8037{
45bb3afb 8038 tree var, ret, etype;
4f46f2b9 8039 unsigned HOST_WIDE_INT length, cval;
9c8a1629 8040
c2f47e15 8041 if (! validate_arg (dest, POINTER_TYPE)
8042 || ! validate_arg (c, INTEGER_TYPE)
8043 || ! validate_arg (len, INTEGER_TYPE))
8044 return NULL_TREE;
9c8a1629 8045
4f46f2b9 8046 if (! host_integerp (len, 1))
c2f47e15 8047 return NULL_TREE;
4f46f2b9 8048
9c8a1629 8049 /* If the LEN parameter is zero, return DEST. */
8050 if (integer_zerop (len))
389dd41b 8051 return omit_one_operand_loc (loc, type, dest, c);
9c8a1629 8052
4f46f2b9 8053 if (! host_integerp (c, 1) || TREE_SIDE_EFFECTS (dest))
c2f47e15 8054 return NULL_TREE;
9c8a1629 8055
4f46f2b9 8056 var = dest;
8057 STRIP_NOPS (var);
8058 if (TREE_CODE (var) != ADDR_EXPR)
c2f47e15 8059 return NULL_TREE;
4f46f2b9 8060
8061 var = TREE_OPERAND (var, 0);
8062 if (TREE_THIS_VOLATILE (var))
c2f47e15 8063 return NULL_TREE;
4f46f2b9 8064
45bb3afb 8065 etype = TREE_TYPE (var);
8066 if (TREE_CODE (etype) == ARRAY_TYPE)
8067 etype = TREE_TYPE (etype);
8068
8069 if (!INTEGRAL_TYPE_P (etype)
8070 && !POINTER_TYPE_P (etype))
c2f47e15 8071 return NULL_TREE;
4f46f2b9 8072
e973ffcc 8073 if (! var_decl_component_p (var))
c2f47e15 8074 return NULL_TREE;
e973ffcc 8075
4f46f2b9 8076 length = tree_low_cst (len, 1);
45bb3afb 8077 if (GET_MODE_SIZE (TYPE_MODE (etype)) != length
4f46f2b9 8078 || get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
8079 < (int) length)
c2f47e15 8080 return NULL_TREE;
4f46f2b9 8081
8082 if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT)
c2f47e15 8083 return NULL_TREE;
4f46f2b9 8084
8085 if (integer_zerop (c))
8086 cval = 0;
8087 else
8088 {
8089 if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64)
c2f47e15 8090 return NULL_TREE;
4f46f2b9 8091
8092 cval = tree_low_cst (c, 1);
8093 cval &= 0xff;
8094 cval |= cval << 8;
8095 cval |= cval << 16;
8096 cval |= (cval << 31) << 1;
8097 }
8098
45bb3afb 8099 ret = build_int_cst_type (etype, cval);
389dd41b 8100 var = build_fold_indirect_ref_loc (loc,
8101 fold_convert_loc (loc,
8102 build_pointer_type (etype),
8103 dest));
45bb3afb 8104 ret = build2 (MODIFY_EXPR, etype, var, ret);
4f46f2b9 8105 if (ignore)
8106 return ret;
8107
389dd41b 8108 return omit_one_operand_loc (loc, type, dest, ret);
9c8a1629 8109}
8110
4f46f2b9 8111/* Fold function call to builtin memset. Return
9c8a1629 8112 NULL_TREE if no simplification can be made. */
8113
8114static tree
389dd41b 8115fold_builtin_bzero (location_t loc, tree dest, tree size, bool ignore)
9c8a1629 8116{
c2f47e15 8117 if (! validate_arg (dest, POINTER_TYPE)
8118 || ! validate_arg (size, INTEGER_TYPE))
8119 return NULL_TREE;
9c8a1629 8120
4f46f2b9 8121 if (!ignore)
c2f47e15 8122 return NULL_TREE;
a0c938f0 8123
4f46f2b9 8124 /* New argument list transforming bzero(ptr x, int y) to
8125 memset(ptr x, int 0, size_t y). This is done this way
8126 so that if it isn't expanded inline, we fallback to
8127 calling bzero instead of memset. */
8128
389dd41b 8129 return fold_builtin_memset (loc, dest, integer_zero_node,
8130 fold_convert_loc (loc, sizetype, size),
c2f47e15 8131 void_type_node, ignore);
9c8a1629 8132}
8133
4f46f2b9 8134/* Fold function call to builtin mem{{,p}cpy,move}. Return
8135 NULL_TREE if no simplification can be made.
8136 If ENDP is 0, return DEST (like memcpy).
8137 If ENDP is 1, return DEST+LEN (like mempcpy).
8138 If ENDP is 2, return DEST+LEN-1 (like stpcpy).
8139 If ENDP is 3, return DEST, additionally *SRC and *DEST may overlap
8140 (memmove). */
9c8a1629 8141
8142static tree
389dd41b 8143fold_builtin_memory_op (location_t loc, tree dest, tree src,
8144 tree len, tree type, bool ignore, int endp)
9c8a1629 8145{
c2f47e15 8146 tree destvar, srcvar, expr;
9c8a1629 8147
c2f47e15 8148 if (! validate_arg (dest, POINTER_TYPE)
8149 || ! validate_arg (src, POINTER_TYPE)
8150 || ! validate_arg (len, INTEGER_TYPE))
8151 return NULL_TREE;
9c8a1629 8152
8153 /* If the LEN parameter is zero, return DEST. */
8154 if (integer_zerop (len))
389dd41b 8155 return omit_one_operand_loc (loc, type, dest, src);
9c8a1629 8156
4f46f2b9 8157 /* If SRC and DEST are the same (and not volatile), return
8158 DEST{,+LEN,+LEN-1}. */
9c8a1629 8159 if (operand_equal_p (src, dest, 0))
4f46f2b9 8160 expr = len;
8161 else
8162 {
5a84fdd6 8163 tree srctype, desttype;
5383fb56 8164 int src_align, dest_align;
8165
3b1757a2 8166 if (endp == 3)
8167 {
5383fb56 8168 src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
8169 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
5a84fdd6 8170
48e1416a 8171 /* Both DEST and SRC must be pointer types.
3b1757a2 8172 ??? This is what old code did. Is the testing for pointer types
8173 really mandatory?
8174
8175 If either SRC is readonly or length is 1, we can use memcpy. */
3f95c690 8176 if (!dest_align || !src_align)
8177 return NULL_TREE;
8178 if (readonly_data_expr (src)
8179 || (host_integerp (len, 1)
8180 && (MIN (src_align, dest_align) / BITS_PER_UNIT
8181 >= tree_low_cst (len, 1))))
3b1757a2 8182 {
8183 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8184 if (!fn)
c2f47e15 8185 return NULL_TREE;
389dd41b 8186 return build_call_expr_loc (loc, fn, 3, dest, src, len);
3b1757a2 8187 }
3f95c690 8188
8189 /* If *src and *dest can't overlap, optimize into memcpy as well. */
f85fb819 8190 srcvar = build_fold_indirect_ref_loc (loc, src);
8191 destvar = build_fold_indirect_ref_loc (loc, dest);
8192 if (srcvar
8193 && !TREE_THIS_VOLATILE (srcvar)
8194 && destvar
8195 && !TREE_THIS_VOLATILE (destvar))
3f95c690 8196 {
f85fb819 8197 tree src_base, dest_base, fn;
8198 HOST_WIDE_INT src_offset = 0, dest_offset = 0;
8199 HOST_WIDE_INT size = -1;
8200 HOST_WIDE_INT maxsize = -1;
8201
8202 src_base = srcvar;
8203 if (handled_component_p (src_base))
8204 src_base = get_ref_base_and_extent (src_base, &src_offset,
8205 &size, &maxsize);
8206 dest_base = destvar;
8207 if (handled_component_p (dest_base))
8208 dest_base = get_ref_base_and_extent (dest_base, &dest_offset,
8209 &size, &maxsize);
8210 if (host_integerp (len, 1))
8211 {
8212 maxsize = tree_low_cst (len, 1);
8213 if (maxsize
8214 > INTTYPE_MAXIMUM (HOST_WIDE_INT) / BITS_PER_UNIT)
8215 maxsize = -1;
8216 else
8217 maxsize *= BITS_PER_UNIT;
8218 }
8219 else
8220 maxsize = -1;
8221 if (SSA_VAR_P (src_base)
8222 && SSA_VAR_P (dest_base))
8223 {
8224 if (operand_equal_p (src_base, dest_base, 0)
8225 && ranges_overlap_p (src_offset, maxsize,
8226 dest_offset, maxsize))
8227 return NULL_TREE;
8228 }
8229 else if (TREE_CODE (src_base) == INDIRECT_REF
8230 && TREE_CODE (dest_base) == INDIRECT_REF)
8231 {
8232 if (! operand_equal_p (TREE_OPERAND (src_base, 0),
8233 TREE_OPERAND (dest_base, 0), 0)
8234 || ranges_overlap_p (src_offset, maxsize,
8235 dest_offset, maxsize))
8236 return NULL_TREE;
8237 }
8238 else
8239 return NULL_TREE;
8240
8241 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
3f95c690 8242 if (!fn)
8243 return NULL_TREE;
389dd41b 8244 return build_call_expr_loc (loc, fn, 3, dest, src, len);
3f95c690 8245 }
c2f47e15 8246 return NULL_TREE;
3b1757a2 8247 }
4f46f2b9 8248
5a84fdd6 8249 if (!host_integerp (len, 0))
c2f47e15 8250 return NULL_TREE;
5a84fdd6 8251 /* FIXME:
8252 This logic lose for arguments like (type *)malloc (sizeof (type)),
8253 since we strip the casts of up to VOID return value from malloc.
8254 Perhaps we ought to inherit type from non-VOID argument here? */
8255 STRIP_NOPS (src);
8256 STRIP_NOPS (dest);
45bb3afb 8257 /* As we fold (void *)(p + CST) to (void *)p + CST undo this here. */
8258 if (TREE_CODE (src) == POINTER_PLUS_EXPR)
8259 {
8260 tree tem = TREE_OPERAND (src, 0);
8261 STRIP_NOPS (tem);
8262 if (tem != TREE_OPERAND (src, 0))
8263 src = build1 (NOP_EXPR, TREE_TYPE (tem), src);
8264 }
8265 if (TREE_CODE (dest) == POINTER_PLUS_EXPR)
8266 {
8267 tree tem = TREE_OPERAND (dest, 0);
8268 STRIP_NOPS (tem);
8269 if (tem != TREE_OPERAND (dest, 0))
8270 dest = build1 (NOP_EXPR, TREE_TYPE (tem), dest);
8271 }
5a84fdd6 8272 srctype = TREE_TYPE (TREE_TYPE (src));
45bb3afb 8273 if (srctype
97d4c6a6 8274 && TREE_CODE (srctype) == ARRAY_TYPE
8275 && !tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
45bb3afb 8276 {
8277 srctype = TREE_TYPE (srctype);
8278 STRIP_NOPS (src);
8279 src = build1 (NOP_EXPR, build_pointer_type (srctype), src);
8280 }
5a84fdd6 8281 desttype = TREE_TYPE (TREE_TYPE (dest));
45bb3afb 8282 if (desttype
97d4c6a6 8283 && TREE_CODE (desttype) == ARRAY_TYPE
8284 && !tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
45bb3afb 8285 {
8286 desttype = TREE_TYPE (desttype);
8287 STRIP_NOPS (dest);
8288 dest = build1 (NOP_EXPR, build_pointer_type (desttype), dest);
8289 }
5a84fdd6 8290 if (!srctype || !desttype
8291 || !TYPE_SIZE_UNIT (srctype)
8292 || !TYPE_SIZE_UNIT (desttype)
8293 || TREE_CODE (TYPE_SIZE_UNIT (srctype)) != INTEGER_CST
6f52ebeb 8294 || TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST
8295 || TYPE_VOLATILE (srctype)
8296 || TYPE_VOLATILE (desttype))
c2f47e15 8297 return NULL_TREE;
4f46f2b9 8298
5383fb56 8299 src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
8300 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
8301 if (dest_align < (int) TYPE_ALIGN (desttype)
8302 || src_align < (int) TYPE_ALIGN (srctype))
c2f47e15 8303 return NULL_TREE;
e973ffcc 8304
5a84fdd6 8305 if (!ignore)
8306 dest = builtin_save_expr (dest);
4f46f2b9 8307
5383fb56 8308 srcvar = NULL_TREE;
8309 if (tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
8310 {
389dd41b 8311 srcvar = build_fold_indirect_ref_loc (loc, src);
5383fb56 8312 if (TREE_THIS_VOLATILE (srcvar))
6f52ebeb 8313 return NULL_TREE;
92ddcd97 8314 else if (!tree_int_cst_equal (tree_expr_size (srcvar), len))
5383fb56 8315 srcvar = NULL_TREE;
8316 /* With memcpy, it is possible to bypass aliasing rules, so without
8317 this check i.e. execute/20060930-2.c would be misoptimized,
8318 because it use conflicting alias set to hold argument for the
8319 memcpy call. This check is probably unnecessary with
8320 -fno-strict-aliasing. Similarly for destvar. See also
8321 PR29286. */
8322 else if (!var_decl_component_p (srcvar))
8323 srcvar = NULL_TREE;
8324 }
4f46f2b9 8325
5383fb56 8326 destvar = NULL_TREE;
8327 if (tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
8328 {
389dd41b 8329 destvar = build_fold_indirect_ref_loc (loc, dest);
5383fb56 8330 if (TREE_THIS_VOLATILE (destvar))
6f52ebeb 8331 return NULL_TREE;
92ddcd97 8332 else if (!tree_int_cst_equal (tree_expr_size (destvar), len))
5383fb56 8333 destvar = NULL_TREE;
8334 else if (!var_decl_component_p (destvar))
8335 destvar = NULL_TREE;
8336 }
8337
8338 if (srcvar == NULL_TREE && destvar == NULL_TREE)
c2f47e15 8339 return NULL_TREE;
4f46f2b9 8340
5383fb56 8341 if (srcvar == NULL_TREE)
8342 {
8343 tree srcptype;
8344 if (TREE_ADDRESSABLE (TREE_TYPE (destvar)))
8345 return NULL_TREE;
8346
6f52ebeb 8347 srctype = build_qualified_type (desttype, 0);
5383fb56 8348 if (src_align < (int) TYPE_ALIGN (srctype))
8349 {
8350 if (AGGREGATE_TYPE_P (srctype)
8351 || SLOW_UNALIGNED_ACCESS (TYPE_MODE (srctype), src_align))
8352 return NULL_TREE;
8353
8354 srctype = build_variant_type_copy (srctype);
8355 TYPE_ALIGN (srctype) = src_align;
8356 TYPE_USER_ALIGN (srctype) = 1;
8357 TYPE_PACKED (srctype) = 1;
8358 }
8359 srcptype = build_pointer_type_for_mode (srctype, ptr_mode, true);
389dd41b 8360 src = fold_convert_loc (loc, srcptype, src);
8361 srcvar = build_fold_indirect_ref_loc (loc, src);
5383fb56 8362 }
8363 else if (destvar == NULL_TREE)
8364 {
8365 tree destptype;
8366 if (TREE_ADDRESSABLE (TREE_TYPE (srcvar)))
8367 return NULL_TREE;
8368
6f52ebeb 8369 desttype = build_qualified_type (srctype, 0);
5383fb56 8370 if (dest_align < (int) TYPE_ALIGN (desttype))
8371 {
8372 if (AGGREGATE_TYPE_P (desttype)
8373 || SLOW_UNALIGNED_ACCESS (TYPE_MODE (desttype), dest_align))
8374 return NULL_TREE;
8375
8376 desttype = build_variant_type_copy (desttype);
8377 TYPE_ALIGN (desttype) = dest_align;
8378 TYPE_USER_ALIGN (desttype) = 1;
8379 TYPE_PACKED (desttype) = 1;
8380 }
8381 destptype = build_pointer_type_for_mode (desttype, ptr_mode, true);
389dd41b 8382 dest = fold_convert_loc (loc, destptype, dest);
8383 destvar = build_fold_indirect_ref_loc (loc, dest);
5383fb56 8384 }
8385
5a84fdd6 8386 if (srctype == desttype
2d04fd8d 8387 || (gimple_in_ssa_p (cfun)
548044d8 8388 && useless_type_conversion_p (desttype, srctype)))
5a84fdd6 8389 expr = srcvar;
8390 else if ((INTEGRAL_TYPE_P (TREE_TYPE (srcvar))
4f46f2b9 8391 || POINTER_TYPE_P (TREE_TYPE (srcvar)))
8392 && (INTEGRAL_TYPE_P (TREE_TYPE (destvar))
8393 || POINTER_TYPE_P (TREE_TYPE (destvar))))
389dd41b 8394 expr = fold_convert_loc (loc, TREE_TYPE (destvar), srcvar);
4f46f2b9 8395 else
389dd41b 8396 expr = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
8397 TREE_TYPE (destvar), srcvar);
41076ef6 8398 expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, expr);
4f46f2b9 8399 }
8400
8401 if (ignore)
8402 return expr;
8403
8404 if (endp == 0 || endp == 3)
389dd41b 8405 return omit_one_operand_loc (loc, type, dest, expr);
4f46f2b9 8406
8407 if (expr == len)
c2f47e15 8408 expr = NULL_TREE;
4f46f2b9 8409
8410 if (endp == 2)
389dd41b 8411 len = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (len), len,
4f46f2b9 8412 ssize_int (1));
8413
389dd41b 8414 len = fold_convert_loc (loc, sizetype, len);
8415 dest = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
8416 dest = fold_convert_loc (loc, type, dest);
4f46f2b9 8417 if (expr)
389dd41b 8418 dest = omit_one_operand_loc (loc, type, dest, expr);
4f46f2b9 8419 return dest;
8420}
8421
c2f47e15 8422/* Fold function call to builtin strcpy with arguments DEST and SRC.
8423 If LEN is not NULL, it represents the length of the string to be
8424 copied. Return NULL_TREE if no simplification can be made. */
9c8a1629 8425
f0613857 8426tree
389dd41b 8427fold_builtin_strcpy (location_t loc, tree fndecl, tree dest, tree src, tree len)
9c8a1629 8428{
c2f47e15 8429 tree fn;
9c8a1629 8430
c2f47e15 8431 if (!validate_arg (dest, POINTER_TYPE)
8432 || !validate_arg (src, POINTER_TYPE))
8433 return NULL_TREE;
9c8a1629 8434
8435 /* If SRC and DEST are the same (and not volatile), return DEST. */
8436 if (operand_equal_p (src, dest, 0))
389dd41b 8437 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
9c8a1629 8438
0bfd8d5c 8439 if (optimize_function_for_size_p (cfun))
c2f47e15 8440 return NULL_TREE;
f0613857 8441
8442 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8443 if (!fn)
c2f47e15 8444 return NULL_TREE;
f0613857 8445
8446 if (!len)
8447 {
8448 len = c_strlen (src, 1);
8449 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 8450 return NULL_TREE;
f0613857 8451 }
8452
389dd41b 8453 len = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
8454 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
8455 build_call_expr_loc (loc, fn, 3, dest, src, len));
9c8a1629 8456}
8457
a65c4d64 8458/* Fold function call to builtin stpcpy with arguments DEST and SRC.
8459 Return NULL_TREE if no simplification can be made. */
8460
8461static tree
8462fold_builtin_stpcpy (location_t loc, tree fndecl, tree dest, tree src)
8463{
8464 tree fn, len, lenp1, call, type;
8465
8466 if (!validate_arg (dest, POINTER_TYPE)
8467 || !validate_arg (src, POINTER_TYPE))
8468 return NULL_TREE;
8469
8470 len = c_strlen (src, 1);
8471 if (!len
8472 || TREE_CODE (len) != INTEGER_CST)
8473 return NULL_TREE;
8474
8475 if (optimize_function_for_size_p (cfun)
8476 /* If length is zero it's small enough. */
8477 && !integer_zerop (len))
8478 return NULL_TREE;
8479
8480 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8481 if (!fn)
8482 return NULL_TREE;
8483
8484 lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
8485 /* We use dest twice in building our expression. Save it from
8486 multiple expansions. */
8487 dest = builtin_save_expr (dest);
8488 call = build_call_expr_loc (loc, fn, 3, dest, src, lenp1);
8489
8490 type = TREE_TYPE (TREE_TYPE (fndecl));
8491 len = fold_convert_loc (loc, sizetype, len);
8492 dest = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
8493 dest = fold_convert_loc (loc, type, dest);
8494 dest = omit_one_operand_loc (loc, type, dest, call);
8495 return dest;
8496}
8497
c2f47e15 8498/* Fold function call to builtin strncpy with arguments DEST, SRC, and LEN.
8499 If SLEN is not NULL, it represents the length of the source string.
8500 Return NULL_TREE if no simplification can be made. */
9c8a1629 8501
f0613857 8502tree
389dd41b 8503fold_builtin_strncpy (location_t loc, tree fndecl, tree dest,
8504 tree src, tree len, tree slen)
9c8a1629 8505{
c2f47e15 8506 tree fn;
9c8a1629 8507
c2f47e15 8508 if (!validate_arg (dest, POINTER_TYPE)
8509 || !validate_arg (src, POINTER_TYPE)
8510 || !validate_arg (len, INTEGER_TYPE))
8511 return NULL_TREE;
9c8a1629 8512
8513 /* If the LEN parameter is zero, return DEST. */
8514 if (integer_zerop (len))
389dd41b 8515 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
9c8a1629 8516
19226313 8517 /* We can't compare slen with len as constants below if len is not a
8518 constant. */
8519 if (len == 0 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 8520 return NULL_TREE;
19226313 8521
f0613857 8522 if (!slen)
8523 slen = c_strlen (src, 1);
8524
8525 /* Now, we must be passed a constant src ptr parameter. */
8526 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
c2f47e15 8527 return NULL_TREE;
f0613857 8528
389dd41b 8529 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
f0613857 8530
8531 /* We do not support simplification of this case, though we do
8532 support it when expanding trees into RTL. */
8533 /* FIXME: generate a call to __builtin_memset. */
8534 if (tree_int_cst_lt (slen, len))
c2f47e15 8535 return NULL_TREE;
f0613857 8536
8537 /* OK transform into builtin memcpy. */
8538 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8539 if (!fn)
c2f47e15 8540 return NULL_TREE;
389dd41b 8541 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
8542 build_call_expr_loc (loc, fn, 3, dest, src, len));
9c8a1629 8543}
8544
7959b13b 8545/* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the
8546 arguments to the call, and TYPE is its return type.
8547 Return NULL_TREE if no simplification can be made. */
8548
8549static tree
389dd41b 8550fold_builtin_memchr (location_t loc, tree arg1, tree arg2, tree len, tree type)
7959b13b 8551{
8552 if (!validate_arg (arg1, POINTER_TYPE)
8553 || !validate_arg (arg2, INTEGER_TYPE)
8554 || !validate_arg (len, INTEGER_TYPE))
8555 return NULL_TREE;
8556 else
8557 {
8558 const char *p1;
8559
8560 if (TREE_CODE (arg2) != INTEGER_CST
8561 || !host_integerp (len, 1))
8562 return NULL_TREE;
8563
8564 p1 = c_getstr (arg1);
8565 if (p1 && compare_tree_int (len, strlen (p1) + 1) <= 0)
8566 {
8567 char c;
8568 const char *r;
8569 tree tem;
8570
8571 if (target_char_cast (arg2, &c))
8572 return NULL_TREE;
8573
364c0c59 8574 r = (char *) memchr (p1, c, tree_low_cst (len, 1));
7959b13b 8575
8576 if (r == NULL)
8577 return build_int_cst (TREE_TYPE (arg1), 0);
8578
389dd41b 8579 tem = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (arg1), arg1,
0de36bdb 8580 size_int (r - p1));
389dd41b 8581 return fold_convert_loc (loc, type, tem);
7959b13b 8582 }
8583 return NULL_TREE;
8584 }
8585}
8586
c2f47e15 8587/* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
8588 Return NULL_TREE if no simplification can be made. */
9c8a1629 8589
8590static tree
389dd41b 8591fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
9c8a1629 8592{
c4fef134 8593 const char *p1, *p2;
9c8a1629 8594
c2f47e15 8595 if (!validate_arg (arg1, POINTER_TYPE)
8596 || !validate_arg (arg2, POINTER_TYPE)
8597 || !validate_arg (len, INTEGER_TYPE))
8598 return NULL_TREE;
9c8a1629 8599
8600 /* If the LEN parameter is zero, return zero. */
8601 if (integer_zerop (len))
389dd41b 8602 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
c4fef134 8603 arg1, arg2);
9c8a1629 8604
8605 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8606 if (operand_equal_p (arg1, arg2, 0))
389dd41b 8607 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
c4fef134 8608
8609 p1 = c_getstr (arg1);
8610 p2 = c_getstr (arg2);
8611
8612 /* If all arguments are constant, and the value of len is not greater
8613 than the lengths of arg1 and arg2, evaluate at compile-time. */
8614 if (host_integerp (len, 1) && p1 && p2
8615 && compare_tree_int (len, strlen (p1) + 1) <= 0
8616 && compare_tree_int (len, strlen (p2) + 1) <= 0)
8617 {
8618 const int r = memcmp (p1, p2, tree_low_cst (len, 1));
8619
8620 if (r > 0)
8621 return integer_one_node;
8622 else if (r < 0)
8623 return integer_minus_one_node;
8624 else
8625 return integer_zero_node;
8626 }
8627
8628 /* If len parameter is one, return an expression corresponding to
8629 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
8630 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
8631 {
8632 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8633 tree cst_uchar_ptr_node
8634 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8635
389dd41b 8636 tree ind1
8637 = fold_convert_loc (loc, integer_type_node,
8638 build1 (INDIRECT_REF, cst_uchar_node,
8639 fold_convert_loc (loc,
8640 cst_uchar_ptr_node,
c4fef134 8641 arg1)));
389dd41b 8642 tree ind2
8643 = fold_convert_loc (loc, integer_type_node,
8644 build1 (INDIRECT_REF, cst_uchar_node,
8645 fold_convert_loc (loc,
8646 cst_uchar_ptr_node,
c4fef134 8647 arg2)));
389dd41b 8648 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
c4fef134 8649 }
9c8a1629 8650
c2f47e15 8651 return NULL_TREE;
9c8a1629 8652}
8653
c2f47e15 8654/* Fold function call to builtin strcmp with arguments ARG1 and ARG2.
8655 Return NULL_TREE if no simplification can be made. */
9c8a1629 8656
8657static tree
389dd41b 8658fold_builtin_strcmp (location_t loc, tree arg1, tree arg2)
9c8a1629 8659{
9c8a1629 8660 const char *p1, *p2;
8661
c2f47e15 8662 if (!validate_arg (arg1, POINTER_TYPE)
8663 || !validate_arg (arg2, POINTER_TYPE))
8664 return NULL_TREE;
9c8a1629 8665
8666 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8667 if (operand_equal_p (arg1, arg2, 0))
c4fef134 8668 return integer_zero_node;
9c8a1629 8669
8670 p1 = c_getstr (arg1);
8671 p2 = c_getstr (arg2);
8672
8673 if (p1 && p2)
8674 {
9c8a1629 8675 const int i = strcmp (p1, p2);
8676 if (i < 0)
c4fef134 8677 return integer_minus_one_node;
9c8a1629 8678 else if (i > 0)
c4fef134 8679 return integer_one_node;
9c8a1629 8680 else
c4fef134 8681 return integer_zero_node;
8682 }
8683
8684 /* If the second arg is "", return *(const unsigned char*)arg1. */
8685 if (p2 && *p2 == '\0')
8686 {
8687 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8688 tree cst_uchar_ptr_node
8689 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8690
389dd41b 8691 return fold_convert_loc (loc, integer_type_node,
8692 build1 (INDIRECT_REF, cst_uchar_node,
8693 fold_convert_loc (loc,
8694 cst_uchar_ptr_node,
8695 arg1)));
c4fef134 8696 }
8697
8698 /* If the first arg is "", return -*(const unsigned char*)arg2. */
8699 if (p1 && *p1 == '\0')
8700 {
8701 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8702 tree cst_uchar_ptr_node
8703 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8704
389dd41b 8705 tree temp
8706 = fold_convert_loc (loc, integer_type_node,
8707 build1 (INDIRECT_REF, cst_uchar_node,
8708 fold_convert_loc (loc,
8709 cst_uchar_ptr_node,
c4fef134 8710 arg2)));
389dd41b 8711 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp);
9c8a1629 8712 }
8713
c2f47e15 8714 return NULL_TREE;
9c8a1629 8715}
8716
c2f47e15 8717/* Fold function call to builtin strncmp with arguments ARG1, ARG2, and LEN.
8718 Return NULL_TREE if no simplification can be made. */
9c8a1629 8719
8720static tree
389dd41b 8721fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len)
9c8a1629 8722{
9c8a1629 8723 const char *p1, *p2;
8724
c2f47e15 8725 if (!validate_arg (arg1, POINTER_TYPE)
8726 || !validate_arg (arg2, POINTER_TYPE)
8727 || !validate_arg (len, INTEGER_TYPE))
8728 return NULL_TREE;
9c8a1629 8729
8730 /* If the LEN parameter is zero, return zero. */
8731 if (integer_zerop (len))
389dd41b 8732 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
c4fef134 8733 arg1, arg2);
9c8a1629 8734
8735 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8736 if (operand_equal_p (arg1, arg2, 0))
389dd41b 8737 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
9c8a1629 8738
8739 p1 = c_getstr (arg1);
8740 p2 = c_getstr (arg2);
8741
8742 if (host_integerp (len, 1) && p1 && p2)
8743 {
9c8a1629 8744 const int i = strncmp (p1, p2, tree_low_cst (len, 1));
c4fef134 8745 if (i > 0)
8746 return integer_one_node;
8747 else if (i < 0)
8748 return integer_minus_one_node;
9c8a1629 8749 else
c4fef134 8750 return integer_zero_node;
8751 }
8752
8753 /* If the second arg is "", and the length is greater than zero,
8754 return *(const unsigned char*)arg1. */
8755 if (p2 && *p2 == '\0'
8756 && TREE_CODE (len) == INTEGER_CST
8757 && tree_int_cst_sgn (len) == 1)
8758 {
8759 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8760 tree cst_uchar_ptr_node
8761 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8762
389dd41b 8763 return fold_convert_loc (loc, integer_type_node,
8764 build1 (INDIRECT_REF, cst_uchar_node,
8765 fold_convert_loc (loc,
8766 cst_uchar_ptr_node,
8767 arg1)));
c4fef134 8768 }
8769
8770 /* If the first arg is "", and the length is greater than zero,
8771 return -*(const unsigned char*)arg2. */
8772 if (p1 && *p1 == '\0'
8773 && TREE_CODE (len) == INTEGER_CST
8774 && tree_int_cst_sgn (len) == 1)
8775 {
8776 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8777 tree cst_uchar_ptr_node
8778 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8779
389dd41b 8780 tree temp = fold_convert_loc (loc, integer_type_node,
8781 build1 (INDIRECT_REF, cst_uchar_node,
8782 fold_convert_loc (loc,
8783 cst_uchar_ptr_node,
8784 arg2)));
8785 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp);
c4fef134 8786 }
8787
8788 /* If len parameter is one, return an expression corresponding to
8789 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
8790 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
8791 {
8792 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8793 tree cst_uchar_ptr_node
8794 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8795
389dd41b 8796 tree ind1 = fold_convert_loc (loc, integer_type_node,
8797 build1 (INDIRECT_REF, cst_uchar_node,
8798 fold_convert_loc (loc,
8799 cst_uchar_ptr_node,
8800 arg1)));
8801 tree ind2 = fold_convert_loc (loc, integer_type_node,
8802 build1 (INDIRECT_REF, cst_uchar_node,
8803 fold_convert_loc (loc,
8804 cst_uchar_ptr_node,
8805 arg2)));
8806 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
9c8a1629 8807 }
8808
c2f47e15 8809 return NULL_TREE;
9c8a1629 8810}
8811
c2f47e15 8812/* Fold function call to builtin signbit, signbitf or signbitl with argument
8813 ARG. Return NULL_TREE if no simplification can be made. */
27f261ef 8814
8815static tree
389dd41b 8816fold_builtin_signbit (location_t loc, tree arg, tree type)
27f261ef 8817{
c2f47e15 8818 tree temp;
27f261ef 8819
c2f47e15 8820 if (!validate_arg (arg, REAL_TYPE))
27f261ef 8821 return NULL_TREE;
8822
27f261ef 8823 /* If ARG is a compile-time constant, determine the result. */
8824 if (TREE_CODE (arg) == REAL_CST
f96bd2bf 8825 && !TREE_OVERFLOW (arg))
27f261ef 8826 {
8827 REAL_VALUE_TYPE c;
8828
8829 c = TREE_REAL_CST (arg);
8830 temp = REAL_VALUE_NEGATIVE (c) ? integer_one_node : integer_zero_node;
389dd41b 8831 return fold_convert_loc (loc, type, temp);
27f261ef 8832 }
8833
8834 /* If ARG is non-negative, the result is always zero. */
8835 if (tree_expr_nonnegative_p (arg))
389dd41b 8836 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
27f261ef 8837
8838 /* If ARG's format doesn't have signed zeros, return "arg < 0.0". */
8839 if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 8840 return fold_build2_loc (loc, LT_EXPR, type, arg,
49d00087 8841 build_real (TREE_TYPE (arg), dconst0));
27f261ef 8842
8843 return NULL_TREE;
8844}
8845
c2f47e15 8846/* Fold function call to builtin copysign, copysignf or copysignl with
8847 arguments ARG1 and ARG2. Return NULL_TREE if no simplification can
8848 be made. */
467214fd 8849
8850static tree
389dd41b 8851fold_builtin_copysign (location_t loc, tree fndecl,
8852 tree arg1, tree arg2, tree type)
467214fd 8853{
c2f47e15 8854 tree tem;
467214fd 8855
c2f47e15 8856 if (!validate_arg (arg1, REAL_TYPE)
8857 || !validate_arg (arg2, REAL_TYPE))
467214fd 8858 return NULL_TREE;
8859
467214fd 8860 /* copysign(X,X) is X. */
8861 if (operand_equal_p (arg1, arg2, 0))
389dd41b 8862 return fold_convert_loc (loc, type, arg1);
467214fd 8863
8864 /* If ARG1 and ARG2 are compile-time constants, determine the result. */
8865 if (TREE_CODE (arg1) == REAL_CST
8866 && TREE_CODE (arg2) == REAL_CST
f96bd2bf 8867 && !TREE_OVERFLOW (arg1)
8868 && !TREE_OVERFLOW (arg2))
467214fd 8869 {
8870 REAL_VALUE_TYPE c1, c2;
8871
8872 c1 = TREE_REAL_CST (arg1);
8873 c2 = TREE_REAL_CST (arg2);
749680e2 8874 /* c1.sign := c2.sign. */
467214fd 8875 real_copysign (&c1, &c2);
8876 return build_real (type, c1);
467214fd 8877 }
8878
8879 /* copysign(X, Y) is fabs(X) when Y is always non-negative.
8880 Remember to evaluate Y for side-effects. */
8881 if (tree_expr_nonnegative_p (arg2))
389dd41b 8882 return omit_one_operand_loc (loc, type,
8883 fold_build1_loc (loc, ABS_EXPR, type, arg1),
467214fd 8884 arg2);
8885
198d9bbe 8886 /* Strip sign changing operations for the first argument. */
8887 tem = fold_strip_sign_ops (arg1);
8888 if (tem)
389dd41b 8889 return build_call_expr_loc (loc, fndecl, 2, tem, arg2);
198d9bbe 8890
467214fd 8891 return NULL_TREE;
8892}
8893
c2f47e15 8894/* Fold a call to builtin isascii with argument ARG. */
d49367d4 8895
8896static tree
389dd41b 8897fold_builtin_isascii (location_t loc, tree arg)
d49367d4 8898{
c2f47e15 8899 if (!validate_arg (arg, INTEGER_TYPE))
8900 return NULL_TREE;
d49367d4 8901 else
8902 {
8903 /* Transform isascii(c) -> ((c & ~0x7f) == 0). */
c90b5d40 8904 arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
8905 build_int_cst (NULL_TREE,
8906 ~ (unsigned HOST_WIDE_INT) 0x7f));
389dd41b 8907 return fold_build2_loc (loc, EQ_EXPR, integer_type_node,
f2532264 8908 arg, integer_zero_node);
d49367d4 8909 }
8910}
8911
c2f47e15 8912/* Fold a call to builtin toascii with argument ARG. */
d49367d4 8913
8914static tree
389dd41b 8915fold_builtin_toascii (location_t loc, tree arg)
d49367d4 8916{
c2f47e15 8917 if (!validate_arg (arg, INTEGER_TYPE))
8918 return NULL_TREE;
48e1416a 8919
c2f47e15 8920 /* Transform toascii(c) -> (c & 0x7f). */
389dd41b 8921 return fold_build2_loc (loc, BIT_AND_EXPR, integer_type_node, arg,
c2f47e15 8922 build_int_cst (NULL_TREE, 0x7f));
d49367d4 8923}
8924
c2f47e15 8925/* Fold a call to builtin isdigit with argument ARG. */
df1cf42e 8926
8927static tree
389dd41b 8928fold_builtin_isdigit (location_t loc, tree arg)
df1cf42e 8929{
c2f47e15 8930 if (!validate_arg (arg, INTEGER_TYPE))
8931 return NULL_TREE;
df1cf42e 8932 else
8933 {
8934 /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */
624d37a6 8935 /* According to the C standard, isdigit is unaffected by locale.
8936 However, it definitely is affected by the target character set. */
624d37a6 8937 unsigned HOST_WIDE_INT target_digit0
8938 = lang_hooks.to_target_charset ('0');
8939
8940 if (target_digit0 == 0)
8941 return NULL_TREE;
8942
389dd41b 8943 arg = fold_convert_loc (loc, unsigned_type_node, arg);
c90b5d40 8944 arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg,
8945 build_int_cst (unsigned_type_node, target_digit0));
389dd41b 8946 return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg,
f2532264 8947 build_int_cst (unsigned_type_node, 9));
df1cf42e 8948 }
8949}
27f261ef 8950
c2f47e15 8951/* Fold a call to fabs, fabsf or fabsl with argument ARG. */
d1aade50 8952
8953static tree
389dd41b 8954fold_builtin_fabs (location_t loc, tree arg, tree type)
d1aade50 8955{
c2f47e15 8956 if (!validate_arg (arg, REAL_TYPE))
8957 return NULL_TREE;
d1aade50 8958
389dd41b 8959 arg = fold_convert_loc (loc, type, arg);
d1aade50 8960 if (TREE_CODE (arg) == REAL_CST)
8961 return fold_abs_const (arg, type);
389dd41b 8962 return fold_build1_loc (loc, ABS_EXPR, type, arg);
d1aade50 8963}
8964
c2f47e15 8965/* Fold a call to abs, labs, llabs or imaxabs with argument ARG. */
d1aade50 8966
8967static tree
389dd41b 8968fold_builtin_abs (location_t loc, tree arg, tree type)
d1aade50 8969{
c2f47e15 8970 if (!validate_arg (arg, INTEGER_TYPE))
8971 return NULL_TREE;
d1aade50 8972
389dd41b 8973 arg = fold_convert_loc (loc, type, arg);
d1aade50 8974 if (TREE_CODE (arg) == INTEGER_CST)
8975 return fold_abs_const (arg, type);
389dd41b 8976 return fold_build1_loc (loc, ABS_EXPR, type, arg);
d1aade50 8977}
8978
d4a43a03 8979/* Fold a call to builtin fmin or fmax. */
8980
8981static tree
389dd41b 8982fold_builtin_fmin_fmax (location_t loc, tree arg0, tree arg1,
8983 tree type, bool max)
d4a43a03 8984{
c2f47e15 8985 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, REAL_TYPE))
d4a43a03 8986 {
d4a43a03 8987 /* Calculate the result when the argument is a constant. */
8988 tree res = do_mpfr_arg2 (arg0, arg1, type, (max ? mpfr_max : mpfr_min));
8989
8990 if (res)
8991 return res;
8992
61fe3555 8993 /* If either argument is NaN, return the other one. Avoid the
8994 transformation if we get (and honor) a signalling NaN. Using
8995 omit_one_operand() ensures we create a non-lvalue. */
8996 if (TREE_CODE (arg0) == REAL_CST
8997 && real_isnan (&TREE_REAL_CST (arg0))
8998 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
8999 || ! TREE_REAL_CST (arg0).signalling))
389dd41b 9000 return omit_one_operand_loc (loc, type, arg1, arg0);
61fe3555 9001 if (TREE_CODE (arg1) == REAL_CST
9002 && real_isnan (&TREE_REAL_CST (arg1))
9003 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
9004 || ! TREE_REAL_CST (arg1).signalling))
389dd41b 9005 return omit_one_operand_loc (loc, type, arg0, arg1);
61fe3555 9006
d4a43a03 9007 /* Transform fmin/fmax(x,x) -> x. */
9008 if (operand_equal_p (arg0, arg1, OEP_PURE_SAME))
389dd41b 9009 return omit_one_operand_loc (loc, type, arg0, arg1);
48e1416a 9010
d4a43a03 9011 /* Convert fmin/fmax to MIN_EXPR/MAX_EXPR. C99 requires these
9012 functions to return the numeric arg if the other one is NaN.
9013 These tree codes don't honor that, so only transform if
9014 -ffinite-math-only is set. C99 doesn't require -0.0 to be
9015 handled, so we don't have to worry about it either. */
9016 if (flag_finite_math_only)
389dd41b 9017 return fold_build2_loc (loc, (max ? MAX_EXPR : MIN_EXPR), type,
9018 fold_convert_loc (loc, type, arg0),
9019 fold_convert_loc (loc, type, arg1));
d4a43a03 9020 }
9021 return NULL_TREE;
9022}
9023
abe4dcf6 9024/* Fold a call to builtin carg(a+bi) -> atan2(b,a). */
9025
9026static tree
389dd41b 9027fold_builtin_carg (location_t loc, tree arg, tree type)
abe4dcf6 9028{
239d491a 9029 if (validate_arg (arg, COMPLEX_TYPE)
9030 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
abe4dcf6 9031 {
9032 tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
48e1416a 9033
abe4dcf6 9034 if (atan2_fn)
9035 {
c2f47e15 9036 tree new_arg = builtin_save_expr (arg);
389dd41b 9037 tree r_arg = fold_build1_loc (loc, REALPART_EXPR, type, new_arg);
9038 tree i_arg = fold_build1_loc (loc, IMAGPART_EXPR, type, new_arg);
9039 return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg);
abe4dcf6 9040 }
9041 }
48e1416a 9042
abe4dcf6 9043 return NULL_TREE;
9044}
9045
cb2b9385 9046/* Fold a call to builtin logb/ilogb. */
9047
9048static tree
389dd41b 9049fold_builtin_logb (location_t loc, tree arg, tree rettype)
cb2b9385 9050{
9051 if (! validate_arg (arg, REAL_TYPE))
9052 return NULL_TREE;
48e1416a 9053
cb2b9385 9054 STRIP_NOPS (arg);
48e1416a 9055
cb2b9385 9056 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9057 {
9058 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
48e1416a 9059
cb2b9385 9060 switch (value->cl)
9061 {
9062 case rvc_nan:
9063 case rvc_inf:
9064 /* If arg is Inf or NaN and we're logb, return it. */
9065 if (TREE_CODE (rettype) == REAL_TYPE)
389dd41b 9066 return fold_convert_loc (loc, rettype, arg);
cb2b9385 9067 /* Fall through... */
9068 case rvc_zero:
9069 /* Zero may set errno and/or raise an exception for logb, also
9070 for ilogb we don't know FP_ILOGB0. */
9071 return NULL_TREE;
9072 case rvc_normal:
9073 /* For normal numbers, proceed iff radix == 2. In GCC,
9074 normalized significands are in the range [0.5, 1.0). We
9075 want the exponent as if they were [1.0, 2.0) so get the
9076 exponent and subtract 1. */
9077 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
389dd41b 9078 return fold_convert_loc (loc, rettype,
9079 build_int_cst (NULL_TREE,
9080 REAL_EXP (value)-1));
cb2b9385 9081 break;
9082 }
9083 }
48e1416a 9084
cb2b9385 9085 return NULL_TREE;
9086}
9087
9088/* Fold a call to builtin significand, if radix == 2. */
9089
9090static tree
389dd41b 9091fold_builtin_significand (location_t loc, tree arg, tree rettype)
cb2b9385 9092{
9093 if (! validate_arg (arg, REAL_TYPE))
9094 return NULL_TREE;
48e1416a 9095
cb2b9385 9096 STRIP_NOPS (arg);
48e1416a 9097
cb2b9385 9098 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9099 {
9100 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
48e1416a 9101
cb2b9385 9102 switch (value->cl)
9103 {
9104 case rvc_zero:
9105 case rvc_nan:
9106 case rvc_inf:
9107 /* If arg is +-0, +-Inf or +-NaN, then return it. */
389dd41b 9108 return fold_convert_loc (loc, rettype, arg);
cb2b9385 9109 case rvc_normal:
9110 /* For normal numbers, proceed iff radix == 2. */
9111 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
9112 {
9113 REAL_VALUE_TYPE result = *value;
9114 /* In GCC, normalized significands are in the range [0.5,
9115 1.0). We want them to be [1.0, 2.0) so set the
9116 exponent to 1. */
9117 SET_REAL_EXP (&result, 1);
9118 return build_real (rettype, result);
9119 }
9120 break;
9121 }
9122 }
48e1416a 9123
cb2b9385 9124 return NULL_TREE;
9125}
9126
3838b9ae 9127/* Fold a call to builtin frexp, we can assume the base is 2. */
9128
9129static tree
389dd41b 9130fold_builtin_frexp (location_t loc, tree arg0, tree arg1, tree rettype)
3838b9ae 9131{
9132 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9133 return NULL_TREE;
48e1416a 9134
3838b9ae 9135 STRIP_NOPS (arg0);
48e1416a 9136
3838b9ae 9137 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9138 return NULL_TREE;
48e1416a 9139
389dd41b 9140 arg1 = build_fold_indirect_ref_loc (loc, arg1);
3838b9ae 9141
9142 /* Proceed if a valid pointer type was passed in. */
9143 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
9144 {
9145 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9146 tree frac, exp;
48e1416a 9147
3838b9ae 9148 switch (value->cl)
9149 {
9150 case rvc_zero:
9151 /* For +-0, return (*exp = 0, +-0). */
9152 exp = integer_zero_node;
9153 frac = arg0;
9154 break;
9155 case rvc_nan:
9156 case rvc_inf:
9157 /* For +-NaN or +-Inf, *exp is unspecified, return arg0. */
389dd41b 9158 return omit_one_operand_loc (loc, rettype, arg0, arg1);
3838b9ae 9159 case rvc_normal:
9160 {
9161 /* Since the frexp function always expects base 2, and in
9162 GCC normalized significands are already in the range
9163 [0.5, 1.0), we have exactly what frexp wants. */
9164 REAL_VALUE_TYPE frac_rvt = *value;
9165 SET_REAL_EXP (&frac_rvt, 0);
9166 frac = build_real (rettype, frac_rvt);
9167 exp = build_int_cst (NULL_TREE, REAL_EXP (value));
9168 }
9169 break;
9170 default:
9171 gcc_unreachable ();
9172 }
48e1416a 9173
3838b9ae 9174 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
389dd41b 9175 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, exp);
3838b9ae 9176 TREE_SIDE_EFFECTS (arg1) = 1;
389dd41b 9177 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1, frac);
3838b9ae 9178 }
9179
9180 return NULL_TREE;
9181}
9182
7587301b 9183/* Fold a call to builtin ldexp or scalbn/scalbln. If LDEXP is true
9184 then we can assume the base is two. If it's false, then we have to
9185 check the mode of the TYPE parameter in certain cases. */
9186
9187static tree
389dd41b 9188fold_builtin_load_exponent (location_t loc, tree arg0, tree arg1,
9189 tree type, bool ldexp)
7587301b 9190{
9191 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, INTEGER_TYPE))
9192 {
9193 STRIP_NOPS (arg0);
9194 STRIP_NOPS (arg1);
9195
9196 /* If arg0 is 0, Inf or NaN, or if arg1 is 0, then return arg0. */
9197 if (real_zerop (arg0) || integer_zerop (arg1)
9198 || (TREE_CODE (arg0) == REAL_CST
776a7bab 9199 && !real_isfinite (&TREE_REAL_CST (arg0))))
389dd41b 9200 return omit_one_operand_loc (loc, type, arg0, arg1);
48e1416a 9201
7587301b 9202 /* If both arguments are constant, then try to evaluate it. */
9203 if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2)
9204 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
9205 && host_integerp (arg1, 0))
9206 {
9207 /* Bound the maximum adjustment to twice the range of the
9208 mode's valid exponents. Use abs to ensure the range is
9209 positive as a sanity check. */
48e1416a 9210 const long max_exp_adj = 2 *
7587301b 9211 labs (REAL_MODE_FORMAT (TYPE_MODE (type))->emax
9212 - REAL_MODE_FORMAT (TYPE_MODE (type))->emin);
9213
9214 /* Get the user-requested adjustment. */
9215 const HOST_WIDE_INT req_exp_adj = tree_low_cst (arg1, 0);
48e1416a 9216
7587301b 9217 /* The requested adjustment must be inside this range. This
9218 is a preliminary cap to avoid things like overflow, we
9219 may still fail to compute the result for other reasons. */
9220 if (-max_exp_adj < req_exp_adj && req_exp_adj < max_exp_adj)
9221 {
9222 REAL_VALUE_TYPE initial_result;
48e1416a 9223
7587301b 9224 real_ldexp (&initial_result, &TREE_REAL_CST (arg0), req_exp_adj);
9225
9226 /* Ensure we didn't overflow. */
9227 if (! real_isinf (&initial_result))
9228 {
9229 const REAL_VALUE_TYPE trunc_result
9230 = real_value_truncate (TYPE_MODE (type), initial_result);
48e1416a 9231
7587301b 9232 /* Only proceed if the target mode can hold the
9233 resulting value. */
9234 if (REAL_VALUES_EQUAL (initial_result, trunc_result))
9235 return build_real (type, trunc_result);
9236 }
9237 }
9238 }
9239 }
9240
9241 return NULL_TREE;
9242}
9243
ebf8b4f5 9244/* Fold a call to builtin modf. */
9245
9246static tree
389dd41b 9247fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
ebf8b4f5 9248{
9249 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9250 return NULL_TREE;
48e1416a 9251
ebf8b4f5 9252 STRIP_NOPS (arg0);
48e1416a 9253
ebf8b4f5 9254 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9255 return NULL_TREE;
48e1416a 9256
389dd41b 9257 arg1 = build_fold_indirect_ref_loc (loc, arg1);
ebf8b4f5 9258
9259 /* Proceed if a valid pointer type was passed in. */
9260 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
9261 {
9262 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9263 REAL_VALUE_TYPE trunc, frac;
9264
9265 switch (value->cl)
9266 {
9267 case rvc_nan:
9268 case rvc_zero:
9269 /* For +-NaN or +-0, return (*arg1 = arg0, arg0). */
9270 trunc = frac = *value;
9271 break;
9272 case rvc_inf:
9273 /* For +-Inf, return (*arg1 = arg0, +-0). */
9274 frac = dconst0;
9275 frac.sign = value->sign;
9276 trunc = *value;
9277 break;
9278 case rvc_normal:
9279 /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)). */
9280 real_trunc (&trunc, VOIDmode, value);
9281 real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
9282 /* If the original number was negative and already
9283 integral, then the fractional part is -0.0. */
9284 if (value->sign && frac.cl == rvc_zero)
9285 frac.sign = value->sign;
9286 break;
9287 }
48e1416a 9288
ebf8b4f5 9289 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
389dd41b 9290 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1,
ebf8b4f5 9291 build_real (rettype, trunc));
9292 TREE_SIDE_EFFECTS (arg1) = 1;
389dd41b 9293 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1,
ebf8b4f5 9294 build_real (rettype, frac));
9295 }
48e1416a 9296
ebf8b4f5 9297 return NULL_TREE;
9298}
9299
a65c4d64 9300/* Given a location LOC, an interclass builtin function decl FNDECL
9301 and its single argument ARG, return an folded expression computing
9302 the same, or NULL_TREE if we either couldn't or didn't want to fold
9303 (the latter happen if there's an RTL instruction available). */
9304
9305static tree
9306fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
9307{
9308 enum machine_mode mode;
9309
9310 if (!validate_arg (arg, REAL_TYPE))
9311 return NULL_TREE;
9312
9313 if (interclass_mathfn_icode (arg, fndecl) != CODE_FOR_nothing)
9314 return NULL_TREE;
9315
9316 mode = TYPE_MODE (TREE_TYPE (arg));
9317
9318 /* If there is no optab, try generic code. */
9319 switch (DECL_FUNCTION_CODE (fndecl))
9320 {
9321 tree result;
9322
9323 CASE_FLT_FN (BUILT_IN_ISINF):
9324 {
9325 /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
9326 tree const isgr_fn = built_in_decls[BUILT_IN_ISGREATER];
9327 tree const type = TREE_TYPE (arg);
9328 REAL_VALUE_TYPE r;
9329 char buf[128];
9330
9331 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9332 real_from_string (&r, buf);
9333 result = build_call_expr (isgr_fn, 2,
9334 fold_build1_loc (loc, ABS_EXPR, type, arg),
9335 build_real (type, r));
9336 return result;
9337 }
9338 CASE_FLT_FN (BUILT_IN_FINITE):
9339 case BUILT_IN_ISFINITE:
9340 {
9341 /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
9342 tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
9343 tree const type = TREE_TYPE (arg);
9344 REAL_VALUE_TYPE r;
9345 char buf[128];
9346
9347 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9348 real_from_string (&r, buf);
9349 result = build_call_expr (isle_fn, 2,
9350 fold_build1_loc (loc, ABS_EXPR, type, arg),
9351 build_real (type, r));
9352 /*result = fold_build2_loc (loc, UNGT_EXPR,
9353 TREE_TYPE (TREE_TYPE (fndecl)),
9354 fold_build1_loc (loc, ABS_EXPR, type, arg),
9355 build_real (type, r));
9356 result = fold_build1_loc (loc, TRUTH_NOT_EXPR,
9357 TREE_TYPE (TREE_TYPE (fndecl)),
9358 result);*/
9359 return result;
9360 }
9361 case BUILT_IN_ISNORMAL:
9362 {
9363 /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
9364 islessequal(fabs(x),DBL_MAX). */
9365 tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
9366 tree const isge_fn = built_in_decls[BUILT_IN_ISGREATEREQUAL];
9367 tree const type = TREE_TYPE (arg);
9368 REAL_VALUE_TYPE rmax, rmin;
9369 char buf[128];
9370
9371 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9372 real_from_string (&rmax, buf);
9373 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
9374 real_from_string (&rmin, buf);
9375 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
9376 result = build_call_expr (isle_fn, 2, arg,
9377 build_real (type, rmax));
9378 result = fold_build2 (BIT_AND_EXPR, integer_type_node, result,
9379 build_call_expr (isge_fn, 2, arg,
9380 build_real (type, rmin)));
9381 return result;
9382 }
9383 default:
9384 break;
9385 }
9386
9387 return NULL_TREE;
9388}
9389
726069ba 9390/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
c2f47e15 9391 ARG is the argument for the call. */
726069ba 9392
9393static tree
389dd41b 9394fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
726069ba 9395{
726069ba 9396 tree type = TREE_TYPE (TREE_TYPE (fndecl));
726069ba 9397 REAL_VALUE_TYPE r;
9398
c2f47e15 9399 if (!validate_arg (arg, REAL_TYPE))
d43cee80 9400 return NULL_TREE;
726069ba 9401
726069ba 9402 switch (builtin_index)
9403 {
9404 case BUILT_IN_ISINF:
b70bfd00 9405 if (!HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 9406 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
726069ba 9407
9408 if (TREE_CODE (arg) == REAL_CST)
9409 {
9410 r = TREE_REAL_CST (arg);
9411 if (real_isinf (&r))
9412 return real_compare (GT_EXPR, &r, &dconst0)
9413 ? integer_one_node : integer_minus_one_node;
9414 else
9415 return integer_zero_node;
9416 }
9417
9418 return NULL_TREE;
9419
c319d56a 9420 case BUILT_IN_ISINF_SIGN:
9421 {
9422 /* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */
9423 /* In a boolean context, GCC will fold the inner COND_EXPR to
9424 1. So e.g. "if (isinf_sign(x))" would be folded to just
9425 "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
9426 tree signbit_fn = mathfn_built_in_1 (TREE_TYPE (arg), BUILT_IN_SIGNBIT, 0);
9427 tree isinf_fn = built_in_decls[BUILT_IN_ISINF];
9428 tree tmp = NULL_TREE;
9429
9430 arg = builtin_save_expr (arg);
9431
9432 if (signbit_fn && isinf_fn)
9433 {
389dd41b 9434 tree signbit_call = build_call_expr_loc (loc, signbit_fn, 1, arg);
9435 tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg);
c319d56a 9436
389dd41b 9437 signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
c319d56a 9438 signbit_call, integer_zero_node);
389dd41b 9439 isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
c319d56a 9440 isinf_call, integer_zero_node);
48e1416a 9441
389dd41b 9442 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call,
c319d56a 9443 integer_minus_one_node, integer_one_node);
389dd41b 9444 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
9445 isinf_call, tmp,
c319d56a 9446 integer_zero_node);
9447 }
9448
9449 return tmp;
9450 }
9451
cde061c1 9452 case BUILT_IN_ISFINITE:
b70bfd00 9453 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
9454 && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 9455 return omit_one_operand_loc (loc, type, integer_one_node, arg);
726069ba 9456
9457 if (TREE_CODE (arg) == REAL_CST)
9458 {
9459 r = TREE_REAL_CST (arg);
776a7bab 9460 return real_isfinite (&r) ? integer_one_node : integer_zero_node;
726069ba 9461 }
9462
9463 return NULL_TREE;
9464
9465 case BUILT_IN_ISNAN:
b70bfd00 9466 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 9467 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
726069ba 9468
9469 if (TREE_CODE (arg) == REAL_CST)
9470 {
9471 r = TREE_REAL_CST (arg);
9472 return real_isnan (&r) ? integer_one_node : integer_zero_node;
9473 }
9474
9475 arg = builtin_save_expr (arg);
389dd41b 9476 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
726069ba 9477
9478 default:
64db345d 9479 gcc_unreachable ();
726069ba 9480 }
9481}
9482
19fbe3a4 9483/* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...).
9484 This builtin will generate code to return the appropriate floating
9485 point classification depending on the value of the floating point
9486 number passed in. The possible return values must be supplied as
921b27c0 9487 int arguments to the call in the following order: FP_NAN, FP_INFINITE,
19fbe3a4 9488 FP_NORMAL, FP_SUBNORMAL and FP_ZERO. The ellipses is for exactly
9489 one floating point argument which is "type generic". */
9490
9491static tree
389dd41b 9492fold_builtin_fpclassify (location_t loc, tree exp)
19fbe3a4 9493{
921b27c0 9494 tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
9495 arg, type, res, tmp;
19fbe3a4 9496 enum machine_mode mode;
9497 REAL_VALUE_TYPE r;
9498 char buf[128];
48e1416a 9499
19fbe3a4 9500 /* Verify the required arguments in the original call. */
9501 if (!validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE,
9502 INTEGER_TYPE, INTEGER_TYPE,
9503 INTEGER_TYPE, REAL_TYPE, VOID_TYPE))
9504 return NULL_TREE;
48e1416a 9505
19fbe3a4 9506 fp_nan = CALL_EXPR_ARG (exp, 0);
921b27c0 9507 fp_infinite = CALL_EXPR_ARG (exp, 1);
19fbe3a4 9508 fp_normal = CALL_EXPR_ARG (exp, 2);
9509 fp_subnormal = CALL_EXPR_ARG (exp, 3);
9510 fp_zero = CALL_EXPR_ARG (exp, 4);
9511 arg = CALL_EXPR_ARG (exp, 5);
9512 type = TREE_TYPE (arg);
9513 mode = TYPE_MODE (type);
389dd41b 9514 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
19fbe3a4 9515
48e1416a 9516 /* fpclassify(x) ->
19fbe3a4 9517 isnan(x) ? FP_NAN :
921b27c0 9518 (fabs(x) == Inf ? FP_INFINITE :
19fbe3a4 9519 (fabs(x) >= DBL_MIN ? FP_NORMAL :
9520 (x == 0 ? FP_ZERO : FP_SUBNORMAL))). */
48e1416a 9521
389dd41b 9522 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
19fbe3a4 9523 build_real (type, dconst0));
389dd41b 9524 res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
9525 tmp, fp_zero, fp_subnormal);
19fbe3a4 9526
9527 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
9528 real_from_string (&r, buf);
389dd41b 9529 tmp = fold_build2_loc (loc, GE_EXPR, integer_type_node,
9530 arg, build_real (type, r));
9531 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, fp_normal, res);
48e1416a 9532
19fbe3a4 9533 if (HONOR_INFINITIES (mode))
9534 {
9535 real_inf (&r);
389dd41b 9536 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
19fbe3a4 9537 build_real (type, r));
389dd41b 9538 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
9539 fp_infinite, res);
19fbe3a4 9540 }
9541
9542 if (HONOR_NANS (mode))
9543 {
389dd41b 9544 tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
9545 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, res, fp_nan);
19fbe3a4 9546 }
48e1416a 9547
19fbe3a4 9548 return res;
9549}
9550
9bc9f15f 9551/* Fold a call to an unordered comparison function such as
d5019fe8 9552 __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function
c2f47e15 9553 being called and ARG0 and ARG1 are the arguments for the call.
726069ba 9554 UNORDERED_CODE and ORDERED_CODE are comparison codes that give
9555 the opposite of the desired result. UNORDERED_CODE is used
9556 for modes that can hold NaNs and ORDERED_CODE is used for
9557 the rest. */
9bc9f15f 9558
9559static tree
389dd41b 9560fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
9bc9f15f 9561 enum tree_code unordered_code,
9562 enum tree_code ordered_code)
9563{
859f903a 9564 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9bc9f15f 9565 enum tree_code code;
6978db0d 9566 tree type0, type1;
9567 enum tree_code code0, code1;
9568 tree cmp_type = NULL_TREE;
9bc9f15f 9569
6978db0d 9570 type0 = TREE_TYPE (arg0);
9571 type1 = TREE_TYPE (arg1);
a0c938f0 9572
6978db0d 9573 code0 = TREE_CODE (type0);
9574 code1 = TREE_CODE (type1);
a0c938f0 9575
6978db0d 9576 if (code0 == REAL_TYPE && code1 == REAL_TYPE)
9577 /* Choose the wider of two real types. */
9578 cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
9579 ? type0 : type1;
9580 else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
9581 cmp_type = type0;
9582 else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
9583 cmp_type = type1;
a0c938f0 9584
389dd41b 9585 arg0 = fold_convert_loc (loc, cmp_type, arg0);
9586 arg1 = fold_convert_loc (loc, cmp_type, arg1);
859f903a 9587
9588 if (unordered_code == UNORDERED_EXPR)
9589 {
b70bfd00 9590 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
389dd41b 9591 return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
9592 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
859f903a 9593 }
9bc9f15f 9594
b70bfd00 9595 code = HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
9596 : ordered_code;
389dd41b 9597 return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
9598 fold_build2_loc (loc, code, type, arg0, arg1));
9bc9f15f 9599}
9600
c2f47e15 9601/* Fold a call to built-in function FNDECL with 0 arguments.
9602 IGNORE is true if the result of the function call is ignored. This
9603 function returns NULL_TREE if no simplification was possible. */
650e4c94 9604
4ee9c684 9605static tree
389dd41b 9606fold_builtin_0 (location_t loc, tree fndecl, bool ignore ATTRIBUTE_UNUSED)
650e4c94 9607{
e9f80ff5 9608 tree type = TREE_TYPE (TREE_TYPE (fndecl));
c2f47e15 9609 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
189b3398 9610 switch (fcode)
650e4c94 9611 {
c2f47e15 9612 CASE_FLT_FN (BUILT_IN_INF):
9613 case BUILT_IN_INFD32:
9614 case BUILT_IN_INFD64:
9615 case BUILT_IN_INFD128:
389dd41b 9616 return fold_builtin_inf (loc, type, true);
7c2f0500 9617
c2f47e15 9618 CASE_FLT_FN (BUILT_IN_HUGE_VAL):
389dd41b 9619 return fold_builtin_inf (loc, type, false);
7c2f0500 9620
c2f47e15 9621 case BUILT_IN_CLASSIFY_TYPE:
9622 return fold_builtin_classify_type (NULL_TREE);
7c2f0500 9623
c2f47e15 9624 default:
9625 break;
9626 }
9627 return NULL_TREE;
9628}
7c2f0500 9629
c2f47e15 9630/* Fold a call to built-in function FNDECL with 1 argument, ARG0.
9631 IGNORE is true if the result of the function call is ignored. This
9632 function returns NULL_TREE if no simplification was possible. */
7c2f0500 9633
c2f47e15 9634static tree
389dd41b 9635fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
c2f47e15 9636{
9637 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9638 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9639 switch (fcode)
9640 {
7c2f0500 9641
650e4c94 9642 case BUILT_IN_CONSTANT_P:
7c2f0500 9643 {
c2f47e15 9644 tree val = fold_builtin_constant_p (arg0);
7c2f0500 9645
7c2f0500 9646 /* Gimplification will pull the CALL_EXPR for the builtin out of
9647 an if condition. When not optimizing, we'll not CSE it back.
9648 To avoid link error types of regressions, return false now. */
9649 if (!val && !optimize)
9650 val = integer_zero_node;
9651
9652 return val;
9653 }
650e4c94 9654
539a3a92 9655 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 9656 return fold_builtin_classify_type (arg0);
539a3a92 9657
650e4c94 9658 case BUILT_IN_STRLEN:
389dd41b 9659 return fold_builtin_strlen (loc, arg0);
650e4c94 9660
4f35b1fc 9661 CASE_FLT_FN (BUILT_IN_FABS):
389dd41b 9662 return fold_builtin_fabs (loc, arg0, type);
d1aade50 9663
9664 case BUILT_IN_ABS:
9665 case BUILT_IN_LABS:
9666 case BUILT_IN_LLABS:
9667 case BUILT_IN_IMAXABS:
389dd41b 9668 return fold_builtin_abs (loc, arg0, type);
c63f4ad3 9669
4f35b1fc 9670 CASE_FLT_FN (BUILT_IN_CONJ):
239d491a 9671 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9672 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 9673 return fold_build1_loc (loc, CONJ_EXPR, type, arg0);
c2f47e15 9674 break;
36d3581d 9675
4f35b1fc 9676 CASE_FLT_FN (BUILT_IN_CREAL):
239d491a 9677 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9678 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 9679 return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));;
c2f47e15 9680 break;
36d3581d 9681
4f35b1fc 9682 CASE_FLT_FN (BUILT_IN_CIMAG):
b0ce8887 9683 if (validate_arg (arg0, COMPLEX_TYPE)
9684 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 9685 return non_lvalue_loc (loc, fold_build1_loc (loc, IMAGPART_EXPR, type, arg0));
c2f47e15 9686 break;
36d3581d 9687
503733d5 9688 CASE_FLT_FN (BUILT_IN_CCOS):
389dd41b 9689 return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ false);
48e1416a 9690
503733d5 9691 CASE_FLT_FN (BUILT_IN_CCOSH):
389dd41b 9692 return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ true);
48e1416a 9693
239d491a 9694 CASE_FLT_FN (BUILT_IN_CSIN):
9695 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9696 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 9697 return do_mpc_arg1 (arg0, type, mpc_sin);
c2f47e15 9698 break;
48e1416a 9699
239d491a 9700 CASE_FLT_FN (BUILT_IN_CSINH):
9701 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9702 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 9703 return do_mpc_arg1 (arg0, type, mpc_sinh);
9704 break;
48e1416a 9705
239d491a 9706 CASE_FLT_FN (BUILT_IN_CTAN):
9707 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9708 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 9709 return do_mpc_arg1 (arg0, type, mpc_tan);
9710 break;
48e1416a 9711
239d491a 9712 CASE_FLT_FN (BUILT_IN_CTANH):
9713 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9714 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 9715 return do_mpc_arg1 (arg0, type, mpc_tanh);
9716 break;
48e1416a 9717
239d491a 9718 CASE_FLT_FN (BUILT_IN_CLOG):
9719 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9720 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 9721 return do_mpc_arg1 (arg0, type, mpc_log);
9722 break;
48e1416a 9723
239d491a 9724 CASE_FLT_FN (BUILT_IN_CSQRT):
9725 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9726 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 9727 return do_mpc_arg1 (arg0, type, mpc_sqrt);
9728 break;
48e1416a 9729
0e7e6e7f 9730 CASE_FLT_FN (BUILT_IN_CASIN):
9731 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9732 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 9733 return do_mpc_arg1 (arg0, type, mpc_asin);
9734 break;
48e1416a 9735
0e7e6e7f 9736 CASE_FLT_FN (BUILT_IN_CACOS):
9737 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9738 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 9739 return do_mpc_arg1 (arg0, type, mpc_acos);
9740 break;
48e1416a 9741
0e7e6e7f 9742 CASE_FLT_FN (BUILT_IN_CATAN):
9743 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9744 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 9745 return do_mpc_arg1 (arg0, type, mpc_atan);
9746 break;
48e1416a 9747
0e7e6e7f 9748 CASE_FLT_FN (BUILT_IN_CASINH):
9749 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9750 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 9751 return do_mpc_arg1 (arg0, type, mpc_asinh);
9752 break;
48e1416a 9753
0e7e6e7f 9754 CASE_FLT_FN (BUILT_IN_CACOSH):
9755 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9756 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 9757 return do_mpc_arg1 (arg0, type, mpc_acosh);
9758 break;
48e1416a 9759
0e7e6e7f 9760 CASE_FLT_FN (BUILT_IN_CATANH):
9761 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 9762 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 9763 return do_mpc_arg1 (arg0, type, mpc_atanh);
9764 break;
48e1416a 9765
4f35b1fc 9766 CASE_FLT_FN (BUILT_IN_CABS):
389dd41b 9767 return fold_builtin_cabs (loc, arg0, type, fndecl);
c63f4ad3 9768
abe4dcf6 9769 CASE_FLT_FN (BUILT_IN_CARG):
389dd41b 9770 return fold_builtin_carg (loc, arg0, type);
abe4dcf6 9771
4f35b1fc 9772 CASE_FLT_FN (BUILT_IN_SQRT):
389dd41b 9773 return fold_builtin_sqrt (loc, arg0, type);
805e22b2 9774
4f35b1fc 9775 CASE_FLT_FN (BUILT_IN_CBRT):
389dd41b 9776 return fold_builtin_cbrt (loc, arg0, type);
3bc5c41b 9777
728bac60 9778 CASE_FLT_FN (BUILT_IN_ASIN):
c2f47e15 9779 if (validate_arg (arg0, REAL_TYPE))
9780 return do_mpfr_arg1 (arg0, type, mpfr_asin,
728bac60 9781 &dconstm1, &dconst1, true);
9782 break;
9783
9784 CASE_FLT_FN (BUILT_IN_ACOS):
c2f47e15 9785 if (validate_arg (arg0, REAL_TYPE))
9786 return do_mpfr_arg1 (arg0, type, mpfr_acos,
728bac60 9787 &dconstm1, &dconst1, true);
9788 break;
9789
9790 CASE_FLT_FN (BUILT_IN_ATAN):
c2f47e15 9791 if (validate_arg (arg0, REAL_TYPE))
9792 return do_mpfr_arg1 (arg0, type, mpfr_atan, NULL, NULL, 0);
728bac60 9793 break;
9794
9795 CASE_FLT_FN (BUILT_IN_ASINH):
c2f47e15 9796 if (validate_arg (arg0, REAL_TYPE))
9797 return do_mpfr_arg1 (arg0, type, mpfr_asinh, NULL, NULL, 0);
728bac60 9798 break;
9799
9800 CASE_FLT_FN (BUILT_IN_ACOSH):
c2f47e15 9801 if (validate_arg (arg0, REAL_TYPE))
9802 return do_mpfr_arg1 (arg0, type, mpfr_acosh,
728bac60 9803 &dconst1, NULL, true);
9804 break;
9805
9806 CASE_FLT_FN (BUILT_IN_ATANH):
c2f47e15 9807 if (validate_arg (arg0, REAL_TYPE))
9808 return do_mpfr_arg1 (arg0, type, mpfr_atanh,
728bac60 9809 &dconstm1, &dconst1, false);
9810 break;
9811
4f35b1fc 9812 CASE_FLT_FN (BUILT_IN_SIN):
c2f47e15 9813 if (validate_arg (arg0, REAL_TYPE))
9814 return do_mpfr_arg1 (arg0, type, mpfr_sin, NULL, NULL, 0);
728bac60 9815 break;
77e89269 9816
4f35b1fc 9817 CASE_FLT_FN (BUILT_IN_COS):
389dd41b 9818 return fold_builtin_cos (loc, arg0, type, fndecl);
77e89269 9819
728bac60 9820 CASE_FLT_FN (BUILT_IN_TAN):
c2f47e15 9821 return fold_builtin_tan (arg0, type);
d735c391 9822
c5bb2c4b 9823 CASE_FLT_FN (BUILT_IN_CEXP):
389dd41b 9824 return fold_builtin_cexp (loc, arg0, type);
c5bb2c4b 9825
d735c391 9826 CASE_FLT_FN (BUILT_IN_CEXPI):
c2f47e15 9827 if (validate_arg (arg0, REAL_TYPE))
9828 return do_mpfr_sincos (arg0, NULL_TREE, NULL_TREE);
9829 break;
d92f994c 9830
728bac60 9831 CASE_FLT_FN (BUILT_IN_SINH):
c2f47e15 9832 if (validate_arg (arg0, REAL_TYPE))
9833 return do_mpfr_arg1 (arg0, type, mpfr_sinh, NULL, NULL, 0);
728bac60 9834 break;
9835
9836 CASE_FLT_FN (BUILT_IN_COSH):
389dd41b 9837 return fold_builtin_cosh (loc, arg0, type, fndecl);
728bac60 9838
9839 CASE_FLT_FN (BUILT_IN_TANH):
c2f47e15 9840 if (validate_arg (arg0, REAL_TYPE))
9841 return do_mpfr_arg1 (arg0, type, mpfr_tanh, NULL, NULL, 0);
728bac60 9842 break;
9843
29f4cd78 9844 CASE_FLT_FN (BUILT_IN_ERF):
c2f47e15 9845 if (validate_arg (arg0, REAL_TYPE))
9846 return do_mpfr_arg1 (arg0, type, mpfr_erf, NULL, NULL, 0);
29f4cd78 9847 break;
9848
9849 CASE_FLT_FN (BUILT_IN_ERFC):
c2f47e15 9850 if (validate_arg (arg0, REAL_TYPE))
9851 return do_mpfr_arg1 (arg0, type, mpfr_erfc, NULL, NULL, 0);
29f4cd78 9852 break;
9853
32dba52b 9854 CASE_FLT_FN (BUILT_IN_TGAMMA):
c2f47e15 9855 if (validate_arg (arg0, REAL_TYPE))
9856 return do_mpfr_arg1 (arg0, type, mpfr_gamma, NULL, NULL, 0);
32dba52b 9857 break;
48e1416a 9858
4f35b1fc 9859 CASE_FLT_FN (BUILT_IN_EXP):
389dd41b 9860 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp);
467214fd 9861
4f35b1fc 9862 CASE_FLT_FN (BUILT_IN_EXP2):
389dd41b 9863 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp2);
467214fd 9864
4f35b1fc 9865 CASE_FLT_FN (BUILT_IN_EXP10):
9866 CASE_FLT_FN (BUILT_IN_POW10):
389dd41b 9867 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp10);
467214fd 9868
29f4cd78 9869 CASE_FLT_FN (BUILT_IN_EXPM1):
c2f47e15 9870 if (validate_arg (arg0, REAL_TYPE))
9871 return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0);
29f4cd78 9872 break;
48e1416a 9873
4f35b1fc 9874 CASE_FLT_FN (BUILT_IN_LOG):
389dd41b 9875 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log);
467214fd 9876
4f35b1fc 9877 CASE_FLT_FN (BUILT_IN_LOG2):
389dd41b 9878 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log2);
467214fd 9879
4f35b1fc 9880 CASE_FLT_FN (BUILT_IN_LOG10):
389dd41b 9881 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log10);
29f4cd78 9882
9883 CASE_FLT_FN (BUILT_IN_LOG1P):
c2f47e15 9884 if (validate_arg (arg0, REAL_TYPE))
9885 return do_mpfr_arg1 (arg0, type, mpfr_log1p,
29f4cd78 9886 &dconstm1, NULL, false);
9887 break;
805e22b2 9888
65dd1378 9889 CASE_FLT_FN (BUILT_IN_J0):
9890 if (validate_arg (arg0, REAL_TYPE))
9891 return do_mpfr_arg1 (arg0, type, mpfr_j0,
9892 NULL, NULL, 0);
9893 break;
9894
9895 CASE_FLT_FN (BUILT_IN_J1):
9896 if (validate_arg (arg0, REAL_TYPE))
9897 return do_mpfr_arg1 (arg0, type, mpfr_j1,
9898 NULL, NULL, 0);
9899 break;
6ff9eeff 9900
9901 CASE_FLT_FN (BUILT_IN_Y0):
9902 if (validate_arg (arg0, REAL_TYPE))
9903 return do_mpfr_arg1 (arg0, type, mpfr_y0,
9904 &dconst0, NULL, false);
9905 break;
9906
9907 CASE_FLT_FN (BUILT_IN_Y1):
9908 if (validate_arg (arg0, REAL_TYPE))
9909 return do_mpfr_arg1 (arg0, type, mpfr_y1,
9910 &dconst0, NULL, false);
9911 break;
65dd1378 9912
4f35b1fc 9913 CASE_FLT_FN (BUILT_IN_NAN):
c4503c0a 9914 case BUILT_IN_NAND32:
9915 case BUILT_IN_NAND64:
9916 case BUILT_IN_NAND128:
c2f47e15 9917 return fold_builtin_nan (arg0, type, true);
b0db7939 9918
4f35b1fc 9919 CASE_FLT_FN (BUILT_IN_NANS):
c2f47e15 9920 return fold_builtin_nan (arg0, type, false);
b0db7939 9921
4f35b1fc 9922 CASE_FLT_FN (BUILT_IN_FLOOR):
389dd41b 9923 return fold_builtin_floor (loc, fndecl, arg0);
277f8dd2 9924
4f35b1fc 9925 CASE_FLT_FN (BUILT_IN_CEIL):
389dd41b 9926 return fold_builtin_ceil (loc, fndecl, arg0);
277f8dd2 9927
4f35b1fc 9928 CASE_FLT_FN (BUILT_IN_TRUNC):
389dd41b 9929 return fold_builtin_trunc (loc, fndecl, arg0);
277f8dd2 9930
4f35b1fc 9931 CASE_FLT_FN (BUILT_IN_ROUND):
389dd41b 9932 return fold_builtin_round (loc, fndecl, arg0);
89ab3887 9933
4f35b1fc 9934 CASE_FLT_FN (BUILT_IN_NEARBYINT):
9935 CASE_FLT_FN (BUILT_IN_RINT):
389dd41b 9936 return fold_trunc_transparent_mathfn (loc, fndecl, arg0);
6528f4f4 9937
4f35b1fc 9938 CASE_FLT_FN (BUILT_IN_LCEIL):
9939 CASE_FLT_FN (BUILT_IN_LLCEIL):
9940 CASE_FLT_FN (BUILT_IN_LFLOOR):
9941 CASE_FLT_FN (BUILT_IN_LLFLOOR):
a0c938f0 9942 CASE_FLT_FN (BUILT_IN_LROUND):
4f35b1fc 9943 CASE_FLT_FN (BUILT_IN_LLROUND):
389dd41b 9944 return fold_builtin_int_roundingfn (loc, fndecl, arg0);
34f17811 9945
4f35b1fc 9946 CASE_FLT_FN (BUILT_IN_LRINT):
9947 CASE_FLT_FN (BUILT_IN_LLRINT):
389dd41b 9948 return fold_fixed_mathfn (loc, fndecl, arg0);
9ed65c7f 9949
42791117 9950 case BUILT_IN_BSWAP32:
9951 case BUILT_IN_BSWAP64:
c2f47e15 9952 return fold_builtin_bswap (fndecl, arg0);
42791117 9953
4f35b1fc 9954 CASE_INT_FN (BUILT_IN_FFS):
9955 CASE_INT_FN (BUILT_IN_CLZ):
9956 CASE_INT_FN (BUILT_IN_CTZ):
9957 CASE_INT_FN (BUILT_IN_POPCOUNT):
9958 CASE_INT_FN (BUILT_IN_PARITY):
c2f47e15 9959 return fold_builtin_bitop (fndecl, arg0);
9c8a1629 9960
4f35b1fc 9961 CASE_FLT_FN (BUILT_IN_SIGNBIT):
389dd41b 9962 return fold_builtin_signbit (loc, arg0, type);
27f261ef 9963
cb2b9385 9964 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
389dd41b 9965 return fold_builtin_significand (loc, arg0, type);
cb2b9385 9966
9967 CASE_FLT_FN (BUILT_IN_ILOGB):
9968 CASE_FLT_FN (BUILT_IN_LOGB):
389dd41b 9969 return fold_builtin_logb (loc, arg0, type);
cb2b9385 9970
d49367d4 9971 case BUILT_IN_ISASCII:
389dd41b 9972 return fold_builtin_isascii (loc, arg0);
d49367d4 9973
9974 case BUILT_IN_TOASCII:
389dd41b 9975 return fold_builtin_toascii (loc, arg0);
d49367d4 9976
df1cf42e 9977 case BUILT_IN_ISDIGIT:
389dd41b 9978 return fold_builtin_isdigit (loc, arg0);
467214fd 9979
4f35b1fc 9980 CASE_FLT_FN (BUILT_IN_FINITE):
c4503c0a 9981 case BUILT_IN_FINITED32:
9982 case BUILT_IN_FINITED64:
9983 case BUILT_IN_FINITED128:
cde061c1 9984 case BUILT_IN_ISFINITE:
a65c4d64 9985 {
9986 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISFINITE);
9987 if (ret)
9988 return ret;
9989 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
9990 }
726069ba 9991
4f35b1fc 9992 CASE_FLT_FN (BUILT_IN_ISINF):
c4503c0a 9993 case BUILT_IN_ISINFD32:
9994 case BUILT_IN_ISINFD64:
9995 case BUILT_IN_ISINFD128:
a65c4d64 9996 {
9997 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF);
9998 if (ret)
9999 return ret;
10000 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10001 }
10002
10003 case BUILT_IN_ISNORMAL:
10004 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
726069ba 10005
c319d56a 10006 case BUILT_IN_ISINF_SIGN:
389dd41b 10007 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF_SIGN);
c319d56a 10008
4f35b1fc 10009 CASE_FLT_FN (BUILT_IN_ISNAN):
c4503c0a 10010 case BUILT_IN_ISNAND32:
10011 case BUILT_IN_ISNAND64:
10012 case BUILT_IN_ISNAND128:
389dd41b 10013 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
c2f47e15 10014
10015 case BUILT_IN_PRINTF:
10016 case BUILT_IN_PRINTF_UNLOCKED:
10017 case BUILT_IN_VPRINTF:
389dd41b 10018 return fold_builtin_printf (loc, fndecl, arg0, NULL_TREE, ignore, fcode);
c2f47e15 10019
10020 default:
10021 break;
10022 }
10023
10024 return NULL_TREE;
10025
10026}
10027
10028/* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1.
10029 IGNORE is true if the result of the function call is ignored. This
10030 function returns NULL_TREE if no simplification was possible. */
10031
10032static tree
389dd41b 10033fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore)
c2f47e15 10034{
10035 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10036 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10037
10038 switch (fcode)
10039 {
65dd1378 10040 CASE_FLT_FN (BUILT_IN_JN):
10041 if (validate_arg (arg0, INTEGER_TYPE)
10042 && validate_arg (arg1, REAL_TYPE))
10043 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_jn, NULL, 0);
10044 break;
6ff9eeff 10045
10046 CASE_FLT_FN (BUILT_IN_YN):
10047 if (validate_arg (arg0, INTEGER_TYPE)
10048 && validate_arg (arg1, REAL_TYPE))
10049 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_yn,
10050 &dconst0, false);
10051 break;
e5407ca6 10052
10053 CASE_FLT_FN (BUILT_IN_DREM):
10054 CASE_FLT_FN (BUILT_IN_REMAINDER):
10055 if (validate_arg (arg0, REAL_TYPE)
10056 && validate_arg(arg1, REAL_TYPE))
10057 return do_mpfr_arg2 (arg0, arg1, type, mpfr_remainder);
10058 break;
e84da7c1 10059
10060 CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
10061 CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
10062 if (validate_arg (arg0, REAL_TYPE)
10063 && validate_arg(arg1, POINTER_TYPE))
10064 return do_mpfr_lgamma_r (arg0, arg1, type);
10065 break;
c2f47e15 10066
10067 CASE_FLT_FN (BUILT_IN_ATAN2):
10068 if (validate_arg (arg0, REAL_TYPE)
10069 && validate_arg(arg1, REAL_TYPE))
10070 return do_mpfr_arg2 (arg0, arg1, type, mpfr_atan2);
10071 break;
10072
10073 CASE_FLT_FN (BUILT_IN_FDIM):
10074 if (validate_arg (arg0, REAL_TYPE)
10075 && validate_arg(arg1, REAL_TYPE))
10076 return do_mpfr_arg2 (arg0, arg1, type, mpfr_dim);
10077 break;
10078
10079 CASE_FLT_FN (BUILT_IN_HYPOT):
389dd41b 10080 return fold_builtin_hypot (loc, fndecl, arg0, arg1, type);
c2f47e15 10081
c699fab8 10082 CASE_FLT_FN (BUILT_IN_CPOW):
10083 if (validate_arg (arg0, COMPLEX_TYPE)
10084 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
10085 && validate_arg (arg1, COMPLEX_TYPE)
48e1416a 10086 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE)
652d9409 10087 return do_mpc_arg2 (arg0, arg1, type, /*do_nonfinite=*/ 0, mpc_pow);
c699fab8 10088 break;
c699fab8 10089
7587301b 10090 CASE_FLT_FN (BUILT_IN_LDEXP):
389dd41b 10091 return fold_builtin_load_exponent (loc, arg0, arg1, type, /*ldexp=*/true);
7587301b 10092 CASE_FLT_FN (BUILT_IN_SCALBN):
10093 CASE_FLT_FN (BUILT_IN_SCALBLN):
389dd41b 10094 return fold_builtin_load_exponent (loc, arg0, arg1,
10095 type, /*ldexp=*/false);
7587301b 10096
3838b9ae 10097 CASE_FLT_FN (BUILT_IN_FREXP):
389dd41b 10098 return fold_builtin_frexp (loc, arg0, arg1, type);
3838b9ae 10099
ebf8b4f5 10100 CASE_FLT_FN (BUILT_IN_MODF):
389dd41b 10101 return fold_builtin_modf (loc, arg0, arg1, type);
ebf8b4f5 10102
c2f47e15 10103 case BUILT_IN_BZERO:
389dd41b 10104 return fold_builtin_bzero (loc, arg0, arg1, ignore);
c2f47e15 10105
10106 case BUILT_IN_FPUTS:
389dd41b 10107 return fold_builtin_fputs (loc, arg0, arg1, ignore, false, NULL_TREE);
c2f47e15 10108
10109 case BUILT_IN_FPUTS_UNLOCKED:
389dd41b 10110 return fold_builtin_fputs (loc, arg0, arg1, ignore, true, NULL_TREE);
c2f47e15 10111
10112 case BUILT_IN_STRSTR:
389dd41b 10113 return fold_builtin_strstr (loc, arg0, arg1, type);
c2f47e15 10114
10115 case BUILT_IN_STRCAT:
389dd41b 10116 return fold_builtin_strcat (loc, arg0, arg1);
c2f47e15 10117
10118 case BUILT_IN_STRSPN:
389dd41b 10119 return fold_builtin_strspn (loc, arg0, arg1);
c2f47e15 10120
10121 case BUILT_IN_STRCSPN:
389dd41b 10122 return fold_builtin_strcspn (loc, arg0, arg1);
c2f47e15 10123
10124 case BUILT_IN_STRCHR:
10125 case BUILT_IN_INDEX:
389dd41b 10126 return fold_builtin_strchr (loc, arg0, arg1, type);
c2f47e15 10127
10128 case BUILT_IN_STRRCHR:
10129 case BUILT_IN_RINDEX:
389dd41b 10130 return fold_builtin_strrchr (loc, arg0, arg1, type);
c2f47e15 10131
10132 case BUILT_IN_STRCPY:
389dd41b 10133 return fold_builtin_strcpy (loc, fndecl, arg0, arg1, NULL_TREE);
c2f47e15 10134
c8b17b2e 10135 case BUILT_IN_STPCPY:
10136 if (ignore)
10137 {
10138 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
10139 if (!fn)
10140 break;
10141
389dd41b 10142 return build_call_expr_loc (loc, fn, 2, arg0, arg1);
c8b17b2e 10143 }
a65c4d64 10144 else
10145 return fold_builtin_stpcpy (loc, fndecl, arg0, arg1);
c8b17b2e 10146 break;
10147
c2f47e15 10148 case BUILT_IN_STRCMP:
389dd41b 10149 return fold_builtin_strcmp (loc, arg0, arg1);
c2f47e15 10150
10151 case BUILT_IN_STRPBRK:
389dd41b 10152 return fold_builtin_strpbrk (loc, arg0, arg1, type);
c2f47e15 10153
10154 case BUILT_IN_EXPECT:
389dd41b 10155 return fold_builtin_expect (loc, arg0, arg1);
c2f47e15 10156
10157 CASE_FLT_FN (BUILT_IN_POW):
389dd41b 10158 return fold_builtin_pow (loc, fndecl, arg0, arg1, type);
c2f47e15 10159
10160 CASE_FLT_FN (BUILT_IN_POWI):
389dd41b 10161 return fold_builtin_powi (loc, fndecl, arg0, arg1, type);
c2f47e15 10162
10163 CASE_FLT_FN (BUILT_IN_COPYSIGN):
389dd41b 10164 return fold_builtin_copysign (loc, fndecl, arg0, arg1, type);
c2f47e15 10165
10166 CASE_FLT_FN (BUILT_IN_FMIN):
389dd41b 10167 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/false);
c2f47e15 10168
10169 CASE_FLT_FN (BUILT_IN_FMAX):
389dd41b 10170 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/true);
726069ba 10171
9bc9f15f 10172 case BUILT_IN_ISGREATER:
389dd41b 10173 return fold_builtin_unordered_cmp (loc, fndecl,
10174 arg0, arg1, UNLE_EXPR, LE_EXPR);
9bc9f15f 10175 case BUILT_IN_ISGREATEREQUAL:
389dd41b 10176 return fold_builtin_unordered_cmp (loc, fndecl,
10177 arg0, arg1, UNLT_EXPR, LT_EXPR);
9bc9f15f 10178 case BUILT_IN_ISLESS:
389dd41b 10179 return fold_builtin_unordered_cmp (loc, fndecl,
10180 arg0, arg1, UNGE_EXPR, GE_EXPR);
9bc9f15f 10181 case BUILT_IN_ISLESSEQUAL:
389dd41b 10182 return fold_builtin_unordered_cmp (loc, fndecl,
10183 arg0, arg1, UNGT_EXPR, GT_EXPR);
9bc9f15f 10184 case BUILT_IN_ISLESSGREATER:
389dd41b 10185 return fold_builtin_unordered_cmp (loc, fndecl,
10186 arg0, arg1, UNEQ_EXPR, EQ_EXPR);
9bc9f15f 10187 case BUILT_IN_ISUNORDERED:
389dd41b 10188 return fold_builtin_unordered_cmp (loc, fndecl,
10189 arg0, arg1, UNORDERED_EXPR,
d5019fe8 10190 NOP_EXPR);
9bc9f15f 10191
7c2f0500 10192 /* We do the folding for va_start in the expander. */
10193 case BUILT_IN_VA_START:
10194 break;
f0613857 10195
c2f47e15 10196 case BUILT_IN_SPRINTF:
389dd41b 10197 return fold_builtin_sprintf (loc, arg0, arg1, NULL_TREE, ignore);
c2f47e15 10198
0a39fd54 10199 case BUILT_IN_OBJECT_SIZE:
c2f47e15 10200 return fold_builtin_object_size (arg0, arg1);
0a39fd54 10201
10202 case BUILT_IN_PRINTF:
10203 case BUILT_IN_PRINTF_UNLOCKED:
10204 case BUILT_IN_VPRINTF:
389dd41b 10205 return fold_builtin_printf (loc, fndecl, arg0, arg1, ignore, fcode);
c2f47e15 10206
0a39fd54 10207 case BUILT_IN_PRINTF_CHK:
10208 case BUILT_IN_VPRINTF_CHK:
c2f47e15 10209 if (!validate_arg (arg0, INTEGER_TYPE)
10210 || TREE_SIDE_EFFECTS (arg0))
10211 return NULL_TREE;
10212 else
389dd41b 10213 return fold_builtin_printf (loc, fndecl,
10214 arg1, NULL_TREE, ignore, fcode);
c2f47e15 10215 break;
0a39fd54 10216
10217 case BUILT_IN_FPRINTF:
10218 case BUILT_IN_FPRINTF_UNLOCKED:
10219 case BUILT_IN_VFPRINTF:
389dd41b 10220 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, NULL_TREE,
c2f47e15 10221 ignore, fcode);
10222
10223 default:
10224 break;
10225 }
10226 return NULL_TREE;
10227}
10228
10229/* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
10230 and ARG2. IGNORE is true if the result of the function call is ignored.
10231 This function returns NULL_TREE if no simplification was possible. */
10232
10233static tree
389dd41b 10234fold_builtin_3 (location_t loc, tree fndecl,
10235 tree arg0, tree arg1, tree arg2, bool ignore)
c2f47e15 10236{
10237 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10238 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10239 switch (fcode)
10240 {
10241
10242 CASE_FLT_FN (BUILT_IN_SINCOS):
389dd41b 10243 return fold_builtin_sincos (loc, arg0, arg1, arg2);
c2f47e15 10244
10245 CASE_FLT_FN (BUILT_IN_FMA):
10246 if (validate_arg (arg0, REAL_TYPE)
10247 && validate_arg(arg1, REAL_TYPE)
10248 && validate_arg(arg2, REAL_TYPE))
10249 return do_mpfr_arg3 (arg0, arg1, arg2, type, mpfr_fma);
10250 break;
10251
e5407ca6 10252 CASE_FLT_FN (BUILT_IN_REMQUO):
10253 if (validate_arg (arg0, REAL_TYPE)
10254 && validate_arg(arg1, REAL_TYPE)
10255 && validate_arg(arg2, POINTER_TYPE))
10256 return do_mpfr_remquo (arg0, arg1, arg2);
10257 break;
e5407ca6 10258
c2f47e15 10259 case BUILT_IN_MEMSET:
389dd41b 10260 return fold_builtin_memset (loc, arg0, arg1, arg2, type, ignore);
c2f47e15 10261
10262 case BUILT_IN_BCOPY:
389dd41b 10263 return fold_builtin_memory_op (loc, arg1, arg0, arg2,
10264 void_type_node, true, /*endp=*/3);
c2f47e15 10265
10266 case BUILT_IN_MEMCPY:
389dd41b 10267 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10268 type, ignore, /*endp=*/0);
c2f47e15 10269
10270 case BUILT_IN_MEMPCPY:
389dd41b 10271 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10272 type, ignore, /*endp=*/1);
c2f47e15 10273
10274 case BUILT_IN_MEMMOVE:
389dd41b 10275 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10276 type, ignore, /*endp=*/3);
c2f47e15 10277
10278 case BUILT_IN_STRNCAT:
389dd41b 10279 return fold_builtin_strncat (loc, arg0, arg1, arg2);
c2f47e15 10280
10281 case BUILT_IN_STRNCPY:
389dd41b 10282 return fold_builtin_strncpy (loc, fndecl, arg0, arg1, arg2, NULL_TREE);
c2f47e15 10283
10284 case BUILT_IN_STRNCMP:
389dd41b 10285 return fold_builtin_strncmp (loc, arg0, arg1, arg2);
c2f47e15 10286
7959b13b 10287 case BUILT_IN_MEMCHR:
389dd41b 10288 return fold_builtin_memchr (loc, arg0, arg1, arg2, type);
7959b13b 10289
c2f47e15 10290 case BUILT_IN_BCMP:
10291 case BUILT_IN_MEMCMP:
389dd41b 10292 return fold_builtin_memcmp (loc, arg0, arg1, arg2);;
c2f47e15 10293
10294 case BUILT_IN_SPRINTF:
389dd41b 10295 return fold_builtin_sprintf (loc, arg0, arg1, arg2, ignore);
c2f47e15 10296
10297 case BUILT_IN_STRCPY_CHK:
10298 case BUILT_IN_STPCPY_CHK:
389dd41b 10299 return fold_builtin_stxcpy_chk (loc, fndecl, arg0, arg1, arg2, NULL_TREE,
c2f47e15 10300 ignore, fcode);
10301
10302 case BUILT_IN_STRCAT_CHK:
389dd41b 10303 return fold_builtin_strcat_chk (loc, fndecl, arg0, arg1, arg2);
c2f47e15 10304
10305 case BUILT_IN_PRINTF_CHK:
10306 case BUILT_IN_VPRINTF_CHK:
10307 if (!validate_arg (arg0, INTEGER_TYPE)
10308 || TREE_SIDE_EFFECTS (arg0))
10309 return NULL_TREE;
10310 else
389dd41b 10311 return fold_builtin_printf (loc, fndecl, arg1, arg2, ignore, fcode);
c2f47e15 10312 break;
10313
10314 case BUILT_IN_FPRINTF:
10315 case BUILT_IN_FPRINTF_UNLOCKED:
10316 case BUILT_IN_VFPRINTF:
389dd41b 10317 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, arg2,
10318 ignore, fcode);
c2f47e15 10319
0a39fd54 10320 case BUILT_IN_FPRINTF_CHK:
10321 case BUILT_IN_VFPRINTF_CHK:
c2f47e15 10322 if (!validate_arg (arg1, INTEGER_TYPE)
10323 || TREE_SIDE_EFFECTS (arg1))
10324 return NULL_TREE;
10325 else
389dd41b 10326 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, NULL_TREE,
c2f47e15 10327 ignore, fcode);
0a39fd54 10328
650e4c94 10329 default:
10330 break;
10331 }
c2f47e15 10332 return NULL_TREE;
10333}
650e4c94 10334
c2f47e15 10335/* Fold a call to built-in function FNDECL with 4 arguments, ARG0, ARG1,
10336 ARG2, and ARG3. IGNORE is true if the result of the function call is
10337 ignored. This function returns NULL_TREE if no simplification was
10338 possible. */
48e1416a 10339
c2f47e15 10340static tree
389dd41b 10341fold_builtin_4 (location_t loc, tree fndecl,
10342 tree arg0, tree arg1, tree arg2, tree arg3, bool ignore)
c2f47e15 10343{
10344 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10345
10346 switch (fcode)
10347 {
10348 case BUILT_IN_MEMCPY_CHK:
10349 case BUILT_IN_MEMPCPY_CHK:
10350 case BUILT_IN_MEMMOVE_CHK:
10351 case BUILT_IN_MEMSET_CHK:
389dd41b 10352 return fold_builtin_memory_chk (loc, fndecl, arg0, arg1, arg2, arg3,
c2f47e15 10353 NULL_TREE, ignore,
10354 DECL_FUNCTION_CODE (fndecl));
10355
10356 case BUILT_IN_STRNCPY_CHK:
389dd41b 10357 return fold_builtin_strncpy_chk (loc, arg0, arg1, arg2, arg3, NULL_TREE);
c2f47e15 10358
10359 case BUILT_IN_STRNCAT_CHK:
389dd41b 10360 return fold_builtin_strncat_chk (loc, fndecl, arg0, arg1, arg2, arg3);
c2f47e15 10361
10362 case BUILT_IN_FPRINTF_CHK:
10363 case BUILT_IN_VFPRINTF_CHK:
10364 if (!validate_arg (arg1, INTEGER_TYPE)
10365 || TREE_SIDE_EFFECTS (arg1))
10366 return NULL_TREE;
10367 else
389dd41b 10368 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, arg3,
c2f47e15 10369 ignore, fcode);
10370 break;
10371
10372 default:
10373 break;
10374 }
10375 return NULL_TREE;
10376}
10377
10378/* Fold a call to built-in function FNDECL. ARGS is an array of NARGS
10379 arguments, where NARGS <= 4. IGNORE is true if the result of the
10380 function call is ignored. This function returns NULL_TREE if no
10381 simplification was possible. Note that this only folds builtins with
10382 fixed argument patterns. Foldings that do varargs-to-varargs
10383 transformations, or that match calls with more than 4 arguments,
10384 need to be handled with fold_builtin_varargs instead. */
48e1416a 10385
c2f47e15 10386#define MAX_ARGS_TO_FOLD_BUILTIN 4
48e1416a 10387
c2f47e15 10388static tree
389dd41b 10389fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool ignore)
c2f47e15 10390{
10391 tree ret = NULL_TREE;
a7f5bb2d 10392
c2f47e15 10393 switch (nargs)
10394 {
10395 case 0:
389dd41b 10396 ret = fold_builtin_0 (loc, fndecl, ignore);
c2f47e15 10397 break;
10398 case 1:
389dd41b 10399 ret = fold_builtin_1 (loc, fndecl, args[0], ignore);
c2f47e15 10400 break;
10401 case 2:
389dd41b 10402 ret = fold_builtin_2 (loc, fndecl, args[0], args[1], ignore);
c2f47e15 10403 break;
10404 case 3:
389dd41b 10405 ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2], ignore);
c2f47e15 10406 break;
10407 case 4:
389dd41b 10408 ret = fold_builtin_4 (loc, fndecl, args[0], args[1], args[2], args[3],
c2f47e15 10409 ignore);
10410 break;
10411 default:
10412 break;
10413 }
10414 if (ret)
10415 {
75a70cf9 10416 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
389dd41b 10417 SET_EXPR_LOCATION (ret, loc);
c2f47e15 10418 TREE_NO_WARNING (ret) = 1;
10419 return ret;
10420 }
10421 return NULL_TREE;
10422}
10423
10424/* Builtins with folding operations that operate on "..." arguments
10425 need special handling; we need to store the arguments in a convenient
10426 data structure before attempting any folding. Fortunately there are
10427 only a few builtins that fall into this category. FNDECL is the
10428 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
10429 result of the function call is ignored. */
10430
10431static tree
389dd41b 10432fold_builtin_varargs (location_t loc, tree fndecl, tree exp,
10433 bool ignore ATTRIBUTE_UNUSED)
c2f47e15 10434{
10435 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10436 tree ret = NULL_TREE;
10437
10438 switch (fcode)
10439 {
10440 case BUILT_IN_SPRINTF_CHK:
10441 case BUILT_IN_VSPRINTF_CHK:
389dd41b 10442 ret = fold_builtin_sprintf_chk (loc, exp, fcode);
c2f47e15 10443 break;
10444
10445 case BUILT_IN_SNPRINTF_CHK:
10446 case BUILT_IN_VSNPRINTF_CHK:
389dd41b 10447 ret = fold_builtin_snprintf_chk (loc, exp, NULL_TREE, fcode);
19fbe3a4 10448 break;
10449
10450 case BUILT_IN_FPCLASSIFY:
389dd41b 10451 ret = fold_builtin_fpclassify (loc, exp);
19fbe3a4 10452 break;
c2f47e15 10453
10454 default:
10455 break;
10456 }
10457 if (ret)
10458 {
10459 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
389dd41b 10460 SET_EXPR_LOCATION (ret, loc);
c2f47e15 10461 TREE_NO_WARNING (ret) = 1;
10462 return ret;
10463 }
10464 return NULL_TREE;
650e4c94 10465}
7e15618b 10466
198622c0 10467/* Return true if FNDECL shouldn't be folded right now.
10468 If a built-in function has an inline attribute always_inline
10469 wrapper, defer folding it after always_inline functions have
10470 been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
10471 might not be performed. */
10472
10473static bool
10474avoid_folding_inline_builtin (tree fndecl)
10475{
10476 return (DECL_DECLARED_INLINE_P (fndecl)
10477 && DECL_DISREGARD_INLINE_LIMITS (fndecl)
10478 && cfun
10479 && !cfun->always_inline_functions_inlined
10480 && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)));
10481}
10482
4ee9c684 10483/* A wrapper function for builtin folding that prevents warnings for
491e04ef 10484 "statement without effect" and the like, caused by removing the
4ee9c684 10485 call node earlier than the warning is generated. */
10486
10487tree
389dd41b 10488fold_call_expr (location_t loc, tree exp, bool ignore)
4ee9c684 10489{
c2f47e15 10490 tree ret = NULL_TREE;
10491 tree fndecl = get_callee_fndecl (exp);
10492 if (fndecl
10493 && TREE_CODE (fndecl) == FUNCTION_DECL
48dc2227 10494 && DECL_BUILT_IN (fndecl)
10495 /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
10496 yet. Defer folding until we see all the arguments
10497 (after inlining). */
10498 && !CALL_EXPR_VA_ARG_PACK (exp))
10499 {
10500 int nargs = call_expr_nargs (exp);
10501
10502 /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
10503 instead last argument is __builtin_va_arg_pack (). Defer folding
10504 even in that case, until arguments are finalized. */
10505 if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
10506 {
10507 tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1));
10508 if (fndecl2
10509 && TREE_CODE (fndecl2) == FUNCTION_DECL
10510 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
10511 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
10512 return NULL_TREE;
10513 }
10514
198622c0 10515 if (avoid_folding_inline_builtin (fndecl))
10516 return NULL_TREE;
10517
c2f47e15 10518 /* FIXME: Don't use a list in this interface. */
10519 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
10520 return targetm.fold_builtin (fndecl, CALL_EXPR_ARGS (exp), ignore);
10521 else
10522 {
c2f47e15 10523 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
10524 {
10525 tree *args = CALL_EXPR_ARGP (exp);
389dd41b 10526 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
c2f47e15 10527 }
10528 if (!ret)
389dd41b 10529 ret = fold_builtin_varargs (loc, fndecl, exp, ignore);
c2f47e15 10530 if (ret)
389dd41b 10531 return ret;
c2f47e15 10532 }
4ee9c684 10533 }
c2f47e15 10534 return NULL_TREE;
10535}
48e1416a 10536
c2f47e15 10537/* Conveniently construct a function call expression. FNDECL names the
10538 function to be called and ARGLIST is a TREE_LIST of arguments. */
48e1416a 10539
c2f47e15 10540tree
389dd41b 10541build_function_call_expr (location_t loc, tree fndecl, tree arglist)
c2f47e15 10542{
10543 tree fntype = TREE_TYPE (fndecl);
10544 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
d01f58f9 10545 int n = list_length (arglist);
10546 tree *argarray = (tree *) alloca (n * sizeof (tree));
10547 int i;
389dd41b 10548
d01f58f9 10549 for (i = 0; i < n; i++, arglist = TREE_CHAIN (arglist))
10550 argarray[i] = TREE_VALUE (arglist);
389dd41b 10551 return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray);
c2f47e15 10552}
10553
10554/* Conveniently construct a function call expression. FNDECL names the
10555 function to be called, N is the number of arguments, and the "..."
10556 parameters are the argument expressions. */
48e1416a 10557
c2f47e15 10558tree
389dd41b 10559build_call_expr_loc (location_t loc, tree fndecl, int n, ...)
c2f47e15 10560{
10561 va_list ap;
c2f47e15 10562 tree fntype = TREE_TYPE (fndecl);
10563 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
d01f58f9 10564 tree *argarray = (tree *) alloca (n * sizeof (tree));
10565 int i;
c2f47e15 10566
10567 va_start (ap, n);
d01f58f9 10568 for (i = 0; i < n; i++)
10569 argarray[i] = va_arg (ap, tree);
c2f47e15 10570 va_end (ap);
389dd41b 10571 return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray);
4ee9c684 10572}
10573
c2f47e15 10574/* Construct a CALL_EXPR with type TYPE with FN as the function expression.
d01f58f9 10575 N arguments are passed in the array ARGARRAY. */
805e22b2 10576
10577tree
389dd41b 10578fold_builtin_call_array (location_t loc, tree type,
d01f58f9 10579 tree fn,
10580 int n,
10581 tree *argarray)
7e15618b 10582{
c2f47e15 10583 tree ret = NULL_TREE;
10584 int i;
10585 tree exp;
10586
10587 if (TREE_CODE (fn) == ADDR_EXPR)
10588 {
10589 tree fndecl = TREE_OPERAND (fn, 0);
10590 if (TREE_CODE (fndecl) == FUNCTION_DECL
10591 && DECL_BUILT_IN (fndecl))
10592 {
48dc2227 10593 /* If last argument is __builtin_va_arg_pack (), arguments to this
10594 function are not finalized yet. Defer folding until they are. */
10595 if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
10596 {
10597 tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
10598 if (fndecl2
10599 && TREE_CODE (fndecl2) == FUNCTION_DECL
10600 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
10601 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
389dd41b 10602 return build_call_array_loc (loc, type, fn, n, argarray);
48dc2227 10603 }
198622c0 10604 if (avoid_folding_inline_builtin (fndecl))
389dd41b 10605 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 10606 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
10607 {
10608 tree arglist = NULL_TREE;
d01f58f9 10609 for (i = n - 1; i >= 0; i--)
10610 arglist = tree_cons (NULL_TREE, argarray[i], arglist);
c2f47e15 10611 ret = targetm.fold_builtin (fndecl, arglist, false);
10612 if (ret)
10613 return ret;
389dd41b 10614 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 10615 }
10616 else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
10617 {
10618 /* First try the transformations that don't require consing up
10619 an exp. */
389dd41b 10620 ret = fold_builtin_n (loc, fndecl, argarray, n, false);
c2f47e15 10621 if (ret)
10622 return ret;
10623 }
10624
10625 /* If we got this far, we need to build an exp. */
389dd41b 10626 exp = build_call_array_loc (loc, type, fn, n, argarray);
10627 ret = fold_builtin_varargs (loc, fndecl, exp, false);
c2f47e15 10628 return ret ? ret : exp;
10629 }
10630 }
10631
389dd41b 10632 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 10633}
10634
10635/* Construct a new CALL_EXPR using the tail of the argument list of EXP
10636 along with N new arguments specified as the "..." parameters. SKIP
10637 is the number of arguments in EXP to be omitted. This function is used
10638 to do varargs-to-varargs transformations. */
10639
10640static tree
389dd41b 10641rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...)
c2f47e15 10642{
10643 int oldnargs = call_expr_nargs (exp);
10644 int nargs = oldnargs - skip + n;
10645 tree fntype = TREE_TYPE (fndecl);
10646 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
10647 tree *buffer;
10648
10649 if (n > 0)
10650 {
10651 int i, j;
10652 va_list ap;
7e15618b 10653
364c0c59 10654 buffer = XALLOCAVEC (tree, nargs);
c2f47e15 10655 va_start (ap, n);
10656 for (i = 0; i < n; i++)
10657 buffer[i] = va_arg (ap, tree);
10658 va_end (ap);
10659 for (j = skip; j < oldnargs; j++, i++)
10660 buffer[i] = CALL_EXPR_ARG (exp, j);
10661 }
48e1416a 10662 else
c2f47e15 10663 buffer = CALL_EXPR_ARGP (exp) + skip;
10664
389dd41b 10665 return fold (build_call_array_loc (loc, TREE_TYPE (exp), fn, nargs, buffer));
c2f47e15 10666}
10667
10668/* Validate a single argument ARG against a tree code CODE representing
10669 a type. */
48e1416a 10670
c2f47e15 10671static bool
b7bf20db 10672validate_arg (const_tree arg, enum tree_code code)
c2f47e15 10673{
10674 if (!arg)
10675 return false;
10676 else if (code == POINTER_TYPE)
10677 return POINTER_TYPE_P (TREE_TYPE (arg));
c7f617c2 10678 else if (code == INTEGER_TYPE)
10679 return INTEGRAL_TYPE_P (TREE_TYPE (arg));
c2f47e15 10680 return code == TREE_CODE (TREE_TYPE (arg));
7e15618b 10681}
0eb671f7 10682
75a70cf9 10683/* This function validates the types of a function call argument list
10684 against a specified list of tree_codes. If the last specifier is a 0,
10685 that represents an ellipses, otherwise the last specifier must be a
10686 VOID_TYPE.
10687
10688 This is the GIMPLE version of validate_arglist. Eventually we want to
10689 completely convert builtins.c to work from GIMPLEs and the tree based
10690 validate_arglist will then be removed. */
10691
10692bool
10693validate_gimple_arglist (const_gimple call, ...)
10694{
10695 enum tree_code code;
10696 bool res = 0;
10697 va_list ap;
10698 const_tree arg;
10699 size_t i;
10700
10701 va_start (ap, call);
10702 i = 0;
10703
10704 do
10705 {
d62e827b 10706 code = (enum tree_code) va_arg (ap, int);
75a70cf9 10707 switch (code)
10708 {
10709 case 0:
10710 /* This signifies an ellipses, any further arguments are all ok. */
10711 res = true;
10712 goto end;
10713 case VOID_TYPE:
10714 /* This signifies an endlink, if no arguments remain, return
10715 true, otherwise return false. */
10716 res = (i == gimple_call_num_args (call));
10717 goto end;
10718 default:
10719 /* If no parameters remain or the parameter's code does not
10720 match the specified code, return false. Otherwise continue
10721 checking any remaining arguments. */
10722 arg = gimple_call_arg (call, i++);
10723 if (!validate_arg (arg, code))
10724 goto end;
10725 break;
10726 }
10727 }
10728 while (1);
10729
10730 /* We need gotos here since we can only have one VA_CLOSE in a
10731 function. */
10732 end: ;
10733 va_end (ap);
10734
10735 return res;
10736}
10737
0eb671f7 10738/* This function validates the types of a function call argument list
c2f47e15 10739 against a specified list of tree_codes. If the last specifier is a 0,
10740 that represents an ellipses, otherwise the last specifier must be a
10741 VOID_TYPE. */
27d0c333 10742
c2f47e15 10743bool
b7bf20db 10744validate_arglist (const_tree callexpr, ...)
0eb671f7 10745{
0eb671f7 10746 enum tree_code code;
c2f47e15 10747 bool res = 0;
ee582a61 10748 va_list ap;
b7bf20db 10749 const_call_expr_arg_iterator iter;
10750 const_tree arg;
aecda0d6 10751
c2f47e15 10752 va_start (ap, callexpr);
b7bf20db 10753 init_const_call_expr_arg_iterator (callexpr, &iter);
0eb671f7 10754
f0ce3b1f 10755 do
0eb671f7 10756 {
d62e827b 10757 code = (enum tree_code) va_arg (ap, int);
f0ce3b1f 10758 switch (code)
10759 {
10760 case 0:
10761 /* This signifies an ellipses, any further arguments are all ok. */
c2f47e15 10762 res = true;
f0ce3b1f 10763 goto end;
10764 case VOID_TYPE:
10765 /* This signifies an endlink, if no arguments remain, return
10766 true, otherwise return false. */
b7bf20db 10767 res = !more_const_call_expr_args_p (&iter);
f0ce3b1f 10768 goto end;
10769 default:
10770 /* If no parameters remain or the parameter's code does not
10771 match the specified code, return false. Otherwise continue
10772 checking any remaining arguments. */
b7bf20db 10773 arg = next_const_call_expr_arg (&iter);
c2f47e15 10774 if (!validate_arg (arg, code))
f0ce3b1f 10775 goto end;
10776 break;
10777 }
0eb671f7 10778 }
f0ce3b1f 10779 while (1);
0903457a 10780
10781 /* We need gotos here since we can only have one VA_CLOSE in a
10782 function. */
10783 end: ;
ee582a61 10784 va_end (ap);
0903457a 10785
10786 return res;
0eb671f7 10787}
fc2a2dcb 10788
fc2a2dcb 10789/* Default target-specific builtin expander that does nothing. */
10790
10791rtx
aecda0d6 10792default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
10793 rtx target ATTRIBUTE_UNUSED,
10794 rtx subtarget ATTRIBUTE_UNUSED,
10795 enum machine_mode mode ATTRIBUTE_UNUSED,
10796 int ignore ATTRIBUTE_UNUSED)
fc2a2dcb 10797{
10798 return NULL_RTX;
10799}
c7926a82 10800
01537105 10801/* Returns true is EXP represents data that would potentially reside
10802 in a readonly section. */
10803
10804static bool
10805readonly_data_expr (tree exp)
10806{
10807 STRIP_NOPS (exp);
10808
9ff0637e 10809 if (TREE_CODE (exp) != ADDR_EXPR)
10810 return false;
10811
10812 exp = get_base_address (TREE_OPERAND (exp, 0));
10813 if (!exp)
10814 return false;
10815
10816 /* Make sure we call decl_readonly_section only for trees it
10817 can handle (since it returns true for everything it doesn't
10818 understand). */
491e04ef 10819 if (TREE_CODE (exp) == STRING_CST
9ff0637e 10820 || TREE_CODE (exp) == CONSTRUCTOR
10821 || (TREE_CODE (exp) == VAR_DECL && TREE_STATIC (exp)))
10822 return decl_readonly_section (exp, 0);
01537105 10823 else
10824 return false;
10825}
4ee9c684 10826
c2f47e15 10827/* Simplify a call to the strstr builtin. S1 and S2 are the arguments
10828 to the call, and TYPE is its return type.
4ee9c684 10829
c2f47e15 10830 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10831 simplified form of the call as a tree.
10832
10833 The simplified form may be a constant or other expression which
10834 computes the same value, but in a more efficient manner (including
10835 calls to other builtin functions).
10836
10837 The call may contain arguments which need to be evaluated, but
10838 which are not useful to determine the result of the call. In
10839 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10840 COMPOUND_EXPR will be an argument which must be evaluated.
10841 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10842 COMPOUND_EXPR in the chain will contain the tree for the simplified
10843 form of the builtin function call. */
10844
10845static tree
389dd41b 10846fold_builtin_strstr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 10847{
c2f47e15 10848 if (!validate_arg (s1, POINTER_TYPE)
10849 || !validate_arg (s2, POINTER_TYPE))
10850 return NULL_TREE;
4ee9c684 10851 else
10852 {
4ee9c684 10853 tree fn;
10854 const char *p1, *p2;
10855
10856 p2 = c_getstr (s2);
10857 if (p2 == NULL)
c2f47e15 10858 return NULL_TREE;
4ee9c684 10859
10860 p1 = c_getstr (s1);
10861 if (p1 != NULL)
10862 {
10863 const char *r = strstr (p1, p2);
daa1d5f5 10864 tree tem;
4ee9c684 10865
4ee9c684 10866 if (r == NULL)
779b4c41 10867 return build_int_cst (TREE_TYPE (s1), 0);
c0c67e38 10868
10869 /* Return an offset into the constant string argument. */
389dd41b 10870 tem = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (s1),
0de36bdb 10871 s1, size_int (r - p1));
389dd41b 10872 return fold_convert_loc (loc, type, tem);
4ee9c684 10873 }
10874
7efa231c 10875 /* The argument is const char *, and the result is char *, so we need
10876 a type conversion here to avoid a warning. */
4ee9c684 10877 if (p2[0] == '\0')
389dd41b 10878 return fold_convert_loc (loc, type, s1);
4ee9c684 10879
10880 if (p2[1] != '\0')
c2f47e15 10881 return NULL_TREE;
4ee9c684 10882
10883 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
10884 if (!fn)
c2f47e15 10885 return NULL_TREE;
4ee9c684 10886
10887 /* New argument list transforming strstr(s1, s2) to
10888 strchr(s1, s2[0]). */
389dd41b 10889 return build_call_expr_loc (loc, fn, 2, s1, build_int_cst (NULL_TREE, p2[0]));
4ee9c684 10890 }
10891}
10892
c2f47e15 10893/* Simplify a call to the strchr builtin. S1 and S2 are the arguments to
10894 the call, and TYPE is its return type.
4ee9c684 10895
c2f47e15 10896 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10897 simplified form of the call as a tree.
10898
10899 The simplified form may be a constant or other expression which
10900 computes the same value, but in a more efficient manner (including
10901 calls to other builtin functions).
10902
10903 The call may contain arguments which need to be evaluated, but
10904 which are not useful to determine the result of the call. In
10905 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10906 COMPOUND_EXPR will be an argument which must be evaluated.
10907 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10908 COMPOUND_EXPR in the chain will contain the tree for the simplified
10909 form of the builtin function call. */
10910
10911static tree
389dd41b 10912fold_builtin_strchr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 10913{
c2f47e15 10914 if (!validate_arg (s1, POINTER_TYPE)
10915 || !validate_arg (s2, INTEGER_TYPE))
10916 return NULL_TREE;
4ee9c684 10917 else
10918 {
4ee9c684 10919 const char *p1;
10920
10921 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 10922 return NULL_TREE;
4ee9c684 10923
10924 p1 = c_getstr (s1);
10925 if (p1 != NULL)
10926 {
10927 char c;
10928 const char *r;
daa1d5f5 10929 tree tem;
4ee9c684 10930
10931 if (target_char_cast (s2, &c))
c2f47e15 10932 return NULL_TREE;
4ee9c684 10933
10934 r = strchr (p1, c);
10935
10936 if (r == NULL)
779b4c41 10937 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 10938
10939 /* Return an offset into the constant string argument. */
389dd41b 10940 tem = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (s1),
0de36bdb 10941 s1, size_int (r - p1));
389dd41b 10942 return fold_convert_loc (loc, type, tem);
4ee9c684 10943 }
c2f47e15 10944 return NULL_TREE;
4ee9c684 10945 }
10946}
10947
c2f47e15 10948/* Simplify a call to the strrchr builtin. S1 and S2 are the arguments to
10949 the call, and TYPE is its return type.
4ee9c684 10950
c2f47e15 10951 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 10952 simplified form of the call as a tree.
10953
10954 The simplified form may be a constant or other expression which
10955 computes the same value, but in a more efficient manner (including
10956 calls to other builtin functions).
10957
10958 The call may contain arguments which need to be evaluated, but
10959 which are not useful to determine the result of the call. In
10960 this case we return a chain of COMPOUND_EXPRs. The LHS of each
10961 COMPOUND_EXPR will be an argument which must be evaluated.
10962 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
10963 COMPOUND_EXPR in the chain will contain the tree for the simplified
10964 form of the builtin function call. */
10965
10966static tree
389dd41b 10967fold_builtin_strrchr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 10968{
c2f47e15 10969 if (!validate_arg (s1, POINTER_TYPE)
10970 || !validate_arg (s2, INTEGER_TYPE))
10971 return NULL_TREE;
4ee9c684 10972 else
10973 {
4ee9c684 10974 tree fn;
10975 const char *p1;
10976
10977 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 10978 return NULL_TREE;
4ee9c684 10979
10980 p1 = c_getstr (s1);
10981 if (p1 != NULL)
10982 {
10983 char c;
10984 const char *r;
daa1d5f5 10985 tree tem;
4ee9c684 10986
10987 if (target_char_cast (s2, &c))
c2f47e15 10988 return NULL_TREE;
4ee9c684 10989
10990 r = strrchr (p1, c);
10991
10992 if (r == NULL)
779b4c41 10993 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 10994
10995 /* Return an offset into the constant string argument. */
389dd41b 10996 tem = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (s1),
0de36bdb 10997 s1, size_int (r - p1));
389dd41b 10998 return fold_convert_loc (loc, type, tem);
4ee9c684 10999 }
11000
11001 if (! integer_zerop (s2))
c2f47e15 11002 return NULL_TREE;
4ee9c684 11003
11004 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
11005 if (!fn)
c2f47e15 11006 return NULL_TREE;
4ee9c684 11007
11008 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
389dd41b 11009 return build_call_expr_loc (loc, fn, 2, s1, s2);
4ee9c684 11010 }
11011}
11012
c2f47e15 11013/* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments
11014 to the call, and TYPE is its return type.
4ee9c684 11015
c2f47e15 11016 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11017 simplified form of the call as a tree.
11018
11019 The simplified form may be a constant or other expression which
11020 computes the same value, but in a more efficient manner (including
11021 calls to other builtin functions).
11022
11023 The call may contain arguments which need to be evaluated, but
11024 which are not useful to determine the result of the call. In
11025 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11026 COMPOUND_EXPR will be an argument which must be evaluated.
11027 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11028 COMPOUND_EXPR in the chain will contain the tree for the simplified
11029 form of the builtin function call. */
11030
11031static tree
389dd41b 11032fold_builtin_strpbrk (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11033{
c2f47e15 11034 if (!validate_arg (s1, POINTER_TYPE)
11035 || !validate_arg (s2, POINTER_TYPE))
11036 return NULL_TREE;
4ee9c684 11037 else
11038 {
4ee9c684 11039 tree fn;
11040 const char *p1, *p2;
11041
11042 p2 = c_getstr (s2);
11043 if (p2 == NULL)
c2f47e15 11044 return NULL_TREE;
4ee9c684 11045
11046 p1 = c_getstr (s1);
11047 if (p1 != NULL)
11048 {
11049 const char *r = strpbrk (p1, p2);
daa1d5f5 11050 tree tem;
4ee9c684 11051
11052 if (r == NULL)
779b4c41 11053 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11054
11055 /* Return an offset into the constant string argument. */
389dd41b 11056 tem = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (s1),
0de36bdb 11057 s1, size_int (r - p1));
389dd41b 11058 return fold_convert_loc (loc, type, tem);
4ee9c684 11059 }
11060
11061 if (p2[0] == '\0')
05abc81b 11062 /* strpbrk(x, "") == NULL.
11063 Evaluate and ignore s1 in case it had side-effects. */
389dd41b 11064 return omit_one_operand_loc (loc, TREE_TYPE (s1), integer_zero_node, s1);
4ee9c684 11065
11066 if (p2[1] != '\0')
c2f47e15 11067 return NULL_TREE; /* Really call strpbrk. */
4ee9c684 11068
11069 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
11070 if (!fn)
c2f47e15 11071 return NULL_TREE;
4ee9c684 11072
11073 /* New argument list transforming strpbrk(s1, s2) to
11074 strchr(s1, s2[0]). */
389dd41b 11075 return build_call_expr_loc (loc, fn, 2, s1, build_int_cst (NULL_TREE, p2[0]));
4ee9c684 11076 }
11077}
11078
c2f47e15 11079/* Simplify a call to the strcat builtin. DST and SRC are the arguments
11080 to the call.
4ee9c684 11081
c2f47e15 11082 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11083 simplified form of the call as a tree.
11084
11085 The simplified form may be a constant or other expression which
11086 computes the same value, but in a more efficient manner (including
11087 calls to other builtin functions).
11088
11089 The call may contain arguments which need to be evaluated, but
11090 which are not useful to determine the result of the call. In
11091 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11092 COMPOUND_EXPR will be an argument which must be evaluated.
11093 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11094 COMPOUND_EXPR in the chain will contain the tree for the simplified
11095 form of the builtin function call. */
11096
11097static tree
389dd41b 11098fold_builtin_strcat (location_t loc ATTRIBUTE_UNUSED, tree dst, tree src)
4ee9c684 11099{
c2f47e15 11100 if (!validate_arg (dst, POINTER_TYPE)
11101 || !validate_arg (src, POINTER_TYPE))
11102 return NULL_TREE;
4ee9c684 11103 else
11104 {
4ee9c684 11105 const char *p = c_getstr (src);
11106
11107 /* If the string length is zero, return the dst parameter. */
11108 if (p && *p == '\0')
11109 return dst;
11110
a65c4d64 11111 if (optimize_insn_for_speed_p ())
11112 {
11113 /* See if we can store by pieces into (dst + strlen(dst)). */
11114 tree newdst, call;
11115 tree strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
11116 tree strcpy_fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11117
11118 if (!strlen_fn || !strcpy_fn)
11119 return NULL_TREE;
11120
11121 /* If we don't have a movstr we don't want to emit an strcpy
11122 call. We have to do that if the length of the source string
11123 isn't computable (in that case we can use memcpy probably
48e1416a 11124 later expanding to a sequence of mov instructions). If we
a65c4d64 11125 have movstr instructions we can emit strcpy calls. */
11126 if (!HAVE_movstr)
11127 {
11128 tree len = c_strlen (src, 1);
11129 if (! len || TREE_SIDE_EFFECTS (len))
11130 return NULL_TREE;
11131 }
11132
11133 /* Stabilize the argument list. */
11134 dst = builtin_save_expr (dst);
11135
11136 /* Create strlen (dst). */
11137 newdst = build_call_expr_loc (loc, strlen_fn, 1, dst);
11138 /* Create (dst p+ strlen (dst)). */
11139
11140 newdst = fold_build2_loc (loc, POINTER_PLUS_EXPR,
11141 TREE_TYPE (dst), dst, newdst);
11142 newdst = builtin_save_expr (newdst);
11143
11144 call = build_call_expr_loc (loc, strcpy_fn, 2, newdst, src);
11145 return build2 (COMPOUND_EXPR, TREE_TYPE (dst), call, dst);
11146 }
c2f47e15 11147 return NULL_TREE;
4ee9c684 11148 }
11149}
11150
c2f47e15 11151/* Simplify a call to the strncat builtin. DST, SRC, and LEN are the
11152 arguments to the call.
4ee9c684 11153
c2f47e15 11154 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11155 simplified form of the call as a tree.
11156
11157 The simplified form may be a constant or other expression which
11158 computes the same value, but in a more efficient manner (including
11159 calls to other builtin functions).
11160
11161 The call may contain arguments which need to be evaluated, but
11162 which are not useful to determine the result of the call. In
11163 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11164 COMPOUND_EXPR will be an argument which must be evaluated.
11165 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11166 COMPOUND_EXPR in the chain will contain the tree for the simplified
11167 form of the builtin function call. */
11168
11169static tree
389dd41b 11170fold_builtin_strncat (location_t loc, tree dst, tree src, tree len)
4ee9c684 11171{
c2f47e15 11172 if (!validate_arg (dst, POINTER_TYPE)
11173 || !validate_arg (src, POINTER_TYPE)
11174 || !validate_arg (len, INTEGER_TYPE))
11175 return NULL_TREE;
4ee9c684 11176 else
11177 {
4ee9c684 11178 const char *p = c_getstr (src);
11179
11180 /* If the requested length is zero, or the src parameter string
0a39fd54 11181 length is zero, return the dst parameter. */
4ee9c684 11182 if (integer_zerop (len) || (p && *p == '\0'))
389dd41b 11183 return omit_two_operands_loc (loc, TREE_TYPE (dst), dst, src, len);
4ee9c684 11184
11185 /* If the requested len is greater than or equal to the string
a0c938f0 11186 length, call strcat. */
4ee9c684 11187 if (TREE_CODE (len) == INTEGER_CST && p
11188 && compare_tree_int (len, strlen (p)) >= 0)
11189 {
4ee9c684 11190 tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
11191
11192 /* If the replacement _DECL isn't initialized, don't do the
11193 transformation. */
11194 if (!fn)
c2f47e15 11195 return NULL_TREE;
4ee9c684 11196
389dd41b 11197 return build_call_expr_loc (loc, fn, 2, dst, src);
4ee9c684 11198 }
c2f47e15 11199 return NULL_TREE;
4ee9c684 11200 }
11201}
11202
c2f47e15 11203/* Simplify a call to the strspn builtin. S1 and S2 are the arguments
11204 to the call.
4ee9c684 11205
c2f47e15 11206 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11207 simplified form of the call as a tree.
11208
11209 The simplified form may be a constant or other expression which
11210 computes the same value, but in a more efficient manner (including
11211 calls to other builtin functions).
11212
11213 The call may contain arguments which need to be evaluated, but
11214 which are not useful to determine the result of the call. In
11215 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11216 COMPOUND_EXPR will be an argument which must be evaluated.
11217 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11218 COMPOUND_EXPR in the chain will contain the tree for the simplified
11219 form of the builtin function call. */
11220
11221static tree
389dd41b 11222fold_builtin_strspn (location_t loc, tree s1, tree s2)
4ee9c684 11223{
c2f47e15 11224 if (!validate_arg (s1, POINTER_TYPE)
11225 || !validate_arg (s2, POINTER_TYPE))
11226 return NULL_TREE;
4ee9c684 11227 else
11228 {
4ee9c684 11229 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11230
11231 /* If both arguments are constants, evaluate at compile-time. */
11232 if (p1 && p2)
11233 {
11234 const size_t r = strspn (p1, p2);
11235 return size_int (r);
11236 }
11237
c2f47e15 11238 /* If either argument is "", return NULL_TREE. */
4ee9c684 11239 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9bc9f15f 11240 /* Evaluate and ignore both arguments in case either one has
11241 side-effects. */
389dd41b 11242 return omit_two_operands_loc (loc, size_type_node, size_zero_node,
9bc9f15f 11243 s1, s2);
c2f47e15 11244 return NULL_TREE;
4ee9c684 11245 }
11246}
11247
c2f47e15 11248/* Simplify a call to the strcspn builtin. S1 and S2 are the arguments
11249 to the call.
4ee9c684 11250
c2f47e15 11251 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11252 simplified form of the call as a tree.
11253
11254 The simplified form may be a constant or other expression which
11255 computes the same value, but in a more efficient manner (including
11256 calls to other builtin functions).
11257
11258 The call may contain arguments which need to be evaluated, but
11259 which are not useful to determine the result of the call. In
11260 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11261 COMPOUND_EXPR will be an argument which must be evaluated.
11262 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11263 COMPOUND_EXPR in the chain will contain the tree for the simplified
11264 form of the builtin function call. */
11265
11266static tree
389dd41b 11267fold_builtin_strcspn (location_t loc, tree s1, tree s2)
4ee9c684 11268{
c2f47e15 11269 if (!validate_arg (s1, POINTER_TYPE)
11270 || !validate_arg (s2, POINTER_TYPE))
11271 return NULL_TREE;
4ee9c684 11272 else
11273 {
4ee9c684 11274 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11275
11276 /* If both arguments are constants, evaluate at compile-time. */
11277 if (p1 && p2)
11278 {
11279 const size_t r = strcspn (p1, p2);
11280 return size_int (r);
11281 }
11282
c2f47e15 11283 /* If the first argument is "", return NULL_TREE. */
4ee9c684 11284 if (p1 && *p1 == '\0')
11285 {
11286 /* Evaluate and ignore argument s2 in case it has
11287 side-effects. */
389dd41b 11288 return omit_one_operand_loc (loc, size_type_node,
39761420 11289 size_zero_node, s2);
4ee9c684 11290 }
11291
11292 /* If the second argument is "", return __builtin_strlen(s1). */
11293 if (p2 && *p2 == '\0')
11294 {
c2f47e15 11295 tree fn = implicit_built_in_decls[BUILT_IN_STRLEN];
4ee9c684 11296
11297 /* If the replacement _DECL isn't initialized, don't do the
11298 transformation. */
11299 if (!fn)
c2f47e15 11300 return NULL_TREE;
4ee9c684 11301
389dd41b 11302 return build_call_expr_loc (loc, fn, 1, s1);
4ee9c684 11303 }
c2f47e15 11304 return NULL_TREE;
4ee9c684 11305 }
11306}
11307
c2f47e15 11308/* Fold a call to the fputs builtin. ARG0 and ARG1 are the arguments
11309 to the call. IGNORE is true if the value returned
f0613857 11310 by the builtin will be ignored. UNLOCKED is true is true if this
11311 actually a call to fputs_unlocked. If LEN in non-NULL, it represents
11312 the known length of the string. Return NULL_TREE if no simplification
11313 was possible. */
4ee9c684 11314
11315tree
389dd41b 11316fold_builtin_fputs (location_t loc, tree arg0, tree arg1,
11317 bool ignore, bool unlocked, tree len)
4ee9c684 11318{
6d77ed92 11319 /* If we're using an unlocked function, assume the other unlocked
11320 functions exist explicitly. */
11321 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
4ee9c684 11322 : implicit_built_in_decls[BUILT_IN_FPUTC];
6d77ed92 11323 tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
4ee9c684 11324 : implicit_built_in_decls[BUILT_IN_FWRITE];
11325
c403edd4 11326 /* If the return value is used, don't do the transformation. */
11327 if (!ignore)
c2f47e15 11328 return NULL_TREE;
4ee9c684 11329
11330 /* Verify the arguments in the original call. */
c2f47e15 11331 if (!validate_arg (arg0, POINTER_TYPE)
11332 || !validate_arg (arg1, POINTER_TYPE))
11333 return NULL_TREE;
4ee9c684 11334
f0613857 11335 if (! len)
c2f47e15 11336 len = c_strlen (arg0, 0);
4ee9c684 11337
11338 /* Get the length of the string passed to fputs. If the length
11339 can't be determined, punt. */
11340 if (!len
11341 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 11342 return NULL_TREE;
4ee9c684 11343
11344 switch (compare_tree_int (len, 1))
11345 {
11346 case -1: /* length is 0, delete the call entirely . */
389dd41b 11347 return omit_one_operand_loc (loc, integer_type_node,
11348 integer_zero_node, arg1);;
05abc81b 11349
4ee9c684 11350 case 0: /* length is 1, call fputc. */
11351 {
c2f47e15 11352 const char *p = c_getstr (arg0);
4ee9c684 11353
11354 if (p != NULL)
11355 {
c2f47e15 11356 if (fn_fputc)
389dd41b 11357 return build_call_expr_loc (loc, fn_fputc, 2,
c2f47e15 11358 build_int_cst (NULL_TREE, p[0]), arg1);
11359 else
11360 return NULL_TREE;
4ee9c684 11361 }
11362 }
11363 /* FALLTHROUGH */
11364 case 1: /* length is greater than 1, call fwrite. */
11365 {
0bed3869 11366 /* If optimizing for size keep fputs. */
0bfd8d5c 11367 if (optimize_function_for_size_p (cfun))
c2f47e15 11368 return NULL_TREE;
4ee9c684 11369 /* New argument list transforming fputs(string, stream) to
11370 fwrite(string, 1, len, stream). */
c2f47e15 11371 if (fn_fwrite)
389dd41b 11372 return build_call_expr_loc (loc, fn_fwrite, 4, arg0,
11373 size_one_node, len, arg1);
c2f47e15 11374 else
11375 return NULL_TREE;
4ee9c684 11376 }
11377 default:
64db345d 11378 gcc_unreachable ();
4ee9c684 11379 }
c2f47e15 11380 return NULL_TREE;
4ee9c684 11381}
11382
c2f47e15 11383/* Fold the next_arg or va_start call EXP. Returns true if there was an error
743b0c6a 11384 produced. False otherwise. This is done so that we don't output the error
11385 or warning twice or three times. */
75a70cf9 11386
743b0c6a 11387bool
c2f47e15 11388fold_builtin_next_arg (tree exp, bool va_start_p)
4ee9c684 11389{
11390 tree fntype = TREE_TYPE (current_function_decl);
c2f47e15 11391 int nargs = call_expr_nargs (exp);
11392 tree arg;
4ee9c684 11393
11394 if (TYPE_ARG_TYPES (fntype) == 0
11395 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
11396 == void_type_node))
743b0c6a 11397 {
11398 error ("%<va_start%> used in function with fixed args");
11399 return true;
11400 }
c2f47e15 11401
11402 if (va_start_p)
79012a9d 11403 {
c2f47e15 11404 if (va_start_p && (nargs != 2))
11405 {
11406 error ("wrong number of arguments to function %<va_start%>");
11407 return true;
11408 }
11409 arg = CALL_EXPR_ARG (exp, 1);
79012a9d 11410 }
11411 /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
11412 when we checked the arguments and if needed issued a warning. */
c2f47e15 11413 else
4ee9c684 11414 {
c2f47e15 11415 if (nargs == 0)
11416 {
11417 /* Evidently an out of date version of <stdarg.h>; can't validate
11418 va_start's second argument, but can still work as intended. */
11419 warning (0, "%<__builtin_next_arg%> called without an argument");
11420 return true;
11421 }
11422 else if (nargs > 1)
a0c938f0 11423 {
c2f47e15 11424 error ("wrong number of arguments to function %<__builtin_next_arg%>");
a0c938f0 11425 return true;
11426 }
c2f47e15 11427 arg = CALL_EXPR_ARG (exp, 0);
11428 }
11429
a8dd994c 11430 if (TREE_CODE (arg) == SSA_NAME)
11431 arg = SSA_NAME_VAR (arg);
11432
c2f47e15 11433 /* We destructively modify the call to be __builtin_va_start (ap, 0)
48e1416a 11434 or __builtin_next_arg (0) the first time we see it, after checking
c2f47e15 11435 the arguments and if needed issuing a warning. */
11436 if (!integer_zerop (arg))
11437 {
11438 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
79012a9d 11439
4ee9c684 11440 /* Strip off all nops for the sake of the comparison. This
11441 is not quite the same as STRIP_NOPS. It does more.
11442 We must also strip off INDIRECT_EXPR for C++ reference
11443 parameters. */
72dd6141 11444 while (CONVERT_EXPR_P (arg)
4ee9c684 11445 || TREE_CODE (arg) == INDIRECT_REF)
11446 arg = TREE_OPERAND (arg, 0);
11447 if (arg != last_parm)
a0c938f0 11448 {
b08cf617 11449 /* FIXME: Sometimes with the tree optimizers we can get the
11450 not the last argument even though the user used the last
11451 argument. We just warn and set the arg to be the last
11452 argument so that we will get wrong-code because of
11453 it. */
c3ceba8e 11454 warning (0, "second parameter of %<va_start%> not last named argument");
743b0c6a 11455 }
24158ad7 11456
11457 /* Undefined by C99 7.15.1.4p4 (va_start):
11458 "If the parameter parmN is declared with the register storage
11459 class, with a function or array type, or with a type that is
11460 not compatible with the type that results after application of
11461 the default argument promotions, the behavior is undefined."
11462 */
11463 else if (DECL_REGISTER (arg))
11464 warning (0, "undefined behaviour when second parameter of "
11465 "%<va_start%> is declared with %<register%> storage");
11466
79012a9d 11467 /* We want to verify the second parameter just once before the tree
a0c938f0 11468 optimizers are run and then avoid keeping it in the tree,
11469 as otherwise we could warn even for correct code like:
11470 void foo (int i, ...)
11471 { va_list ap; i++; va_start (ap, i); va_end (ap); } */
c2f47e15 11472 if (va_start_p)
11473 CALL_EXPR_ARG (exp, 1) = integer_zero_node;
11474 else
11475 CALL_EXPR_ARG (exp, 0) = integer_zero_node;
743b0c6a 11476 }
11477 return false;
4ee9c684 11478}
11479
11480
c2f47e15 11481/* Simplify a call to the sprintf builtin with arguments DEST, FMT, and ORIG.
11482 ORIG may be null if this is a 2-argument call. We don't attempt to
11483 simplify calls with more than 3 arguments.
4ee9c684 11484
c2f47e15 11485 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11486 simplified form of the call as a tree. If IGNORED is true, it means that
11487 the caller does not use the returned value of the function. */
11488
11489static tree
389dd41b 11490fold_builtin_sprintf (location_t loc, tree dest, tree fmt,
11491 tree orig, int ignored)
4ee9c684 11492{
c2f47e15 11493 tree call, retval;
4ee9c684 11494 const char *fmt_str = NULL;
11495
11496 /* Verify the required arguments in the original call. We deal with two
11497 types of sprintf() calls: 'sprintf (str, fmt)' and
11498 'sprintf (dest, "%s", orig)'. */
c2f47e15 11499 if (!validate_arg (dest, POINTER_TYPE)
11500 || !validate_arg (fmt, POINTER_TYPE))
11501 return NULL_TREE;
11502 if (orig && !validate_arg (orig, POINTER_TYPE))
4ee9c684 11503 return NULL_TREE;
4ee9c684 11504
11505 /* Check whether the format is a literal string constant. */
11506 fmt_str = c_getstr (fmt);
11507 if (fmt_str == NULL)
11508 return NULL_TREE;
11509
11510 call = NULL_TREE;
11511 retval = NULL_TREE;
11512
d4473c84 11513 if (!init_target_chars ())
c2f47e15 11514 return NULL_TREE;
99eabcc1 11515
4ee9c684 11516 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 11517 if (strchr (fmt_str, target_percent) == NULL)
4ee9c684 11518 {
11519 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11520
11521 if (!fn)
11522 return NULL_TREE;
11523
72dfb3f2 11524 /* Don't optimize sprintf (buf, "abc", ptr++). */
c2f47e15 11525 if (orig)
72dfb3f2 11526 return NULL_TREE;
11527
4ee9c684 11528 /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
11529 'format' is known to contain no % formats. */
389dd41b 11530 call = build_call_expr_loc (loc, fn, 2, dest, fmt);
4ee9c684 11531 if (!ignored)
7016c612 11532 retval = build_int_cst (NULL_TREE, strlen (fmt_str));
4ee9c684 11533 }
11534
11535 /* If the format is "%s", use strcpy if the result isn't used. */
99eabcc1 11536 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
4ee9c684 11537 {
c2f47e15 11538 tree fn;
4ee9c684 11539 fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11540
11541 if (!fn)
11542 return NULL_TREE;
11543
72dfb3f2 11544 /* Don't crash on sprintf (str1, "%s"). */
c2f47e15 11545 if (!orig)
72dfb3f2 11546 return NULL_TREE;
11547
4ee9c684 11548 /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2). */
4ee9c684 11549 if (!ignored)
11550 {
11551 retval = c_strlen (orig, 1);
11552 if (!retval || TREE_CODE (retval) != INTEGER_CST)
11553 return NULL_TREE;
11554 }
389dd41b 11555 call = build_call_expr_loc (loc, fn, 2, dest, orig);
4ee9c684 11556 }
11557
11558 if (call && retval)
11559 {
389dd41b 11560 retval = fold_convert_loc
11561 (loc, TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])),
4ee9c684 11562 retval);
05abc81b 11563 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
4ee9c684 11564 }
11565 else
11566 return call;
11567}
0a39fd54 11568
c2f47e15 11569/* Expand a call EXP to __builtin_object_size. */
0a39fd54 11570
11571rtx
11572expand_builtin_object_size (tree exp)
11573{
11574 tree ost;
11575 int object_size_type;
11576 tree fndecl = get_callee_fndecl (exp);
0a39fd54 11577
c2f47e15 11578 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
0a39fd54 11579 {
b8c23db3 11580 error ("%Kfirst argument of %D must be a pointer, second integer constant",
11581 exp, fndecl);
0a39fd54 11582 expand_builtin_trap ();
11583 return const0_rtx;
11584 }
11585
c2f47e15 11586 ost = CALL_EXPR_ARG (exp, 1);
0a39fd54 11587 STRIP_NOPS (ost);
11588
11589 if (TREE_CODE (ost) != INTEGER_CST
11590 || tree_int_cst_sgn (ost) < 0
11591 || compare_tree_int (ost, 3) > 0)
11592 {
b8c23db3 11593 error ("%Klast argument of %D is not integer constant between 0 and 3",
11594 exp, fndecl);
0a39fd54 11595 expand_builtin_trap ();
11596 return const0_rtx;
11597 }
11598
11599 object_size_type = tree_low_cst (ost, 0);
11600
11601 return object_size_type < 2 ? constm1_rtx : const0_rtx;
11602}
11603
11604/* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
11605 FCODE is the BUILT_IN_* to use.
c2f47e15 11606 Return NULL_RTX if we failed; the caller should emit a normal call,
0a39fd54 11607 otherwise try to get the result in TARGET, if convenient (and in
11608 mode MODE if that's convenient). */
11609
11610static rtx
11611expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
11612 enum built_in_function fcode)
11613{
0a39fd54 11614 tree dest, src, len, size;
11615
c2f47e15 11616 if (!validate_arglist (exp,
0a39fd54 11617 POINTER_TYPE,
11618 fcode == BUILT_IN_MEMSET_CHK
11619 ? INTEGER_TYPE : POINTER_TYPE,
11620 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
c2f47e15 11621 return NULL_RTX;
0a39fd54 11622
c2f47e15 11623 dest = CALL_EXPR_ARG (exp, 0);
11624 src = CALL_EXPR_ARG (exp, 1);
11625 len = CALL_EXPR_ARG (exp, 2);
11626 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11627
11628 if (! host_integerp (size, 1))
c2f47e15 11629 return NULL_RTX;
0a39fd54 11630
11631 if (host_integerp (len, 1) || integer_all_onesp (size))
11632 {
11633 tree fn;
11634
11635 if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
11636 {
b430e8d9 11637 warning_at (tree_nonartificial_location (exp),
11638 0, "%Kcall to %D will always overflow destination buffer",
11639 exp, get_callee_fndecl (exp));
c2f47e15 11640 return NULL_RTX;
0a39fd54 11641 }
11642
0a39fd54 11643 fn = NULL_TREE;
11644 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
11645 mem{cpy,pcpy,move,set} is available. */
11646 switch (fcode)
11647 {
11648 case BUILT_IN_MEMCPY_CHK:
11649 fn = built_in_decls[BUILT_IN_MEMCPY];
11650 break;
11651 case BUILT_IN_MEMPCPY_CHK:
11652 fn = built_in_decls[BUILT_IN_MEMPCPY];
11653 break;
11654 case BUILT_IN_MEMMOVE_CHK:
11655 fn = built_in_decls[BUILT_IN_MEMMOVE];
11656 break;
11657 case BUILT_IN_MEMSET_CHK:
11658 fn = built_in_decls[BUILT_IN_MEMSET];
11659 break;
11660 default:
11661 break;
11662 }
11663
11664 if (! fn)
c2f47e15 11665 return NULL_RTX;
0a39fd54 11666
a65c4d64 11667 fn = build_call_nofold (fn, 3, dest, src, len);
11668 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
11669 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0a39fd54 11670 return expand_expr (fn, target, mode, EXPAND_NORMAL);
11671 }
11672 else if (fcode == BUILT_IN_MEMSET_CHK)
c2f47e15 11673 return NULL_RTX;
0a39fd54 11674 else
11675 {
11676 unsigned int dest_align
11677 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
11678
11679 /* If DEST is not a pointer type, call the normal function. */
11680 if (dest_align == 0)
c2f47e15 11681 return NULL_RTX;
0a39fd54 11682
11683 /* If SRC and DEST are the same (and not volatile), do nothing. */
11684 if (operand_equal_p (src, dest, 0))
11685 {
11686 tree expr;
11687
11688 if (fcode != BUILT_IN_MEMPCPY_CHK)
11689 {
11690 /* Evaluate and ignore LEN in case it has side-effects. */
11691 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
11692 return expand_expr (dest, target, mode, EXPAND_NORMAL);
11693 }
11694
0de36bdb 11695 expr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
0a39fd54 11696 return expand_expr (expr, target, mode, EXPAND_NORMAL);
11697 }
11698
11699 /* __memmove_chk special case. */
11700 if (fcode == BUILT_IN_MEMMOVE_CHK)
11701 {
11702 unsigned int src_align
11703 = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
11704
11705 if (src_align == 0)
c2f47e15 11706 return NULL_RTX;
0a39fd54 11707
11708 /* If src is categorized for a readonly section we can use
11709 normal __memcpy_chk. */
11710 if (readonly_data_expr (src))
11711 {
11712 tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
11713 if (!fn)
c2f47e15 11714 return NULL_RTX;
a65c4d64 11715 fn = build_call_nofold (fn, 4, dest, src, len, size);
11716 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
11717 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0a39fd54 11718 return expand_expr (fn, target, mode, EXPAND_NORMAL);
11719 }
11720 }
c2f47e15 11721 return NULL_RTX;
0a39fd54 11722 }
11723}
11724
11725/* Emit warning if a buffer overflow is detected at compile time. */
11726
11727static void
11728maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
11729{
c2f47e15 11730 int is_strlen = 0;
0a39fd54 11731 tree len, size;
b430e8d9 11732 location_t loc = tree_nonartificial_location (exp);
0a39fd54 11733
11734 switch (fcode)
11735 {
11736 case BUILT_IN_STRCPY_CHK:
11737 case BUILT_IN_STPCPY_CHK:
11738 /* For __strcat_chk the warning will be emitted only if overflowing
11739 by at least strlen (dest) + 1 bytes. */
11740 case BUILT_IN_STRCAT_CHK:
c2f47e15 11741 len = CALL_EXPR_ARG (exp, 1);
11742 size = CALL_EXPR_ARG (exp, 2);
0a39fd54 11743 is_strlen = 1;
11744 break;
b356dfef 11745 case BUILT_IN_STRNCAT_CHK:
0a39fd54 11746 case BUILT_IN_STRNCPY_CHK:
c2f47e15 11747 len = CALL_EXPR_ARG (exp, 2);
11748 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11749 break;
11750 case BUILT_IN_SNPRINTF_CHK:
11751 case BUILT_IN_VSNPRINTF_CHK:
c2f47e15 11752 len = CALL_EXPR_ARG (exp, 1);
11753 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11754 break;
11755 default:
11756 gcc_unreachable ();
11757 }
11758
0a39fd54 11759 if (!len || !size)
11760 return;
11761
0a39fd54 11762 if (! host_integerp (size, 1) || integer_all_onesp (size))
11763 return;
11764
11765 if (is_strlen)
11766 {
11767 len = c_strlen (len, 1);
11768 if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
11769 return;
11770 }
b356dfef 11771 else if (fcode == BUILT_IN_STRNCAT_CHK)
11772 {
c2f47e15 11773 tree src = CALL_EXPR_ARG (exp, 1);
b356dfef 11774 if (! src || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
11775 return;
11776 src = c_strlen (src, 1);
11777 if (! src || ! host_integerp (src, 1))
11778 {
b430e8d9 11779 warning_at (loc, 0, "%Kcall to %D might overflow destination buffer",
11780 exp, get_callee_fndecl (exp));
b356dfef 11781 return;
11782 }
11783 else if (tree_int_cst_lt (src, size))
11784 return;
11785 }
0a39fd54 11786 else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
11787 return;
11788
b430e8d9 11789 warning_at (loc, 0, "%Kcall to %D will always overflow destination buffer",
11790 exp, get_callee_fndecl (exp));
0a39fd54 11791}
11792
11793/* Emit warning if a buffer overflow is detected at compile time
11794 in __sprintf_chk/__vsprintf_chk calls. */
11795
11796static void
11797maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
11798{
1e4adcfc 11799 tree size, len, fmt;
0a39fd54 11800 const char *fmt_str;
c2f47e15 11801 int nargs = call_expr_nargs (exp);
0a39fd54 11802
11803 /* Verify the required arguments in the original call. */
48e1416a 11804
c2f47e15 11805 if (nargs < 4)
0a39fd54 11806 return;
c2f47e15 11807 size = CALL_EXPR_ARG (exp, 2);
11808 fmt = CALL_EXPR_ARG (exp, 3);
0a39fd54 11809
11810 if (! host_integerp (size, 1) || integer_all_onesp (size))
11811 return;
11812
11813 /* Check whether the format is a literal string constant. */
11814 fmt_str = c_getstr (fmt);
11815 if (fmt_str == NULL)
11816 return;
11817
d4473c84 11818 if (!init_target_chars ())
99eabcc1 11819 return;
11820
0a39fd54 11821 /* If the format doesn't contain % args or %%, we know its size. */
99eabcc1 11822 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 11823 len = build_int_cstu (size_type_node, strlen (fmt_str));
11824 /* If the format is "%s" and first ... argument is a string literal,
11825 we know it too. */
c2f47e15 11826 else if (fcode == BUILT_IN_SPRINTF_CHK
11827 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 11828 {
11829 tree arg;
11830
c2f47e15 11831 if (nargs < 5)
0a39fd54 11832 return;
c2f47e15 11833 arg = CALL_EXPR_ARG (exp, 4);
0a39fd54 11834 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
11835 return;
11836
11837 len = c_strlen (arg, 1);
11838 if (!len || ! host_integerp (len, 1))
11839 return;
11840 }
11841 else
11842 return;
11843
11844 if (! tree_int_cst_lt (len, size))
b430e8d9 11845 warning_at (tree_nonartificial_location (exp),
11846 0, "%Kcall to %D will always overflow destination buffer",
11847 exp, get_callee_fndecl (exp));
0a39fd54 11848}
11849
2c281b15 11850/* Emit warning if a free is called with address of a variable. */
11851
11852static void
11853maybe_emit_free_warning (tree exp)
11854{
11855 tree arg = CALL_EXPR_ARG (exp, 0);
11856
11857 STRIP_NOPS (arg);
11858 if (TREE_CODE (arg) != ADDR_EXPR)
11859 return;
11860
11861 arg = get_base_address (TREE_OPERAND (arg, 0));
11862 if (arg == NULL || INDIRECT_REF_P (arg))
11863 return;
11864
11865 if (SSA_VAR_P (arg))
b430e8d9 11866 warning_at (tree_nonartificial_location (exp),
11867 0, "%Kattempt to free a non-heap object %qD", exp, arg);
2c281b15 11868 else
b430e8d9 11869 warning_at (tree_nonartificial_location (exp),
11870 0, "%Kattempt to free a non-heap object", exp);
2c281b15 11871}
11872
c2f47e15 11873/* Fold a call to __builtin_object_size with arguments PTR and OST,
11874 if possible. */
0a39fd54 11875
11876tree
c2f47e15 11877fold_builtin_object_size (tree ptr, tree ost)
0a39fd54 11878{
c2f47e15 11879 tree ret = NULL_TREE;
0a39fd54 11880 int object_size_type;
11881
c2f47e15 11882 if (!validate_arg (ptr, POINTER_TYPE)
11883 || !validate_arg (ost, INTEGER_TYPE))
11884 return NULL_TREE;
0a39fd54 11885
0a39fd54 11886 STRIP_NOPS (ost);
11887
11888 if (TREE_CODE (ost) != INTEGER_CST
11889 || tree_int_cst_sgn (ost) < 0
11890 || compare_tree_int (ost, 3) > 0)
c2f47e15 11891 return NULL_TREE;
0a39fd54 11892
11893 object_size_type = tree_low_cst (ost, 0);
11894
11895 /* __builtin_object_size doesn't evaluate side-effects in its arguments;
11896 if there are any side-effects, it returns (size_t) -1 for types 0 and 1
11897 and (size_t) 0 for types 2 and 3. */
11898 if (TREE_SIDE_EFFECTS (ptr))
697bbc3f 11899 return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
0a39fd54 11900
11901 if (TREE_CODE (ptr) == ADDR_EXPR)
11902 ret = build_int_cstu (size_type_node,
697bbc3f 11903 compute_builtin_object_size (ptr, object_size_type));
0a39fd54 11904
11905 else if (TREE_CODE (ptr) == SSA_NAME)
11906 {
11907 unsigned HOST_WIDE_INT bytes;
11908
11909 /* If object size is not known yet, delay folding until
11910 later. Maybe subsequent passes will help determining
11911 it. */
11912 bytes = compute_builtin_object_size (ptr, object_size_type);
11913 if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2
11914 ? -1 : 0))
11915 ret = build_int_cstu (size_type_node, bytes);
11916 }
11917
11918 if (ret)
11919 {
697bbc3f 11920 unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (ret);
11921 HOST_WIDE_INT high = TREE_INT_CST_HIGH (ret);
11922 if (fit_double_type (low, high, &low, &high, TREE_TYPE (ret)))
11923 ret = NULL_TREE;
0a39fd54 11924 }
11925
11926 return ret;
11927}
11928
11929/* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
c2f47e15 11930 DEST, SRC, LEN, and SIZE are the arguments to the call.
0a39fd54 11931 IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_*
11932 code of the builtin. If MAXLEN is not NULL, it is maximum length
11933 passed as third argument. */
11934
11935tree
389dd41b 11936fold_builtin_memory_chk (location_t loc, tree fndecl,
c2f47e15 11937 tree dest, tree src, tree len, tree size,
11938 tree maxlen, bool ignore,
0a39fd54 11939 enum built_in_function fcode)
11940{
c2f47e15 11941 tree fn;
0a39fd54 11942
c2f47e15 11943 if (!validate_arg (dest, POINTER_TYPE)
11944 || !validate_arg (src,
11945 (fcode == BUILT_IN_MEMSET_CHK
11946 ? INTEGER_TYPE : POINTER_TYPE))
11947 || !validate_arg (len, INTEGER_TYPE)
11948 || !validate_arg (size, INTEGER_TYPE))
11949 return NULL_TREE;
0a39fd54 11950
11951 /* If SRC and DEST are the same (and not volatile), return DEST
11952 (resp. DEST+LEN for __mempcpy_chk). */
11953 if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
11954 {
11955 if (fcode != BUILT_IN_MEMPCPY_CHK)
389dd41b 11956 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
11957 dest, len);
0a39fd54 11958 else
11959 {
389dd41b 11960 tree temp = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (dest),
11961 dest, len);
11962 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), temp);
0a39fd54 11963 }
11964 }
11965
11966 if (! host_integerp (size, 1))
c2f47e15 11967 return NULL_TREE;
0a39fd54 11968
11969 if (! integer_all_onesp (size))
11970 {
11971 if (! host_integerp (len, 1))
11972 {
11973 /* If LEN is not constant, try MAXLEN too.
11974 For MAXLEN only allow optimizing into non-_ocs function
11975 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
11976 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
11977 {
11978 if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
11979 {
11980 /* (void) __mempcpy_chk () can be optimized into
11981 (void) __memcpy_chk (). */
11982 fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
11983 if (!fn)
c2f47e15 11984 return NULL_TREE;
0a39fd54 11985
389dd41b 11986 return build_call_expr_loc (loc, fn, 4, dest, src, len, size);
0a39fd54 11987 }
c2f47e15 11988 return NULL_TREE;
0a39fd54 11989 }
0a39fd54 11990 }
ad89623c 11991 else
11992 maxlen = len;
0a39fd54 11993
ad89623c 11994 if (tree_int_cst_lt (size, maxlen))
c2f47e15 11995 return NULL_TREE;
0a39fd54 11996 }
11997
0a39fd54 11998 fn = NULL_TREE;
11999 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
12000 mem{cpy,pcpy,move,set} is available. */
12001 switch (fcode)
12002 {
12003 case BUILT_IN_MEMCPY_CHK:
12004 fn = built_in_decls[BUILT_IN_MEMCPY];
12005 break;
12006 case BUILT_IN_MEMPCPY_CHK:
12007 fn = built_in_decls[BUILT_IN_MEMPCPY];
12008 break;
12009 case BUILT_IN_MEMMOVE_CHK:
12010 fn = built_in_decls[BUILT_IN_MEMMOVE];
12011 break;
12012 case BUILT_IN_MEMSET_CHK:
12013 fn = built_in_decls[BUILT_IN_MEMSET];
12014 break;
12015 default:
12016 break;
12017 }
12018
12019 if (!fn)
c2f47e15 12020 return NULL_TREE;
0a39fd54 12021
389dd41b 12022 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12023}
12024
12025/* Fold a call to the __st[rp]cpy_chk builtin.
c2f47e15 12026 DEST, SRC, and SIZE are the arguments to the call.
12027 IGNORE is true if return value can be ignored. FCODE is the BUILT_IN_*
0a39fd54 12028 code of the builtin. If MAXLEN is not NULL, it is maximum length of
12029 strings passed as second argument. */
12030
12031tree
389dd41b 12032fold_builtin_stxcpy_chk (location_t loc, tree fndecl, tree dest,
12033 tree src, tree size,
c2f47e15 12034 tree maxlen, bool ignore,
0a39fd54 12035 enum built_in_function fcode)
12036{
c2f47e15 12037 tree len, fn;
0a39fd54 12038
c2f47e15 12039 if (!validate_arg (dest, POINTER_TYPE)
12040 || !validate_arg (src, POINTER_TYPE)
12041 || !validate_arg (size, INTEGER_TYPE))
12042 return NULL_TREE;
0a39fd54 12043
12044 /* If SRC and DEST are the same (and not volatile), return DEST. */
12045 if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
389dd41b 12046 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
a0c938f0 12047
0a39fd54 12048 if (! host_integerp (size, 1))
c2f47e15 12049 return NULL_TREE;
0a39fd54 12050
12051 if (! integer_all_onesp (size))
12052 {
12053 len = c_strlen (src, 1);
12054 if (! len || ! host_integerp (len, 1))
12055 {
12056 /* If LEN is not constant, try MAXLEN too.
12057 For MAXLEN only allow optimizing into non-_ocs function
12058 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12059 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
12060 {
12061 if (fcode == BUILT_IN_STPCPY_CHK)
12062 {
12063 if (! ignore)
c2f47e15 12064 return NULL_TREE;
0a39fd54 12065
12066 /* If return value of __stpcpy_chk is ignored,
12067 optimize into __strcpy_chk. */
12068 fn = built_in_decls[BUILT_IN_STRCPY_CHK];
12069 if (!fn)
c2f47e15 12070 return NULL_TREE;
0a39fd54 12071
389dd41b 12072 return build_call_expr_loc (loc, fn, 3, dest, src, size);
0a39fd54 12073 }
12074
12075 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 12076 return NULL_TREE;
0a39fd54 12077
12078 /* If c_strlen returned something, but not a constant,
12079 transform __strcpy_chk into __memcpy_chk. */
12080 fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
12081 if (!fn)
c2f47e15 12082 return NULL_TREE;
0a39fd54 12083
389dd41b 12084 len = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
12085 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
12086 build_call_expr_loc (loc, fn, 4,
12087 dest, src, len, size));
0a39fd54 12088 }
0a39fd54 12089 }
ad89623c 12090 else
12091 maxlen = len;
12092
12093 if (! tree_int_cst_lt (maxlen, size))
c2f47e15 12094 return NULL_TREE;
0a39fd54 12095 }
12096
0a39fd54 12097 /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available. */
12098 fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK
12099 ? BUILT_IN_STPCPY : BUILT_IN_STRCPY];
12100 if (!fn)
c2f47e15 12101 return NULL_TREE;
0a39fd54 12102
389dd41b 12103 return build_call_expr_loc (loc, fn, 2, dest, src);
0a39fd54 12104}
12105
c2f47e15 12106/* Fold a call to the __strncpy_chk builtin. DEST, SRC, LEN, and SIZE
12107 are the arguments to the call. If MAXLEN is not NULL, it is maximum
12108 length passed as third argument. */
0a39fd54 12109
12110tree
389dd41b 12111fold_builtin_strncpy_chk (location_t loc, tree dest, tree src,
12112 tree len, tree size, tree maxlen)
0a39fd54 12113{
c2f47e15 12114 tree fn;
0a39fd54 12115
c2f47e15 12116 if (!validate_arg (dest, POINTER_TYPE)
12117 || !validate_arg (src, POINTER_TYPE)
12118 || !validate_arg (len, INTEGER_TYPE)
12119 || !validate_arg (size, INTEGER_TYPE))
12120 return NULL_TREE;
0a39fd54 12121
12122 if (! host_integerp (size, 1))
c2f47e15 12123 return NULL_TREE;
0a39fd54 12124
12125 if (! integer_all_onesp (size))
12126 {
12127 if (! host_integerp (len, 1))
12128 {
12129 /* If LEN is not constant, try MAXLEN too.
12130 For MAXLEN only allow optimizing into non-_ocs function
12131 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12132 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 12133 return NULL_TREE;
0a39fd54 12134 }
ad89623c 12135 else
12136 maxlen = len;
0a39fd54 12137
ad89623c 12138 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12139 return NULL_TREE;
0a39fd54 12140 }
12141
0a39fd54 12142 /* If __builtin_strncpy_chk is used, assume strncpy is available. */
12143 fn = built_in_decls[BUILT_IN_STRNCPY];
12144 if (!fn)
c2f47e15 12145 return NULL_TREE;
0a39fd54 12146
389dd41b 12147 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12148}
12149
c2f47e15 12150/* Fold a call to the __strcat_chk builtin FNDECL. DEST, SRC, and SIZE
12151 are the arguments to the call. */
0a39fd54 12152
12153static tree
389dd41b 12154fold_builtin_strcat_chk (location_t loc, tree fndecl, tree dest,
12155 tree src, tree size)
0a39fd54 12156{
c2f47e15 12157 tree fn;
0a39fd54 12158 const char *p;
12159
c2f47e15 12160 if (!validate_arg (dest, POINTER_TYPE)
12161 || !validate_arg (src, POINTER_TYPE)
12162 || !validate_arg (size, INTEGER_TYPE))
12163 return NULL_TREE;
0a39fd54 12164
12165 p = c_getstr (src);
12166 /* If the SRC parameter is "", return DEST. */
12167 if (p && *p == '\0')
389dd41b 12168 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
0a39fd54 12169
12170 if (! host_integerp (size, 1) || ! integer_all_onesp (size))
c2f47e15 12171 return NULL_TREE;
0a39fd54 12172
12173 /* If __builtin_strcat_chk is used, assume strcat is available. */
12174 fn = built_in_decls[BUILT_IN_STRCAT];
12175 if (!fn)
c2f47e15 12176 return NULL_TREE;
0a39fd54 12177
389dd41b 12178 return build_call_expr_loc (loc, fn, 2, dest, src);
0a39fd54 12179}
12180
c2f47e15 12181/* Fold a call to the __strncat_chk builtin with arguments DEST, SRC,
12182 LEN, and SIZE. */
0a39fd54 12183
12184static tree
389dd41b 12185fold_builtin_strncat_chk (location_t loc, tree fndecl,
c2f47e15 12186 tree dest, tree src, tree len, tree size)
0a39fd54 12187{
c2f47e15 12188 tree fn;
0a39fd54 12189 const char *p;
12190
c2f47e15 12191 if (!validate_arg (dest, POINTER_TYPE)
12192 || !validate_arg (src, POINTER_TYPE)
12193 || !validate_arg (size, INTEGER_TYPE)
12194 || !validate_arg (size, INTEGER_TYPE))
12195 return NULL_TREE;
0a39fd54 12196
12197 p = c_getstr (src);
12198 /* If the SRC parameter is "" or if LEN is 0, return DEST. */
12199 if (p && *p == '\0')
389dd41b 12200 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
0a39fd54 12201 else if (integer_zerop (len))
389dd41b 12202 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
0a39fd54 12203
12204 if (! host_integerp (size, 1))
c2f47e15 12205 return NULL_TREE;
0a39fd54 12206
12207 if (! integer_all_onesp (size))
12208 {
12209 tree src_len = c_strlen (src, 1);
12210 if (src_len
12211 && host_integerp (src_len, 1)
12212 && host_integerp (len, 1)
12213 && ! tree_int_cst_lt (len, src_len))
12214 {
12215 /* If LEN >= strlen (SRC), optimize into __strcat_chk. */
12216 fn = built_in_decls[BUILT_IN_STRCAT_CHK];
12217 if (!fn)
c2f47e15 12218 return NULL_TREE;
0a39fd54 12219
389dd41b 12220 return build_call_expr_loc (loc, fn, 3, dest, src, size);
0a39fd54 12221 }
c2f47e15 12222 return NULL_TREE;
0a39fd54 12223 }
12224
0a39fd54 12225 /* If __builtin_strncat_chk is used, assume strncat is available. */
12226 fn = built_in_decls[BUILT_IN_STRNCAT];
12227 if (!fn)
c2f47e15 12228 return NULL_TREE;
0a39fd54 12229
389dd41b 12230 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12231}
12232
c2f47e15 12233/* Fold a call EXP to __{,v}sprintf_chk. Return NULL_TREE if
0a39fd54 12234 a normal call should be emitted rather than expanding the function
12235 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
12236
12237static tree
389dd41b 12238fold_builtin_sprintf_chk (location_t loc, tree exp,
12239 enum built_in_function fcode)
0a39fd54 12240{
12241 tree dest, size, len, fn, fmt, flag;
12242 const char *fmt_str;
c2f47e15 12243 int nargs = call_expr_nargs (exp);
0a39fd54 12244
12245 /* Verify the required arguments in the original call. */
c2f47e15 12246 if (nargs < 4)
12247 return NULL_TREE;
12248 dest = CALL_EXPR_ARG (exp, 0);
12249 if (!validate_arg (dest, POINTER_TYPE))
12250 return NULL_TREE;
12251 flag = CALL_EXPR_ARG (exp, 1);
12252 if (!validate_arg (flag, INTEGER_TYPE))
12253 return NULL_TREE;
12254 size = CALL_EXPR_ARG (exp, 2);
12255 if (!validate_arg (size, INTEGER_TYPE))
12256 return NULL_TREE;
12257 fmt = CALL_EXPR_ARG (exp, 3);
12258 if (!validate_arg (fmt, POINTER_TYPE))
12259 return NULL_TREE;
0a39fd54 12260
12261 if (! host_integerp (size, 1))
c2f47e15 12262 return NULL_TREE;
0a39fd54 12263
12264 len = NULL_TREE;
12265
d4473c84 12266 if (!init_target_chars ())
c2f47e15 12267 return NULL_TREE;
99eabcc1 12268
0a39fd54 12269 /* Check whether the format is a literal string constant. */
12270 fmt_str = c_getstr (fmt);
12271 if (fmt_str != NULL)
12272 {
12273 /* If the format doesn't contain % args or %%, we know the size. */
99eabcc1 12274 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 12275 {
c2f47e15 12276 if (fcode != BUILT_IN_SPRINTF_CHK || nargs == 4)
0a39fd54 12277 len = build_int_cstu (size_type_node, strlen (fmt_str));
12278 }
12279 /* If the format is "%s" and first ... argument is a string literal,
12280 we know the size too. */
c2f47e15 12281 else if (fcode == BUILT_IN_SPRINTF_CHK
12282 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12283 {
12284 tree arg;
12285
c2f47e15 12286 if (nargs == 5)
0a39fd54 12287 {
c2f47e15 12288 arg = CALL_EXPR_ARG (exp, 4);
12289 if (validate_arg (arg, POINTER_TYPE))
0a39fd54 12290 {
12291 len = c_strlen (arg, 1);
12292 if (! len || ! host_integerp (len, 1))
12293 len = NULL_TREE;
12294 }
12295 }
12296 }
12297 }
12298
12299 if (! integer_all_onesp (size))
12300 {
12301 if (! len || ! tree_int_cst_lt (len, size))
c2f47e15 12302 return NULL_TREE;
0a39fd54 12303 }
12304
12305 /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
12306 or if format doesn't contain % chars or is "%s". */
12307 if (! integer_zerop (flag))
12308 {
12309 if (fmt_str == NULL)
c2f47e15 12310 return NULL_TREE;
12311 if (strchr (fmt_str, target_percent) != NULL
12312 && strcmp (fmt_str, target_percent_s))
12313 return NULL_TREE;
0a39fd54 12314 }
12315
0a39fd54 12316 /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
12317 fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
12318 ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
12319 if (!fn)
c2f47e15 12320 return NULL_TREE;
0a39fd54 12321
389dd41b 12322 return rewrite_call_expr (loc, exp, 4, fn, 2, dest, fmt);
0a39fd54 12323}
12324
c2f47e15 12325/* Fold a call EXP to {,v}snprintf. Return NULL_TREE if
0a39fd54 12326 a normal call should be emitted rather than expanding the function
12327 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
12328 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
12329 passed as second argument. */
12330
12331tree
389dd41b 12332fold_builtin_snprintf_chk (location_t loc, tree exp, tree maxlen,
0a39fd54 12333 enum built_in_function fcode)
12334{
12335 tree dest, size, len, fn, fmt, flag;
12336 const char *fmt_str;
12337
12338 /* Verify the required arguments in the original call. */
c2f47e15 12339 if (call_expr_nargs (exp) < 5)
12340 return NULL_TREE;
12341 dest = CALL_EXPR_ARG (exp, 0);
12342 if (!validate_arg (dest, POINTER_TYPE))
12343 return NULL_TREE;
12344 len = CALL_EXPR_ARG (exp, 1);
12345 if (!validate_arg (len, INTEGER_TYPE))
12346 return NULL_TREE;
12347 flag = CALL_EXPR_ARG (exp, 2);
12348 if (!validate_arg (flag, INTEGER_TYPE))
12349 return NULL_TREE;
12350 size = CALL_EXPR_ARG (exp, 3);
12351 if (!validate_arg (size, INTEGER_TYPE))
12352 return NULL_TREE;
12353 fmt = CALL_EXPR_ARG (exp, 4);
12354 if (!validate_arg (fmt, POINTER_TYPE))
12355 return NULL_TREE;
0a39fd54 12356
12357 if (! host_integerp (size, 1))
c2f47e15 12358 return NULL_TREE;
0a39fd54 12359
12360 if (! integer_all_onesp (size))
12361 {
12362 if (! host_integerp (len, 1))
12363 {
12364 /* If LEN is not constant, try MAXLEN too.
12365 For MAXLEN only allow optimizing into non-_ocs function
12366 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12367 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 12368 return NULL_TREE;
0a39fd54 12369 }
ad89623c 12370 else
12371 maxlen = len;
0a39fd54 12372
ad89623c 12373 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12374 return NULL_TREE;
0a39fd54 12375 }
12376
d4473c84 12377 if (!init_target_chars ())
c2f47e15 12378 return NULL_TREE;
99eabcc1 12379
0a39fd54 12380 /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
12381 or if format doesn't contain % chars or is "%s". */
12382 if (! integer_zerop (flag))
12383 {
12384 fmt_str = c_getstr (fmt);
12385 if (fmt_str == NULL)
c2f47e15 12386 return NULL_TREE;
12387 if (strchr (fmt_str, target_percent) != NULL
12388 && strcmp (fmt_str, target_percent_s))
12389 return NULL_TREE;
0a39fd54 12390 }
12391
0a39fd54 12392 /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
12393 available. */
12394 fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
12395 ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
12396 if (!fn)
c2f47e15 12397 return NULL_TREE;
0a39fd54 12398
389dd41b 12399 return rewrite_call_expr (loc, exp, 5, fn, 3, dest, len, fmt);
0a39fd54 12400}
12401
12402/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 12403 FMT and ARG are the arguments to the call; we don't fold cases with
12404 more than 2 arguments, and ARG may be null if this is a 1-argument case.
0a39fd54 12405
c2f47e15 12406 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 12407 simplified form of the call as a tree. FCODE is the BUILT_IN_*
12408 code of the function to be simplified. */
12409
12410static tree
389dd41b 12411fold_builtin_printf (location_t loc, tree fndecl, tree fmt,
12412 tree arg, bool ignore,
0a39fd54 12413 enum built_in_function fcode)
12414{
c2f47e15 12415 tree fn_putchar, fn_puts, newarg, call = NULL_TREE;
0a39fd54 12416 const char *fmt_str = NULL;
12417
12418 /* If the return value is used, don't do the transformation. */
12419 if (! ignore)
c2f47e15 12420 return NULL_TREE;
0a39fd54 12421
12422 /* Verify the required arguments in the original call. */
c2f47e15 12423 if (!validate_arg (fmt, POINTER_TYPE))
12424 return NULL_TREE;
0a39fd54 12425
12426 /* Check whether the format is a literal string constant. */
12427 fmt_str = c_getstr (fmt);
12428 if (fmt_str == NULL)
12429 return NULL_TREE;
12430
12431 if (fcode == BUILT_IN_PRINTF_UNLOCKED)
12432 {
6d77ed92 12433 /* If we're using an unlocked function, assume the other
12434 unlocked functions exist explicitly. */
12435 fn_putchar = built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED];
12436 fn_puts = built_in_decls[BUILT_IN_PUTS_UNLOCKED];
0a39fd54 12437 }
12438 else
12439 {
12440 fn_putchar = implicit_built_in_decls[BUILT_IN_PUTCHAR];
12441 fn_puts = implicit_built_in_decls[BUILT_IN_PUTS];
12442 }
12443
d4473c84 12444 if (!init_target_chars ())
c2f47e15 12445 return NULL_TREE;
a0c938f0 12446
c2f47e15 12447 if (strcmp (fmt_str, target_percent_s) == 0
12448 || strchr (fmt_str, target_percent) == NULL)
0a39fd54 12449 {
12450 const char *str;
12451
99eabcc1 12452 if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12453 {
12454 if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 12455 return NULL_TREE;
0a39fd54 12456
c2f47e15 12457 if (!arg || !validate_arg (arg, POINTER_TYPE))
12458 return NULL_TREE;
0a39fd54 12459
c2f47e15 12460 str = c_getstr (arg);
0a39fd54 12461 if (str == NULL)
c2f47e15 12462 return NULL_TREE;
0a39fd54 12463 }
12464 else
12465 {
12466 /* The format specifier doesn't contain any '%' characters. */
12467 if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
c2f47e15 12468 && arg)
12469 return NULL_TREE;
0a39fd54 12470 str = fmt_str;
12471 }
12472
12473 /* If the string was "", printf does nothing. */
12474 if (str[0] == '\0')
12475 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
12476
12477 /* If the string has length of 1, call putchar. */
12478 if (str[1] == '\0')
12479 {
12480 /* Given printf("c"), (where c is any one character,)
12481 convert "c"[0] to an int and pass that to the replacement
12482 function. */
c2f47e15 12483 newarg = build_int_cst (NULL_TREE, str[0]);
12484 if (fn_putchar)
389dd41b 12485 call = build_call_expr_loc (loc, fn_putchar, 1, newarg);
0a39fd54 12486 }
12487 else
12488 {
12489 /* If the string was "string\n", call puts("string"). */
12490 size_t len = strlen (str);
99eabcc1 12491 if ((unsigned char)str[len - 1] == target_newline)
0a39fd54 12492 {
12493 /* Create a NUL-terminated string that's one char shorter
12494 than the original, stripping off the trailing '\n'. */
364c0c59 12495 char *newstr = XALLOCAVEC (char, len);
0a39fd54 12496 memcpy (newstr, str, len - 1);
12497 newstr[len - 1] = 0;
12498
c2f47e15 12499 newarg = build_string_literal (len, newstr);
12500 if (fn_puts)
389dd41b 12501 call = build_call_expr_loc (loc, fn_puts, 1, newarg);
0a39fd54 12502 }
12503 else
12504 /* We'd like to arrange to call fputs(string,stdout) here,
12505 but we need stdout and don't have a way to get it yet. */
c2f47e15 12506 return NULL_TREE;
0a39fd54 12507 }
12508 }
12509
12510 /* The other optimizations can be done only on the non-va_list variants. */
12511 else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 12512 return NULL_TREE;
0a39fd54 12513
12514 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
99eabcc1 12515 else if (strcmp (fmt_str, target_percent_s_newline) == 0)
0a39fd54 12516 {
c2f47e15 12517 if (!arg || !validate_arg (arg, POINTER_TYPE))
12518 return NULL_TREE;
12519 if (fn_puts)
389dd41b 12520 call = build_call_expr_loc (loc, fn_puts, 1, arg);
0a39fd54 12521 }
12522
12523 /* If the format specifier was "%c", call __builtin_putchar(arg). */
99eabcc1 12524 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 12525 {
c2f47e15 12526 if (!arg || !validate_arg (arg, INTEGER_TYPE))
12527 return NULL_TREE;
12528 if (fn_putchar)
389dd41b 12529 call = build_call_expr_loc (loc, fn_putchar, 1, arg);
0a39fd54 12530 }
12531
c2f47e15 12532 if (!call)
12533 return NULL_TREE;
0a39fd54 12534
389dd41b 12535 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
0a39fd54 12536}
12537
12538/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 12539 FP, FMT, and ARG are the arguments to the call. We don't fold calls with
12540 more than 3 arguments, and ARG may be null in the 2-argument case.
0a39fd54 12541
c2f47e15 12542 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 12543 simplified form of the call as a tree. FCODE is the BUILT_IN_*
12544 code of the function to be simplified. */
12545
12546static tree
389dd41b 12547fold_builtin_fprintf (location_t loc, tree fndecl, tree fp,
12548 tree fmt, tree arg, bool ignore,
0a39fd54 12549 enum built_in_function fcode)
12550{
c2f47e15 12551 tree fn_fputc, fn_fputs, call = NULL_TREE;
0a39fd54 12552 const char *fmt_str = NULL;
12553
12554 /* If the return value is used, don't do the transformation. */
12555 if (! ignore)
c2f47e15 12556 return NULL_TREE;
0a39fd54 12557
12558 /* Verify the required arguments in the original call. */
c2f47e15 12559 if (!validate_arg (fp, POINTER_TYPE))
12560 return NULL_TREE;
12561 if (!validate_arg (fmt, POINTER_TYPE))
12562 return NULL_TREE;
0a39fd54 12563
12564 /* Check whether the format is a literal string constant. */
12565 fmt_str = c_getstr (fmt);
12566 if (fmt_str == NULL)
12567 return NULL_TREE;
12568
12569 if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
12570 {
6d77ed92 12571 /* If we're using an unlocked function, assume the other
12572 unlocked functions exist explicitly. */
12573 fn_fputc = built_in_decls[BUILT_IN_FPUTC_UNLOCKED];
12574 fn_fputs = built_in_decls[BUILT_IN_FPUTS_UNLOCKED];
0a39fd54 12575 }
12576 else
12577 {
12578 fn_fputc = implicit_built_in_decls[BUILT_IN_FPUTC];
12579 fn_fputs = implicit_built_in_decls[BUILT_IN_FPUTS];
12580 }
12581
d4473c84 12582 if (!init_target_chars ())
c2f47e15 12583 return NULL_TREE;
a0c938f0 12584
0a39fd54 12585 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 12586 if (strchr (fmt_str, target_percent) == NULL)
0a39fd54 12587 {
12588 if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
c2f47e15 12589 && arg)
12590 return NULL_TREE;
0a39fd54 12591
12592 /* If the format specifier was "", fprintf does nothing. */
12593 if (fmt_str[0] == '\0')
12594 {
12595 /* If FP has side-effects, just wait until gimplification is
12596 done. */
12597 if (TREE_SIDE_EFFECTS (fp))
c2f47e15 12598 return NULL_TREE;
0a39fd54 12599
12600 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
12601 }
12602
12603 /* When "string" doesn't contain %, replace all cases of
12604 fprintf (fp, string) with fputs (string, fp). The fputs
12605 builtin will take care of special cases like length == 1. */
c2f47e15 12606 if (fn_fputs)
389dd41b 12607 call = build_call_expr_loc (loc, fn_fputs, 2, fmt, fp);
0a39fd54 12608 }
12609
12610 /* The other optimizations can be done only on the non-va_list variants. */
12611 else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
c2f47e15 12612 return NULL_TREE;
0a39fd54 12613
12614 /* If the format specifier was "%s", call __builtin_fputs (arg, fp). */
99eabcc1 12615 else if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12616 {
c2f47e15 12617 if (!arg || !validate_arg (arg, POINTER_TYPE))
12618 return NULL_TREE;
12619 if (fn_fputs)
389dd41b 12620 call = build_call_expr_loc (loc, fn_fputs, 2, arg, fp);
0a39fd54 12621 }
12622
12623 /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */
99eabcc1 12624 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 12625 {
c2f47e15 12626 if (!arg || !validate_arg (arg, INTEGER_TYPE))
12627 return NULL_TREE;
12628 if (fn_fputc)
389dd41b 12629 call = build_call_expr_loc (loc, fn_fputc, 2, arg, fp);
0a39fd54 12630 }
12631
c2f47e15 12632 if (!call)
12633 return NULL_TREE;
389dd41b 12634 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
0a39fd54 12635}
99eabcc1 12636
12637/* Initialize format string characters in the target charset. */
12638
12639static bool
12640init_target_chars (void)
12641{
12642 static bool init;
12643 if (!init)
12644 {
12645 target_newline = lang_hooks.to_target_charset ('\n');
12646 target_percent = lang_hooks.to_target_charset ('%');
12647 target_c = lang_hooks.to_target_charset ('c');
12648 target_s = lang_hooks.to_target_charset ('s');
12649 if (target_newline == 0 || target_percent == 0 || target_c == 0
12650 || target_s == 0)
12651 return false;
12652
12653 target_percent_c[0] = target_percent;
12654 target_percent_c[1] = target_c;
12655 target_percent_c[2] = '\0';
12656
12657 target_percent_s[0] = target_percent;
12658 target_percent_s[1] = target_s;
12659 target_percent_s[2] = '\0';
12660
12661 target_percent_s_newline[0] = target_percent;
12662 target_percent_s_newline[1] = target_s;
12663 target_percent_s_newline[2] = target_newline;
12664 target_percent_s_newline[3] = '\0';
a0c938f0 12665
99eabcc1 12666 init = true;
12667 }
12668 return true;
12669}
bffb7645 12670
f0c477f2 12671/* Helper function for do_mpfr_arg*(). Ensure M is a normal number
12672 and no overflow/underflow occurred. INEXACT is true if M was not
fa7637bd 12673 exactly calculated. TYPE is the tree type for the result. This
f0c477f2 12674 function assumes that you cleared the MPFR flags and then
12675 calculated M to see if anything subsequently set a flag prior to
12676 entering this function. Return NULL_TREE if any checks fail. */
12677
12678static tree
d4473c84 12679do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
f0c477f2 12680{
12681 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
12682 overflow/underflow occurred. If -frounding-math, proceed iff the
12683 result of calling FUNC was exact. */
d4473c84 12684 if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
f0c477f2 12685 && (!flag_rounding_math || !inexact))
12686 {
12687 REAL_VALUE_TYPE rr;
12688
66fa16e6 12689 real_from_mpfr (&rr, m, type, GMP_RNDN);
f0c477f2 12690 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
12691 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
12692 but the mpft_t is not, then we underflowed in the
12693 conversion. */
776a7bab 12694 if (real_isfinite (&rr)
f0c477f2 12695 && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
12696 {
12697 REAL_VALUE_TYPE rmode;
12698
12699 real_convert (&rmode, TYPE_MODE (type), &rr);
12700 /* Proceed iff the specified mode can hold the value. */
12701 if (real_identical (&rmode, &rr))
12702 return build_real (type, rmode);
12703 }
12704 }
12705 return NULL_TREE;
12706}
12707
239d491a 12708/* Helper function for do_mpc_arg*(). Ensure M is a normal complex
12709 number and no overflow/underflow occurred. INEXACT is true if M
12710 was not exactly calculated. TYPE is the tree type for the result.
12711 This function assumes that you cleared the MPFR flags and then
12712 calculated M to see if anything subsequently set a flag prior to
652d9409 12713 entering this function. Return NULL_TREE if any checks fail, if
12714 FORCE_CONVERT is true, then bypass the checks. */
239d491a 12715
12716static tree
652d9409 12717do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert)
239d491a 12718{
12719 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
12720 overflow/underflow occurred. If -frounding-math, proceed iff the
12721 result of calling FUNC was exact. */
652d9409 12722 if (force_convert
12723 || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m))
12724 && !mpfr_overflow_p () && !mpfr_underflow_p ()
12725 && (!flag_rounding_math || !inexact)))
239d491a 12726 {
12727 REAL_VALUE_TYPE re, im;
12728
c3cfad90 12729 real_from_mpfr (&re, mpc_realref (m), type, GMP_RNDN);
12730 real_from_mpfr (&im, mpc_imagref (m), type, GMP_RNDN);
239d491a 12731 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
12732 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
12733 but the mpft_t is not, then we underflowed in the
12734 conversion. */
652d9409 12735 if (force_convert
12736 || (real_isfinite (&re) && real_isfinite (&im)
12737 && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0)
12738 && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0)))
239d491a 12739 {
12740 REAL_VALUE_TYPE re_mode, im_mode;
12741
12742 real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re);
12743 real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im);
12744 /* Proceed iff the specified mode can hold the value. */
652d9409 12745 if (force_convert
12746 || (real_identical (&re_mode, &re)
12747 && real_identical (&im_mode, &im)))
239d491a 12748 return build_complex (type, build_real (TREE_TYPE (type), re_mode),
12749 build_real (TREE_TYPE (type), im_mode));
12750 }
12751 }
12752 return NULL_TREE;
12753}
239d491a 12754
bffb7645 12755/* If argument ARG is a REAL_CST, call the one-argument mpfr function
12756 FUNC on it and return the resulting value as a tree with type TYPE.
728bac60 12757 If MIN and/or MAX are not NULL, then the supplied ARG must be
12758 within those bounds. If INCLUSIVE is true, then MIN/MAX are
12759 acceptable values, otherwise they are not. The mpfr precision is
12760 set to the precision of TYPE. We assume that function FUNC returns
12761 zero if the result could be calculated exactly within the requested
12762 precision. */
bffb7645 12763
12764static tree
728bac60 12765do_mpfr_arg1 (tree arg, tree type, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
12766 const REAL_VALUE_TYPE *min, const REAL_VALUE_TYPE *max,
12767 bool inclusive)
bffb7645 12768{
12769 tree result = NULL_TREE;
48e1416a 12770
bffb7645 12771 STRIP_NOPS (arg);
12772
bd7d6fa4 12773 /* To proceed, MPFR must exactly represent the target floating point
12774 format, which only happens when the target base equals two. */
12775 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12776 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
bffb7645 12777 {
f0c477f2 12778 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
bffb7645 12779
776a7bab 12780 if (real_isfinite (ra)
f0c477f2 12781 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min))
12782 && (!max || real_compare (inclusive ? LE_EXPR: LT_EXPR , ra, max)))
bffb7645 12783 {
e2eb2b7f 12784 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
12785 const int prec = fmt->p;
12786 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
debf9994 12787 int inexact;
bffb7645 12788 mpfr_t m;
12789
12790 mpfr_init2 (m, prec);
66fa16e6 12791 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 12792 mpfr_clear_flags ();
e2eb2b7f 12793 inexact = func (m, m, rnd);
f0c477f2 12794 result = do_mpfr_ckconv (m, type, inexact);
bffb7645 12795 mpfr_clear (m);
12796 }
12797 }
48e1416a 12798
bffb7645 12799 return result;
12800}
f0c477f2 12801
12802/* If argument ARG is a REAL_CST, call the two-argument mpfr function
12803 FUNC on it and return the resulting value as a tree with type TYPE.
12804 The mpfr precision is set to the precision of TYPE. We assume that
12805 function FUNC returns zero if the result could be calculated
12806 exactly within the requested precision. */
12807
12808static tree
12809do_mpfr_arg2 (tree arg1, tree arg2, tree type,
12810 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
12811{
12812 tree result = NULL_TREE;
48e1416a 12813
f0c477f2 12814 STRIP_NOPS (arg1);
12815 STRIP_NOPS (arg2);
12816
bd7d6fa4 12817 /* To proceed, MPFR must exactly represent the target floating point
12818 format, which only happens when the target base equals two. */
12819 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12820 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
12821 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
f0c477f2 12822 {
12823 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
12824 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
12825
776a7bab 12826 if (real_isfinite (ra1) && real_isfinite (ra2))
f0c477f2 12827 {
e2eb2b7f 12828 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
12829 const int prec = fmt->p;
12830 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
f0c477f2 12831 int inexact;
12832 mpfr_t m1, m2;
12833
12834 mpfr_inits2 (prec, m1, m2, NULL);
66fa16e6 12835 mpfr_from_real (m1, ra1, GMP_RNDN);
12836 mpfr_from_real (m2, ra2, GMP_RNDN);
d4473c84 12837 mpfr_clear_flags ();
e2eb2b7f 12838 inexact = func (m1, m1, m2, rnd);
f0c477f2 12839 result = do_mpfr_ckconv (m1, type, inexact);
12840 mpfr_clears (m1, m2, NULL);
12841 }
12842 }
48e1416a 12843
f0c477f2 12844 return result;
12845}
d92f994c 12846
9917422b 12847/* If argument ARG is a REAL_CST, call the three-argument mpfr function
12848 FUNC on it and return the resulting value as a tree with type TYPE.
12849 The mpfr precision is set to the precision of TYPE. We assume that
12850 function FUNC returns zero if the result could be calculated
12851 exactly within the requested precision. */
12852
12853static tree
12854do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type,
12855 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
12856{
12857 tree result = NULL_TREE;
48e1416a 12858
9917422b 12859 STRIP_NOPS (arg1);
12860 STRIP_NOPS (arg2);
12861 STRIP_NOPS (arg3);
12862
bd7d6fa4 12863 /* To proceed, MPFR must exactly represent the target floating point
12864 format, which only happens when the target base equals two. */
12865 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12866 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
12867 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2)
12868 && TREE_CODE (arg3) == REAL_CST && !TREE_OVERFLOW (arg3))
9917422b 12869 {
12870 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
12871 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
12872 const REAL_VALUE_TYPE *const ra3 = &TREE_REAL_CST (arg3);
12873
776a7bab 12874 if (real_isfinite (ra1) && real_isfinite (ra2) && real_isfinite (ra3))
9917422b 12875 {
e2eb2b7f 12876 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
12877 const int prec = fmt->p;
12878 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
9917422b 12879 int inexact;
12880 mpfr_t m1, m2, m3;
12881
12882 mpfr_inits2 (prec, m1, m2, m3, NULL);
66fa16e6 12883 mpfr_from_real (m1, ra1, GMP_RNDN);
12884 mpfr_from_real (m2, ra2, GMP_RNDN);
12885 mpfr_from_real (m3, ra3, GMP_RNDN);
d4473c84 12886 mpfr_clear_flags ();
e2eb2b7f 12887 inexact = func (m1, m1, m2, m3, rnd);
9917422b 12888 result = do_mpfr_ckconv (m1, type, inexact);
12889 mpfr_clears (m1, m2, m3, NULL);
12890 }
12891 }
48e1416a 12892
9917422b 12893 return result;
12894}
12895
d92f994c 12896/* If argument ARG is a REAL_CST, call mpfr_sin_cos() on it and set
12897 the pointers *(ARG_SINP) and *(ARG_COSP) to the resulting values.
d735c391 12898 If ARG_SINP and ARG_COSP are NULL then the result is returned
12899 as a complex value.
d92f994c 12900 The type is taken from the type of ARG and is used for setting the
12901 precision of the calculation and results. */
12902
12903static tree
12904do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp)
12905{
bd7d6fa4 12906 tree const type = TREE_TYPE (arg);
d92f994c 12907 tree result = NULL_TREE;
48e1416a 12908
d92f994c 12909 STRIP_NOPS (arg);
48e1416a 12910
bd7d6fa4 12911 /* To proceed, MPFR must exactly represent the target floating point
12912 format, which only happens when the target base equals two. */
12913 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 12914 && TREE_CODE (arg) == REAL_CST
12915 && !TREE_OVERFLOW (arg))
d92f994c 12916 {
12917 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
12918
776a7bab 12919 if (real_isfinite (ra))
d92f994c 12920 {
e2eb2b7f 12921 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
12922 const int prec = fmt->p;
12923 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
d92f994c 12924 tree result_s, result_c;
12925 int inexact;
12926 mpfr_t m, ms, mc;
12927
12928 mpfr_inits2 (prec, m, ms, mc, NULL);
66fa16e6 12929 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 12930 mpfr_clear_flags ();
e2eb2b7f 12931 inexact = mpfr_sin_cos (ms, mc, m, rnd);
d92f994c 12932 result_s = do_mpfr_ckconv (ms, type, inexact);
12933 result_c = do_mpfr_ckconv (mc, type, inexact);
12934 mpfr_clears (m, ms, mc, NULL);
12935 if (result_s && result_c)
12936 {
d735c391 12937 /* If we are to return in a complex value do so. */
12938 if (!arg_sinp && !arg_cosp)
12939 return build_complex (build_complex_type (type),
12940 result_c, result_s);
12941
d92f994c 12942 /* Dereference the sin/cos pointer arguments. */
12943 arg_sinp = build_fold_indirect_ref (arg_sinp);
12944 arg_cosp = build_fold_indirect_ref (arg_cosp);
12945 /* Proceed if valid pointer type were passed in. */
12946 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_sinp)) == TYPE_MAIN_VARIANT (type)
12947 && TYPE_MAIN_VARIANT (TREE_TYPE (arg_cosp)) == TYPE_MAIN_VARIANT (type))
12948 {
12949 /* Set the values. */
41076ef6 12950 result_s = fold_build2 (MODIFY_EXPR, type, arg_sinp,
35cc02b5 12951 result_s);
d92f994c 12952 TREE_SIDE_EFFECTS (result_s) = 1;
41076ef6 12953 result_c = fold_build2 (MODIFY_EXPR, type, arg_cosp,
35cc02b5 12954 result_c);
d92f994c 12955 TREE_SIDE_EFFECTS (result_c) = 1;
12956 /* Combine the assignments into a compound expr. */
12957 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
12958 result_s, result_c));
12959 }
12960 }
12961 }
12962 }
12963 return result;
12964}
65dd1378 12965
65dd1378 12966/* If argument ARG1 is an INTEGER_CST and ARG2 is a REAL_CST, call the
12967 two-argument mpfr order N Bessel function FUNC on them and return
12968 the resulting value as a tree with type TYPE. The mpfr precision
12969 is set to the precision of TYPE. We assume that function FUNC
12970 returns zero if the result could be calculated exactly within the
12971 requested precision. */
12972static tree
12973do_mpfr_bessel_n (tree arg1, tree arg2, tree type,
12974 int (*func)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
12975 const REAL_VALUE_TYPE *min, bool inclusive)
12976{
12977 tree result = NULL_TREE;
12978
12979 STRIP_NOPS (arg1);
12980 STRIP_NOPS (arg2);
12981
12982 /* To proceed, MPFR must exactly represent the target floating point
12983 format, which only happens when the target base equals two. */
12984 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
12985 && host_integerp (arg1, 0)
12986 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
12987 {
12988 const HOST_WIDE_INT n = tree_low_cst(arg1, 0);
12989 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg2);
12990
12991 if (n == (long)n
776a7bab 12992 && real_isfinite (ra)
65dd1378 12993 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min)))
12994 {
e2eb2b7f 12995 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
12996 const int prec = fmt->p;
12997 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
65dd1378 12998 int inexact;
12999 mpfr_t m;
13000
13001 mpfr_init2 (m, prec);
13002 mpfr_from_real (m, ra, GMP_RNDN);
13003 mpfr_clear_flags ();
e2eb2b7f 13004 inexact = func (m, n, m, rnd);
65dd1378 13005 result = do_mpfr_ckconv (m, type, inexact);
13006 mpfr_clear (m);
13007 }
13008 }
48e1416a 13009
65dd1378 13010 return result;
13011}
e5407ca6 13012
13013/* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
13014 the pointer *(ARG_QUO) and return the result. The type is taken
13015 from the type of ARG0 and is used for setting the precision of the
13016 calculation and results. */
13017
13018static tree
13019do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
13020{
13021 tree const type = TREE_TYPE (arg0);
13022 tree result = NULL_TREE;
48e1416a 13023
e5407ca6 13024 STRIP_NOPS (arg0);
13025 STRIP_NOPS (arg1);
48e1416a 13026
e5407ca6 13027 /* To proceed, MPFR must exactly represent the target floating point
13028 format, which only happens when the target base equals two. */
13029 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13030 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
13031 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
13032 {
13033 const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
13034 const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
13035
776a7bab 13036 if (real_isfinite (ra0) && real_isfinite (ra1))
e5407ca6 13037 {
e2eb2b7f 13038 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13039 const int prec = fmt->p;
13040 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
e5407ca6 13041 tree result_rem;
13042 long integer_quo;
13043 mpfr_t m0, m1;
13044
13045 mpfr_inits2 (prec, m0, m1, NULL);
13046 mpfr_from_real (m0, ra0, GMP_RNDN);
13047 mpfr_from_real (m1, ra1, GMP_RNDN);
13048 mpfr_clear_flags ();
e2eb2b7f 13049 mpfr_remquo (m0, &integer_quo, m0, m1, rnd);
e5407ca6 13050 /* Remquo is independent of the rounding mode, so pass
13051 inexact=0 to do_mpfr_ckconv(). */
13052 result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
13053 mpfr_clears (m0, m1, NULL);
13054 if (result_rem)
13055 {
13056 /* MPFR calculates quo in the host's long so it may
13057 return more bits in quo than the target int can hold
13058 if sizeof(host long) > sizeof(target int). This can
13059 happen even for native compilers in LP64 mode. In
13060 these cases, modulo the quo value with the largest
13061 number that the target int can hold while leaving one
13062 bit for the sign. */
13063 if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
13064 integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
13065
13066 /* Dereference the quo pointer argument. */
13067 arg_quo = build_fold_indirect_ref (arg_quo);
13068 /* Proceed iff a valid pointer type was passed in. */
13069 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
13070 {
13071 /* Set the value. */
13072 tree result_quo = fold_build2 (MODIFY_EXPR,
13073 TREE_TYPE (arg_quo), arg_quo,
13074 build_int_cst (NULL, integer_quo));
13075 TREE_SIDE_EFFECTS (result_quo) = 1;
13076 /* Combine the quo assignment with the rem. */
13077 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13078 result_quo, result_rem));
13079 }
13080 }
13081 }
13082 }
13083 return result;
13084}
e84da7c1 13085
13086/* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
13087 resulting value as a tree with type TYPE. The mpfr precision is
13088 set to the precision of TYPE. We assume that this mpfr function
13089 returns zero if the result could be calculated exactly within the
13090 requested precision. In addition, the integer pointer represented
13091 by ARG_SG will be dereferenced and set to the appropriate signgam
13092 (-1,1) value. */
13093
13094static tree
13095do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
13096{
13097 tree result = NULL_TREE;
13098
13099 STRIP_NOPS (arg);
48e1416a 13100
e84da7c1 13101 /* To proceed, MPFR must exactly represent the target floating point
13102 format, which only happens when the target base equals two. Also
13103 verify ARG is a constant and that ARG_SG is an int pointer. */
13104 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13105 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
13106 && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
13107 && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
13108 {
13109 const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
13110
13111 /* In addition to NaN and Inf, the argument cannot be zero or a
13112 negative integer. */
776a7bab 13113 if (real_isfinite (ra)
e84da7c1 13114 && ra->cl != rvc_zero
13115 && !(real_isneg(ra) && real_isinteger(ra, TYPE_MODE (type))))
13116 {
e2eb2b7f 13117 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13118 const int prec = fmt->p;
13119 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
e84da7c1 13120 int inexact, sg;
13121 mpfr_t m;
13122 tree result_lg;
13123
13124 mpfr_init2 (m, prec);
13125 mpfr_from_real (m, ra, GMP_RNDN);
13126 mpfr_clear_flags ();
e2eb2b7f 13127 inexact = mpfr_lgamma (m, &sg, m, rnd);
e84da7c1 13128 result_lg = do_mpfr_ckconv (m, type, inexact);
13129 mpfr_clear (m);
13130 if (result_lg)
13131 {
13132 tree result_sg;
13133
13134 /* Dereference the arg_sg pointer argument. */
13135 arg_sg = build_fold_indirect_ref (arg_sg);
13136 /* Assign the signgam value into *arg_sg. */
13137 result_sg = fold_build2 (MODIFY_EXPR,
13138 TREE_TYPE (arg_sg), arg_sg,
13139 build_int_cst (NULL, sg));
13140 TREE_SIDE_EFFECTS (result_sg) = 1;
13141 /* Combine the signgam assignment with the lgamma result. */
13142 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13143 result_sg, result_lg));
13144 }
13145 }
13146 }
13147
13148 return result;
13149}
75a70cf9 13150
239d491a 13151/* If argument ARG is a COMPLEX_CST, call the one-argument mpc
13152 function FUNC on it and return the resulting value as a tree with
13153 type TYPE. The mpfr precision is set to the precision of TYPE. We
13154 assume that function FUNC returns zero if the result could be
13155 calculated exactly within the requested precision. */
13156
13157static tree
13158do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t))
13159{
13160 tree result = NULL_TREE;
48e1416a 13161
239d491a 13162 STRIP_NOPS (arg);
13163
13164 /* To proceed, MPFR must exactly represent the target floating point
13165 format, which only happens when the target base equals two. */
13166 if (TREE_CODE (arg) == COMPLEX_CST && !TREE_OVERFLOW (arg)
13167 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE
13168 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))))->b == 2)
13169 {
13170 const REAL_VALUE_TYPE *const re = TREE_REAL_CST_PTR (TREE_REALPART (arg));
13171 const REAL_VALUE_TYPE *const im = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
13172
13173 if (real_isfinite (re) && real_isfinite (im))
13174 {
13175 const struct real_format *const fmt =
13176 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
13177 const int prec = fmt->p;
13178 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
44d89feb 13179 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
239d491a 13180 int inexact;
13181 mpc_t m;
48e1416a 13182
239d491a 13183 mpc_init2 (m, prec);
c3cfad90 13184 mpfr_from_real (mpc_realref(m), re, rnd);
13185 mpfr_from_real (mpc_imagref(m), im, rnd);
239d491a 13186 mpfr_clear_flags ();
44d89feb 13187 inexact = func (m, m, crnd);
652d9409 13188 result = do_mpc_ckconv (m, type, inexact, /*force_convert=*/ 0);
239d491a 13189 mpc_clear (m);
13190 }
13191 }
13192
13193 return result;
13194}
c699fab8 13195
13196/* If arguments ARG0 and ARG1 are a COMPLEX_CST, call the two-argument
13197 mpc function FUNC on it and return the resulting value as a tree
13198 with type TYPE. The mpfr precision is set to the precision of
13199 TYPE. We assume that function FUNC returns zero if the result
652d9409 13200 could be calculated exactly within the requested precision. If
13201 DO_NONFINITE is true, then fold expressions containing Inf or NaN
13202 in the arguments and/or results. */
c699fab8 13203
63e89698 13204tree
652d9409 13205do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
c699fab8 13206 int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
13207{
13208 tree result = NULL_TREE;
48e1416a 13209
c699fab8 13210 STRIP_NOPS (arg0);
13211 STRIP_NOPS (arg1);
13212
13213 /* To proceed, MPFR must exactly represent the target floating point
13214 format, which only happens when the target base equals two. */
13215 if (TREE_CODE (arg0) == COMPLEX_CST && !TREE_OVERFLOW (arg0)
13216 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
13217 && TREE_CODE (arg1) == COMPLEX_CST && !TREE_OVERFLOW (arg1)
13218 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE
13219 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))))->b == 2)
13220 {
13221 const REAL_VALUE_TYPE *const re0 = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
13222 const REAL_VALUE_TYPE *const im0 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
13223 const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1));
13224 const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1));
13225
652d9409 13226 if (do_nonfinite
13227 || (real_isfinite (re0) && real_isfinite (im0)
13228 && real_isfinite (re1) && real_isfinite (im1)))
c699fab8 13229 {
13230 const struct real_format *const fmt =
13231 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
13232 const int prec = fmt->p;
13233 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
13234 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
13235 int inexact;
13236 mpc_t m0, m1;
48e1416a 13237
c699fab8 13238 mpc_init2 (m0, prec);
13239 mpc_init2 (m1, prec);
13240 mpfr_from_real (mpc_realref(m0), re0, rnd);
13241 mpfr_from_real (mpc_imagref(m0), im0, rnd);
13242 mpfr_from_real (mpc_realref(m1), re1, rnd);
13243 mpfr_from_real (mpc_imagref(m1), im1, rnd);
13244 mpfr_clear_flags ();
13245 inexact = func (m0, m0, m1, crnd);
652d9409 13246 result = do_mpc_ckconv (m0, type, inexact, do_nonfinite);
c699fab8 13247 mpc_clear (m0);
13248 mpc_clear (m1);
13249 }
13250 }
13251
13252 return result;
13253}
239d491a 13254
75a70cf9 13255/* FIXME tuples.
13256 The functions below provide an alternate interface for folding
13257 builtin function calls presented as GIMPLE_CALL statements rather
13258 than as CALL_EXPRs. The folded result is still expressed as a
13259 tree. There is too much code duplication in the handling of
13260 varargs functions, and a more intrusive re-factoring would permit
13261 better sharing of code between the tree and statement-based
13262 versions of these functions. */
13263
13264/* Construct a new CALL_EXPR using the tail of the argument list of STMT
13265 along with N new arguments specified as the "..." parameters. SKIP
13266 is the number of arguments in STMT to be omitted. This function is used
13267 to do varargs-to-varargs transformations. */
13268
13269static tree
13270gimple_rewrite_call_expr (gimple stmt, int skip, tree fndecl, int n, ...)
13271{
13272 int oldnargs = gimple_call_num_args (stmt);
13273 int nargs = oldnargs - skip + n;
13274 tree fntype = TREE_TYPE (fndecl);
13275 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
13276 tree *buffer;
13277 int i, j;
13278 va_list ap;
389dd41b 13279 location_t loc = gimple_location (stmt);
75a70cf9 13280
13281 buffer = XALLOCAVEC (tree, nargs);
13282 va_start (ap, n);
13283 for (i = 0; i < n; i++)
13284 buffer[i] = va_arg (ap, tree);
13285 va_end (ap);
13286 for (j = skip; j < oldnargs; j++, i++)
13287 buffer[i] = gimple_call_arg (stmt, j);
13288
389dd41b 13289 return fold (build_call_array_loc (loc, TREE_TYPE (fntype), fn, nargs, buffer));
75a70cf9 13290}
13291
13292/* Fold a call STMT to __{,v}sprintf_chk. Return NULL_TREE if
13293 a normal call should be emitted rather than expanding the function
13294 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
13295
13296static tree
13297gimple_fold_builtin_sprintf_chk (gimple stmt, enum built_in_function fcode)
13298{
13299 tree dest, size, len, fn, fmt, flag;
13300 const char *fmt_str;
13301 int nargs = gimple_call_num_args (stmt);
13302
13303 /* Verify the required arguments in the original call. */
13304 if (nargs < 4)
13305 return NULL_TREE;
13306 dest = gimple_call_arg (stmt, 0);
13307 if (!validate_arg (dest, POINTER_TYPE))
13308 return NULL_TREE;
13309 flag = gimple_call_arg (stmt, 1);
13310 if (!validate_arg (flag, INTEGER_TYPE))
13311 return NULL_TREE;
13312 size = gimple_call_arg (stmt, 2);
13313 if (!validate_arg (size, INTEGER_TYPE))
13314 return NULL_TREE;
13315 fmt = gimple_call_arg (stmt, 3);
13316 if (!validate_arg (fmt, POINTER_TYPE))
13317 return NULL_TREE;
13318
13319 if (! host_integerp (size, 1))
13320 return NULL_TREE;
13321
13322 len = NULL_TREE;
13323
13324 if (!init_target_chars ())
13325 return NULL_TREE;
13326
13327 /* Check whether the format is a literal string constant. */
13328 fmt_str = c_getstr (fmt);
13329 if (fmt_str != NULL)
13330 {
13331 /* If the format doesn't contain % args or %%, we know the size. */
13332 if (strchr (fmt_str, target_percent) == 0)
13333 {
13334 if (fcode != BUILT_IN_SPRINTF_CHK || nargs == 4)
13335 len = build_int_cstu (size_type_node, strlen (fmt_str));
13336 }
13337 /* If the format is "%s" and first ... argument is a string literal,
13338 we know the size too. */
13339 else if (fcode == BUILT_IN_SPRINTF_CHK
13340 && strcmp (fmt_str, target_percent_s) == 0)
13341 {
13342 tree arg;
13343
13344 if (nargs == 5)
13345 {
13346 arg = gimple_call_arg (stmt, 4);
13347 if (validate_arg (arg, POINTER_TYPE))
13348 {
13349 len = c_strlen (arg, 1);
13350 if (! len || ! host_integerp (len, 1))
13351 len = NULL_TREE;
13352 }
13353 }
13354 }
13355 }
13356
13357 if (! integer_all_onesp (size))
13358 {
13359 if (! len || ! tree_int_cst_lt (len, size))
13360 return NULL_TREE;
13361 }
13362
13363 /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
13364 or if format doesn't contain % chars or is "%s". */
13365 if (! integer_zerop (flag))
13366 {
13367 if (fmt_str == NULL)
13368 return NULL_TREE;
13369 if (strchr (fmt_str, target_percent) != NULL
13370 && strcmp (fmt_str, target_percent_s))
13371 return NULL_TREE;
13372 }
13373
13374 /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
13375 fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
13376 ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
13377 if (!fn)
13378 return NULL_TREE;
13379
13380 return gimple_rewrite_call_expr (stmt, 4, fn, 2, dest, fmt);
13381}
13382
13383/* Fold a call STMT to {,v}snprintf. Return NULL_TREE if
13384 a normal call should be emitted rather than expanding the function
13385 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
13386 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
13387 passed as second argument. */
13388
13389tree
13390gimple_fold_builtin_snprintf_chk (gimple stmt, tree maxlen,
13391 enum built_in_function fcode)
13392{
13393 tree dest, size, len, fn, fmt, flag;
13394 const char *fmt_str;
13395
13396 /* Verify the required arguments in the original call. */
13397 if (gimple_call_num_args (stmt) < 5)
13398 return NULL_TREE;
13399 dest = gimple_call_arg (stmt, 0);
13400 if (!validate_arg (dest, POINTER_TYPE))
13401 return NULL_TREE;
13402 len = gimple_call_arg (stmt, 1);
13403 if (!validate_arg (len, INTEGER_TYPE))
13404 return NULL_TREE;
13405 flag = gimple_call_arg (stmt, 2);
13406 if (!validate_arg (flag, INTEGER_TYPE))
13407 return NULL_TREE;
13408 size = gimple_call_arg (stmt, 3);
13409 if (!validate_arg (size, INTEGER_TYPE))
13410 return NULL_TREE;
13411 fmt = gimple_call_arg (stmt, 4);
13412 if (!validate_arg (fmt, POINTER_TYPE))
13413 return NULL_TREE;
13414
13415 if (! host_integerp (size, 1))
13416 return NULL_TREE;
13417
13418 if (! integer_all_onesp (size))
13419 {
13420 if (! host_integerp (len, 1))
13421 {
13422 /* If LEN is not constant, try MAXLEN too.
13423 For MAXLEN only allow optimizing into non-_ocs function
13424 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
13425 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
13426 return NULL_TREE;
13427 }
13428 else
13429 maxlen = len;
13430
13431 if (tree_int_cst_lt (size, maxlen))
13432 return NULL_TREE;
13433 }
13434
13435 if (!init_target_chars ())
13436 return NULL_TREE;
13437
13438 /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
13439 or if format doesn't contain % chars or is "%s". */
13440 if (! integer_zerop (flag))
13441 {
13442 fmt_str = c_getstr (fmt);
13443 if (fmt_str == NULL)
13444 return NULL_TREE;
13445 if (strchr (fmt_str, target_percent) != NULL
13446 && strcmp (fmt_str, target_percent_s))
13447 return NULL_TREE;
13448 }
13449
13450 /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
13451 available. */
13452 fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
13453 ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
13454 if (!fn)
13455 return NULL_TREE;
13456
13457 return gimple_rewrite_call_expr (stmt, 5, fn, 3, dest, len, fmt);
13458}
13459
13460/* Builtins with folding operations that operate on "..." arguments
13461 need special handling; we need to store the arguments in a convenient
13462 data structure before attempting any folding. Fortunately there are
13463 only a few builtins that fall into this category. FNDECL is the
13464 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
13465 result of the function call is ignored. */
13466
13467static tree
389dd41b 13468gimple_fold_builtin_varargs (tree fndecl, gimple stmt,
13469 bool ignore ATTRIBUTE_UNUSED)
75a70cf9 13470{
13471 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
13472 tree ret = NULL_TREE;
13473
13474 switch (fcode)
13475 {
13476 case BUILT_IN_SPRINTF_CHK:
13477 case BUILT_IN_VSPRINTF_CHK:
13478 ret = gimple_fold_builtin_sprintf_chk (stmt, fcode);
13479 break;
13480
13481 case BUILT_IN_SNPRINTF_CHK:
13482 case BUILT_IN_VSNPRINTF_CHK:
13483 ret = gimple_fold_builtin_snprintf_chk (stmt, NULL_TREE, fcode);
13484
13485 default:
13486 break;
13487 }
13488 if (ret)
13489 {
13490 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
13491 TREE_NO_WARNING (ret) = 1;
13492 return ret;
13493 }
13494 return NULL_TREE;
13495}
13496
13497/* A wrapper function for builtin folding that prevents warnings for
13498 "statement without effect" and the like, caused by removing the
13499 call node earlier than the warning is generated. */
13500
13501tree
13502fold_call_stmt (gimple stmt, bool ignore)
13503{
13504 tree ret = NULL_TREE;
13505 tree fndecl = gimple_call_fndecl (stmt);
389dd41b 13506 location_t loc = gimple_location (stmt);
75a70cf9 13507 if (fndecl
13508 && TREE_CODE (fndecl) == FUNCTION_DECL
13509 && DECL_BUILT_IN (fndecl)
13510 && !gimple_call_va_arg_pack_p (stmt))
13511 {
13512 int nargs = gimple_call_num_args (stmt);
13513
198622c0 13514 if (avoid_folding_inline_builtin (fndecl))
13515 return NULL_TREE;
75a70cf9 13516 /* FIXME: Don't use a list in this interface. */
13517 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
13518 {
13519 tree arglist = NULL_TREE;
13520 int i;
13521 for (i = nargs - 1; i >= 0; i--)
13522 arglist = tree_cons (NULL_TREE, gimple_call_arg (stmt, i), arglist);
13523 return targetm.fold_builtin (fndecl, arglist, ignore);
13524 }
13525 else
13526 {
13527 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
13528 {
13529 tree args[MAX_ARGS_TO_FOLD_BUILTIN];
13530 int i;
13531 for (i = 0; i < nargs; i++)
13532 args[i] = gimple_call_arg (stmt, i);
389dd41b 13533 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
75a70cf9 13534 }
13535 if (!ret)
13536 ret = gimple_fold_builtin_varargs (fndecl, stmt, ignore);
13537 if (ret)
13538 {
13539 /* Propagate location information from original call to
13540 expansion of builtin. Otherwise things like
13541 maybe_emit_chk_warning, that operate on the expansion
13542 of a builtin, will use the wrong location information. */
13543 if (gimple_has_location (stmt))
13544 {
13545 tree realret = ret;
13546 if (TREE_CODE (ret) == NOP_EXPR)
13547 realret = TREE_OPERAND (ret, 0);
13548 if (CAN_HAVE_LOCATION_P (realret)
13549 && !EXPR_HAS_LOCATION (realret))
389dd41b 13550 SET_EXPR_LOCATION (realret, loc);
75a70cf9 13551 return realret;
13552 }
13553 return ret;
13554 }
13555 }
13556 }
13557 return NULL_TREE;
13558}
7bfefa9d 13559
13560/* Look up the function in built_in_decls that corresponds to DECL
13561 and set ASMSPEC as its user assembler name. DECL must be a
13562 function decl that declares a builtin. */
13563
13564void
13565set_builtin_user_assembler_name (tree decl, const char *asmspec)
13566{
13567 tree builtin;
13568 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
13569 && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
13570 && asmspec != 0);
13571
13572 builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
13573 set_user_assembler_name (builtin, asmspec);
13574 switch (DECL_FUNCTION_CODE (decl))
13575 {
13576 case BUILT_IN_MEMCPY:
13577 init_block_move_fn (asmspec);
13578 memcpy_libfunc = set_user_assembler_libfunc ("memcpy", asmspec);
13579 break;
13580 case BUILT_IN_MEMSET:
13581 init_block_clear_fn (asmspec);
13582 memset_libfunc = set_user_assembler_libfunc ("memset", asmspec);
13583 break;
13584 case BUILT_IN_MEMMOVE:
13585 memmove_libfunc = set_user_assembler_libfunc ("memmove", asmspec);
13586 break;
13587 case BUILT_IN_MEMCMP:
13588 memcmp_libfunc = set_user_assembler_libfunc ("memcmp", asmspec);
13589 break;
13590 case BUILT_IN_ABORT:
13591 abort_libfunc = set_user_assembler_libfunc ("abort", asmspec);
13592 break;
13593 default:
13594 break;
13595 }
13596}