]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/builtins.c
* g++.dg/abi/regparm1.C: Fix execute test.
[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 61#ifdef HAVE_mpc
62static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_rnd_t));
63#endif
726e2588 64
ab7943b9 65/* Define the names of the builtin function types and codes. */
8934cb0c 66const char *const built_in_class_names[4]
ab7943b9 67 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
68
9cfddb70 69#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
0dfc45b5 70const char * built_in_names[(int) END_BUILTINS] =
4e9d90c7 71{
72#include "builtins.def"
73};
74#undef DEF_BUILTIN
ab7943b9 75
df94cd3b 76/* Setup an array of _DECL trees, make sure each element is
77 initialized to NULL_TREE. */
d2d4bdde 78tree built_in_decls[(int) END_BUILTINS];
0a68165a 79/* Declarations used when constructing the builtin implicitly in the compiler.
80 It may be NULL_TREE when this is invalid (for instance runtime is not
4ee9c684 81 required to implement the function call in all cases). */
0a68165a 82tree implicit_built_in_decls[(int) END_BUILTINS];
df94cd3b 83
aecda0d6 84static const char *c_getstr (tree);
85static rtx c_readstr (const char *, enum machine_mode);
86static int target_char_cast (tree, char *);
d8ae1baa 87static rtx get_memory_rtx (tree, tree);
aecda0d6 88static int apply_args_size (void);
89static int apply_result_size (void);
d8c9779c 90#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
aecda0d6 91static rtx result_vector (int, rtx);
d8c9779c 92#endif
843d08a9 93static void expand_builtin_update_setjmp_buf (rtx);
aecda0d6 94static void expand_builtin_prefetch (tree);
95static rtx expand_builtin_apply_args (void);
96static rtx expand_builtin_apply_args_1 (void);
97static rtx expand_builtin_apply (rtx, rtx, rtx);
98static void expand_builtin_return (rtx);
99static enum type_class type_to_class (tree);
100static rtx expand_builtin_classify_type (tree);
101static void expand_errno_check (tree, rtx);
102static rtx expand_builtin_mathfn (tree, rtx, rtx);
103static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
6b43bae4 104static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
a67a90e5 105static rtx expand_builtin_interclass_mathfn (tree, rtx, rtx);
c3147c1a 106static rtx expand_builtin_sincos (tree);
d735c391 107static rtx expand_builtin_cexpi (tree, rtx, rtx);
ff1b14e4 108static rtx expand_builtin_int_roundingfn (tree, rtx);
109static rtx expand_builtin_int_roundingfn_2 (tree, rtx);
aecda0d6 110static rtx expand_builtin_args_info (tree);
79012a9d 111static rtx expand_builtin_next_arg (void);
aecda0d6 112static rtx expand_builtin_va_start (tree);
113static rtx expand_builtin_va_end (tree);
114static rtx expand_builtin_va_copy (tree);
c2f47e15 115static rtx expand_builtin_memcmp (tree, rtx, enum machine_mode);
a65c4d64 116static rtx expand_builtin_strcmp (tree, rtx);
aecda0d6 117static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
118static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
a65c4d64 119static rtx expand_builtin_memcpy (tree, rtx);
c2f47e15 120static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode);
a65c4d64 121static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx,
c2f47e15 122 enum machine_mode, int);
a65c4d64 123static rtx expand_builtin_strcpy (tree, rtx);
124static rtx expand_builtin_strcpy_args (tree, tree, rtx);
aecda0d6 125static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
a65c4d64 126static rtx expand_builtin_strncpy (tree, rtx);
aecda0d6 127static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
c2f47e15 128static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
129static rtx expand_builtin_memset_args (tree, tree, tree, rtx, enum machine_mode, tree);
aecda0d6 130static rtx expand_builtin_bzero (tree);
131static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
aecda0d6 132static rtx expand_builtin_alloca (tree, rtx);
133static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
134static rtx expand_builtin_frame_address (tree, tree);
19bf118a 135static rtx expand_builtin_printf (tree, rtx, enum machine_mode, bool);
136static rtx expand_builtin_fprintf (tree, rtx, enum machine_mode, bool);
6411575e 137static rtx expand_builtin_sprintf (tree, rtx, enum machine_mode);
389dd41b 138static tree stabilize_va_list_loc (location_t, tree, int);
aecda0d6 139static rtx expand_builtin_expect (tree, rtx);
140static tree fold_builtin_constant_p (tree);
389dd41b 141static tree fold_builtin_expect (location_t, tree, tree);
aecda0d6 142static tree fold_builtin_classify_type (tree);
389dd41b 143static tree fold_builtin_strlen (location_t, tree);
144static tree fold_builtin_inf (location_t, tree, int);
aecda0d6 145static tree fold_builtin_nan (tree, tree, int);
389dd41b 146static tree rewrite_call_expr (location_t, tree, int, tree, int, ...);
b7bf20db 147static bool validate_arg (const_tree, enum tree_code code);
277f8dd2 148static bool integer_valued_real_p (tree);
389dd41b 149static tree fold_trunc_transparent_mathfn (location_t, tree, tree);
aecda0d6 150static bool readonly_data_expr (tree);
151static rtx expand_builtin_fabs (tree, rtx, rtx);
27f261ef 152static rtx expand_builtin_signbit (tree, rtx);
389dd41b 153static tree fold_builtin_sqrt (location_t, tree, tree);
154static tree fold_builtin_cbrt (location_t, tree, tree);
155static tree fold_builtin_pow (location_t, tree, tree, tree, tree);
156static tree fold_builtin_powi (location_t, tree, tree, tree, tree);
157static tree fold_builtin_cos (location_t, tree, tree, tree);
158static tree fold_builtin_cosh (location_t, tree, tree, tree);
bffb7645 159static tree fold_builtin_tan (tree, tree);
389dd41b 160static tree fold_builtin_trunc (location_t, tree, tree);
161static tree fold_builtin_floor (location_t, tree, tree);
162static tree fold_builtin_ceil (location_t, tree, tree);
163static tree fold_builtin_round (location_t, tree, tree);
164static tree fold_builtin_int_roundingfn (location_t, tree, tree);
10b9666f 165static tree fold_builtin_bitop (tree, tree);
389dd41b 166static tree fold_builtin_memory_op (location_t, tree, tree, tree, tree, bool, int);
167static tree fold_builtin_strchr (location_t, tree, tree, tree);
168static tree fold_builtin_memchr (location_t, tree, tree, tree, tree);
169static tree fold_builtin_memcmp (location_t, tree, tree, tree);
170static tree fold_builtin_strcmp (location_t, tree, tree);
171static tree fold_builtin_strncmp (location_t, tree, tree, tree);
172static tree fold_builtin_signbit (location_t, tree, tree);
173static tree fold_builtin_copysign (location_t, tree, tree, tree, tree);
174static tree fold_builtin_isascii (location_t, tree);
175static tree fold_builtin_toascii (location_t, tree);
176static tree fold_builtin_isdigit (location_t, tree);
177static tree fold_builtin_fabs (location_t, tree, tree);
178static tree fold_builtin_abs (location_t, tree, tree);
179static tree fold_builtin_unordered_cmp (location_t, tree, tree, tree, enum tree_code,
d5019fe8 180 enum tree_code);
389dd41b 181static tree fold_builtin_n (location_t, tree, tree *, int, bool);
182static tree fold_builtin_0 (location_t, tree, bool);
183static tree fold_builtin_1 (location_t, tree, tree, bool);
184static tree fold_builtin_2 (location_t, tree, tree, tree, bool);
185static tree fold_builtin_3 (location_t, tree, tree, tree, tree, bool);
186static tree fold_builtin_4 (location_t, tree, tree, tree, tree, tree, bool);
187static tree fold_builtin_varargs (location_t, tree, tree, bool);
188
189static tree fold_builtin_strpbrk (location_t, tree, tree, tree);
190static tree fold_builtin_strstr (location_t, tree, tree, tree);
191static tree fold_builtin_strrchr (location_t, tree, tree, tree);
192static tree fold_builtin_strcat (location_t, tree, tree);
193static tree fold_builtin_strncat (location_t, tree, tree, tree);
194static tree fold_builtin_strspn (location_t, tree, tree);
195static tree fold_builtin_strcspn (location_t, tree, tree);
196static tree fold_builtin_sprintf (location_t, tree, tree, tree, int);
4ee9c684 197
0a39fd54 198static rtx expand_builtin_object_size (tree);
199static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
200 enum built_in_function);
201static void maybe_emit_chk_warning (tree, enum built_in_function);
202static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
2c281b15 203static void maybe_emit_free_warning (tree);
c2f47e15 204static tree fold_builtin_object_size (tree, tree);
389dd41b 205static tree fold_builtin_strcat_chk (location_t, tree, tree, tree, tree);
206static tree fold_builtin_strncat_chk (location_t, tree, tree, tree, tree, tree);
207static tree fold_builtin_sprintf_chk (location_t, tree, enum built_in_function);
208static tree fold_builtin_printf (location_t, tree, tree, tree, bool, enum built_in_function);
209static tree fold_builtin_fprintf (location_t, tree, tree, tree, tree, bool,
c2f47e15 210 enum built_in_function);
99eabcc1 211static bool init_target_chars (void);
212
213static unsigned HOST_WIDE_INT target_newline;
214static unsigned HOST_WIDE_INT target_percent;
215static unsigned HOST_WIDE_INT target_c;
216static unsigned HOST_WIDE_INT target_s;
217static char target_percent_c[3];
218static char target_percent_s[3];
219static char target_percent_s_newline[4];
728bac60 220static tree do_mpfr_arg1 (tree, tree, int (*)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
221 const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, bool);
f0c477f2 222static tree do_mpfr_arg2 (tree, tree, tree,
223 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
9917422b 224static tree do_mpfr_arg3 (tree, tree, tree, tree,
225 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
d92f994c 226static tree do_mpfr_sincos (tree, tree, tree);
65dd1378 227static tree do_mpfr_bessel_n (tree, tree, tree,
228 int (*)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
229 const REAL_VALUE_TYPE *, bool);
e5407ca6 230static tree do_mpfr_remquo (tree, tree, tree);
e84da7c1 231static tree do_mpfr_lgamma_r (tree, tree, tree);
0a39fd54 232
7bfefa9d 233/* Return true if NAME starts with __builtin_ or __sync_. */
234
1c47b3e8 235bool
236is_builtin_name (const char *name)
b6a5fc45 237{
b6a5fc45 238 if (strncmp (name, "__builtin_", 10) == 0)
239 return true;
240 if (strncmp (name, "__sync_", 7) == 0)
241 return true;
242 return false;
243}
4ee9c684 244
7bfefa9d 245
246/* Return true if DECL is a function symbol representing a built-in. */
247
248bool
249is_builtin_fn (tree decl)
250{
251 return TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl);
252}
253
254
1c47b3e8 255/* Return true if NODE should be considered for inline expansion regardless
256 of the optimization level. This means whenever a function is invoked with
257 its "internal" name, which normally contains the prefix "__builtin". */
258
259static bool
260called_as_built_in (tree node)
261{
262 /* Note that we must use DECL_NAME, not DECL_ASSEMBLER_NAME_SET_P since
263 we want the name used to call the function, not the name it
264 will have. */
265 const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
266 return is_builtin_name (name);
267}
268
698537d1 269/* Return the alignment in bits of EXP, an object.
270 Don't return more than MAX_ALIGN no matter what, ALIGN is the inital
271 guessed alignment e.g. from type alignment. */
272
273int
274get_object_alignment (tree exp, unsigned int align, unsigned int max_align)
275{
276 unsigned int inner;
277
278 inner = max_align;
279 if (handled_component_p (exp))
280 {
281 HOST_WIDE_INT bitsize, bitpos;
282 tree offset;
283 enum machine_mode mode;
284 int unsignedp, volatilep;
285
286 exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
287 &mode, &unsignedp, &volatilep, true);
288 if (bitpos)
289 inner = MIN (inner, (unsigned) (bitpos & -bitpos));
290 while (offset)
291 {
292 tree next_offset;
293
294 if (TREE_CODE (offset) == PLUS_EXPR)
295 {
296 next_offset = TREE_OPERAND (offset, 0);
297 offset = TREE_OPERAND (offset, 1);
298 }
299 else
300 next_offset = NULL;
301 if (host_integerp (offset, 1))
302 {
303 /* Any overflow in calculating offset_bits won't change
304 the alignment. */
305 unsigned offset_bits
306 = ((unsigned) tree_low_cst (offset, 1) * BITS_PER_UNIT);
307
308 if (offset_bits)
309 inner = MIN (inner, (offset_bits & -offset_bits));
310 }
311 else if (TREE_CODE (offset) == MULT_EXPR
312 && host_integerp (TREE_OPERAND (offset, 1), 1))
313 {
314 /* Any overflow in calculating offset_factor won't change
315 the alignment. */
316 unsigned offset_factor
317 = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
318 * BITS_PER_UNIT);
319
320 if (offset_factor)
321 inner = MIN (inner, (offset_factor & -offset_factor));
322 }
323 else
324 {
325 inner = MIN (inner, BITS_PER_UNIT);
326 break;
327 }
328 offset = next_offset;
329 }
330 }
331 if (DECL_P (exp))
332 align = MIN (inner, DECL_ALIGN (exp));
333#ifdef CONSTANT_ALIGNMENT
334 else if (CONSTANT_CLASS_P (exp))
335 align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align));
336#endif
337 else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR
338 || TREE_CODE (exp) == INDIRECT_REF)
339 align = MIN (TYPE_ALIGN (TREE_TYPE (exp)), inner);
340 else
341 align = MIN (align, inner);
342 return MIN (align, max_align);
343}
344
7abca321 345/* Returns true iff we can trust that alignment information has been
346 calculated properly. */
347
348bool
349can_trust_pointer_alignment (void)
350{
351 /* We rely on TER to compute accurate alignment information. */
352 return (optimize && flag_tree_ter);
353}
354
53800dbe 355/* Return the alignment in bits of EXP, a pointer valued expression.
356 But don't return more than MAX_ALIGN no matter what.
357 The alignment returned is, by default, the alignment of the thing that
27d0c333 358 EXP points to. If it is not a POINTER_TYPE, 0 is returned.
53800dbe 359
360 Otherwise, look at the expression to see if we can do better, i.e., if the
361 expression is actually pointing at an object whose alignment is tighter. */
362
f656b751 363int
aecda0d6 364get_pointer_alignment (tree exp, unsigned int max_align)
53800dbe 365{
27d0c333 366 unsigned int align, inner;
53800dbe 367
7abca321 368 if (!can_trust_pointer_alignment ())
189575ff 369 return 0;
370
535e2026 371 if (!POINTER_TYPE_P (TREE_TYPE (exp)))
372 return 0;
373
53800dbe 374 align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
375 align = MIN (align, max_align);
376
377 while (1)
378 {
379 switch (TREE_CODE (exp))
380 {
72dd6141 381 CASE_CONVERT:
53800dbe 382 exp = TREE_OPERAND (exp, 0);
552752f7 383 if (! POINTER_TYPE_P (TREE_TYPE (exp)))
53800dbe 384 return align;
325d1c45 385
53800dbe 386 inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
387 align = MIN (inner, max_align);
388 break;
389
0de36bdb 390 case POINTER_PLUS_EXPR:
53800dbe 391 /* If sum of pointer + int, restrict our maximum alignment to that
392 imposed by the integer. If not, we can't do any better than
393 ALIGN. */
325d1c45 394 if (! host_integerp (TREE_OPERAND (exp, 1), 1))
53800dbe 395 return align;
396
0994d2ed 397 while (((tree_low_cst (TREE_OPERAND (exp, 1), 1))
398 & (max_align / BITS_PER_UNIT - 1))
53800dbe 399 != 0)
400 max_align >>= 1;
401
402 exp = TREE_OPERAND (exp, 0);
403 break;
404
405 case ADDR_EXPR:
406 /* See what we are pointing at and look at its alignment. */
698537d1 407 return get_object_alignment (TREE_OPERAND (exp, 0), align, max_align);
53800dbe 408
409 default:
410 return align;
411 }
412 }
413}
414
415/* Compute the length of a C string. TREE_STRING_LENGTH is not the right
416 way, because it could contain a zero byte in the middle.
417 TREE_STRING_LENGTH is the size of the character array, not the string.
418
4172d65e 419 ONLY_VALUE should be nonzero if the result is not going to be emitted
c09841f6 420 into the instruction stream and zero if it is going to be expanded.
4172d65e 421 E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
681fab1e 422 is returned, otherwise NULL, since
423 len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
424 evaluate the side-effects.
425
902de8ed 426 The value returned is of type `ssizetype'.
427
53800dbe 428 Unfortunately, string_constant can't access the values of const char
429 arrays with initializers, so neither can we do so here. */
430
4ee9c684 431tree
681fab1e 432c_strlen (tree src, int only_value)
53800dbe 433{
434 tree offset_node;
27d0c333 435 HOST_WIDE_INT offset;
436 int max;
44acf429 437 const char *ptr;
53800dbe 438
681fab1e 439 STRIP_NOPS (src);
440 if (TREE_CODE (src) == COND_EXPR
441 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
442 {
443 tree len1, len2;
444
445 len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
446 len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
0862b7e9 447 if (tree_int_cst_equal (len1, len2))
681fab1e 448 return len1;
449 }
450
451 if (TREE_CODE (src) == COMPOUND_EXPR
452 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
453 return c_strlen (TREE_OPERAND (src, 1), only_value);
454
53800dbe 455 src = string_constant (src, &offset_node);
456 if (src == 0)
c2f47e15 457 return NULL_TREE;
902de8ed 458
83d79705 459 max = TREE_STRING_LENGTH (src) - 1;
53800dbe 460 ptr = TREE_STRING_POINTER (src);
902de8ed 461
53800dbe 462 if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
463 {
464 /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
465 compute the offset to the following null if we don't know where to
466 start searching for it. */
467 int i;
902de8ed 468
53800dbe 469 for (i = 0; i < max; i++)
470 if (ptr[i] == 0)
c2f47e15 471 return NULL_TREE;
902de8ed 472
53800dbe 473 /* We don't know the starting offset, but we do know that the string
474 has no internal zero bytes. We can assume that the offset falls
475 within the bounds of the string; otherwise, the programmer deserves
476 what he gets. Subtract the offset from the length of the string,
902de8ed 477 and return that. This would perhaps not be valid if we were dealing
478 with named arrays in addition to literal string constants. */
479
389dd41b 480 return size_diffop_loc (input_location, size_int (max), offset_node);
53800dbe 481 }
482
483 /* We have a known offset into the string. Start searching there for
27d0c333 484 a null character if we can represent it as a single HOST_WIDE_INT. */
dabc4084 485 if (offset_node == 0)
53800dbe 486 offset = 0;
dabc4084 487 else if (! host_integerp (offset_node, 0))
488 offset = -1;
53800dbe 489 else
27d0c333 490 offset = tree_low_cst (offset_node, 0);
902de8ed 491
1f63a7d6 492 /* If the offset is known to be out of bounds, warn, and call strlen at
493 runtime. */
53800dbe 494 if (offset < 0 || offset > max)
495 {
1f63a7d6 496 /* Suppress multiple warnings for propagated constant strings. */
497 if (! TREE_NO_WARNING (src))
498 {
499 warning (0, "offset outside bounds of constant string");
500 TREE_NO_WARNING (src) = 1;
501 }
c2f47e15 502 return NULL_TREE;
53800dbe 503 }
902de8ed 504
53800dbe 505 /* Use strlen to search for the first zero byte. Since any strings
506 constructed with build_string will have nulls appended, we win even
507 if we get handed something like (char[4])"abcd".
508
509 Since OFFSET is our starting index into the string, no further
510 calculation is needed. */
902de8ed 511 return ssize_int (strlen (ptr + offset));
53800dbe 512}
513
83d79705 514/* Return a char pointer for a C string if it is a string constant
515 or sum of string constant and integer constant. */
516
517static const char *
aecda0d6 518c_getstr (tree src)
83d79705 519{
520 tree offset_node;
83d79705 521
522 src = string_constant (src, &offset_node);
523 if (src == 0)
524 return 0;
525
8c85fcb7 526 if (offset_node == 0)
527 return TREE_STRING_POINTER (src);
528 else if (!host_integerp (offset_node, 1)
529 || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
83d79705 530 return 0;
83d79705 531
8c85fcb7 532 return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
83d79705 533}
534
8c85fcb7 535/* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
536 GET_MODE_BITSIZE (MODE) bits from string constant STR. */
ecc318ff 537
6840589f 538static rtx
aecda0d6 539c_readstr (const char *str, enum machine_mode mode)
6840589f 540{
541 HOST_WIDE_INT c[2];
542 HOST_WIDE_INT ch;
543 unsigned int i, j;
544
64db345d 545 gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
7d3f6cc7 546
6840589f 547 c[0] = 0;
548 c[1] = 0;
549 ch = 1;
550 for (i = 0; i < GET_MODE_SIZE (mode); i++)
551 {
552 j = i;
553 if (WORDS_BIG_ENDIAN)
554 j = GET_MODE_SIZE (mode) - i - 1;
555 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
556 && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
557 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
558 j *= BITS_PER_UNIT;
64db345d 559 gcc_assert (j <= 2 * HOST_BITS_PER_WIDE_INT);
7d3f6cc7 560
6840589f 561 if (ch)
562 ch = (unsigned char) str[i];
563 c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
564 }
565 return immed_double_const (c[0], c[1], mode);
566}
567
ecc318ff 568/* Cast a target constant CST to target CHAR and if that value fits into
5206b159 569 host char type, return zero and put that value into variable pointed to by
ecc318ff 570 P. */
571
572static int
aecda0d6 573target_char_cast (tree cst, char *p)
ecc318ff 574{
575 unsigned HOST_WIDE_INT val, hostval;
576
27d0c333 577 if (!host_integerp (cst, 1)
ecc318ff 578 || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
579 return 1;
580
27d0c333 581 val = tree_low_cst (cst, 1);
ecc318ff 582 if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
583 val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
584
585 hostval = val;
586 if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
587 hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
588
589 if (val != hostval)
590 return 1;
591
592 *p = hostval;
593 return 0;
594}
595
4ee9c684 596/* Similar to save_expr, but assumes that arbitrary code is not executed
597 in between the multiple evaluations. In particular, we assume that a
598 non-addressable local variable will not be modified. */
599
600static tree
601builtin_save_expr (tree exp)
602{
603 if (TREE_ADDRESSABLE (exp) == 0
604 && (TREE_CODE (exp) == PARM_DECL
605 || (TREE_CODE (exp) == VAR_DECL && !TREE_STATIC (exp))))
606 return exp;
607
608 return save_expr (exp);
609}
610
53800dbe 611/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
612 times to get the address of either a higher stack frame, or a return
613 address located within it (depending on FNDECL_CODE). */
902de8ed 614
c626df3d 615static rtx
869d0ef0 616expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
53800dbe 617{
618 int i;
619
869d0ef0 620#ifdef INITIAL_FRAME_ADDRESS_RTX
621 rtx tem = INITIAL_FRAME_ADDRESS_RTX;
622#else
e3e15c50 623 rtx tem;
624
1b74fde7 625 /* For a zero count with __builtin_return_address, we don't care what
626 frame address we return, because target-specific definitions will
627 override us. Therefore frame pointer elimination is OK, and using
628 the soft frame pointer is OK.
629
fa7637bd 630 For a nonzero count, or a zero count with __builtin_frame_address,
1b74fde7 631 we require a stable offset from the current frame pointer to the
632 previous one, so we must use the hard frame pointer, and
e3e15c50 633 we must disable frame pointer elimination. */
1b74fde7 634 if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
e3e15c50 635 tem = frame_pointer_rtx;
a0c938f0 636 else
e3e15c50 637 {
638 tem = hard_frame_pointer_rtx;
639
640 /* Tell reload not to eliminate the frame pointer. */
18d50ae6 641 crtl->accesses_prior_frames = 1;
e3e15c50 642 }
869d0ef0 643#endif
644
53800dbe 645 /* Some machines need special handling before we can access
3a69c60c 646 arbitrary frames. For example, on the SPARC, we must first flush
53800dbe 647 all register windows to the stack. */
648#ifdef SETUP_FRAME_ADDRESSES
649 if (count > 0)
650 SETUP_FRAME_ADDRESSES ();
651#endif
652
3a69c60c 653 /* On the SPARC, the return address is not in the frame, it is in a
53800dbe 654 register. There is no way to access it off of the current frame
655 pointer, but it can be accessed off the previous frame pointer by
656 reading the value from the register window save area. */
657#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
658 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
659 count--;
660#endif
661
662 /* Scan back COUNT frames to the specified frame. */
663 for (i = 0; i < count; i++)
664 {
665 /* Assume the dynamic chain pointer is in the word that the
666 frame address points to, unless otherwise specified. */
667#ifdef DYNAMIC_CHAIN_ADDRESS
668 tem = DYNAMIC_CHAIN_ADDRESS (tem);
669#endif
670 tem = memory_address (Pmode, tem);
00060fc2 671 tem = gen_frame_mem (Pmode, tem);
83fc1478 672 tem = copy_to_reg (tem);
53800dbe 673 }
674
3a69c60c 675 /* For __builtin_frame_address, return what we've got. But, on
676 the SPARC for example, we may have to add a bias. */
53800dbe 677 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
3a69c60c 678#ifdef FRAME_ADDR_RTX
679 return FRAME_ADDR_RTX (tem);
680#else
53800dbe 681 return tem;
3a69c60c 682#endif
53800dbe 683
3a69c60c 684 /* For __builtin_return_address, get the return address from that frame. */
53800dbe 685#ifdef RETURN_ADDR_RTX
686 tem = RETURN_ADDR_RTX (count, tem);
687#else
688 tem = memory_address (Pmode,
689 plus_constant (tem, GET_MODE_SIZE (Pmode)));
00060fc2 690 tem = gen_frame_mem (Pmode, tem);
53800dbe 691#endif
692 return tem;
693}
694
f7c44134 695/* Alias set used for setjmp buffer. */
32c2fdea 696static alias_set_type setjmp_alias_set = -1;
f7c44134 697
6b7f6858 698/* Construct the leading half of a __builtin_setjmp call. Control will
2c8a1497 699 return to RECEIVER_LABEL. This is also called directly by the SJLJ
700 exception handling code. */
53800dbe 701
6b7f6858 702void
aecda0d6 703expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
53800dbe 704{
53800dbe 705 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
53800dbe 706 rtx stack_save;
f7c44134 707 rtx mem;
53800dbe 708
f7c44134 709 if (setjmp_alias_set == -1)
710 setjmp_alias_set = new_alias_set ();
711
85d654dd 712 buf_addr = convert_memory_address (Pmode, buf_addr);
53800dbe 713
37ae8504 714 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
53800dbe 715
6b7f6858 716 /* We store the frame pointer and the address of receiver_label in
717 the buffer and use the rest of it for the stack save area, which
718 is machine-dependent. */
53800dbe 719
f7c44134 720 mem = gen_rtx_MEM (Pmode, buf_addr);
ab6ab77e 721 set_mem_alias_set (mem, setjmp_alias_set);
e3e026e8 722 emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
f7c44134 723
724 mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
ab6ab77e 725 set_mem_alias_set (mem, setjmp_alias_set);
f7c44134 726
727 emit_move_insn (validize_mem (mem),
6b7f6858 728 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
53800dbe 729
730 stack_save = gen_rtx_MEM (sa_mode,
731 plus_constant (buf_addr,
732 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 733 set_mem_alias_set (stack_save, setjmp_alias_set);
53800dbe 734 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
735
736 /* If there is further processing to do, do it. */
737#ifdef HAVE_builtin_setjmp_setup
738 if (HAVE_builtin_setjmp_setup)
739 emit_insn (gen_builtin_setjmp_setup (buf_addr));
740#endif
741
6b7f6858 742 /* Tell optimize_save_area_alloca that extra work is going to
743 need to go on during alloca. */
18d50ae6 744 cfun->calls_setjmp = 1;
80ab81b9 745
29f09705 746 /* We have a nonlocal label. */
18d50ae6 747 cfun->has_nonlocal_label = 1;
6b7f6858 748}
53800dbe 749
2c8a1497 750/* Construct the trailing part of a __builtin_setjmp call. This is
751 also called directly by the SJLJ exception handling code. */
6b7f6858 752
753void
aecda0d6 754expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
6b7f6858 755{
82c7907c 756 rtx chain;
757
53800dbe 758 /* Clobber the FP when we get here, so we have to make sure it's
759 marked as used by this function. */
18b42941 760 emit_use (hard_frame_pointer_rtx);
53800dbe 761
762 /* Mark the static chain as clobbered here so life information
763 doesn't get messed up for it. */
82c7907c 764 chain = targetm.calls.static_chain (current_function_decl, true);
765 if (chain && REG_P (chain))
766 emit_clobber (chain);
53800dbe 767
768 /* Now put in the code to restore the frame pointer, and argument
491e04ef 769 pointer, if needed. */
53800dbe 770#ifdef HAVE_nonlocal_goto
771 if (! HAVE_nonlocal_goto)
772#endif
5a1c3f40 773 {
774 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
775 /* This might change the hard frame pointer in ways that aren't
776 apparent to early optimization passes, so force a clobber. */
18b42941 777 emit_clobber (hard_frame_pointer_rtx);
5a1c3f40 778 }
53800dbe 779
780#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
781 if (fixed_regs[ARG_POINTER_REGNUM])
782 {
783#ifdef ELIMINABLE_REGS
784 size_t i;
e99c3a1d 785 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
53800dbe 786
3098b2d3 787 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
53800dbe 788 if (elim_regs[i].from == ARG_POINTER_REGNUM
789 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
790 break;
791
3098b2d3 792 if (i == ARRAY_SIZE (elim_regs))
53800dbe 793#endif
794 {
795 /* Now restore our arg pointer from the address at which it
05927e40 796 was saved in our stack frame. */
27a7a23a 797 emit_move_insn (crtl->args.internal_arg_pointer,
b079a207 798 copy_to_reg (get_arg_pointer_save_area ()));
53800dbe 799 }
800 }
801#endif
802
803#ifdef HAVE_builtin_setjmp_receiver
804 if (HAVE_builtin_setjmp_receiver)
6b7f6858 805 emit_insn (gen_builtin_setjmp_receiver (receiver_label));
53800dbe 806 else
807#endif
808#ifdef HAVE_nonlocal_goto_receiver
809 if (HAVE_nonlocal_goto_receiver)
810 emit_insn (gen_nonlocal_goto_receiver ());
811 else
812#endif
6b7f6858 813 { /* Nothing */ }
57f6bb94 814
3072d30e 815 /* We must not allow the code we just generated to be reordered by
816 scheduling. Specifically, the update of the frame pointer must
817 happen immediately, not later. */
818 emit_insn (gen_blockage ());
6b7f6858 819}
53800dbe 820
53800dbe 821/* __builtin_longjmp is passed a pointer to an array of five words (not
822 all will be used on all machines). It operates similarly to the C
823 library function of the same name, but is more efficient. Much of
2c8a1497 824 the code below is copied from the handling of non-local gotos. */
53800dbe 825
c626df3d 826static void
aecda0d6 827expand_builtin_longjmp (rtx buf_addr, rtx value)
53800dbe 828{
4712c7d6 829 rtx fp, lab, stack, insn, last;
53800dbe 830 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
831
27a7a23a 832 /* DRAP is needed for stack realign if longjmp is expanded to current
833 function */
834 if (SUPPORTS_STACK_ALIGNMENT)
835 crtl->need_drap = true;
836
f7c44134 837 if (setjmp_alias_set == -1)
838 setjmp_alias_set = new_alias_set ();
839
85d654dd 840 buf_addr = convert_memory_address (Pmode, buf_addr);
479e4d5e 841
53800dbe 842 buf_addr = force_reg (Pmode, buf_addr);
843
82c7907c 844 /* We require that the user must pass a second argument of 1, because
845 that is what builtin_setjmp will return. */
64db345d 846 gcc_assert (value == const1_rtx);
53800dbe 847
4712c7d6 848 last = get_last_insn ();
53800dbe 849#ifdef HAVE_builtin_longjmp
850 if (HAVE_builtin_longjmp)
851 emit_insn (gen_builtin_longjmp (buf_addr));
852 else
853#endif
854 {
855 fp = gen_rtx_MEM (Pmode, buf_addr);
856 lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
857 GET_MODE_SIZE (Pmode)));
858
859 stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
860 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 861 set_mem_alias_set (fp, setjmp_alias_set);
862 set_mem_alias_set (lab, setjmp_alias_set);
863 set_mem_alias_set (stack, setjmp_alias_set);
53800dbe 864
865 /* Pick up FP, label, and SP from the block and jump. This code is
866 from expand_goto in stmt.c; see there for detailed comments. */
03fd9d2c 867#ifdef HAVE_nonlocal_goto
53800dbe 868 if (HAVE_nonlocal_goto)
869 /* We have to pass a value to the nonlocal_goto pattern that will
870 get copied into the static_chain pointer, but it does not matter
871 what that value is, because builtin_setjmp does not use it. */
28d202a8 872 emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
53800dbe 873 else
874#endif
875 {
876 lab = copy_to_reg (lab);
877
18b42941 878 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
879 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
2a871ad1 880
53800dbe 881 emit_move_insn (hard_frame_pointer_rtx, fp);
882 emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
883
18b42941 884 emit_use (hard_frame_pointer_rtx);
885 emit_use (stack_pointer_rtx);
53800dbe 886 emit_indirect_jump (lab);
887 }
888 }
615166bb 889
890 /* Search backwards and mark the jump insn as a non-local goto.
891 Note that this precludes the use of __builtin_longjmp to a
892 __builtin_setjmp target in the same function. However, we've
893 already cautioned the user that these functions are for
894 internal exception handling use only. */
449c0509 895 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
896 {
64db345d 897 gcc_assert (insn != last);
7d3f6cc7 898
6d7dc5b9 899 if (JUMP_P (insn))
449c0509 900 {
a1ddb869 901 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
449c0509 902 break;
903 }
6d7dc5b9 904 else if (CALL_P (insn))
9342ee68 905 break;
449c0509 906 }
53800dbe 907}
908
4ee9c684 909/* Expand a call to __builtin_nonlocal_goto. We're passed the target label
910 and the address of the save area. */
911
912static rtx
c2f47e15 913expand_builtin_nonlocal_goto (tree exp)
4ee9c684 914{
915 tree t_label, t_save_area;
916 rtx r_label, r_save_area, r_fp, r_sp, insn;
917
c2f47e15 918 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4ee9c684 919 return NULL_RTX;
920
c2f47e15 921 t_label = CALL_EXPR_ARG (exp, 0);
922 t_save_area = CALL_EXPR_ARG (exp, 1);
4ee9c684 923
8ec3c5c2 924 r_label = expand_normal (t_label);
3dce56cc 925 r_label = convert_memory_address (Pmode, r_label);
8ec3c5c2 926 r_save_area = expand_normal (t_save_area);
3dce56cc 927 r_save_area = convert_memory_address (Pmode, r_save_area);
51adbc8a 928 /* Copy the address of the save location to a register just in case it was based
929 on the frame pointer. */
930 r_save_area = copy_to_reg (r_save_area);
4ee9c684 931 r_fp = gen_rtx_MEM (Pmode, r_save_area);
932 r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
933 plus_constant (r_save_area, GET_MODE_SIZE (Pmode)));
934
18d50ae6 935 crtl->has_nonlocal_goto = 1;
4ee9c684 936
03fd9d2c 937#ifdef HAVE_nonlocal_goto
4ee9c684 938 /* ??? We no longer need to pass the static chain value, afaik. */
939 if (HAVE_nonlocal_goto)
940 emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
941 else
942#endif
943 {
944 r_label = copy_to_reg (r_label);
945
18b42941 946 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
947 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
491e04ef 948
4ee9c684 949 /* Restore frame pointer for containing function.
950 This sets the actual hard register used for the frame pointer
951 to the location of the function's incoming static chain info.
952 The non-local goto handler will then adjust it to contain the
953 proper value and reload the argument pointer, if needed. */
954 emit_move_insn (hard_frame_pointer_rtx, r_fp);
955 emit_stack_restore (SAVE_NONLOCAL, r_sp, NULL_RTX);
491e04ef 956
4ee9c684 957 /* USE of hard_frame_pointer_rtx added for consistency;
958 not clear if really needed. */
18b42941 959 emit_use (hard_frame_pointer_rtx);
960 emit_use (stack_pointer_rtx);
ad0d0af8 961
962 /* If the architecture is using a GP register, we must
963 conservatively assume that the target function makes use of it.
964 The prologue of functions with nonlocal gotos must therefore
965 initialize the GP register to the appropriate value, and we
966 must then make sure that this value is live at the point
967 of the jump. (Note that this doesn't necessarily apply
968 to targets with a nonlocal_goto pattern; they are free
969 to implement it in their own way. Note also that this is
970 a no-op if the GP register is a global invariant.) */
971 if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
972 && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
18b42941 973 emit_use (pic_offset_table_rtx);
ad0d0af8 974
4ee9c684 975 emit_indirect_jump (r_label);
976 }
491e04ef 977
4ee9c684 978 /* Search backwards to the jump insn and mark it as a
979 non-local goto. */
980 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
981 {
6d7dc5b9 982 if (JUMP_P (insn))
4ee9c684 983 {
a1ddb869 984 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
4ee9c684 985 break;
986 }
6d7dc5b9 987 else if (CALL_P (insn))
4ee9c684 988 break;
989 }
990
991 return const0_rtx;
992}
993
843d08a9 994/* __builtin_update_setjmp_buf is passed a pointer to an array of five words
995 (not all will be used on all machines) that was passed to __builtin_setjmp.
996 It updates the stack pointer in that block to correspond to the current
997 stack pointer. */
998
999static void
1000expand_builtin_update_setjmp_buf (rtx buf_addr)
1001{
1002 enum machine_mode sa_mode = Pmode;
1003 rtx stack_save;
1004
1005
1006#ifdef HAVE_save_stack_nonlocal
1007 if (HAVE_save_stack_nonlocal)
1008 sa_mode = insn_data[(int) CODE_FOR_save_stack_nonlocal].operand[0].mode;
1009#endif
1010#ifdef STACK_SAVEAREA_MODE
1011 sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
1012#endif
1013
1014 stack_save
1015 = gen_rtx_MEM (sa_mode,
1016 memory_address
1017 (sa_mode,
1018 plus_constant (buf_addr, 2 * GET_MODE_SIZE (Pmode))));
1019
1020#ifdef HAVE_setjmp
1021 if (HAVE_setjmp)
1022 emit_insn (gen_setjmp ());
1023#endif
1024
1025 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
1026}
1027
5e3608d8 1028/* Expand a call to __builtin_prefetch. For a target that does not support
1029 data prefetch, evaluate the memory address argument in case it has side
1030 effects. */
1031
1032static void
c2f47e15 1033expand_builtin_prefetch (tree exp)
5e3608d8 1034{
1035 tree arg0, arg1, arg2;
c2f47e15 1036 int nargs;
5e3608d8 1037 rtx op0, op1, op2;
1038
c2f47e15 1039 if (!validate_arglist (exp, POINTER_TYPE, 0))
26a5cadb 1040 return;
1041
c2f47e15 1042 arg0 = CALL_EXPR_ARG (exp, 0);
1043
26a5cadb 1044 /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
1045 zero (read) and argument 2 (locality) defaults to 3 (high degree of
1046 locality). */
c2f47e15 1047 nargs = call_expr_nargs (exp);
1048 if (nargs > 1)
1049 arg1 = CALL_EXPR_ARG (exp, 1);
26a5cadb 1050 else
c2f47e15 1051 arg1 = integer_zero_node;
1052 if (nargs > 2)
1053 arg2 = CALL_EXPR_ARG (exp, 2);
1054 else
1055 arg2 = build_int_cst (NULL_TREE, 3);
5e3608d8 1056
1057 /* Argument 0 is an address. */
1058 op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
1059
1060 /* Argument 1 (read/write flag) must be a compile-time constant int. */
1061 if (TREE_CODE (arg1) != INTEGER_CST)
1062 {
07e3a3d2 1063 error ("second argument to %<__builtin_prefetch%> must be a constant");
9342ee68 1064 arg1 = integer_zero_node;
5e3608d8 1065 }
8ec3c5c2 1066 op1 = expand_normal (arg1);
5e3608d8 1067 /* Argument 1 must be either zero or one. */
1068 if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
1069 {
c3ceba8e 1070 warning (0, "invalid second argument to %<__builtin_prefetch%>;"
07e3a3d2 1071 " using zero");
5e3608d8 1072 op1 = const0_rtx;
1073 }
1074
1075 /* Argument 2 (locality) must be a compile-time constant int. */
1076 if (TREE_CODE (arg2) != INTEGER_CST)
1077 {
07e3a3d2 1078 error ("third argument to %<__builtin_prefetch%> must be a constant");
5e3608d8 1079 arg2 = integer_zero_node;
1080 }
8ec3c5c2 1081 op2 = expand_normal (arg2);
5e3608d8 1082 /* Argument 2 must be 0, 1, 2, or 3. */
1083 if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
1084 {
c3ceba8e 1085 warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
5e3608d8 1086 op2 = const0_rtx;
1087 }
1088
1089#ifdef HAVE_prefetch
1090 if (HAVE_prefetch)
1091 {
f0ce3b1f 1092 if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate)
4cd21437 1093 (op0,
f0ce3b1f 1094 insn_data[(int) CODE_FOR_prefetch].operand[0].mode))
19bf118a 1095 || (GET_MODE (op0) != Pmode))
9342ee68 1096 {
85d654dd 1097 op0 = convert_memory_address (Pmode, op0);
9342ee68 1098 op0 = force_reg (Pmode, op0);
1099 }
5e3608d8 1100 emit_insn (gen_prefetch (op0, op1, op2));
1101 }
5e3608d8 1102#endif
0a534ba7 1103
f0ce3b1f 1104 /* Don't do anything with direct references to volatile memory, but
1105 generate code to handle other side effects. */
e16ceb8e 1106 if (!MEM_P (op0) && side_effects_p (op0))
f0ce3b1f 1107 emit_insn (op0);
5e3608d8 1108}
1109
f7c44134 1110/* Get a MEM rtx for expression EXP which is the address of an operand
d8ae1baa 1111 to be used in a string instruction (cmpstrsi, movmemsi, ..). LEN is
1112 the maximum length of the block of memory that might be accessed or
1113 NULL if unknown. */
f7c44134 1114
53800dbe 1115static rtx
d8ae1baa 1116get_memory_rtx (tree exp, tree len)
53800dbe 1117{
ad0a178f 1118 tree orig_exp = exp;
1119 rtx addr, mem;
1120 HOST_WIDE_INT off;
1121
1122 /* When EXP is not resolved SAVE_EXPR, MEM_ATTRS can be still derived
1123 from its expression, for expr->a.b only <variable>.a.b is recorded. */
1124 if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp))
1125 exp = TREE_OPERAND (exp, 0);
1126
1127 addr = expand_expr (orig_exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
1128 mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
2a631e19 1129
f7c44134 1130 /* Get an expression we can use to find the attributes to assign to MEM.
1131 If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
1132 we can. First remove any nops. */
72dd6141 1133 while (CONVERT_EXPR_P (exp)
f7c44134 1134 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
1135 exp = TREE_OPERAND (exp, 0);
1136
ad0a178f 1137 off = 0;
1138 if (TREE_CODE (exp) == POINTER_PLUS_EXPR
1139 && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
1140 && host_integerp (TREE_OPERAND (exp, 1), 0)
1141 && (off = tree_low_cst (TREE_OPERAND (exp, 1), 0)) > 0)
1142 exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
1143 else if (TREE_CODE (exp) == ADDR_EXPR)
a1a25d19 1144 exp = TREE_OPERAND (exp, 0);
f7c44134 1145 else if (POINTER_TYPE_P (TREE_TYPE (exp)))
a1a25d19 1146 exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
1147 else
1148 exp = NULL;
1149
1150 /* Honor attributes derived from exp, except for the alias set
1151 (as builtin stringops may alias with anything) and the size
1152 (as stringops may access multiple array elements). */
1153 if (exp)
eec8e941 1154 {
a1a25d19 1155 set_mem_attributes (mem, exp, 0);
d8ae1baa 1156
ad0a178f 1157 if (off)
1158 mem = adjust_automodify_address_nv (mem, BLKmode, NULL, off);
1159
d8ae1baa 1160 /* Allow the string and memory builtins to overflow from one
1161 field into another, see http://gcc.gnu.org/PR23561.
1162 Thus avoid COMPONENT_REFs in MEM_EXPR unless we know the whole
1163 memory accessed by the string or memory builtin will fit
1164 within the field. */
1165 if (MEM_EXPR (mem) && TREE_CODE (MEM_EXPR (mem)) == COMPONENT_REF)
1166 {
1167 tree mem_expr = MEM_EXPR (mem);
1168 HOST_WIDE_INT offset = -1, length = -1;
1169 tree inner = exp;
1170
1171 while (TREE_CODE (inner) == ARRAY_REF
72dd6141 1172 || CONVERT_EXPR_P (inner)
d8ae1baa 1173 || TREE_CODE (inner) == VIEW_CONVERT_EXPR
1174 || TREE_CODE (inner) == SAVE_EXPR)
1175 inner = TREE_OPERAND (inner, 0);
1176
1177 gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
1178
1179 if (MEM_OFFSET (mem)
971ba038 1180 && CONST_INT_P (MEM_OFFSET (mem)))
d8ae1baa 1181 offset = INTVAL (MEM_OFFSET (mem));
1182
1183 if (offset >= 0 && len && host_integerp (len, 0))
1184 length = tree_low_cst (len, 0);
1185
1186 while (TREE_CODE (inner) == COMPONENT_REF)
1187 {
1188 tree field = TREE_OPERAND (inner, 1);
d8ae1baa 1189 gcc_assert (TREE_CODE (mem_expr) == COMPONENT_REF);
1190 gcc_assert (field == TREE_OPERAND (mem_expr, 1));
1191
6933ebec 1192 /* Bitfields are generally not byte-addressable. */
1193 gcc_assert (!DECL_BIT_FIELD (field)
1194 || ((tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
1195 % BITS_PER_UNIT) == 0
1196 && host_integerp (DECL_SIZE (field), 0)
1197 && (TREE_INT_CST_LOW (DECL_SIZE (field))
1198 % BITS_PER_UNIT) == 0));
1199
b2f0b2a3 1200 /* If we can prove that the memory starting at XEXP (mem, 0) and
1201 ending at XEXP (mem, 0) + LENGTH will fit into this field, we
1202 can keep the COMPONENT_REF in MEM_EXPR. But be careful with
1203 fields without DECL_SIZE_UNIT like flexible array members. */
d8ae1baa 1204 if (length >= 0
b2f0b2a3 1205 && DECL_SIZE_UNIT (field)
6933ebec 1206 && host_integerp (DECL_SIZE_UNIT (field), 0))
d8ae1baa 1207 {
1208 HOST_WIDE_INT size
6933ebec 1209 = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
d8ae1baa 1210 if (offset <= size
1211 && length <= size
1212 && offset + length <= size)
1213 break;
1214 }
1215
1216 if (offset >= 0
1217 && host_integerp (DECL_FIELD_OFFSET (field), 0))
6933ebec 1218 offset += TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
d8ae1baa 1219 + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
1220 / BITS_PER_UNIT;
1221 else
1222 {
1223 offset = -1;
1224 length = -1;
1225 }
1226
1227 mem_expr = TREE_OPERAND (mem_expr, 0);
1228 inner = TREE_OPERAND (inner, 0);
d8ae1baa 1229 }
1230
1231 if (mem_expr == NULL)
1232 offset = -1;
1233 if (mem_expr != MEM_EXPR (mem))
1234 {
1235 set_mem_expr (mem, mem_expr);
1236 set_mem_offset (mem, offset >= 0 ? GEN_INT (offset) : NULL_RTX);
1237 }
1238 }
eec8e941 1239 set_mem_alias_set (mem, 0);
a1a25d19 1240 set_mem_size (mem, NULL_RTX);
eec8e941 1241 }
53800dbe 1242
53800dbe 1243 return mem;
1244}
1245\f
1246/* Built-in functions to perform an untyped call and return. */
1247
1248/* For each register that may be used for calling a function, this
1249 gives a mode used to copy the register's value. VOIDmode indicates
1250 the register is not used for calling a function. If the machine
1251 has register windows, this gives only the outbound registers.
1252 INCOMING_REGNO gives the corresponding inbound register. */
1253static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
1254
1255/* For each register that may be used for returning values, this gives
1256 a mode used to copy the register's value. VOIDmode indicates the
1257 register is not used for returning values. If the machine has
1258 register windows, this gives only the outbound registers.
1259 INCOMING_REGNO gives the corresponding inbound register. */
1260static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
1261
1262/* For each register that may be used for calling a function, this
1263 gives the offset of that register into the block returned by
1264 __builtin_apply_args. 0 indicates that the register is not
1265 used for calling a function. */
1266static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
1267
53800dbe 1268/* Return the size required for the block returned by __builtin_apply_args,
1269 and initialize apply_args_mode. */
1270
1271static int
aecda0d6 1272apply_args_size (void)
53800dbe 1273{
1274 static int size = -1;
58e9ce8f 1275 int align;
1276 unsigned int regno;
53800dbe 1277 enum machine_mode mode;
1278
1279 /* The values computed by this function never change. */
1280 if (size < 0)
1281 {
1282 /* The first value is the incoming arg-pointer. */
1283 size = GET_MODE_SIZE (Pmode);
1284
1285 /* The second value is the structure value address unless this is
1286 passed as an "invisible" first argument. */
6812c89e 1287 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1288 size += GET_MODE_SIZE (Pmode);
1289
1290 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1291 if (FUNCTION_ARG_REGNO_P (regno))
1292 {
0862b7e9 1293 mode = reg_raw_mode[regno];
1294
64db345d 1295 gcc_assert (mode != VOIDmode);
53800dbe 1296
1297 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1298 if (size % align != 0)
1299 size = CEIL (size, align) * align;
1300 apply_args_reg_offset[regno] = size;
1301 size += GET_MODE_SIZE (mode);
1302 apply_args_mode[regno] = mode;
1303 }
1304 else
1305 {
1306 apply_args_mode[regno] = VOIDmode;
1307 apply_args_reg_offset[regno] = 0;
1308 }
1309 }
1310 return size;
1311}
1312
1313/* Return the size required for the block returned by __builtin_apply,
1314 and initialize apply_result_mode. */
1315
1316static int
aecda0d6 1317apply_result_size (void)
53800dbe 1318{
1319 static int size = -1;
1320 int align, regno;
1321 enum machine_mode mode;
1322
1323 /* The values computed by this function never change. */
1324 if (size < 0)
1325 {
1326 size = 0;
1327
1328 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1329 if (FUNCTION_VALUE_REGNO_P (regno))
1330 {
0862b7e9 1331 mode = reg_raw_mode[regno];
1332
64db345d 1333 gcc_assert (mode != VOIDmode);
53800dbe 1334
1335 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1336 if (size % align != 0)
1337 size = CEIL (size, align) * align;
1338 size += GET_MODE_SIZE (mode);
1339 apply_result_mode[regno] = mode;
1340 }
1341 else
1342 apply_result_mode[regno] = VOIDmode;
1343
1344 /* Allow targets that use untyped_call and untyped_return to override
1345 the size so that machine-specific information can be stored here. */
1346#ifdef APPLY_RESULT_SIZE
1347 size = APPLY_RESULT_SIZE;
1348#endif
1349 }
1350 return size;
1351}
1352
1353#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1354/* Create a vector describing the result block RESULT. If SAVEP is true,
1355 the result block is used to save the values; otherwise it is used to
1356 restore the values. */
1357
1358static rtx
aecda0d6 1359result_vector (int savep, rtx result)
53800dbe 1360{
1361 int regno, size, align, nelts;
1362 enum machine_mode mode;
1363 rtx reg, mem;
364c0c59 1364 rtx *savevec = XALLOCAVEC (rtx, FIRST_PSEUDO_REGISTER);
bf8e3599 1365
53800dbe 1366 size = nelts = 0;
1367 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1368 if ((mode = apply_result_mode[regno]) != VOIDmode)
1369 {
1370 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1371 if (size % align != 0)
1372 size = CEIL (size, align) * align;
1373 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
e513d163 1374 mem = adjust_address (result, mode, size);
53800dbe 1375 savevec[nelts++] = (savep
1376 ? gen_rtx_SET (VOIDmode, mem, reg)
1377 : gen_rtx_SET (VOIDmode, reg, mem));
1378 size += GET_MODE_SIZE (mode);
1379 }
1380 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1381}
1382#endif /* HAVE_untyped_call or HAVE_untyped_return */
1383
1384/* Save the state required to perform an untyped call with the same
1385 arguments as were passed to the current function. */
1386
1387static rtx
aecda0d6 1388expand_builtin_apply_args_1 (void)
53800dbe 1389{
1c7e61a7 1390 rtx registers, tem;
53800dbe 1391 int size, align, regno;
1392 enum machine_mode mode;
6812c89e 1393 rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
53800dbe 1394
1395 /* Create a block where the arg-pointer, structure value address,
1396 and argument registers can be saved. */
1397 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1398
1399 /* Walk past the arg-pointer and structure value address. */
1400 size = GET_MODE_SIZE (Pmode);
6812c89e 1401 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1402 size += GET_MODE_SIZE (Pmode);
1403
1404 /* Save each register used in calling a function to the block. */
1405 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1406 if ((mode = apply_args_mode[regno]) != VOIDmode)
1407 {
53800dbe 1408 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1409 if (size % align != 0)
1410 size = CEIL (size, align) * align;
1411
1412 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1413
e513d163 1414 emit_move_insn (adjust_address (registers, mode, size), tem);
53800dbe 1415 size += GET_MODE_SIZE (mode);
1416 }
1417
1418 /* Save the arg pointer to the block. */
27a7a23a 1419 tem = copy_to_reg (crtl->args.internal_arg_pointer);
f083a92b 1420#ifdef STACK_GROWS_DOWNWARD
1c7e61a7 1421 /* We need the pointer as the caller actually passed them to us, not
9d4b544c 1422 as we might have pretended they were passed. Make sure it's a valid
1423 operand, as emit_move_insn isn't expected to handle a PLUS. */
1424 tem
abe32cce 1425 = force_operand (plus_constant (tem, crtl->args.pretend_args_size),
9d4b544c 1426 NULL_RTX);
1c7e61a7 1427#endif
1428 emit_move_insn (adjust_address (registers, Pmode, 0), tem);
0862b7e9 1429
53800dbe 1430 size = GET_MODE_SIZE (Pmode);
1431
1432 /* Save the structure value address unless this is passed as an
1433 "invisible" first argument. */
45550790 1434 if (struct_incoming_value)
53800dbe 1435 {
e513d163 1436 emit_move_insn (adjust_address (registers, Pmode, size),
45550790 1437 copy_to_reg (struct_incoming_value));
53800dbe 1438 size += GET_MODE_SIZE (Pmode);
1439 }
1440
1441 /* Return the address of the block. */
1442 return copy_addr_to_reg (XEXP (registers, 0));
1443}
1444
1445/* __builtin_apply_args returns block of memory allocated on
1446 the stack into which is stored the arg pointer, structure
1447 value address, static chain, and all the registers that might
1448 possibly be used in performing a function call. The code is
1449 moved to the start of the function so the incoming values are
1450 saved. */
27d0c333 1451
53800dbe 1452static rtx
aecda0d6 1453expand_builtin_apply_args (void)
53800dbe 1454{
1455 /* Don't do __builtin_apply_args more than once in a function.
1456 Save the result of the first call and reuse it. */
1457 if (apply_args_value != 0)
1458 return apply_args_value;
1459 {
1460 /* When this function is called, it means that registers must be
1461 saved on entry to this function. So we migrate the
1462 call to the first insn of this function. */
1463 rtx temp;
1464 rtx seq;
1465
1466 start_sequence ();
1467 temp = expand_builtin_apply_args_1 ();
1468 seq = get_insns ();
1469 end_sequence ();
1470
1471 apply_args_value = temp;
1472
31d3e01c 1473 /* Put the insns after the NOTE that starts the function.
1474 If this is inside a start_sequence, make the outer-level insn
53800dbe 1475 chain current, so the code is placed at the start of the
0ef1a651 1476 function. If internal_arg_pointer is a non-virtual pseudo,
1477 it needs to be placed after the function that initializes
1478 that pseudo. */
53800dbe 1479 push_topmost_sequence ();
0ef1a651 1480 if (REG_P (crtl->args.internal_arg_pointer)
1481 && REGNO (crtl->args.internal_arg_pointer) > LAST_VIRTUAL_REGISTER)
1482 emit_insn_before (seq, parm_birth_insn);
1483 else
1484 emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
53800dbe 1485 pop_topmost_sequence ();
1486 return temp;
1487 }
1488}
1489
1490/* Perform an untyped call and save the state required to perform an
1491 untyped return of whatever value was returned by the given function. */
1492
1493static rtx
aecda0d6 1494expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
53800dbe 1495{
1496 int size, align, regno;
1497 enum machine_mode mode;
2a631e19 1498 rtx incoming_args, result, reg, dest, src, call_insn;
53800dbe 1499 rtx old_stack_level = 0;
1500 rtx call_fusage = 0;
6812c89e 1501 rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
53800dbe 1502
85d654dd 1503 arguments = convert_memory_address (Pmode, arguments);
726ec87c 1504
53800dbe 1505 /* Create a block where the return registers can be saved. */
1506 result = assign_stack_local (BLKmode, apply_result_size (), -1);
1507
53800dbe 1508 /* Fetch the arg pointer from the ARGUMENTS block. */
1509 incoming_args = gen_reg_rtx (Pmode);
726ec87c 1510 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
53800dbe 1511#ifndef STACK_GROWS_DOWNWARD
ad99e708 1512 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1513 incoming_args, 0, OPTAB_LIB_WIDEN);
53800dbe 1514#endif
1515
04a46d40 1516 /* Push a new argument block and copy the arguments. Do not allow
1517 the (potential) memcpy call below to interfere with our stack
1518 manipulations. */
53800dbe 1519 do_pending_stack_adjust ();
04a46d40 1520 NO_DEFER_POP;
53800dbe 1521
2358393e 1522 /* Save the stack with nonlocal if available. */
53800dbe 1523#ifdef HAVE_save_stack_nonlocal
1524 if (HAVE_save_stack_nonlocal)
1525 emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
1526 else
1527#endif
1528 emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
1529
59647703 1530 /* Allocate a block of memory onto the stack and copy the memory
1531 arguments to the outgoing arguments address. */
1532 allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
27a7a23a 1533
1534 /* Set DRAP flag to true, even though allocate_dynamic_stack_space
1535 may have already set current_function_calls_alloca to true.
1536 current_function_calls_alloca won't be set if argsize is zero,
1537 so we have to guarantee need_drap is true here. */
1538 if (SUPPORTS_STACK_ALIGNMENT)
1539 crtl->need_drap = true;
1540
59647703 1541 dest = virtual_outgoing_args_rtx;
1542#ifndef STACK_GROWS_DOWNWARD
971ba038 1543 if (CONST_INT_P (argsize))
59647703 1544 dest = plus_constant (dest, -INTVAL (argsize));
1545 else
1546 dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1547#endif
2a631e19 1548 dest = gen_rtx_MEM (BLKmode, dest);
1549 set_mem_align (dest, PARM_BOUNDARY);
1550 src = gen_rtx_MEM (BLKmode, incoming_args);
1551 set_mem_align (src, PARM_BOUNDARY);
0378dbdc 1552 emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
53800dbe 1553
1554 /* Refer to the argument block. */
1555 apply_args_size ();
1556 arguments = gen_rtx_MEM (BLKmode, arguments);
2a631e19 1557 set_mem_align (arguments, PARM_BOUNDARY);
53800dbe 1558
1559 /* Walk past the arg-pointer and structure value address. */
1560 size = GET_MODE_SIZE (Pmode);
45550790 1561 if (struct_value)
53800dbe 1562 size += GET_MODE_SIZE (Pmode);
1563
1564 /* Restore each of the registers previously saved. Make USE insns
1565 for each of these registers for use in making the call. */
1566 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1567 if ((mode = apply_args_mode[regno]) != VOIDmode)
1568 {
1569 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1570 if (size % align != 0)
1571 size = CEIL (size, align) * align;
1572 reg = gen_rtx_REG (mode, regno);
e513d163 1573 emit_move_insn (reg, adjust_address (arguments, mode, size));
53800dbe 1574 use_reg (&call_fusage, reg);
1575 size += GET_MODE_SIZE (mode);
1576 }
1577
1578 /* Restore the structure value address unless this is passed as an
1579 "invisible" first argument. */
1580 size = GET_MODE_SIZE (Pmode);
45550790 1581 if (struct_value)
53800dbe 1582 {
1583 rtx value = gen_reg_rtx (Pmode);
e513d163 1584 emit_move_insn (value, adjust_address (arguments, Pmode, size));
45550790 1585 emit_move_insn (struct_value, value);
8ad4c111 1586 if (REG_P (struct_value))
45550790 1587 use_reg (&call_fusage, struct_value);
53800dbe 1588 size += GET_MODE_SIZE (Pmode);
1589 }
1590
1591 /* All arguments and registers used for the call are set up by now! */
82c7907c 1592 function = prepare_call_address (NULL, function, NULL, &call_fusage, 0, 0);
53800dbe 1593
1594 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1595 and we don't want to load it into a register as an optimization,
1596 because prepare_call_address already did it if it should be done. */
1597 if (GET_CODE (function) != SYMBOL_REF)
1598 function = memory_address (FUNCTION_MODE, function);
1599
1600 /* Generate the actual call instruction and save the return value. */
1601#ifdef HAVE_untyped_call
1602 if (HAVE_untyped_call)
1603 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1604 result, result_vector (1, result)));
1605 else
1606#endif
1607#ifdef HAVE_call_value
1608 if (HAVE_call_value)
1609 {
1610 rtx valreg = 0;
1611
1612 /* Locate the unique return register. It is not possible to
1613 express a call that sets more than one return register using
1614 call_value; use untyped_call for that. In fact, untyped_call
1615 only needs to save the return registers in the given block. */
1616 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1617 if ((mode = apply_result_mode[regno]) != VOIDmode)
1618 {
64db345d 1619 gcc_assert (!valreg); /* HAVE_untyped_call required. */
7d3f6cc7 1620
53800dbe 1621 valreg = gen_rtx_REG (mode, regno);
1622 }
1623
2ed6c343 1624 emit_call_insn (GEN_CALL_VALUE (valreg,
53800dbe 1625 gen_rtx_MEM (FUNCTION_MODE, function),
1626 const0_rtx, NULL_RTX, const0_rtx));
1627
e513d163 1628 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
53800dbe 1629 }
1630 else
1631#endif
64db345d 1632 gcc_unreachable ();
53800dbe 1633
d5f9786f 1634 /* Find the CALL insn we just emitted, and attach the register usage
1635 information. */
1636 call_insn = last_call_insn ();
1637 add_function_usage_to (call_insn, call_fusage);
53800dbe 1638
1639 /* Restore the stack. */
1640#ifdef HAVE_save_stack_nonlocal
1641 if (HAVE_save_stack_nonlocal)
1642 emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1643 else
1644#endif
1645 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1646
04a46d40 1647 OK_DEFER_POP;
1648
53800dbe 1649 /* Return the address of the result block. */
85d654dd 1650 result = copy_addr_to_reg (XEXP (result, 0));
1651 return convert_memory_address (ptr_mode, result);
53800dbe 1652}
1653
1654/* Perform an untyped return. */
1655
1656static void
aecda0d6 1657expand_builtin_return (rtx result)
53800dbe 1658{
1659 int size, align, regno;
1660 enum machine_mode mode;
1661 rtx reg;
1662 rtx call_fusage = 0;
1663
85d654dd 1664 result = convert_memory_address (Pmode, result);
726ec87c 1665
53800dbe 1666 apply_result_size ();
1667 result = gen_rtx_MEM (BLKmode, result);
1668
1669#ifdef HAVE_untyped_return
1670 if (HAVE_untyped_return)
1671 {
1672 emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1673 emit_barrier ();
1674 return;
1675 }
1676#endif
1677
1678 /* Restore the return value and note that each value is used. */
1679 size = 0;
1680 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1681 if ((mode = apply_result_mode[regno]) != VOIDmode)
1682 {
1683 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1684 if (size % align != 0)
1685 size = CEIL (size, align) * align;
1686 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
e513d163 1687 emit_move_insn (reg, adjust_address (result, mode, size));
53800dbe 1688
1689 push_to_sequence (call_fusage);
18b42941 1690 emit_use (reg);
53800dbe 1691 call_fusage = get_insns ();
1692 end_sequence ();
1693 size += GET_MODE_SIZE (mode);
1694 }
1695
1696 /* Put the USE insns before the return. */
31d3e01c 1697 emit_insn (call_fusage);
53800dbe 1698
1699 /* Return whatever values was restored by jumping directly to the end
1700 of the function. */
62380d2d 1701 expand_naked_return ();
53800dbe 1702}
1703
539a3a92 1704/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
27d0c333 1705
539a3a92 1706static enum type_class
aecda0d6 1707type_to_class (tree type)
539a3a92 1708{
1709 switch (TREE_CODE (type))
1710 {
1711 case VOID_TYPE: return void_type_class;
1712 case INTEGER_TYPE: return integer_type_class;
539a3a92 1713 case ENUMERAL_TYPE: return enumeral_type_class;
1714 case BOOLEAN_TYPE: return boolean_type_class;
1715 case POINTER_TYPE: return pointer_type_class;
1716 case REFERENCE_TYPE: return reference_type_class;
1717 case OFFSET_TYPE: return offset_type_class;
1718 case REAL_TYPE: return real_type_class;
1719 case COMPLEX_TYPE: return complex_type_class;
1720 case FUNCTION_TYPE: return function_type_class;
1721 case METHOD_TYPE: return method_type_class;
1722 case RECORD_TYPE: return record_type_class;
1723 case UNION_TYPE:
1724 case QUAL_UNION_TYPE: return union_type_class;
1725 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1726 ? string_type_class : array_type_class);
539a3a92 1727 case LANG_TYPE: return lang_type_class;
1728 default: return no_type_class;
1729 }
1730}
bf8e3599 1731
c2f47e15 1732/* Expand a call EXP to __builtin_classify_type. */
27d0c333 1733
53800dbe 1734static rtx
c2f47e15 1735expand_builtin_classify_type (tree exp)
53800dbe 1736{
c2f47e15 1737 if (call_expr_nargs (exp))
1738 return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0))));
53800dbe 1739 return GEN_INT (no_type_class);
1740}
1741
07976da7 1742/* This helper macro, meant to be used in mathfn_built_in below,
1743 determines which among a set of three builtin math functions is
1744 appropriate for a given type mode. The `F' and `L' cases are
1745 automatically generated from the `double' case. */
1746#define CASE_MATHFN(BUILT_IN_MATHFN) \
1747 case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1748 fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1749 fcodel = BUILT_IN_MATHFN##L ; break;
cd2656b0 1750/* Similar to above, but appends _R after any F/L suffix. */
1751#define CASE_MATHFN_REENT(BUILT_IN_MATHFN) \
1752 case BUILT_IN_MATHFN##_R: case BUILT_IN_MATHFN##F_R: case BUILT_IN_MATHFN##L_R: \
1753 fcode = BUILT_IN_MATHFN##_R; fcodef = BUILT_IN_MATHFN##F_R ; \
1754 fcodel = BUILT_IN_MATHFN##L_R ; break;
07976da7 1755
1756/* Return mathematic function equivalent to FN but operating directly
c319d56a 1757 on TYPE, if available. If IMPLICIT is true find the function in
1758 implicit_built_in_decls[], otherwise use built_in_decls[]. If we
1759 can't do the conversion, return zero. */
1760
1761static tree
1762mathfn_built_in_1 (tree type, enum built_in_function fn, bool implicit)
0a68165a 1763{
c319d56a 1764 tree const *const fn_arr
1765 = implicit ? implicit_built_in_decls : built_in_decls;
07976da7 1766 enum built_in_function fcode, fcodef, fcodel;
1767
1768 switch (fn)
1769 {
746114e8 1770 CASE_MATHFN (BUILT_IN_ACOS)
1771 CASE_MATHFN (BUILT_IN_ACOSH)
1772 CASE_MATHFN (BUILT_IN_ASIN)
1773 CASE_MATHFN (BUILT_IN_ASINH)
07976da7 1774 CASE_MATHFN (BUILT_IN_ATAN)
746114e8 1775 CASE_MATHFN (BUILT_IN_ATAN2)
1776 CASE_MATHFN (BUILT_IN_ATANH)
1777 CASE_MATHFN (BUILT_IN_CBRT)
07976da7 1778 CASE_MATHFN (BUILT_IN_CEIL)
d735c391 1779 CASE_MATHFN (BUILT_IN_CEXPI)
746114e8 1780 CASE_MATHFN (BUILT_IN_COPYSIGN)
07976da7 1781 CASE_MATHFN (BUILT_IN_COS)
746114e8 1782 CASE_MATHFN (BUILT_IN_COSH)
1783 CASE_MATHFN (BUILT_IN_DREM)
1784 CASE_MATHFN (BUILT_IN_ERF)
1785 CASE_MATHFN (BUILT_IN_ERFC)
07976da7 1786 CASE_MATHFN (BUILT_IN_EXP)
746114e8 1787 CASE_MATHFN (BUILT_IN_EXP10)
1788 CASE_MATHFN (BUILT_IN_EXP2)
1789 CASE_MATHFN (BUILT_IN_EXPM1)
1790 CASE_MATHFN (BUILT_IN_FABS)
1791 CASE_MATHFN (BUILT_IN_FDIM)
07976da7 1792 CASE_MATHFN (BUILT_IN_FLOOR)
746114e8 1793 CASE_MATHFN (BUILT_IN_FMA)
1794 CASE_MATHFN (BUILT_IN_FMAX)
1795 CASE_MATHFN (BUILT_IN_FMIN)
1796 CASE_MATHFN (BUILT_IN_FMOD)
1797 CASE_MATHFN (BUILT_IN_FREXP)
1798 CASE_MATHFN (BUILT_IN_GAMMA)
cd2656b0 1799 CASE_MATHFN_REENT (BUILT_IN_GAMMA) /* GAMMA_R */
746114e8 1800 CASE_MATHFN (BUILT_IN_HUGE_VAL)
1801 CASE_MATHFN (BUILT_IN_HYPOT)
1802 CASE_MATHFN (BUILT_IN_ILOGB)
1803 CASE_MATHFN (BUILT_IN_INF)
69b779ea 1804 CASE_MATHFN (BUILT_IN_ISINF)
746114e8 1805 CASE_MATHFN (BUILT_IN_J0)
1806 CASE_MATHFN (BUILT_IN_J1)
1807 CASE_MATHFN (BUILT_IN_JN)
ac148751 1808 CASE_MATHFN (BUILT_IN_LCEIL)
746114e8 1809 CASE_MATHFN (BUILT_IN_LDEXP)
ad52b9b7 1810 CASE_MATHFN (BUILT_IN_LFLOOR)
746114e8 1811 CASE_MATHFN (BUILT_IN_LGAMMA)
cd2656b0 1812 CASE_MATHFN_REENT (BUILT_IN_LGAMMA) /* LGAMMA_R */
ac148751 1813 CASE_MATHFN (BUILT_IN_LLCEIL)
ad52b9b7 1814 CASE_MATHFN (BUILT_IN_LLFLOOR)
746114e8 1815 CASE_MATHFN (BUILT_IN_LLRINT)
1816 CASE_MATHFN (BUILT_IN_LLROUND)
07976da7 1817 CASE_MATHFN (BUILT_IN_LOG)
746114e8 1818 CASE_MATHFN (BUILT_IN_LOG10)
1819 CASE_MATHFN (BUILT_IN_LOG1P)
1820 CASE_MATHFN (BUILT_IN_LOG2)
1821 CASE_MATHFN (BUILT_IN_LOGB)
1822 CASE_MATHFN (BUILT_IN_LRINT)
1823 CASE_MATHFN (BUILT_IN_LROUND)
1824 CASE_MATHFN (BUILT_IN_MODF)
1825 CASE_MATHFN (BUILT_IN_NAN)
1826 CASE_MATHFN (BUILT_IN_NANS)
07976da7 1827 CASE_MATHFN (BUILT_IN_NEARBYINT)
746114e8 1828 CASE_MATHFN (BUILT_IN_NEXTAFTER)
1829 CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1830 CASE_MATHFN (BUILT_IN_POW)
757c219d 1831 CASE_MATHFN (BUILT_IN_POWI)
746114e8 1832 CASE_MATHFN (BUILT_IN_POW10)
1833 CASE_MATHFN (BUILT_IN_REMAINDER)
1834 CASE_MATHFN (BUILT_IN_REMQUO)
1835 CASE_MATHFN (BUILT_IN_RINT)
07976da7 1836 CASE_MATHFN (BUILT_IN_ROUND)
746114e8 1837 CASE_MATHFN (BUILT_IN_SCALB)
1838 CASE_MATHFN (BUILT_IN_SCALBLN)
1839 CASE_MATHFN (BUILT_IN_SCALBN)
c319d56a 1840 CASE_MATHFN (BUILT_IN_SIGNBIT)
746114e8 1841 CASE_MATHFN (BUILT_IN_SIGNIFICAND)
07976da7 1842 CASE_MATHFN (BUILT_IN_SIN)
746114e8 1843 CASE_MATHFN (BUILT_IN_SINCOS)
1844 CASE_MATHFN (BUILT_IN_SINH)
07976da7 1845 CASE_MATHFN (BUILT_IN_SQRT)
1846 CASE_MATHFN (BUILT_IN_TAN)
746114e8 1847 CASE_MATHFN (BUILT_IN_TANH)
1848 CASE_MATHFN (BUILT_IN_TGAMMA)
07976da7 1849 CASE_MATHFN (BUILT_IN_TRUNC)
746114e8 1850 CASE_MATHFN (BUILT_IN_Y0)
1851 CASE_MATHFN (BUILT_IN_Y1)
1852 CASE_MATHFN (BUILT_IN_YN)
07976da7 1853
0a68165a 1854 default:
c2f47e15 1855 return NULL_TREE;
0a68165a 1856 }
07976da7 1857
96b9f485 1858 if (TYPE_MAIN_VARIANT (type) == double_type_node)
c319d56a 1859 return fn_arr[fcode];
96b9f485 1860 else if (TYPE_MAIN_VARIANT (type) == float_type_node)
c319d56a 1861 return fn_arr[fcodef];
96b9f485 1862 else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
c319d56a 1863 return fn_arr[fcodel];
07976da7 1864 else
c2f47e15 1865 return NULL_TREE;
0a68165a 1866}
1867
c319d56a 1868/* Like mathfn_built_in_1(), but always use the implicit array. */
1869
1870tree
1871mathfn_built_in (tree type, enum built_in_function fn)
1872{
1873 return mathfn_built_in_1 (type, fn, /*implicit=*/ 1);
1874}
1875
0fd605a5 1876/* If errno must be maintained, expand the RTL to check if the result,
1877 TARGET, of a built-in function call, EXP, is NaN, and if so set
1878 errno to EDOM. */
1879
1880static void
aecda0d6 1881expand_errno_check (tree exp, rtx target)
0fd605a5 1882{
7f05340e 1883 rtx lab = gen_label_rtx ();
0fd605a5 1884
7f05340e 1885 /* Test the result; if it is NaN, set errno=EDOM because
1886 the argument was not in the domain. */
3fcf767f 1887 do_compare_rtx_and_jump (target, target, EQ, 0, GET_MODE (target),
1888 NULL_RTX, NULL_RTX, lab);
0fd605a5 1889
1890#ifdef TARGET_EDOM
7f05340e 1891 /* If this built-in doesn't throw an exception, set errno directly. */
c2f47e15 1892 if (TREE_NOTHROW (TREE_OPERAND (CALL_EXPR_FN (exp), 0)))
7f05340e 1893 {
0fd605a5 1894#ifdef GEN_ERRNO_RTX
7f05340e 1895 rtx errno_rtx = GEN_ERRNO_RTX;
0fd605a5 1896#else
7f05340e 1897 rtx errno_rtx
0fd605a5 1898 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1899#endif
7f05340e 1900 emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
0fd605a5 1901 emit_label (lab);
7f05340e 1902 return;
0fd605a5 1903 }
7f05340e 1904#endif
1905
08491912 1906 /* Make sure the library call isn't expanded as a tail call. */
1907 CALL_EXPR_TAILCALL (exp) = 0;
1908
7f05340e 1909 /* We can't set errno=EDOM directly; let the library call do it.
1910 Pop the arguments right away in case the call gets deleted. */
1911 NO_DEFER_POP;
1912 expand_call (exp, target, 0);
1913 OK_DEFER_POP;
1914 emit_label (lab);
0fd605a5 1915}
1916
6b43bae4 1917/* Expand a call to one of the builtin math functions (sqrt, exp, or log).
c2f47e15 1918 Return NULL_RTX if a normal call should be emitted rather than expanding
1919 the function in-line. EXP is the expression that is a call to the builtin
53800dbe 1920 function; if convenient, the result should be placed in TARGET.
1921 SUBTARGET may be used as the target for computing one of EXP's operands. */
27d0c333 1922
53800dbe 1923static rtx
aecda0d6 1924expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
53800dbe 1925{
bf8e3599 1926 optab builtin_optab;
bd421108 1927 rtx op0, insns, before_call;
c6e6ecb1 1928 tree fndecl = get_callee_fndecl (exp);
7f05340e 1929 enum machine_mode mode;
528ee710 1930 bool errno_set = false;
abfea505 1931 tree arg;
53800dbe 1932
c2f47e15 1933 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
1934 return NULL_RTX;
53800dbe 1935
c2f47e15 1936 arg = CALL_EXPR_ARG (exp, 0);
53800dbe 1937
1938 switch (DECL_FUNCTION_CODE (fndecl))
1939 {
4f35b1fc 1940 CASE_FLT_FN (BUILT_IN_SQRT):
7f05340e 1941 errno_set = ! tree_expr_nonnegative_p (arg);
1942 builtin_optab = sqrt_optab;
1943 break;
4f35b1fc 1944 CASE_FLT_FN (BUILT_IN_EXP):
528ee710 1945 errno_set = true; builtin_optab = exp_optab; break;
4f35b1fc 1946 CASE_FLT_FN (BUILT_IN_EXP10):
1947 CASE_FLT_FN (BUILT_IN_POW10):
750ef9f5 1948 errno_set = true; builtin_optab = exp10_optab; break;
4f35b1fc 1949 CASE_FLT_FN (BUILT_IN_EXP2):
750ef9f5 1950 errno_set = true; builtin_optab = exp2_optab; break;
4f35b1fc 1951 CASE_FLT_FN (BUILT_IN_EXPM1):
a6b4eed2 1952 errno_set = true; builtin_optab = expm1_optab; break;
4f35b1fc 1953 CASE_FLT_FN (BUILT_IN_LOGB):
4efbc641 1954 errno_set = true; builtin_optab = logb_optab; break;
4f35b1fc 1955 CASE_FLT_FN (BUILT_IN_LOG):
528ee710 1956 errno_set = true; builtin_optab = log_optab; break;
4f35b1fc 1957 CASE_FLT_FN (BUILT_IN_LOG10):
d3cd9bde 1958 errno_set = true; builtin_optab = log10_optab; break;
4f35b1fc 1959 CASE_FLT_FN (BUILT_IN_LOG2):
d3cd9bde 1960 errno_set = true; builtin_optab = log2_optab; break;
4f35b1fc 1961 CASE_FLT_FN (BUILT_IN_LOG1P):
f474cd93 1962 errno_set = true; builtin_optab = log1p_optab; break;
4f35b1fc 1963 CASE_FLT_FN (BUILT_IN_ASIN):
8de2f465 1964 builtin_optab = asin_optab; break;
4f35b1fc 1965 CASE_FLT_FN (BUILT_IN_ACOS):
8de2f465 1966 builtin_optab = acos_optab; break;
4f35b1fc 1967 CASE_FLT_FN (BUILT_IN_TAN):
528ee710 1968 builtin_optab = tan_optab; break;
4f35b1fc 1969 CASE_FLT_FN (BUILT_IN_ATAN):
528ee710 1970 builtin_optab = atan_optab; break;
4f35b1fc 1971 CASE_FLT_FN (BUILT_IN_FLOOR):
528ee710 1972 builtin_optab = floor_optab; break;
4f35b1fc 1973 CASE_FLT_FN (BUILT_IN_CEIL):
528ee710 1974 builtin_optab = ceil_optab; break;
4f35b1fc 1975 CASE_FLT_FN (BUILT_IN_TRUNC):
a7cc195f 1976 builtin_optab = btrunc_optab; break;
4f35b1fc 1977 CASE_FLT_FN (BUILT_IN_ROUND):
528ee710 1978 builtin_optab = round_optab; break;
4f35b1fc 1979 CASE_FLT_FN (BUILT_IN_NEARBYINT):
0ddf4ad9 1980 builtin_optab = nearbyint_optab;
1981 if (flag_trapping_math)
1982 break;
1983 /* Else fallthrough and expand as rint. */
4f35b1fc 1984 CASE_FLT_FN (BUILT_IN_RINT):
aef94a0f 1985 builtin_optab = rint_optab; break;
b3154a1f 1986 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
1987 builtin_optab = significand_optab; break;
42721db0 1988 default:
64db345d 1989 gcc_unreachable ();
53800dbe 1990 }
1991
7f05340e 1992 /* Make a suitable register to place result in. */
1993 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 1994
7f05340e 1995 if (! flag_errno_math || ! HONOR_NANS (mode))
1996 errno_set = false;
1997
bd421108 1998 /* Before working hard, check whether the instruction is available. */
99bdde56 1999 if (optab_handler (builtin_optab, mode)->insn_code != CODE_FOR_nothing)
68e6cb9d 2000 {
bd421108 2001 target = gen_reg_rtx (mode);
7f05340e 2002
bd421108 2003 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2004 need to expand the argument again. This way, we will not perform
2005 side-effects more the once. */
abfea505 2006 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7f05340e 2007
1db6d067 2008 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
7f05340e 2009
bd421108 2010 start_sequence ();
53800dbe 2011
bd421108 2012 /* Compute into TARGET.
2013 Set TARGET to wherever the result comes back. */
2014 target = expand_unop (mode, builtin_optab, op0, target, 0);
2015
2016 if (target != 0)
2017 {
2018 if (errno_set)
2019 expand_errno_check (exp, target);
2020
2021 /* Output the entire sequence. */
2022 insns = get_insns ();
2023 end_sequence ();
2024 emit_insn (insns);
2025 return target;
2026 }
2027
2028 /* If we were unable to expand via the builtin, stop the sequence
2029 (without outputting the insns) and call to the library function
2030 with the stabilized argument list. */
53800dbe 2031 end_sequence ();
53800dbe 2032 }
2033
bd421108 2034 before_call = get_last_insn ();
2035
1e5b92fa 2036 return expand_call (exp, target, target == const0_rtx);
0fd605a5 2037}
2038
2039/* Expand a call to the builtin binary math functions (pow and atan2).
c2f47e15 2040 Return NULL_RTX if a normal call should be emitted rather than expanding the
0fd605a5 2041 function in-line. EXP is the expression that is a call to the builtin
2042 function; if convenient, the result should be placed in TARGET.
2043 SUBTARGET may be used as the target for computing one of EXP's
2044 operands. */
2045
2046static rtx
aecda0d6 2047expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
0fd605a5 2048{
2049 optab builtin_optab;
2050 rtx op0, op1, insns;
4737caf2 2051 int op1_type = REAL_TYPE;
c6e6ecb1 2052 tree fndecl = get_callee_fndecl (exp);
abfea505 2053 tree arg0, arg1;
7f05340e 2054 enum machine_mode mode;
0fd605a5 2055 bool errno_set = true;
0fd605a5 2056
73a954a1 2057 switch (DECL_FUNCTION_CODE (fndecl))
2058 {
2059 CASE_FLT_FN (BUILT_IN_SCALBN):
2060 CASE_FLT_FN (BUILT_IN_SCALBLN):
2061 CASE_FLT_FN (BUILT_IN_LDEXP):
2062 op1_type = INTEGER_TYPE;
2063 default:
2064 break;
2065 }
4737caf2 2066
c2f47e15 2067 if (!validate_arglist (exp, REAL_TYPE, op1_type, VOID_TYPE))
2068 return NULL_RTX;
0fd605a5 2069
c2f47e15 2070 arg0 = CALL_EXPR_ARG (exp, 0);
2071 arg1 = CALL_EXPR_ARG (exp, 1);
0fd605a5 2072
0fd605a5 2073 switch (DECL_FUNCTION_CODE (fndecl))
2074 {
4f35b1fc 2075 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 2076 builtin_optab = pow_optab; break;
4f35b1fc 2077 CASE_FLT_FN (BUILT_IN_ATAN2):
0fd605a5 2078 builtin_optab = atan2_optab; break;
73a954a1 2079 CASE_FLT_FN (BUILT_IN_SCALB):
2080 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2081 return 0;
2082 builtin_optab = scalb_optab; break;
2083 CASE_FLT_FN (BUILT_IN_SCALBN):
2084 CASE_FLT_FN (BUILT_IN_SCALBLN):
2085 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2086 return 0;
2087 /* Fall through... */
4f35b1fc 2088 CASE_FLT_FN (BUILT_IN_LDEXP):
4737caf2 2089 builtin_optab = ldexp_optab; break;
4f35b1fc 2090 CASE_FLT_FN (BUILT_IN_FMOD):
80ed5c06 2091 builtin_optab = fmod_optab; break;
ef722005 2092 CASE_FLT_FN (BUILT_IN_REMAINDER):
4f35b1fc 2093 CASE_FLT_FN (BUILT_IN_DREM):
ef722005 2094 builtin_optab = remainder_optab; break;
0fd605a5 2095 default:
64db345d 2096 gcc_unreachable ();
0fd605a5 2097 }
2098
7f05340e 2099 /* Make a suitable register to place result in. */
2100 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2101
2102 /* Before working hard, check whether the instruction is available. */
99bdde56 2103 if (optab_handler (builtin_optab, mode)->insn_code == CODE_FOR_nothing)
c2f47e15 2104 return NULL_RTX;
fc4eef90 2105
7f05340e 2106 target = gen_reg_rtx (mode);
2107
2108 if (! flag_errno_math || ! HONOR_NANS (mode))
2109 errno_set = false;
2110
4ee9c684 2111 /* Always stabilize the argument list. */
abfea505 2112 CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
2113 CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
7f05340e 2114
8ec3c5c2 2115 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2116 op1 = expand_normal (arg1);
7f05340e 2117
7f05340e 2118 start_sequence ();
2119
0fd605a5 2120 /* Compute into TARGET.
2121 Set TARGET to wherever the result comes back. */
7f05340e 2122 target = expand_binop (mode, builtin_optab, op0, op1,
0fd605a5 2123 target, 0, OPTAB_DIRECT);
53800dbe 2124
68e6cb9d 2125 /* If we were unable to expand via the builtin, stop the sequence
2126 (without outputting the insns) and call to the library function
2127 with the stabilized argument list. */
0fd605a5 2128 if (target == 0)
2129 {
2130 end_sequence ();
68e6cb9d 2131 return expand_call (exp, target, target == const0_rtx);
53800dbe 2132 }
2133
a4356fb9 2134 if (errno_set)
2135 expand_errno_check (exp, target);
0fd605a5 2136
53800dbe 2137 /* Output the entire sequence. */
2138 insns = get_insns ();
2139 end_sequence ();
31d3e01c 2140 emit_insn (insns);
bf8e3599 2141
53800dbe 2142 return target;
2143}
2144
6b43bae4 2145/* Expand a call to the builtin sin and cos math functions.
c2f47e15 2146 Return NULL_RTX if a normal call should be emitted rather than expanding the
6b43bae4 2147 function in-line. EXP is the expression that is a call to the builtin
2148 function; if convenient, the result should be placed in TARGET.
2149 SUBTARGET may be used as the target for computing one of EXP's
2150 operands. */
2151
2152static rtx
2153expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
2154{
2155 optab builtin_optab;
7511b819 2156 rtx op0, insns;
6b43bae4 2157 tree fndecl = get_callee_fndecl (exp);
6b43bae4 2158 enum machine_mode mode;
abfea505 2159 tree arg;
6b43bae4 2160
c2f47e15 2161 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2162 return NULL_RTX;
6b43bae4 2163
c2f47e15 2164 arg = CALL_EXPR_ARG (exp, 0);
6b43bae4 2165
2166 switch (DECL_FUNCTION_CODE (fndecl))
2167 {
4f35b1fc 2168 CASE_FLT_FN (BUILT_IN_SIN):
2169 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2170 builtin_optab = sincos_optab; break;
2171 default:
64db345d 2172 gcc_unreachable ();
6b43bae4 2173 }
2174
2175 /* Make a suitable register to place result in. */
2176 mode = TYPE_MODE (TREE_TYPE (exp));
2177
6b43bae4 2178 /* Check if sincos insn is available, otherwise fallback
0bed3869 2179 to sin or cos insn. */
99bdde56 2180 if (optab_handler (builtin_optab, mode)->insn_code == CODE_FOR_nothing)
6b43bae4 2181 switch (DECL_FUNCTION_CODE (fndecl))
2182 {
4f35b1fc 2183 CASE_FLT_FN (BUILT_IN_SIN):
6b43bae4 2184 builtin_optab = sin_optab; break;
4f35b1fc 2185 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2186 builtin_optab = cos_optab; break;
2187 default:
64db345d 2188 gcc_unreachable ();
6b43bae4 2189 }
6b43bae4 2190
2191 /* Before working hard, check whether the instruction is available. */
99bdde56 2192 if (optab_handler (builtin_optab, mode)->insn_code != CODE_FOR_nothing)
6b43bae4 2193 {
2194 target = gen_reg_rtx (mode);
2195
2196 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2197 need to expand the argument again. This way, we will not perform
2198 side-effects more the once. */
abfea505 2199 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
6b43bae4 2200
1db6d067 2201 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
6b43bae4 2202
6b43bae4 2203 start_sequence ();
2204
2205 /* Compute into TARGET.
2206 Set TARGET to wherever the result comes back. */
2207 if (builtin_optab == sincos_optab)
2208 {
64db345d 2209 int result;
7d3f6cc7 2210
6b43bae4 2211 switch (DECL_FUNCTION_CODE (fndecl))
2212 {
4f35b1fc 2213 CASE_FLT_FN (BUILT_IN_SIN):
64db345d 2214 result = expand_twoval_unop (builtin_optab, op0, 0, target, 0);
6b43bae4 2215 break;
4f35b1fc 2216 CASE_FLT_FN (BUILT_IN_COS):
64db345d 2217 result = expand_twoval_unop (builtin_optab, op0, target, 0, 0);
6b43bae4 2218 break;
2219 default:
64db345d 2220 gcc_unreachable ();
6b43bae4 2221 }
64db345d 2222 gcc_assert (result);
6b43bae4 2223 }
2224 else
2225 {
2226 target = expand_unop (mode, builtin_optab, op0, target, 0);
2227 }
2228
2229 if (target != 0)
2230 {
6b43bae4 2231 /* Output the entire sequence. */
2232 insns = get_insns ();
2233 end_sequence ();
2234 emit_insn (insns);
2235 return target;
2236 }
2237
2238 /* If we were unable to expand via the builtin, stop the sequence
2239 (without outputting the insns) and call to the library function
2240 with the stabilized argument list. */
2241 end_sequence ();
2242 }
2243
6b43bae4 2244 target = expand_call (exp, target, target == const0_rtx);
2245
2246 return target;
2247}
2248
a65c4d64 2249/* Given an interclass math builtin decl FNDECL and it's argument ARG
2250 return an RTL instruction code that implements the functionality.
2251 If that isn't possible or available return CODE_FOR_nothing. */
a67a90e5 2252
a65c4d64 2253static enum insn_code
2254interclass_mathfn_icode (tree arg, tree fndecl)
a67a90e5 2255{
a65c4d64 2256 bool errno_set = false;
cde061c1 2257 optab builtin_optab = 0;
a67a90e5 2258 enum machine_mode mode;
a67a90e5 2259
2260 switch (DECL_FUNCTION_CODE (fndecl))
2261 {
2262 CASE_FLT_FN (BUILT_IN_ILOGB):
2263 errno_set = true; builtin_optab = ilogb_optab; break;
69b779ea 2264 CASE_FLT_FN (BUILT_IN_ISINF):
2265 builtin_optab = isinf_optab; break;
8a1a9cb7 2266 case BUILT_IN_ISNORMAL:
cde061c1 2267 case BUILT_IN_ISFINITE:
2268 CASE_FLT_FN (BUILT_IN_FINITE):
a65c4d64 2269 case BUILT_IN_FINITED32:
2270 case BUILT_IN_FINITED64:
2271 case BUILT_IN_FINITED128:
2272 case BUILT_IN_ISINFD32:
2273 case BUILT_IN_ISINFD64:
2274 case BUILT_IN_ISINFD128:
cde061c1 2275 /* These builtins have no optabs (yet). */
2276 break;
a67a90e5 2277 default:
2278 gcc_unreachable ();
2279 }
2280
2281 /* There's no easy way to detect the case we need to set EDOM. */
2282 if (flag_errno_math && errno_set)
a65c4d64 2283 return CODE_FOR_nothing;
a67a90e5 2284
2285 /* Optab mode depends on the mode of the input argument. */
2286 mode = TYPE_MODE (TREE_TYPE (arg));
2287
cde061c1 2288 if (builtin_optab)
a65c4d64 2289 return optab_handler (builtin_optab, mode)->insn_code;
2290 return CODE_FOR_nothing;
2291}
2292
2293/* Expand a call to one of the builtin math functions that operate on
2294 floating point argument and output an integer result (ilogb, isinf,
2295 isnan, etc).
2296 Return 0 if a normal call should be emitted rather than expanding the
2297 function in-line. EXP is the expression that is a call to the builtin
2298 function; if convenient, the result should be placed in TARGET.
2299 SUBTARGET may be used as the target for computing one of EXP's operands. */
2300
2301static rtx
2302expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
2303{
2304 enum insn_code icode = CODE_FOR_nothing;
2305 rtx op0;
2306 tree fndecl = get_callee_fndecl (exp);
2307 enum machine_mode mode;
2308 tree arg;
2309
2310 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2311 return NULL_RTX;
2312
2313 arg = CALL_EXPR_ARG (exp, 0);
2314 icode = interclass_mathfn_icode (arg, fndecl);
2315 mode = TYPE_MODE (TREE_TYPE (arg));
2316
a67a90e5 2317 if (icode != CODE_FOR_nothing)
2318 {
2319 /* Make a suitable register to place result in. */
2320 if (!target
2321 || GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
2322 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
2323
2324 gcc_assert (insn_data[icode].operand[0].predicate
2325 (target, GET_MODE (target)));
2326
2327 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2328 need to expand the argument again. This way, we will not perform
2329 side-effects more the once. */
abfea505 2330 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
a67a90e5 2331
1db6d067 2332 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
a67a90e5 2333
2334 if (mode != GET_MODE (op0))
2335 op0 = convert_to_mode (mode, op0, 0);
2336
2337 /* Compute into TARGET.
2338 Set TARGET to wherever the result comes back. */
2339 emit_unop_insn (icode, target, op0, UNKNOWN);
2340 return target;
2341 }
2342
a65c4d64 2343 return NULL_RTX;
a67a90e5 2344}
2345
c3147c1a 2346/* Expand a call to the builtin sincos math function.
c2f47e15 2347 Return NULL_RTX if a normal call should be emitted rather than expanding the
c3147c1a 2348 function in-line. EXP is the expression that is a call to the builtin
2349 function. */
2350
2351static rtx
2352expand_builtin_sincos (tree exp)
2353{
2354 rtx op0, op1, op2, target1, target2;
c3147c1a 2355 enum machine_mode mode;
2356 tree arg, sinp, cosp;
2357 int result;
389dd41b 2358 location_t loc = EXPR_LOCATION (exp);
c3147c1a 2359
c2f47e15 2360 if (!validate_arglist (exp, REAL_TYPE,
2361 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2362 return NULL_RTX;
c3147c1a 2363
c2f47e15 2364 arg = CALL_EXPR_ARG (exp, 0);
2365 sinp = CALL_EXPR_ARG (exp, 1);
2366 cosp = CALL_EXPR_ARG (exp, 2);
c3147c1a 2367
2368 /* Make a suitable register to place result in. */
2369 mode = TYPE_MODE (TREE_TYPE (arg));
2370
2371 /* Check if sincos insn is available, otherwise emit the call. */
99bdde56 2372 if (optab_handler (sincos_optab, mode)->insn_code == CODE_FOR_nothing)
c3147c1a 2373 return NULL_RTX;
2374
2375 target1 = gen_reg_rtx (mode);
2376 target2 = gen_reg_rtx (mode);
2377
8ec3c5c2 2378 op0 = expand_normal (arg);
389dd41b 2379 op1 = expand_normal (build_fold_indirect_ref_loc (loc, sinp));
2380 op2 = expand_normal (build_fold_indirect_ref_loc (loc, cosp));
c3147c1a 2381
2382 /* Compute into target1 and target2.
2383 Set TARGET to wherever the result comes back. */
2384 result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
2385 gcc_assert (result);
2386
2387 /* Move target1 and target2 to the memory locations indicated
2388 by op1 and op2. */
2389 emit_move_insn (op1, target1);
2390 emit_move_insn (op2, target2);
2391
2392 return const0_rtx;
2393}
2394
d735c391 2395/* Expand a call to the internal cexpi builtin to the sincos math function.
2396 EXP is the expression that is a call to the builtin function; if convenient,
2397 the result should be placed in TARGET. SUBTARGET may be used as the target
2398 for computing one of EXP's operands. */
2399
2400static rtx
2401expand_builtin_cexpi (tree exp, rtx target, rtx subtarget)
2402{
2403 tree fndecl = get_callee_fndecl (exp);
d735c391 2404 tree arg, type;
c2f47e15 2405 enum machine_mode mode;
d735c391 2406 rtx op0, op1, op2;
389dd41b 2407 location_t loc = EXPR_LOCATION (exp);
d735c391 2408
c2f47e15 2409 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2410 return NULL_RTX;
d735c391 2411
c2f47e15 2412 arg = CALL_EXPR_ARG (exp, 0);
d735c391 2413 type = TREE_TYPE (arg);
2414 mode = TYPE_MODE (TREE_TYPE (arg));
2415
2416 /* Try expanding via a sincos optab, fall back to emitting a libcall
18b8d8ae 2417 to sincos or cexp. We are sure we have sincos or cexp because cexpi
2418 is only generated from sincos, cexp or if we have either of them. */
99bdde56 2419 if (optab_handler (sincos_optab, mode)->insn_code != CODE_FOR_nothing)
d735c391 2420 {
2421 op1 = gen_reg_rtx (mode);
2422 op2 = gen_reg_rtx (mode);
2423
1db6d067 2424 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
d735c391 2425
2426 /* Compute into op1 and op2. */
2427 expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
2428 }
18b8d8ae 2429 else if (TARGET_HAS_SINCOS)
d735c391 2430 {
c2f47e15 2431 tree call, fn = NULL_TREE;
d735c391 2432 tree top1, top2;
2433 rtx op1a, op2a;
2434
2435 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2436 fn = built_in_decls[BUILT_IN_SINCOSF];
2437 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2438 fn = built_in_decls[BUILT_IN_SINCOS];
2439 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2440 fn = built_in_decls[BUILT_IN_SINCOSL];
c2f47e15 2441 else
2442 gcc_unreachable ();
d735c391 2443
2444 op1 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
2445 op2 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
2446 op1a = copy_to_mode_reg (Pmode, XEXP (op1, 0));
2447 op2a = copy_to_mode_reg (Pmode, XEXP (op2, 0));
2448 top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
2449 top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
2450
d735c391 2451 /* Make sure not to fold the sincos call again. */
2452 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
c2f47e15 2453 expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
2454 call, 3, arg, top1, top2));
d735c391 2455 }
18b8d8ae 2456 else
2457 {
0ecbc158 2458 tree call, fn = NULL_TREE, narg;
18b8d8ae 2459 tree ctype = build_complex_type (type);
2460
0ecbc158 2461 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2462 fn = built_in_decls[BUILT_IN_CEXPF];
2463 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2464 fn = built_in_decls[BUILT_IN_CEXP];
2465 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2466 fn = built_in_decls[BUILT_IN_CEXPL];
c2f47e15 2467 else
2468 gcc_unreachable ();
fc0dfa6e 2469
2470 /* If we don't have a decl for cexp create one. This is the
2471 friendliest fallback if the user calls __builtin_cexpi
2472 without full target C99 function support. */
2473 if (fn == NULL_TREE)
2474 {
2475 tree fntype;
2476 const char *name = NULL;
2477
2478 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2479 name = "cexpf";
2480 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2481 name = "cexp";
2482 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2483 name = "cexpl";
2484
2485 fntype = build_function_type_list (ctype, ctype, NULL_TREE);
2486 fn = build_fn_decl (name, fntype);
2487 }
2488
389dd41b 2489 narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype,
18b8d8ae 2490 build_real (type, dconst0), arg);
2491
2492 /* Make sure not to fold the cexp call again. */
2493 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
3737e769 2494 return expand_expr (build_call_nary (ctype, call, 1, narg),
1db6d067 2495 target, VOIDmode, EXPAND_NORMAL);
18b8d8ae 2496 }
d735c391 2497
2498 /* Now build the proper return type. */
2499 return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
2500 make_tree (TREE_TYPE (arg), op2),
2501 make_tree (TREE_TYPE (arg), op1)),
1db6d067 2502 target, VOIDmode, EXPAND_NORMAL);
d735c391 2503}
2504
a65c4d64 2505/* Conveniently construct a function call expression. FNDECL names the
2506 function to be called, N is the number of arguments, and the "..."
2507 parameters are the argument expressions. Unlike build_call_exr
2508 this doesn't fold the call, hence it will always return a CALL_EXPR. */
2509
2510static tree
2511build_call_nofold_loc (location_t loc, tree fndecl, int n, ...)
2512{
2513 va_list ap;
2514 tree fntype = TREE_TYPE (fndecl);
2515 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
2516
2517 va_start (ap, n);
2518 fn = build_call_valist (TREE_TYPE (fntype), fn, n, ap);
2519 va_end (ap);
2520 SET_EXPR_LOCATION (fn, loc);
2521 return fn;
2522}
2523#define build_call_nofold(...) \
2524 build_call_nofold_loc (UNKNOWN_LOCATION, __VA_ARGS__)
2525
7d3afc77 2526/* Expand a call to one of the builtin rounding functions gcc defines
2527 as an extension (lfloor and lceil). As these are gcc extensions we
2528 do not need to worry about setting errno to EDOM.
ad52b9b7 2529 If expanding via optab fails, lower expression to (int)(floor(x)).
2530 EXP is the expression that is a call to the builtin function;
ff1b14e4 2531 if convenient, the result should be placed in TARGET. */
ad52b9b7 2532
2533static rtx
ff1b14e4 2534expand_builtin_int_roundingfn (tree exp, rtx target)
ad52b9b7 2535{
9c42dd28 2536 convert_optab builtin_optab;
ad52b9b7 2537 rtx op0, insns, tmp;
2538 tree fndecl = get_callee_fndecl (exp);
ad52b9b7 2539 enum built_in_function fallback_fn;
2540 tree fallback_fndecl;
2541 enum machine_mode mode;
4de0924f 2542 tree arg;
ad52b9b7 2543
c2f47e15 2544 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
ad52b9b7 2545 gcc_unreachable ();
2546
c2f47e15 2547 arg = CALL_EXPR_ARG (exp, 0);
ad52b9b7 2548
2549 switch (DECL_FUNCTION_CODE (fndecl))
2550 {
4f35b1fc 2551 CASE_FLT_FN (BUILT_IN_LCEIL):
2552 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 2553 builtin_optab = lceil_optab;
2554 fallback_fn = BUILT_IN_CEIL;
2555 break;
2556
4f35b1fc 2557 CASE_FLT_FN (BUILT_IN_LFLOOR):
2558 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 2559 builtin_optab = lfloor_optab;
2560 fallback_fn = BUILT_IN_FLOOR;
2561 break;
2562
2563 default:
2564 gcc_unreachable ();
2565 }
2566
2567 /* Make a suitable register to place result in. */
2568 mode = TYPE_MODE (TREE_TYPE (exp));
2569
9c42dd28 2570 target = gen_reg_rtx (mode);
ad52b9b7 2571
9c42dd28 2572 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2573 need to expand the argument again. This way, we will not perform
2574 side-effects more the once. */
abfea505 2575 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
ad52b9b7 2576
ff1b14e4 2577 op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
ad52b9b7 2578
9c42dd28 2579 start_sequence ();
ad52b9b7 2580
9c42dd28 2581 /* Compute into TARGET. */
2582 if (expand_sfix_optab (target, op0, builtin_optab))
2583 {
2584 /* Output the entire sequence. */
2585 insns = get_insns ();
ad52b9b7 2586 end_sequence ();
9c42dd28 2587 emit_insn (insns);
2588 return target;
ad52b9b7 2589 }
2590
9c42dd28 2591 /* If we were unable to expand via the builtin, stop the sequence
2592 (without outputting the insns). */
2593 end_sequence ();
2594
ad52b9b7 2595 /* Fall back to floating point rounding optab. */
2596 fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
fc0dfa6e 2597
2598 /* For non-C99 targets we may end up without a fallback fndecl here
2599 if the user called __builtin_lfloor directly. In this case emit
2600 a call to the floor/ceil variants nevertheless. This should result
2601 in the best user experience for not full C99 targets. */
2602 if (fallback_fndecl == NULL_TREE)
2603 {
2604 tree fntype;
2605 const char *name = NULL;
2606
2607 switch (DECL_FUNCTION_CODE (fndecl))
2608 {
2609 case BUILT_IN_LCEIL:
2610 case BUILT_IN_LLCEIL:
2611 name = "ceil";
2612 break;
2613 case BUILT_IN_LCEILF:
2614 case BUILT_IN_LLCEILF:
2615 name = "ceilf";
2616 break;
2617 case BUILT_IN_LCEILL:
2618 case BUILT_IN_LLCEILL:
2619 name = "ceill";
2620 break;
2621 case BUILT_IN_LFLOOR:
2622 case BUILT_IN_LLFLOOR:
2623 name = "floor";
2624 break;
2625 case BUILT_IN_LFLOORF:
2626 case BUILT_IN_LLFLOORF:
2627 name = "floorf";
2628 break;
2629 case BUILT_IN_LFLOORL:
2630 case BUILT_IN_LLFLOORL:
2631 name = "floorl";
2632 break;
2633 default:
2634 gcc_unreachable ();
2635 }
2636
2637 fntype = build_function_type_list (TREE_TYPE (arg),
2638 TREE_TYPE (arg), NULL_TREE);
2639 fallback_fndecl = build_fn_decl (name, fntype);
2640 }
2641
a65c4d64 2642 exp = build_call_nofold (fallback_fndecl, 1, arg);
ad52b9b7 2643
d4c690af 2644 tmp = expand_normal (exp);
ad52b9b7 2645
2646 /* Truncate the result of floating point optab to integer
2647 via expand_fix (). */
2648 target = gen_reg_rtx (mode);
2649 expand_fix (target, tmp, 0);
2650
2651 return target;
2652}
2653
7d3afc77 2654/* Expand a call to one of the builtin math functions doing integer
2655 conversion (lrint).
2656 Return 0 if a normal call should be emitted rather than expanding the
2657 function in-line. EXP is the expression that is a call to the builtin
ff1b14e4 2658 function; if convenient, the result should be placed in TARGET. */
7d3afc77 2659
2660static rtx
ff1b14e4 2661expand_builtin_int_roundingfn_2 (tree exp, rtx target)
7d3afc77 2662{
5f51ee59 2663 convert_optab builtin_optab;
7d3afc77 2664 rtx op0, insns;
2665 tree fndecl = get_callee_fndecl (exp);
4de0924f 2666 tree arg;
c2f47e15 2667 enum machine_mode mode;
7d3afc77 2668
2669 /* There's no easy way to detect the case we need to set EDOM. */
2670 if (flag_errno_math)
2671 return NULL_RTX;
2672
c2f47e15 2673 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2674 gcc_unreachable ();
2675
2676 arg = CALL_EXPR_ARG (exp, 0);
7d3afc77 2677
2678 switch (DECL_FUNCTION_CODE (fndecl))
2679 {
2680 CASE_FLT_FN (BUILT_IN_LRINT):
2681 CASE_FLT_FN (BUILT_IN_LLRINT):
2682 builtin_optab = lrint_optab; break;
ef2f1a10 2683 CASE_FLT_FN (BUILT_IN_LROUND):
2684 CASE_FLT_FN (BUILT_IN_LLROUND):
2685 builtin_optab = lround_optab; break;
7d3afc77 2686 default:
2687 gcc_unreachable ();
2688 }
2689
2690 /* Make a suitable register to place result in. */
2691 mode = TYPE_MODE (TREE_TYPE (exp));
2692
5f51ee59 2693 target = gen_reg_rtx (mode);
7d3afc77 2694
5f51ee59 2695 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2696 need to expand the argument again. This way, we will not perform
2697 side-effects more the once. */
abfea505 2698 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7d3afc77 2699
ff1b14e4 2700 op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
7d3afc77 2701
5f51ee59 2702 start_sequence ();
7d3afc77 2703
5f51ee59 2704 if (expand_sfix_optab (target, op0, builtin_optab))
2705 {
2706 /* Output the entire sequence. */
2707 insns = get_insns ();
7d3afc77 2708 end_sequence ();
5f51ee59 2709 emit_insn (insns);
2710 return target;
7d3afc77 2711 }
2712
5f51ee59 2713 /* If we were unable to expand via the builtin, stop the sequence
2714 (without outputting the insns) and call to the library function
2715 with the stabilized argument list. */
2716 end_sequence ();
2717
7d3afc77 2718 target = expand_call (exp, target, target == const0_rtx);
2719
2720 return target;
2721}
2722
f1b844c6 2723/* To evaluate powi(x,n), the floating point value x raised to the
2724 constant integer exponent n, we use a hybrid algorithm that
2725 combines the "window method" with look-up tables. For an
2726 introduction to exponentiation algorithms and "addition chains",
2727 see section 4.6.3, "Evaluation of Powers" of Donald E. Knuth,
2728 "Seminumerical Algorithms", Vol. 2, "The Art of Computer Programming",
2729 3rd Edition, 1998, and Daniel M. Gordon, "A Survey of Fast Exponentiation
2730 Methods", Journal of Algorithms, Vol. 27, pp. 129-146, 1998. */
2731
2732/* Provide a default value for POWI_MAX_MULTS, the maximum number of
2733 multiplications to inline before calling the system library's pow
2734 function. powi(x,n) requires at worst 2*bits(n)-2 multiplications,
2735 so this default never requires calling pow, powf or powl. */
0862b7e9 2736
f1b844c6 2737#ifndef POWI_MAX_MULTS
2738#define POWI_MAX_MULTS (2*HOST_BITS_PER_WIDE_INT-2)
2739#endif
2740
2741/* The size of the "optimal power tree" lookup table. All
2742 exponents less than this value are simply looked up in the
2743 powi_table below. This threshold is also used to size the
2744 cache of pseudo registers that hold intermediate results. */
2745#define POWI_TABLE_SIZE 256
2746
2747/* The size, in bits of the window, used in the "window method"
2748 exponentiation algorithm. This is equivalent to a radix of
2749 (1<<POWI_WINDOW_SIZE) in the corresponding "m-ary method". */
2750#define POWI_WINDOW_SIZE 3
2751
2752/* The following table is an efficient representation of an
2753 "optimal power tree". For each value, i, the corresponding
2754 value, j, in the table states than an optimal evaluation
2755 sequence for calculating pow(x,i) can be found by evaluating
2756 pow(x,j)*pow(x,i-j). An optimal power tree for the first
2757 100 integers is given in Knuth's "Seminumerical algorithms". */
2758
2759static const unsigned char powi_table[POWI_TABLE_SIZE] =
2760 {
2761 0, 1, 1, 2, 2, 3, 3, 4, /* 0 - 7 */
2762 4, 6, 5, 6, 6, 10, 7, 9, /* 8 - 15 */
2763 8, 16, 9, 16, 10, 12, 11, 13, /* 16 - 23 */
2764 12, 17, 13, 18, 14, 24, 15, 26, /* 24 - 31 */
2765 16, 17, 17, 19, 18, 33, 19, 26, /* 32 - 39 */
2766 20, 25, 21, 40, 22, 27, 23, 44, /* 40 - 47 */
2767 24, 32, 25, 34, 26, 29, 27, 44, /* 48 - 55 */
2768 28, 31, 29, 34, 30, 60, 31, 36, /* 56 - 63 */
2769 32, 64, 33, 34, 34, 46, 35, 37, /* 64 - 71 */
2770 36, 65, 37, 50, 38, 48, 39, 69, /* 72 - 79 */
2771 40, 49, 41, 43, 42, 51, 43, 58, /* 80 - 87 */
2772 44, 64, 45, 47, 46, 59, 47, 76, /* 88 - 95 */
2773 48, 65, 49, 66, 50, 67, 51, 66, /* 96 - 103 */
2774 52, 70, 53, 74, 54, 104, 55, 74, /* 104 - 111 */
2775 56, 64, 57, 69, 58, 78, 59, 68, /* 112 - 119 */
2776 60, 61, 61, 80, 62, 75, 63, 68, /* 120 - 127 */
2777 64, 65, 65, 128, 66, 129, 67, 90, /* 128 - 135 */
2778 68, 73, 69, 131, 70, 94, 71, 88, /* 136 - 143 */
2779 72, 128, 73, 98, 74, 132, 75, 121, /* 144 - 151 */
2780 76, 102, 77, 124, 78, 132, 79, 106, /* 152 - 159 */
2781 80, 97, 81, 160, 82, 99, 83, 134, /* 160 - 167 */
2782 84, 86, 85, 95, 86, 160, 87, 100, /* 168 - 175 */
2783 88, 113, 89, 98, 90, 107, 91, 122, /* 176 - 183 */
2784 92, 111, 93, 102, 94, 126, 95, 150, /* 184 - 191 */
2785 96, 128, 97, 130, 98, 133, 99, 195, /* 192 - 199 */
2786 100, 128, 101, 123, 102, 164, 103, 138, /* 200 - 207 */
2787 104, 145, 105, 146, 106, 109, 107, 149, /* 208 - 215 */
2788 108, 200, 109, 146, 110, 170, 111, 157, /* 216 - 223 */
2789 112, 128, 113, 130, 114, 182, 115, 132, /* 224 - 231 */
2790 116, 200, 117, 132, 118, 158, 119, 206, /* 232 - 239 */
2791 120, 240, 121, 162, 122, 147, 123, 152, /* 240 - 247 */
2792 124, 166, 125, 214, 126, 138, 127, 153, /* 248 - 255 */
2793 };
2794
2795
2796/* Return the number of multiplications required to calculate
2797 powi(x,n) where n is less than POWI_TABLE_SIZE. This is a
2798 subroutine of powi_cost. CACHE is an array indicating
2799 which exponents have already been calculated. */
2800
2801static int
2802powi_lookup_cost (unsigned HOST_WIDE_INT n, bool *cache)
2803{
2804 /* If we've already calculated this exponent, then this evaluation
2805 doesn't require any additional multiplications. */
2806 if (cache[n])
2807 return 0;
2808
2809 cache[n] = true;
2810 return powi_lookup_cost (n - powi_table[n], cache)
2811 + powi_lookup_cost (powi_table[n], cache) + 1;
2812}
2813
2814/* Return the number of multiplications required to calculate
2815 powi(x,n) for an arbitrary x, given the exponent N. This
2816 function needs to be kept in sync with expand_powi below. */
2817
2818static int
2819powi_cost (HOST_WIDE_INT n)
2820{
2821 bool cache[POWI_TABLE_SIZE];
2822 unsigned HOST_WIDE_INT digit;
2823 unsigned HOST_WIDE_INT val;
2824 int result;
2825
2826 if (n == 0)
2827 return 0;
2828
2829 /* Ignore the reciprocal when calculating the cost. */
2830 val = (n < 0) ? -n : n;
2831
2832 /* Initialize the exponent cache. */
2833 memset (cache, 0, POWI_TABLE_SIZE * sizeof (bool));
2834 cache[1] = true;
2835
2836 result = 0;
2837
2838 while (val >= POWI_TABLE_SIZE)
2839 {
2840 if (val & 1)
2841 {
2842 digit = val & ((1 << POWI_WINDOW_SIZE) - 1);
2843 result += powi_lookup_cost (digit, cache)
2844 + POWI_WINDOW_SIZE + 1;
2845 val >>= POWI_WINDOW_SIZE;
2846 }
2847 else
2848 {
2849 val >>= 1;
2850 result++;
2851 }
2852 }
0862b7e9 2853
6881dbab 2854 return result + powi_lookup_cost (val, cache);
f1b844c6 2855}
2856
2857/* Recursive subroutine of expand_powi. This function takes the array,
2858 CACHE, of already calculated exponents and an exponent N and returns
2859 an RTX that corresponds to CACHE[1]**N, as calculated in mode MODE. */
2860
2861static rtx
2862expand_powi_1 (enum machine_mode mode, unsigned HOST_WIDE_INT n, rtx *cache)
2863{
2864 unsigned HOST_WIDE_INT digit;
2865 rtx target, result;
2866 rtx op0, op1;
2867
2868 if (n < POWI_TABLE_SIZE)
2869 {
2870 if (cache[n])
a0c938f0 2871 return cache[n];
f1b844c6 2872
2873 target = gen_reg_rtx (mode);
2874 cache[n] = target;
2875
2876 op0 = expand_powi_1 (mode, n - powi_table[n], cache);
2877 op1 = expand_powi_1 (mode, powi_table[n], cache);
2878 }
2879 else if (n & 1)
2880 {
2881 target = gen_reg_rtx (mode);
2882 digit = n & ((1 << POWI_WINDOW_SIZE) - 1);
2883 op0 = expand_powi_1 (mode, n - digit, cache);
2884 op1 = expand_powi_1 (mode, digit, cache);
2885 }
2886 else
2887 {
2888 target = gen_reg_rtx (mode);
2889 op0 = expand_powi_1 (mode, n >> 1, cache);
2890 op1 = op0;
2891 }
2892
2893 result = expand_mult (mode, op0, op1, target, 0);
2894 if (result != target)
2895 emit_move_insn (target, result);
2896 return target;
2897}
2898
2899/* Expand the RTL to evaluate powi(x,n) in mode MODE. X is the
2900 floating point operand in mode MODE, and N is the exponent. This
2901 function needs to be kept in sync with powi_cost above. */
0862b7e9 2902
f1b844c6 2903static rtx
2904expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n)
2905{
2906 unsigned HOST_WIDE_INT val;
2907 rtx cache[POWI_TABLE_SIZE];
2908 rtx result;
2909
2910 if (n == 0)
2911 return CONST1_RTX (mode);
2912
2913 val = (n < 0) ? -n : n;
2914
19bf118a 2915 memset (cache, 0, sizeof (cache));
f1b844c6 2916 cache[1] = x;
2917
2918 result = expand_powi_1 (mode, (n < 0) ? -n : n, cache);
2919
2920 /* If the original exponent was negative, reciprocate the result. */
2921 if (n < 0)
2922 result = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2923 result, NULL_RTX, 0, OPTAB_LIB_WIDEN);
2924
2925 return result;
2926}
2927
c2f47e15 2928/* Expand a call to the pow built-in mathematical function. Return NULL_RTX if
f1b844c6 2929 a normal call should be emitted rather than expanding the function
2930 in-line. EXP is the expression that is a call to the builtin
2931 function; if convenient, the result should be placed in TARGET. */
2932
2933static rtx
2934expand_builtin_pow (tree exp, rtx target, rtx subtarget)
2935{
c2f47e15 2936 tree arg0, arg1;
2937 tree fn, narg0;
1c4709b4 2938 tree type = TREE_TYPE (exp);
2939 REAL_VALUE_TYPE cint, c, c2;
2940 HOST_WIDE_INT n;
2941 rtx op, op2;
2942 enum machine_mode mode = TYPE_MODE (type);
f1b844c6 2943
c2f47e15 2944 if (! validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2945 return NULL_RTX;
f1b844c6 2946
c2f47e15 2947 arg0 = CALL_EXPR_ARG (exp, 0);
2948 arg1 = CALL_EXPR_ARG (exp, 1);
f1b844c6 2949
1c4709b4 2950 if (TREE_CODE (arg1) != REAL_CST
f96bd2bf 2951 || TREE_OVERFLOW (arg1))
1c4709b4 2952 return expand_builtin_mathfn_2 (exp, target, subtarget);
2953
2954 /* Handle constant exponents. */
2955
2956 /* For integer valued exponents we can expand to an optimal multiplication
2957 sequence using expand_powi. */
2958 c = TREE_REAL_CST (arg1);
2959 n = real_to_integer (&c);
2960 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
2961 if (real_identical (&c, &cint)
2962 && ((n >= -1 && n <= 2)
2963 || (flag_unsafe_math_optimizations
a0d18cec 2964 && optimize_insn_for_speed_p ()
1c4709b4 2965 && powi_cost (n) <= POWI_MAX_MULTS)))
f1b844c6 2966 {
1db6d067 2967 op = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 2968 if (n != 1)
2969 {
2970 op = force_reg (mode, op);
2971 op = expand_powi (op, mode, n);
2972 }
2973 return op;
2974 }
2975
2976 narg0 = builtin_save_expr (arg0);
f1b844c6 2977
1c4709b4 2978 /* If the exponent is not integer valued, check if it is half of an integer.
2979 In this case we can expand to sqrt (x) * x**(n/2). */
2980 fn = mathfn_built_in (type, BUILT_IN_SQRT);
2981 if (fn != NULL_TREE)
2982 {
2983 real_arithmetic (&c2, MULT_EXPR, &c, &dconst2);
2984 n = real_to_integer (&c2);
f1b844c6 2985 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
1c4709b4 2986 if (real_identical (&c2, &cint)
2987 && ((flag_unsafe_math_optimizations
a0d18cec 2988 && optimize_insn_for_speed_p ()
1c4709b4 2989 && powi_cost (n/2) <= POWI_MAX_MULTS)
2990 || n == 1))
f1b844c6 2991 {
a65c4d64 2992 tree call_expr = build_call_nofold (fn, 1, narg0);
8697cf4d 2993 /* Use expand_expr in case the newly built call expression
2994 was folded to a non-call. */
2995 op = expand_expr (call_expr, subtarget, mode, EXPAND_NORMAL);
1c4709b4 2996 if (n != 1)
8c5cac78 2997 {
1db6d067 2998 op2 = expand_expr (narg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 2999 op2 = force_reg (mode, op2);
3000 op2 = expand_powi (op2, mode, abs (n / 2));
3001 op = expand_simple_binop (mode, MULT, op, op2, NULL_RTX,
3002 0, OPTAB_LIB_WIDEN);
3003 /* If the original exponent was negative, reciprocate the
3004 result. */
3005 if (n < 0)
3006 op = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
3007 op, NULL_RTX, 0, OPTAB_LIB_WIDEN);
8c5cac78 3008 }
1c4709b4 3009 return op;
f1b844c6 3010 }
3011 }
b613c2a6 3012
1c4709b4 3013 /* Try if the exponent is a third of an integer. In this case
5a84ba55 3014 we can expand to x**(n/3) * cbrt(x)**(n%3). As cbrt (x) is
3015 different from pow (x, 1./3.) due to rounding and behavior
3016 with negative x we need to constrain this transformation to
3017 unsafe math and positive x or finite math. */
1c4709b4 3018 fn = mathfn_built_in (type, BUILT_IN_CBRT);
5a84ba55 3019 if (fn != NULL_TREE
3020 && flag_unsafe_math_optimizations
3021 && (tree_expr_nonnegative_p (arg0)
3022 || !HONOR_NANS (mode)))
1c4709b4 3023 {
3fa759a9 3024 REAL_VALUE_TYPE dconst3;
3025 real_from_integer (&dconst3, VOIDmode, 3, 0, 0);
1c4709b4 3026 real_arithmetic (&c2, MULT_EXPR, &c, &dconst3);
3027 real_round (&c2, mode, &c2);
3028 n = real_to_integer (&c2);
3029 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
3030 real_arithmetic (&c2, RDIV_EXPR, &cint, &dconst3);
3031 real_convert (&c2, mode, &c2);
3032 if (real_identical (&c2, &c)
a0d18cec 3033 && ((optimize_insn_for_speed_p ()
1c4709b4 3034 && powi_cost (n/3) <= POWI_MAX_MULTS)
3035 || n == 1))
3036 {
a65c4d64 3037 tree call_expr = build_call_nofold (fn, 1,narg0);
1c4709b4 3038 op = expand_builtin (call_expr, NULL_RTX, subtarget, mode, 0);
3039 if (abs (n) % 3 == 2)
3040 op = expand_simple_binop (mode, MULT, op, op, op,
3041 0, OPTAB_LIB_WIDEN);
3042 if (n != 1)
3043 {
1db6d067 3044 op2 = expand_expr (narg0, subtarget, VOIDmode, EXPAND_NORMAL);
1c4709b4 3045 op2 = force_reg (mode, op2);
3046 op2 = expand_powi (op2, mode, abs (n / 3));
3047 op = expand_simple_binop (mode, MULT, op, op2, NULL_RTX,
3048 0, OPTAB_LIB_WIDEN);
3049 /* If the original exponent was negative, reciprocate the
3050 result. */
3051 if (n < 0)
3052 op = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
3053 op, NULL_RTX, 0, OPTAB_LIB_WIDEN);
3054 }
3055 return op;
3056 }
3057 }
3058
3059 /* Fall back to optab expansion. */
b613c2a6 3060 return expand_builtin_mathfn_2 (exp, target, subtarget);
f1b844c6 3061}
3062
c2f47e15 3063/* Expand a call to the powi built-in mathematical function. Return NULL_RTX if
757c219d 3064 a normal call should be emitted rather than expanding the function
3065 in-line. EXP is the expression that is a call to the builtin
3066 function; if convenient, the result should be placed in TARGET. */
3067
3068static rtx
3069expand_builtin_powi (tree exp, rtx target, rtx subtarget)
3070{
757c219d 3071 tree arg0, arg1;
3072 rtx op0, op1;
3073 enum machine_mode mode;
d0405f40 3074 enum machine_mode mode2;
757c219d 3075
c2f47e15 3076 if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
3077 return NULL_RTX;
757c219d 3078
c2f47e15 3079 arg0 = CALL_EXPR_ARG (exp, 0);
3080 arg1 = CALL_EXPR_ARG (exp, 1);
757c219d 3081 mode = TYPE_MODE (TREE_TYPE (exp));
3082
3083 /* Handle constant power. */
3084
3085 if (TREE_CODE (arg1) == INTEGER_CST
f96bd2bf 3086 && !TREE_OVERFLOW (arg1))
757c219d 3087 {
3088 HOST_WIDE_INT n = TREE_INT_CST_LOW (arg1);
3089
3090 /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
3091 Otherwise, check the number of multiplications required. */
3092 if ((TREE_INT_CST_HIGH (arg1) == 0
3093 || TREE_INT_CST_HIGH (arg1) == -1)
3094 && ((n >= -1 && n <= 2)
a0d18cec 3095 || (optimize_insn_for_speed_p ()
757c219d 3096 && powi_cost (n) <= POWI_MAX_MULTS)))
3097 {
1db6d067 3098 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
757c219d 3099 op0 = force_reg (mode, op0);
3100 return expand_powi (op0, mode, n);
3101 }
3102 }
3103
3104 /* Emit a libcall to libgcc. */
3105
c2f47e15 3106 /* Mode of the 2nd argument must match that of an int. */
d0405f40 3107 mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
3108
757c219d 3109 if (target == NULL_RTX)
3110 target = gen_reg_rtx (mode);
3111
1db6d067 3112 op0 = expand_expr (arg0, subtarget, mode, EXPAND_NORMAL);
757c219d 3113 if (GET_MODE (op0) != mode)
3114 op0 = convert_to_mode (mode, op0, 0);
1db6d067 3115 op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
d0405f40 3116 if (GET_MODE (op1) != mode2)
3117 op1 = convert_to_mode (mode2, op1, 0);
757c219d 3118
f36b9f69 3119 target = emit_library_call_value (optab_libfunc (powi_optab, mode),
2dd6f9ed 3120 target, LCT_CONST, mode, 2,
d0405f40 3121 op0, mode, op1, mode2);
757c219d 3122
3123 return target;
3124}
3125
c2f47e15 3126/* Expand expression EXP which is a call to the strlen builtin. Return
3127 NULL_RTX if we failed the caller should emit a normal call, otherwise
aed0bd19 3128 try to get the result in TARGET, if convenient. */
f7c44134 3129
53800dbe 3130static rtx
c2f47e15 3131expand_builtin_strlen (tree exp, rtx target,
aecda0d6 3132 enum machine_mode target_mode)
53800dbe 3133{
c2f47e15 3134 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
3135 return NULL_RTX;
53800dbe 3136 else
3137 {
911c0150 3138 rtx pat;
c2f47e15 3139 tree len;
3140 tree src = CALL_EXPR_ARG (exp, 0);
911c0150 3141 rtx result, src_reg, char_rtx, before_strlen;
80cd7a5e 3142 enum machine_mode insn_mode = target_mode, char_mode;
ef2c4a29 3143 enum insn_code icode = CODE_FOR_nothing;
6248e345 3144 int align;
3145
3146 /* If the length can be computed at compile-time, return it. */
681fab1e 3147 len = c_strlen (src, 0);
6248e345 3148 if (len)
80cd7a5e 3149 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
6248e345 3150
681fab1e 3151 /* If the length can be computed at compile-time and is constant
3152 integer, but there are side-effects in src, evaluate
3153 src for side-effects, then return len.
3154 E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
3155 can be optimized into: i++; x = 3; */
3156 len = c_strlen (src, 1);
3157 if (len && TREE_CODE (len) == INTEGER_CST)
3158 {
3159 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
3160 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
3161 }
3162
6248e345 3163 align = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
53800dbe 3164
53800dbe 3165 /* If SRC is not a pointer type, don't do this operation inline. */
3166 if (align == 0)
c2f47e15 3167 return NULL_RTX;
53800dbe 3168
911c0150 3169 /* Bail out if we can't compute strlen in the right mode. */
53800dbe 3170 while (insn_mode != VOIDmode)
3171 {
99bdde56 3172 icode = optab_handler (strlen_optab, insn_mode)->insn_code;
53800dbe 3173 if (icode != CODE_FOR_nothing)
c28ae87f 3174 break;
53800dbe 3175
3176 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
3177 }
3178 if (insn_mode == VOIDmode)
c2f47e15 3179 return NULL_RTX;
53800dbe 3180
3181 /* Make a place to write the result of the instruction. */
3182 result = target;
3183 if (! (result != 0
8ad4c111 3184 && REG_P (result)
53800dbe 3185 && GET_MODE (result) == insn_mode
3186 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3187 result = gen_reg_rtx (insn_mode);
3188
911c0150 3189 /* Make a place to hold the source address. We will not expand
3190 the actual source until we are sure that the expansion will
3191 not fail -- there are trees that cannot be expanded twice. */
3192 src_reg = gen_reg_rtx (Pmode);
53800dbe 3193
911c0150 3194 /* Mark the beginning of the strlen sequence so we can emit the
3195 source operand later. */
f0ce3b1f 3196 before_strlen = get_last_insn ();
53800dbe 3197
53800dbe 3198 char_rtx = const0_rtx;
f7c44134 3199 char_mode = insn_data[(int) icode].operand[2].mode;
3200 if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
3201 char_mode))
53800dbe 3202 char_rtx = copy_to_mode_reg (char_mode, char_rtx);
3203
911c0150 3204 pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
3205 char_rtx, GEN_INT (align));
3206 if (! pat)
c2f47e15 3207 return NULL_RTX;
911c0150 3208 emit_insn (pat);
3209
3210 /* Now that we are assured of success, expand the source. */
3211 start_sequence ();
c5aba89c 3212 pat = expand_expr (src, src_reg, ptr_mode, EXPAND_NORMAL);
911c0150 3213 if (pat != src_reg)
3214 emit_move_insn (src_reg, pat);
31d3e01c 3215 pat = get_insns ();
911c0150 3216 end_sequence ();
bceb0d1f 3217
3218 if (before_strlen)
3219 emit_insn_after (pat, before_strlen);
3220 else
3221 emit_insn_before (pat, get_insns ());
53800dbe 3222
3223 /* Return the value in the proper mode for this function. */
80cd7a5e 3224 if (GET_MODE (result) == target_mode)
911c0150 3225 target = result;
53800dbe 3226 else if (target != 0)
911c0150 3227 convert_move (target, result, 0);
53800dbe 3228 else
80cd7a5e 3229 target = convert_to_mode (target_mode, result, 0);
911c0150 3230
3231 return target;
53800dbe 3232 }
3233}
3234
6840589f 3235/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3236 bytes from constant string DATA + OFFSET and return it as target
3237 constant. */
3238
3239static rtx
aecda0d6 3240builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
3241 enum machine_mode mode)
6840589f 3242{
3243 const char *str = (const char *) data;
3244
64db345d 3245 gcc_assert (offset >= 0
3246 && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
3247 <= strlen (str) + 1));
6840589f 3248
3249 return c_readstr (str + offset, mode);
3250}
3251
c2f47e15 3252/* Expand a call EXP to the memcpy builtin.
3253 Return NULL_RTX if we failed, the caller should emit a normal call,
3b824fa6 3254 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3255 mode MODE if that's convenient). */
c2f47e15 3256
53800dbe 3257static rtx
a65c4d64 3258expand_builtin_memcpy (tree exp, rtx target)
53800dbe 3259{
c2f47e15 3260 if (!validate_arglist (exp,
3261 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3262 return NULL_RTX;
53800dbe 3263 else
3264 {
c2f47e15 3265 tree dest = CALL_EXPR_ARG (exp, 0);
3266 tree src = CALL_EXPR_ARG (exp, 1);
3267 tree len = CALL_EXPR_ARG (exp, 2);
6840589f 3268 const char *src_str;
27d0c333 3269 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3270 unsigned int dest_align
3271 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
53800dbe 3272 rtx dest_mem, src_mem, dest_addr, len_rtx;
162719b3 3273 HOST_WIDE_INT expected_size = -1;
3274 unsigned int expected_align = 0;
75a70cf9 3275 tree_ann_common_t ann;
5a0de151 3276
6f428e8b 3277 /* If DEST is not a pointer type, call the normal function. */
3278 if (dest_align == 0)
c2f47e15 3279 return NULL_RTX;
6f428e8b 3280
6f428e8b 3281 /* If either SRC is not a pointer type, don't do this
a0c938f0 3282 operation in-line. */
6f428e8b 3283 if (src_align == 0)
c2f47e15 3284 return NULL_RTX;
162719b3 3285
75a70cf9 3286 ann = tree_common_ann (exp);
3287 if (ann)
3288 stringop_block_profile (ann->stmt, &expected_align, &expected_size);
3289
162719b3 3290 if (expected_align < dest_align)
3291 expected_align = dest_align;
d8ae1baa 3292 dest_mem = get_memory_rtx (dest, len);
2a631e19 3293 set_mem_align (dest_mem, dest_align);
8ec3c5c2 3294 len_rtx = expand_normal (len);
6840589f 3295 src_str = c_getstr (src);
3296
3297 /* If SRC is a string constant and block move would be done
3298 by pieces, we can avoid loading the string from memory
3299 and only stored the computed constants. */
3300 if (src_str
971ba038 3301 && CONST_INT_P (len_rtx)
6840589f 3302 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3303 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3304 CONST_CAST (char *, src_str),
3305 dest_align, false))
6840589f 3306 {
9fe0e1b8 3307 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3308 builtin_memcpy_read_str,
364c0c59 3309 CONST_CAST (char *, src_str),
3310 dest_align, false, 0);
a65c4d64 3311 dest_mem = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3312 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3313 return dest_mem;
6840589f 3314 }
3315
d8ae1baa 3316 src_mem = get_memory_rtx (src, len);
2a631e19 3317 set_mem_align (src_mem, src_align);
53800dbe 3318
53800dbe 3319 /* Copy word part most expediently. */
162719b3 3320 dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
3321 CALL_EXPR_TAILCALL (exp)
3322 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3323 expected_align, expected_size);
53800dbe 3324
3325 if (dest_addr == 0)
e5716f7e 3326 {
a65c4d64 3327 dest_addr = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3328 dest_addr = convert_memory_address (ptr_mode, dest_addr);
e5716f7e 3329 }
9fe0e1b8 3330 return dest_addr;
53800dbe 3331 }
3332}
3333
c2f47e15 3334/* Expand a call EXP to the mempcpy builtin.
3335 Return NULL_RTX if we failed; the caller should emit a normal call,
647661c6 3336 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3337 mode MODE if that's convenient). If ENDP is 0 return the
3338 destination pointer, if ENDP is 1 return the end pointer ala
3339 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3340 stpcpy. */
647661c6 3341
3342static rtx
c8b17b2e 3343expand_builtin_mempcpy (tree exp, rtx target, enum machine_mode mode)
647661c6 3344{
c2f47e15 3345 if (!validate_arglist (exp,
3346 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3347 return NULL_RTX;
3348 else
3349 {
3350 tree dest = CALL_EXPR_ARG (exp, 0);
3351 tree src = CALL_EXPR_ARG (exp, 1);
3352 tree len = CALL_EXPR_ARG (exp, 2);
3353 return expand_builtin_mempcpy_args (dest, src, len,
c2f47e15 3354 target, mode, /*endp=*/ 1);
3355 }
3356}
3357
3358/* Helper function to do the actual work for expand_builtin_mempcpy. The
3359 arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out
3360 so that this can also be called without constructing an actual CALL_EXPR.
a65c4d64 3361 The other arguments and return value are the same as for
3362 expand_builtin_mempcpy. */
c2f47e15 3363
3364static rtx
a65c4d64 3365expand_builtin_mempcpy_args (tree dest, tree src, tree len,
c2f47e15 3366 rtx target, enum machine_mode mode, int endp)
3367{
3368 /* If return value is ignored, transform mempcpy into memcpy. */
c8b17b2e 3369 if (target == const0_rtx && implicit_built_in_decls[BUILT_IN_MEMCPY])
9fe0e1b8 3370 {
3371 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
a65c4d64 3372 tree result = build_call_nofold (fn, 3, dest, src, len);
c8b17b2e 3373 return expand_expr (result, target, mode, EXPAND_NORMAL);
9fe0e1b8 3374 }
647661c6 3375 else
3376 {
9fe0e1b8 3377 const char *src_str;
3378 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3379 unsigned int dest_align
3380 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3381 rtx dest_mem, src_mem, len_rtx;
a0c938f0 3382
7da1412b 3383 /* If either SRC or DEST is not a pointer type, don't do this
a0c938f0 3384 operation in-line. */
7da1412b 3385 if (dest_align == 0 || src_align == 0)
c2f47e15 3386 return NULL_RTX;
9fe0e1b8 3387
6217c238 3388 /* If LEN is not constant, call the normal function. */
3389 if (! host_integerp (len, 1))
c2f47e15 3390 return NULL_RTX;
0862b7e9 3391
8ec3c5c2 3392 len_rtx = expand_normal (len);
9fe0e1b8 3393 src_str = c_getstr (src);
647661c6 3394
9fe0e1b8 3395 /* If SRC is a string constant and block move would be done
3396 by pieces, we can avoid loading the string from memory
3397 and only stored the computed constants. */
3398 if (src_str
971ba038 3399 && CONST_INT_P (len_rtx)
9fe0e1b8 3400 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3401 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3402 CONST_CAST (char *, src_str),
3403 dest_align, false))
9fe0e1b8 3404 {
d8ae1baa 3405 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3406 set_mem_align (dest_mem, dest_align);
3407 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3408 builtin_memcpy_read_str,
364c0c59 3409 CONST_CAST (char *, src_str),
3410 dest_align, false, endp);
9fe0e1b8 3411 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3412 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3413 return dest_mem;
647661c6 3414 }
3415
971ba038 3416 if (CONST_INT_P (len_rtx)
9fe0e1b8 3417 && can_move_by_pieces (INTVAL (len_rtx),
3418 MIN (dest_align, src_align)))
3419 {
d8ae1baa 3420 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3421 set_mem_align (dest_mem, dest_align);
d8ae1baa 3422 src_mem = get_memory_rtx (src, len);
9fe0e1b8 3423 set_mem_align (src_mem, src_align);
3424 dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
3425 MIN (dest_align, src_align), endp);
3426 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3427 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3428 return dest_mem;
3429 }
3430
c2f47e15 3431 return NULL_RTX;
647661c6 3432 }
3433}
3434
727c62dd 3435#ifndef HAVE_movstr
3436# define HAVE_movstr 0
3437# define CODE_FOR_movstr CODE_FOR_nothing
3438#endif
3439
c2f47e15 3440/* Expand into a movstr instruction, if one is available. Return NULL_RTX if
727c62dd 3441 we failed, the caller should emit a normal call, otherwise try to
3442 get the result in TARGET, if convenient. If ENDP is 0 return the
3443 destination pointer, if ENDP is 1 return the end pointer ala
3444 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3445 stpcpy. */
3446
3447static rtx
3448expand_movstr (tree dest, tree src, rtx target, int endp)
3449{
3450 rtx end;
3451 rtx dest_mem;
3452 rtx src_mem;
3453 rtx insn;
3454 const struct insn_data * data;
3455
3456 if (!HAVE_movstr)
c2f47e15 3457 return NULL_RTX;
727c62dd 3458
d8ae1baa 3459 dest_mem = get_memory_rtx (dest, NULL);
3460 src_mem = get_memory_rtx (src, NULL);
727c62dd 3461 if (!endp)
3462 {
3463 target = force_reg (Pmode, XEXP (dest_mem, 0));
3464 dest_mem = replace_equiv_address (dest_mem, target);
3465 end = gen_reg_rtx (Pmode);
3466 }
3467 else
3468 {
3469 if (target == 0 || target == const0_rtx)
3470 {
3471 end = gen_reg_rtx (Pmode);
3472 if (target == 0)
3473 target = end;
3474 }
3475 else
3476 end = target;
3477 }
3478
3479 data = insn_data + CODE_FOR_movstr;
3480
3481 if (data->operand[0].mode != VOIDmode)
3482 end = gen_lowpart (data->operand[0].mode, end);
3483
3484 insn = data->genfun (end, dest_mem, src_mem);
3485
64db345d 3486 gcc_assert (insn);
727c62dd 3487
3488 emit_insn (insn);
3489
3490 /* movstr is supposed to set end to the address of the NUL
3491 terminator. If the caller requested a mempcpy-like return value,
3492 adjust it. */
3493 if (endp == 1 && target != const0_rtx)
c5aba89c 3494 {
3495 rtx tem = plus_constant (gen_lowpart (GET_MODE (target), end), 1);
3496 emit_move_insn (target, force_operand (tem, NULL_RTX));
3497 }
727c62dd 3498
3499 return target;
3500}
3501
c2f47e15 3502/* Expand expression EXP, which is a call to the strcpy builtin. Return
3503 NULL_RTX if we failed the caller should emit a normal call, otherwise
3504 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3505 convenient). */
902de8ed 3506
53800dbe 3507static rtx
a65c4d64 3508expand_builtin_strcpy (tree exp, rtx target)
53800dbe 3509{
c2f47e15 3510 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3511 {
3512 tree dest = CALL_EXPR_ARG (exp, 0);
3513 tree src = CALL_EXPR_ARG (exp, 1);
a65c4d64 3514 return expand_builtin_strcpy_args (dest, src, target);
c2f47e15 3515 }
3516 return NULL_RTX;
3517}
3518
3519/* Helper function to do the actual work for expand_builtin_strcpy. The
3520 arguments to the builtin_strcpy call DEST and SRC are broken out
3521 so that this can also be called without constructing an actual CALL_EXPR.
3522 The other arguments and return value are the same as for
3523 expand_builtin_strcpy. */
3524
3525static rtx
a65c4d64 3526expand_builtin_strcpy_args (tree dest, tree src, rtx target)
c2f47e15 3527{
c2f47e15 3528 return expand_movstr (dest, src, target, /*endp=*/0);
53800dbe 3529}
3530
c2f47e15 3531/* Expand a call EXP to the stpcpy builtin.
3532 Return NULL_RTX if we failed the caller should emit a normal call,
3b824fa6 3533 otherwise try to get the result in TARGET, if convenient (and in
3534 mode MODE if that's convenient). */
3535
3536static rtx
dc369150 3537expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
3b824fa6 3538{
c2f47e15 3539 tree dst, src;
389dd41b 3540 location_t loc = EXPR_LOCATION (exp);
c2f47e15 3541
3542 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3543 return NULL_RTX;
3544
3545 dst = CALL_EXPR_ARG (exp, 0);
3546 src = CALL_EXPR_ARG (exp, 1);
3547
727c62dd 3548 /* If return value is ignored, transform stpcpy into strcpy. */
c8b17b2e 3549 if (target == const0_rtx && implicit_built_in_decls[BUILT_IN_STRCPY])
978836e5 3550 {
3551 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
a65c4d64 3552 tree result = build_call_nofold (fn, 2, dst, src);
c8b17b2e 3553 return expand_expr (result, target, mode, EXPAND_NORMAL);
978836e5 3554 }
3b824fa6 3555 else
3556 {
c2f47e15 3557 tree len, lenp1;
727c62dd 3558 rtx ret;
647661c6 3559
9fe0e1b8 3560 /* Ensure we get an actual string whose length can be evaluated at
a0c938f0 3561 compile-time, not an expression containing a string. This is
3562 because the latter will potentially produce pessimized code
3563 when used to produce the return value. */
681fab1e 3564 if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
c2f47e15 3565 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3566
389dd41b 3567 lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
a65c4d64 3568 ret = expand_builtin_mempcpy_args (dst, src, lenp1,
c2f47e15 3569 target, mode, /*endp=*/2);
727c62dd 3570
3571 if (ret)
3572 return ret;
3573
3574 if (TREE_CODE (len) == INTEGER_CST)
3575 {
8ec3c5c2 3576 rtx len_rtx = expand_normal (len);
727c62dd 3577
971ba038 3578 if (CONST_INT_P (len_rtx))
727c62dd 3579 {
a65c4d64 3580 ret = expand_builtin_strcpy_args (dst, src, target);
727c62dd 3581
3582 if (ret)
3583 {
3584 if (! target)
7ac87324 3585 {
3586 if (mode != VOIDmode)
3587 target = gen_reg_rtx (mode);
3588 else
3589 target = gen_reg_rtx (GET_MODE (ret));
3590 }
727c62dd 3591 if (GET_MODE (target) != GET_MODE (ret))
3592 ret = gen_lowpart (GET_MODE (target), ret);
3593
c5aba89c 3594 ret = plus_constant (ret, INTVAL (len_rtx));
3595 ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
64db345d 3596 gcc_assert (ret);
727c62dd 3597
3598 return target;
3599 }
3600 }
3601 }
3602
c2f47e15 3603 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3604 }
3605}
3606
6840589f 3607/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3608 bytes from constant string DATA + OFFSET and return it as target
3609 constant. */
3610
09879952 3611rtx
aecda0d6 3612builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
3613 enum machine_mode mode)
6840589f 3614{
3615 const char *str = (const char *) data;
3616
3617 if ((unsigned HOST_WIDE_INT) offset > strlen (str))
3618 return const0_rtx;
3619
3620 return c_readstr (str + offset, mode);
3621}
3622
c2f47e15 3623/* Expand expression EXP, which is a call to the strncpy builtin. Return
3624 NULL_RTX if we failed the caller should emit a normal call. */
ed09096d 3625
3626static rtx
a65c4d64 3627expand_builtin_strncpy (tree exp, rtx target)
ed09096d 3628{
389dd41b 3629 location_t loc = EXPR_LOCATION (exp);
c2f47e15 3630
3631 if (validate_arglist (exp,
3632 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
ed09096d 3633 {
c2f47e15 3634 tree dest = CALL_EXPR_ARG (exp, 0);
3635 tree src = CALL_EXPR_ARG (exp, 1);
3636 tree len = CALL_EXPR_ARG (exp, 2);
3637 tree slen = c_strlen (src, 1);
6840589f 3638
8ff6a5cd 3639 /* We must be passed a constant len and src parameter. */
3640 if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
c2f47e15 3641 return NULL_RTX;
ed09096d 3642
389dd41b 3643 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
ed09096d 3644
3645 /* We're required to pad with trailing zeros if the requested
a0c938f0 3646 len is greater than strlen(s2)+1. In that case try to
6840589f 3647 use store_by_pieces, if it fails, punt. */
ed09096d 3648 if (tree_int_cst_lt (slen, len))
6840589f 3649 {
27d0c333 3650 unsigned int dest_align
3651 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
c2f47e15 3652 const char *p = c_getstr (src);
6840589f 3653 rtx dest_mem;
3654
27d0c333 3655 if (!p || dest_align == 0 || !host_integerp (len, 1)
3656 || !can_store_by_pieces (tree_low_cst (len, 1),
6840589f 3657 builtin_strncpy_read_str,
364c0c59 3658 CONST_CAST (char *, p),
3659 dest_align, false))
c2f47e15 3660 return NULL_RTX;
6840589f 3661
d8ae1baa 3662 dest_mem = get_memory_rtx (dest, len);
27d0c333 3663 store_by_pieces (dest_mem, tree_low_cst (len, 1),
6840589f 3664 builtin_strncpy_read_str,
364c0c59 3665 CONST_CAST (char *, p), dest_align, false, 0);
a65c4d64 3666 dest_mem = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3667 dest_mem = convert_memory_address (ptr_mode, dest_mem);
e5716f7e 3668 return dest_mem;
6840589f 3669 }
ed09096d 3670 }
c2f47e15 3671 return NULL_RTX;
ed09096d 3672}
3673
ecc318ff 3674/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3675 bytes from constant string DATA + OFFSET and return it as target
3676 constant. */
3677
f656b751 3678rtx
aecda0d6 3679builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3680 enum machine_mode mode)
ecc318ff 3681{
3682 const char *c = (const char *) data;
364c0c59 3683 char *p = XALLOCAVEC (char, GET_MODE_SIZE (mode));
ecc318ff 3684
3685 memset (p, *c, GET_MODE_SIZE (mode));
3686
3687 return c_readstr (p, mode);
3688}
3689
a7ec6974 3690/* Callback routine for store_by_pieces. Return the RTL of a register
3691 containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
3692 char value given in the RTL register data. For example, if mode is
3693 4 bytes wide, return the RTL for 0x01010101*data. */
3694
3695static rtx
aecda0d6 3696builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3697 enum machine_mode mode)
a7ec6974 3698{
3699 rtx target, coeff;
3700 size_t size;
3701 char *p;
3702
3703 size = GET_MODE_SIZE (mode);
f0ce3b1f 3704 if (size == 1)
3705 return (rtx) data;
a7ec6974 3706
364c0c59 3707 p = XALLOCAVEC (char, size);
a7ec6974 3708 memset (p, 1, size);
3709 coeff = c_readstr (p, mode);
3710
f0ce3b1f 3711 target = convert_to_mode (mode, (rtx) data, 1);
a7ec6974 3712 target = expand_mult (mode, target, coeff, NULL_RTX, 1);
3713 return force_reg (mode, target);
3714}
3715
c2f47e15 3716/* Expand expression EXP, which is a call to the memset builtin. Return
3717 NULL_RTX if we failed the caller should emit a normal call, otherwise
3718 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3719 convenient). */
902de8ed 3720
53800dbe 3721static rtx
c2f47e15 3722expand_builtin_memset (tree exp, rtx target, enum machine_mode mode)
53800dbe 3723{
c2f47e15 3724 if (!validate_arglist (exp,
3725 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
3726 return NULL_RTX;
53800dbe 3727 else
3728 {
c2f47e15 3729 tree dest = CALL_EXPR_ARG (exp, 0);
3730 tree val = CALL_EXPR_ARG (exp, 1);
3731 tree len = CALL_EXPR_ARG (exp, 2);
3732 return expand_builtin_memset_args (dest, val, len, target, mode, exp);
3733 }
3734}
53800dbe 3735
c2f47e15 3736/* Helper function to do the actual work for expand_builtin_memset. The
3737 arguments to the builtin_memset call DEST, VAL, and LEN are broken out
3738 so that this can also be called without constructing an actual CALL_EXPR.
3739 The other arguments and return value are the same as for
3740 expand_builtin_memset. */
6b961939 3741
c2f47e15 3742static rtx
3743expand_builtin_memset_args (tree dest, tree val, tree len,
3744 rtx target, enum machine_mode mode, tree orig_exp)
3745{
3746 tree fndecl, fn;
3747 enum built_in_function fcode;
3748 char c;
3749 unsigned int dest_align;
3750 rtx dest_mem, dest_addr, len_rtx;
3751 HOST_WIDE_INT expected_size = -1;
3752 unsigned int expected_align = 0;
75a70cf9 3753 tree_ann_common_t ann;
53800dbe 3754
c2f47e15 3755 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
162719b3 3756
c2f47e15 3757 /* If DEST is not a pointer type, don't do this operation in-line. */
3758 if (dest_align == 0)
3759 return NULL_RTX;
6f428e8b 3760
75a70cf9 3761 ann = tree_common_ann (orig_exp);
3762 if (ann)
3763 stringop_block_profile (ann->stmt, &expected_align, &expected_size);
3764
c2f47e15 3765 if (expected_align < dest_align)
3766 expected_align = dest_align;
6b961939 3767
c2f47e15 3768 /* If the LEN parameter is zero, return DEST. */
3769 if (integer_zerop (len))
3770 {
3771 /* Evaluate and ignore VAL in case it has side-effects. */
3772 expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
3773 return expand_expr (dest, target, mode, EXPAND_NORMAL);
3774 }
7a3e5564 3775
c2f47e15 3776 /* Stabilize the arguments in case we fail. */
3777 dest = builtin_save_expr (dest);
3778 val = builtin_save_expr (val);
3779 len = builtin_save_expr (len);
a7ec6974 3780
c2f47e15 3781 len_rtx = expand_normal (len);
3782 dest_mem = get_memory_rtx (dest, len);
a7ec6974 3783
c2f47e15 3784 if (TREE_CODE (val) != INTEGER_CST)
3785 {
3786 rtx val_rtx;
a7ec6974 3787
c2f47e15 3788 val_rtx = expand_normal (val);
3789 val_rtx = convert_to_mode (TYPE_MODE (unsigned_char_type_node),
3790 val_rtx, 0);
53800dbe 3791
c2f47e15 3792 /* Assume that we can memset by pieces if we can store
3793 * the coefficients by pieces (in the required modes).
3794 * We can't pass builtin_memset_gen_str as that emits RTL. */
3795 c = 1;
3796 if (host_integerp (len, 1)
c2f47e15 3797 && can_store_by_pieces (tree_low_cst (len, 1),
4b297e2e 3798 builtin_memset_read_str, &c, dest_align,
3799 true))
c2f47e15 3800 {
3801 val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
3802 val_rtx);
3803 store_by_pieces (dest_mem, tree_low_cst (len, 1),
4b297e2e 3804 builtin_memset_gen_str, val_rtx, dest_align,
3805 true, 0);
c2f47e15 3806 }
3807 else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
3808 dest_align, expected_align,
3809 expected_size))
6b961939 3810 goto do_libcall;
c2f47e15 3811
3812 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3813 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3814 return dest_mem;
3815 }
53800dbe 3816
c2f47e15 3817 if (target_char_cast (val, &c))
3818 goto do_libcall;
ecc318ff 3819
c2f47e15 3820 if (c)
3821 {
3822 if (host_integerp (len, 1)
c2f47e15 3823 && can_store_by_pieces (tree_low_cst (len, 1),
4b297e2e 3824 builtin_memset_read_str, &c, dest_align,
3825 true))
c2f47e15 3826 store_by_pieces (dest_mem, tree_low_cst (len, 1),
4b297e2e 3827 builtin_memset_read_str, &c, dest_align, true, 0);
c2f47e15 3828 else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
3829 dest_align, expected_align,
3830 expected_size))
3831 goto do_libcall;
3832
3833 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3834 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3835 return dest_mem;
3836 }
ecc318ff 3837
c2f47e15 3838 set_mem_align (dest_mem, dest_align);
3839 dest_addr = clear_storage_hints (dest_mem, len_rtx,
3840 CALL_EXPR_TAILCALL (orig_exp)
3841 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3842 expected_align, expected_size);
53800dbe 3843
c2f47e15 3844 if (dest_addr == 0)
3845 {
3846 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3847 dest_addr = convert_memory_address (ptr_mode, dest_addr);
3848 }
53800dbe 3849
c2f47e15 3850 return dest_addr;
6b961939 3851
c2f47e15 3852 do_libcall:
3853 fndecl = get_callee_fndecl (orig_exp);
3854 fcode = DECL_FUNCTION_CODE (fndecl);
3855 if (fcode == BUILT_IN_MEMSET)
a65c4d64 3856 fn = build_call_nofold (fndecl, 3, dest, val, len);
c2f47e15 3857 else if (fcode == BUILT_IN_BZERO)
a65c4d64 3858 fn = build_call_nofold (fndecl, 2, dest, len);
c2f47e15 3859 else
3860 gcc_unreachable ();
a65c4d64 3861 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
3862 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
c2f47e15 3863 return expand_call (fn, target, target == const0_rtx);
53800dbe 3864}
3865
c2f47e15 3866/* Expand expression EXP, which is a call to the bzero builtin. Return
3867 NULL_RTX if we failed the caller should emit a normal call. */
27d0c333 3868
ffc83088 3869static rtx
0b25db21 3870expand_builtin_bzero (tree exp)
ffc83088 3871{
c2f47e15 3872 tree dest, size;
389dd41b 3873 location_t loc = EXPR_LOCATION (exp);
ffc83088 3874
c2f47e15 3875 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
7369e7ba 3876 return NULL_RTX;
ffc83088 3877
c2f47e15 3878 dest = CALL_EXPR_ARG (exp, 0);
3879 size = CALL_EXPR_ARG (exp, 1);
bf8e3599 3880
7369e7ba 3881 /* New argument list transforming bzero(ptr x, int y) to
6f428e8b 3882 memset(ptr x, int 0, size_t y). This is done this way
3883 so that if it isn't expanded inline, we fallback to
3884 calling bzero instead of memset. */
bf8e3599 3885
c2f47e15 3886 return expand_builtin_memset_args (dest, integer_zero_node,
389dd41b 3887 fold_convert_loc (loc, sizetype, size),
c2f47e15 3888 const0_rtx, VOIDmode, exp);
ffc83088 3889}
3890
7a3f89b5 3891/* Expand expression EXP, which is a call to the memcmp built-in function.
c2f47e15 3892 Return NULL_RTX if we failed and the
53800dbe 3893 caller should emit a normal call, otherwise try to get the result in
6f428e8b 3894 TARGET, if convenient (and in mode MODE, if that's convenient). */
27d0c333 3895
53800dbe 3896static rtx
a65c4d64 3897expand_builtin_memcmp (tree exp, ATTRIBUTE_UNUSED rtx target,
3898 ATTRIBUTE_UNUSED enum machine_mode mode)
53800dbe 3899{
a65c4d64 3900 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
389dd41b 3901
c2f47e15 3902 if (!validate_arglist (exp,
3903 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3904 return NULL_RTX;
6f428e8b 3905
6ac5504b 3906#if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi
53800dbe 3907 {
0cd832f0 3908 rtx arg1_rtx, arg2_rtx, arg3_rtx;
53800dbe 3909 rtx result;
0cd832f0 3910 rtx insn;
c2f47e15 3911 tree arg1 = CALL_EXPR_ARG (exp, 0);
3912 tree arg2 = CALL_EXPR_ARG (exp, 1);
3913 tree len = CALL_EXPR_ARG (exp, 2);
53800dbe 3914
3915 int arg1_align
3916 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3917 int arg2_align
3918 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
b428c0a5 3919 enum machine_mode insn_mode;
3920
3921#ifdef HAVE_cmpmemsi
3922 if (HAVE_cmpmemsi)
3923 insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
3924 else
3925#endif
6ac5504b 3926#ifdef HAVE_cmpstrnsi
3927 if (HAVE_cmpstrnsi)
3928 insn_mode = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
b428c0a5 3929 else
3930#endif
c2f47e15 3931 return NULL_RTX;
53800dbe 3932
3933 /* If we don't have POINTER_TYPE, call the function. */
3934 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 3935 return NULL_RTX;
53800dbe 3936
3937 /* Make a place to write the result of the instruction. */
3938 result = target;
3939 if (! (result != 0
8ad4c111 3940 && REG_P (result) && GET_MODE (result) == insn_mode
53800dbe 3941 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3942 result = gen_reg_rtx (insn_mode);
3943
d8ae1baa 3944 arg1_rtx = get_memory_rtx (arg1, len);
3945 arg2_rtx = get_memory_rtx (arg2, len);
389dd41b 3946 arg3_rtx = expand_normal (fold_convert_loc (loc, sizetype, len));
83f88f8e 3947
3948 /* Set MEM_SIZE as appropriate. */
971ba038 3949 if (CONST_INT_P (arg3_rtx))
83f88f8e 3950 {
3951 set_mem_size (arg1_rtx, arg3_rtx);
3952 set_mem_size (arg2_rtx, arg3_rtx);
3953 }
3954
b428c0a5 3955#ifdef HAVE_cmpmemsi
3956 if (HAVE_cmpmemsi)
3957 insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3958 GEN_INT (MIN (arg1_align, arg2_align)));
0cd832f0 3959 else
b428c0a5 3960#endif
6ac5504b 3961#ifdef HAVE_cmpstrnsi
3962 if (HAVE_cmpstrnsi)
3963 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3964 GEN_INT (MIN (arg1_align, arg2_align)));
b428c0a5 3965 else
3966#endif
64db345d 3967 gcc_unreachable ();
0cd832f0 3968
3969 if (insn)
3970 emit_insn (insn);
3971 else
2dd6f9ed 3972 emit_library_call_value (memcmp_libfunc, result, LCT_PURE,
0cd832f0 3973 TYPE_MODE (integer_type_node), 3,
3974 XEXP (arg1_rtx, 0), Pmode,
3975 XEXP (arg2_rtx, 0), Pmode,
3976 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
78a8ed03 3977 TYPE_UNSIGNED (sizetype)),
0cd832f0 3978 TYPE_MODE (sizetype));
53800dbe 3979
3980 /* Return the value in the proper mode for this function. */
3981 mode = TYPE_MODE (TREE_TYPE (exp));
3982 if (GET_MODE (result) == mode)
3983 return result;
3984 else if (target != 0)
3985 {
3986 convert_move (target, result, 0);
3987 return target;
3988 }
3989 else
3990 return convert_to_mode (mode, result, 0);
3991 }
83d79705 3992#endif
53800dbe 3993
c2f47e15 3994 return NULL_RTX;
6f428e8b 3995}
3996
c2f47e15 3997/* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX
53800dbe 3998 if we failed the caller should emit a normal call, otherwise try to get
3999 the result in TARGET, if convenient. */
902de8ed 4000
53800dbe 4001static rtx
a65c4d64 4002expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
53800dbe 4003{
c2f47e15 4004 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4005 return NULL_RTX;
bf8e3599 4006
6ac5504b 4007#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
4008 if (cmpstr_optab[SImode] != CODE_FOR_nothing
4009 || cmpstrn_optab[SImode] != CODE_FOR_nothing)
4010 {
4011 rtx arg1_rtx, arg2_rtx;
4012 rtx result, insn = NULL_RTX;
4013 tree fndecl, fn;
c2f47e15 4014 tree arg1 = CALL_EXPR_ARG (exp, 0);
4015 tree arg2 = CALL_EXPR_ARG (exp, 1);
a0c938f0 4016
6ac5504b 4017 int arg1_align
4018 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4019 int arg2_align
4020 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4021
4022 /* If we don't have POINTER_TYPE, call the function. */
4023 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4024 return NULL_RTX;
7a3f89b5 4025
6ac5504b 4026 /* Stabilize the arguments in case gen_cmpstr(n)si fail. */
4027 arg1 = builtin_save_expr (arg1);
4028 arg2 = builtin_save_expr (arg2);
7a3f89b5 4029
d8ae1baa 4030 arg1_rtx = get_memory_rtx (arg1, NULL);
4031 arg2_rtx = get_memory_rtx (arg2, NULL);
53800dbe 4032
6ac5504b 4033#ifdef HAVE_cmpstrsi
4034 /* Try to call cmpstrsi. */
4035 if (HAVE_cmpstrsi)
4036 {
a0c938f0 4037 enum machine_mode insn_mode
6ac5504b 4038 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
4039
4040 /* Make a place to write the result of the instruction. */
4041 result = target;
4042 if (! (result != 0
4043 && REG_P (result) && GET_MODE (result) == insn_mode
4044 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4045 result = gen_reg_rtx (insn_mode);
4046
4047 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
4048 GEN_INT (MIN (arg1_align, arg2_align)));
4049 }
4050#endif
03fd9d2c 4051#ifdef HAVE_cmpstrnsi
6ac5504b 4052 /* Try to determine at least one length and call cmpstrnsi. */
a0c938f0 4053 if (!insn && HAVE_cmpstrnsi)
6ac5504b 4054 {
4055 tree len;
4056 rtx arg3_rtx;
4057
a0c938f0 4058 enum machine_mode insn_mode
6ac5504b 4059 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
4060 tree len1 = c_strlen (arg1, 1);
4061 tree len2 = c_strlen (arg2, 1);
4062
4063 if (len1)
4064 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
4065 if (len2)
4066 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
4067
4068 /* If we don't have a constant length for the first, use the length
4069 of the second, if we know it. We don't require a constant for
4070 this case; some cost analysis could be done if both are available
4071 but neither is constant. For now, assume they're equally cheap,
4072 unless one has side effects. If both strings have constant lengths,
4073 use the smaller. */
4074
4075 if (!len1)
4076 len = len2;
4077 else if (!len2)
4078 len = len1;
4079 else if (TREE_SIDE_EFFECTS (len1))
4080 len = len2;
4081 else if (TREE_SIDE_EFFECTS (len2))
4082 len = len1;
4083 else if (TREE_CODE (len1) != INTEGER_CST)
4084 len = len2;
4085 else if (TREE_CODE (len2) != INTEGER_CST)
4086 len = len1;
4087 else if (tree_int_cst_lt (len1, len2))
4088 len = len1;
4089 else
4090 len = len2;
4091
4092 /* If both arguments have side effects, we cannot optimize. */
4093 if (!len || TREE_SIDE_EFFECTS (len))
6b961939 4094 goto do_libcall;
53800dbe 4095
8ec3c5c2 4096 arg3_rtx = expand_normal (len);
902de8ed 4097
6ac5504b 4098 /* Make a place to write the result of the instruction. */
4099 result = target;
4100 if (! (result != 0
4101 && REG_P (result) && GET_MODE (result) == insn_mode
4102 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4103 result = gen_reg_rtx (insn_mode);
53800dbe 4104
6ac5504b 4105 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4106 GEN_INT (MIN (arg1_align, arg2_align)));
4107 }
4108#endif
3f8aefe2 4109
6ac5504b 4110 if (insn)
4111 {
a65c4d64 4112 enum machine_mode mode;
6ac5504b 4113 emit_insn (insn);
3f8aefe2 4114
6ac5504b 4115 /* Return the value in the proper mode for this function. */
4116 mode = TYPE_MODE (TREE_TYPE (exp));
4117 if (GET_MODE (result) == mode)
4118 return result;
4119 if (target == 0)
4120 return convert_to_mode (mode, result, 0);
4121 convert_move (target, result, 0);
4122 return target;
4123 }
902de8ed 4124
6ac5504b 4125 /* Expand the library call ourselves using a stabilized argument
4126 list to avoid re-evaluating the function's arguments twice. */
2694880e 4127#ifdef HAVE_cmpstrnsi
6b961939 4128 do_libcall:
2694880e 4129#endif
6ac5504b 4130 fndecl = get_callee_fndecl (exp);
a65c4d64 4131 fn = build_call_nofold (fndecl, 2, arg1, arg2);
4132 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
4133 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
6ac5504b 4134 return expand_call (fn, target, target == const0_rtx);
4135 }
7a3f89b5 4136#endif
c2f47e15 4137 return NULL_RTX;
83d79705 4138}
53800dbe 4139
c2f47e15 4140/* Expand expression EXP, which is a call to the strncmp builtin. Return
4141 NULL_RTX if we failed the caller should emit a normal call, otherwise try to get
ed09096d 4142 the result in TARGET, if convenient. */
27d0c333 4143
ed09096d 4144static rtx
a65c4d64 4145expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
4146 ATTRIBUTE_UNUSED enum machine_mode mode)
ed09096d 4147{
a65c4d64 4148 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
389dd41b 4149
c2f47e15 4150 if (!validate_arglist (exp,
4151 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4152 return NULL_RTX;
ed09096d 4153
6e34e617 4154 /* If c_strlen can determine an expression for one of the string
6ac5504b 4155 lengths, and it doesn't have side effects, then emit cmpstrnsi
7a3f89b5 4156 using length MIN(strlen(string)+1, arg3). */
6ac5504b 4157#ifdef HAVE_cmpstrnsi
4158 if (HAVE_cmpstrnsi)
7a3f89b5 4159 {
4160 tree len, len1, len2;
4161 rtx arg1_rtx, arg2_rtx, arg3_rtx;
4162 rtx result, insn;
0b25db21 4163 tree fndecl, fn;
c2f47e15 4164 tree arg1 = CALL_EXPR_ARG (exp, 0);
4165 tree arg2 = CALL_EXPR_ARG (exp, 1);
4166 tree arg3 = CALL_EXPR_ARG (exp, 2);
6f428e8b 4167
7a3f89b5 4168 int arg1_align
4169 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4170 int arg2_align
4171 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
4172 enum machine_mode insn_mode
6ac5504b 4173 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
bf8e3599 4174
681fab1e 4175 len1 = c_strlen (arg1, 1);
4176 len2 = c_strlen (arg2, 1);
7a3f89b5 4177
4178 if (len1)
389dd41b 4179 len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1);
7a3f89b5 4180 if (len2)
389dd41b 4181 len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2);
7a3f89b5 4182
4183 /* If we don't have a constant length for the first, use the length
4184 of the second, if we know it. We don't require a constant for
4185 this case; some cost analysis could be done if both are available
4186 but neither is constant. For now, assume they're equally cheap,
4187 unless one has side effects. If both strings have constant lengths,
4188 use the smaller. */
4189
4190 if (!len1)
4191 len = len2;
4192 else if (!len2)
4193 len = len1;
4194 else if (TREE_SIDE_EFFECTS (len1))
4195 len = len2;
4196 else if (TREE_SIDE_EFFECTS (len2))
4197 len = len1;
4198 else if (TREE_CODE (len1) != INTEGER_CST)
4199 len = len2;
4200 else if (TREE_CODE (len2) != INTEGER_CST)
4201 len = len1;
4202 else if (tree_int_cst_lt (len1, len2))
4203 len = len1;
4204 else
4205 len = len2;
6e34e617 4206
7a3f89b5 4207 /* If both arguments have side effects, we cannot optimize. */
4208 if (!len || TREE_SIDE_EFFECTS (len))
c2f47e15 4209 return NULL_RTX;
bf8e3599 4210
7a3f89b5 4211 /* The actual new length parameter is MIN(len,arg3). */
389dd41b 4212 len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len,
4213 fold_convert_loc (loc, TREE_TYPE (len), arg3));
7a3f89b5 4214
4215 /* If we don't have POINTER_TYPE, call the function. */
4216 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4217 return NULL_RTX;
7a3f89b5 4218
4219 /* Make a place to write the result of the instruction. */
4220 result = target;
4221 if (! (result != 0
8ad4c111 4222 && REG_P (result) && GET_MODE (result) == insn_mode
7a3f89b5 4223 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4224 result = gen_reg_rtx (insn_mode);
4225
a65c4d64 4226 /* Stabilize the arguments in case gen_cmpstrnsi fails. */
4227 arg1 = builtin_save_expr (arg1);
4228 arg2 = builtin_save_expr (arg2);
4229 len = builtin_save_expr (len);
27d0c333 4230
a65c4d64 4231 arg1_rtx = get_memory_rtx (arg1, len);
4232 arg2_rtx = get_memory_rtx (arg2, len);
4233 arg3_rtx = expand_normal (len);
4234 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4235 GEN_INT (MIN (arg1_align, arg2_align)));
4236 if (insn)
4237 {
4238 emit_insn (insn);
49f0327b 4239
a65c4d64 4240 /* Return the value in the proper mode for this function. */
4241 mode = TYPE_MODE (TREE_TYPE (exp));
4242 if (GET_MODE (result) == mode)
4243 return result;
4244 if (target == 0)
4245 return convert_to_mode (mode, result, 0);
4246 convert_move (target, result, 0);
4247 return target;
4248 }
27d0c333 4249
a65c4d64 4250 /* Expand the library call ourselves using a stabilized argument
4251 list to avoid re-evaluating the function's arguments twice. */
4252 fndecl = get_callee_fndecl (exp);
4253 fn = build_call_nofold (fndecl, 3, arg1, arg2, len);
4254 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
4255 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4256 return expand_call (fn, target, target == const0_rtx);
4257 }
4258#endif
c2f47e15 4259 return NULL_RTX;
49f0327b 4260}
4261
a66c9326 4262/* Expand a call to __builtin_saveregs, generating the result in TARGET,
4263 if that's convenient. */
902de8ed 4264
a66c9326 4265rtx
aecda0d6 4266expand_builtin_saveregs (void)
53800dbe 4267{
a66c9326 4268 rtx val, seq;
53800dbe 4269
4270 /* Don't do __builtin_saveregs more than once in a function.
4271 Save the result of the first call and reuse it. */
4272 if (saveregs_value != 0)
4273 return saveregs_value;
53800dbe 4274
a66c9326 4275 /* When this function is called, it means that registers must be
4276 saved on entry to this function. So we migrate the call to the
4277 first insn of this function. */
4278
4279 start_sequence ();
53800dbe 4280
a66c9326 4281 /* Do whatever the machine needs done in this case. */
45550790 4282 val = targetm.calls.expand_builtin_saveregs ();
53800dbe 4283
a66c9326 4284 seq = get_insns ();
4285 end_sequence ();
53800dbe 4286
a66c9326 4287 saveregs_value = val;
53800dbe 4288
31d3e01c 4289 /* Put the insns after the NOTE that starts the function. If this
4290 is inside a start_sequence, make the outer-level insn chain current, so
a66c9326 4291 the code is placed at the start of the function. */
4292 push_topmost_sequence ();
0ec80471 4293 emit_insn_after (seq, entry_of_function ());
a66c9326 4294 pop_topmost_sequence ();
4295
4296 return val;
53800dbe 4297}
4298
4299/* __builtin_args_info (N) returns word N of the arg space info
4300 for the current function. The number and meanings of words
4301 is controlled by the definition of CUMULATIVE_ARGS. */
f7c44134 4302
53800dbe 4303static rtx
c2f47e15 4304expand_builtin_args_info (tree exp)
53800dbe 4305{
53800dbe 4306 int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
abe32cce 4307 int *word_ptr = (int *) &crtl->args.info;
53800dbe 4308
64db345d 4309 gcc_assert (sizeof (CUMULATIVE_ARGS) % sizeof (int) == 0);
53800dbe 4310
c2f47e15 4311 if (call_expr_nargs (exp) != 0)
53800dbe 4312 {
c2f47e15 4313 if (!host_integerp (CALL_EXPR_ARG (exp, 0), 0))
eb586f2c 4314 error ("argument of %<__builtin_args_info%> must be constant");
53800dbe 4315 else
4316 {
c2f47e15 4317 HOST_WIDE_INT wordnum = tree_low_cst (CALL_EXPR_ARG (exp, 0), 0);
53800dbe 4318
27d0c333 4319 if (wordnum < 0 || wordnum >= nwords)
eb586f2c 4320 error ("argument of %<__builtin_args_info%> out of range");
53800dbe 4321 else
4322 return GEN_INT (word_ptr[wordnum]);
4323 }
4324 }
4325 else
eb586f2c 4326 error ("missing argument in %<__builtin_args_info%>");
53800dbe 4327
4328 return const0_rtx;
53800dbe 4329}
4330
79012a9d 4331/* Expand a call to __builtin_next_arg. */
27d0c333 4332
53800dbe 4333static rtx
79012a9d 4334expand_builtin_next_arg (void)
53800dbe 4335{
79012a9d 4336 /* Checking arguments is already done in fold_builtin_next_arg
4337 that must be called before this function. */
940ddc5c 4338 return expand_binop (ptr_mode, add_optab,
abe32cce 4339 crtl->args.internal_arg_pointer,
4340 crtl->args.arg_offset_rtx,
53800dbe 4341 NULL_RTX, 0, OPTAB_LIB_WIDEN);
4342}
4343
a66c9326 4344/* Make it easier for the backends by protecting the valist argument
4345 from multiple evaluations. */
4346
4347static tree
389dd41b 4348stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
a66c9326 4349{
5f57a8b1 4350 tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
4351
4352 gcc_assert (vatype != NULL_TREE);
4353
4354 if (TREE_CODE (vatype) == ARRAY_TYPE)
a66c9326 4355 {
2d47cc32 4356 if (TREE_SIDE_EFFECTS (valist))
4357 valist = save_expr (valist);
11a61dea 4358
2d47cc32 4359 /* For this case, the backends will be expecting a pointer to
5f57a8b1 4360 vatype, but it's possible we've actually been given an array
4361 (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)).
2d47cc32 4362 So fix it. */
4363 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
8a15c04a 4364 {
5f57a8b1 4365 tree p1 = build_pointer_type (TREE_TYPE (vatype));
389dd41b 4366 valist = build_fold_addr_expr_with_type_loc (loc, valist, p1);
8a15c04a 4367 }
a66c9326 4368 }
11a61dea 4369 else
a66c9326 4370 {
2d47cc32 4371 tree pt;
11a61dea 4372
2d47cc32 4373 if (! needs_lvalue)
4374 {
11a61dea 4375 if (! TREE_SIDE_EFFECTS (valist))
4376 return valist;
bf8e3599 4377
5f57a8b1 4378 pt = build_pointer_type (vatype);
389dd41b 4379 valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist);
a66c9326 4380 TREE_SIDE_EFFECTS (valist) = 1;
a66c9326 4381 }
2d47cc32 4382
11a61dea 4383 if (TREE_SIDE_EFFECTS (valist))
2d47cc32 4384 valist = save_expr (valist);
389dd41b 4385 valist = build_fold_indirect_ref_loc (loc, valist);
a66c9326 4386 }
4387
4388 return valist;
4389}
4390
2e15d750 4391/* The "standard" definition of va_list is void*. */
4392
4393tree
4394std_build_builtin_va_list (void)
4395{
4396 return ptr_type_node;
4397}
4398
5f57a8b1 4399/* The "standard" abi va_list is va_list_type_node. */
4400
4401tree
4402std_fn_abi_va_list (tree fndecl ATTRIBUTE_UNUSED)
4403{
4404 return va_list_type_node;
4405}
4406
4407/* The "standard" type of va_list is va_list_type_node. */
4408
4409tree
4410std_canonical_va_list_type (tree type)
4411{
4412 tree wtype, htype;
4413
4414 if (INDIRECT_REF_P (type))
4415 type = TREE_TYPE (type);
4416 else if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE(type)))
4417 type = TREE_TYPE (type);
5f57a8b1 4418 wtype = va_list_type_node;
4419 htype = type;
7b36f9ab 4420 /* Treat structure va_list types. */
4421 if (TREE_CODE (wtype) == RECORD_TYPE && POINTER_TYPE_P (htype))
4422 htype = TREE_TYPE (htype);
4423 else if (TREE_CODE (wtype) == ARRAY_TYPE)
5f57a8b1 4424 {
4425 /* If va_list is an array type, the argument may have decayed
4426 to a pointer type, e.g. by being passed to another function.
4427 In that case, unwrap both types so that we can compare the
4428 underlying records. */
4429 if (TREE_CODE (htype) == ARRAY_TYPE
4430 || POINTER_TYPE_P (htype))
4431 {
4432 wtype = TREE_TYPE (wtype);
4433 htype = TREE_TYPE (htype);
4434 }
4435 }
4436 if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype))
4437 return va_list_type_node;
4438
4439 return NULL_TREE;
4440}
4441
a66c9326 4442/* The "standard" implementation of va_start: just assign `nextarg' to
4443 the variable. */
27d0c333 4444
a66c9326 4445void
aecda0d6 4446std_expand_builtin_va_start (tree valist, rtx nextarg)
a66c9326 4447{
f03c17bc 4448 rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
4449 convert_move (va_r, nextarg, 0);
a66c9326 4450}
4451
c2f47e15 4452/* Expand EXP, a call to __builtin_va_start. */
27d0c333 4453
a66c9326 4454static rtx
c2f47e15 4455expand_builtin_va_start (tree exp)
a66c9326 4456{
4457 rtx nextarg;
c2f47e15 4458 tree valist;
389dd41b 4459 location_t loc = EXPR_LOCATION (exp);
a66c9326 4460
c2f47e15 4461 if (call_expr_nargs (exp) < 2)
cb166087 4462 {
389dd41b 4463 error_at (loc, "too few arguments to function %<va_start%>");
cb166087 4464 return const0_rtx;
4465 }
a66c9326 4466
c2f47e15 4467 if (fold_builtin_next_arg (exp, true))
79012a9d 4468 return const0_rtx;
7c2f0500 4469
79012a9d 4470 nextarg = expand_builtin_next_arg ();
389dd41b 4471 valist = stabilize_va_list_loc (loc, CALL_EXPR_ARG (exp, 0), 1);
a66c9326 4472
8a58ed0a 4473 if (targetm.expand_builtin_va_start)
4474 targetm.expand_builtin_va_start (valist, nextarg);
4475 else
4476 std_expand_builtin_va_start (valist, nextarg);
a66c9326 4477
4478 return const0_rtx;
4479}
4480
a66c9326 4481/* The "standard" implementation of va_arg: read the value from the
4482 current (padded) address and increment by the (padded) size. */
f7c44134 4483
e0eca1fa 4484tree
75a70cf9 4485std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
4486 gimple_seq *post_p)
fcdd3ab3 4487{
52cc2eeb 4488 tree addr, t, type_size, rounded_size, valist_tmp;
b8e8e485 4489 unsigned HOST_WIDE_INT align, boundary;
bef380a4 4490 bool indirect;
52cc2eeb 4491
4492#ifdef ARGS_GROW_DOWNWARD
4493 /* All of the alignment and movement below is for args-grow-up machines.
4494 As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
4495 implement their own specialized gimplify_va_arg_expr routines. */
64db345d 4496 gcc_unreachable ();
52cc2eeb 4497#endif
fcdd3ab3 4498
bef380a4 4499 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
4500 if (indirect)
4501 type = build_pointer_type (type);
4502
52cc2eeb 4503 align = PARM_BOUNDARY / BITS_PER_UNIT;
c8b779eb 4504 boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type);
4505
4506 /* When we align parameter on stack for caller, if the parameter
befa808c 4507 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
4508 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
c8b779eb 4509 here with caller. */
befa808c 4510 if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
4511 boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
c8b779eb 4512
4513 boundary /= BITS_PER_UNIT;
fcdd3ab3 4514
52cc2eeb 4515 /* Hoist the valist value into a temporary for the moment. */
ecdeeb37 4516 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
4517
fcdd3ab3 4518 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
4519 requires greater alignment, we must perform dynamic alignment. */
85c1f587 4520 if (boundary > align
4521 && !integer_zerop (TYPE_SIZE (type)))
fcdd3ab3 4522 {
41076ef6 4523 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
389dd41b 4524 fold_build2 (POINTER_PLUS_EXPR,
4525 TREE_TYPE (valist),
0de36bdb 4526 valist_tmp, size_int (boundary - 1)));
52cc2eeb 4527 gimplify_and_add (t, pre_p);
4528
0de36bdb 4529 t = fold_convert (sizetype, valist_tmp);
41076ef6 4530 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
0de36bdb 4531 fold_convert (TREE_TYPE (valist),
4532 fold_build2 (BIT_AND_EXPR, sizetype, t,
4533 size_int (-boundary))));
ecdeeb37 4534 gimplify_and_add (t, pre_p);
fcdd3ab3 4535 }
c5dc0c32 4536 else
4537 boundary = align;
4538
4539 /* If the actual alignment is less than the alignment of the type,
4540 adjust the type accordingly so that we don't assume strict alignment
f0b5f617 4541 when dereferencing the pointer. */
c5dc0c32 4542 boundary *= BITS_PER_UNIT;
4543 if (boundary < TYPE_ALIGN (type))
4544 {
4545 type = build_variant_type_copy (type);
4546 TYPE_ALIGN (type) = boundary;
4547 }
fcdd3ab3 4548
bcff3604 4549 /* Compute the rounded size of the type. */
52cc2eeb 4550 type_size = size_in_bytes (type);
4551 rounded_size = round_up (type_size, align);
4552
fcdd3ab3 4553 /* Reduce rounded_size so it's sharable with the postqueue. */
4554 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
4555
4556 /* Get AP. */
ecdeeb37 4557 addr = valist_tmp;
52cc2eeb 4558 if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
fcdd3ab3 4559 {
4560 /* Small args are padded downward. */
389dd41b 4561 t = fold_build2_loc (input_location, GT_EXPR, sizetype,
4562 rounded_size, size_int (align));
49d00087 4563 t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
4564 size_binop (MINUS_EXPR, rounded_size, type_size));
389dd41b 4565 addr = fold_build2 (POINTER_PLUS_EXPR,
4566 TREE_TYPE (addr), addr, t);
fcdd3ab3 4567 }
4568
fcdd3ab3 4569 /* Compute new value for AP. */
0de36bdb 4570 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (valist), valist_tmp, rounded_size);
41076ef6 4571 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
ecdeeb37 4572 gimplify_and_add (t, pre_p);
e0eca1fa 4573
4574 addr = fold_convert (build_pointer_type (type), addr);
fcdd3ab3 4575
bef380a4 4576 if (indirect)
f2462d6c 4577 addr = build_va_arg_indirect_ref (addr);
4578
4579 return build_va_arg_indirect_ref (addr);
4580}
a0930a69 4581
f2462d6c 4582/* Build an indirect-ref expression over the given TREE, which represents a
4583 piece of a va_arg() expansion. */
4584tree
4585build_va_arg_indirect_ref (tree addr)
4586{
389dd41b 4587 addr = build_fold_indirect_ref_loc (EXPR_LOCATION (addr), addr);
f2462d6c 4588
a0930a69 4589 if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */
4590 mf_mark (addr);
bef380a4 4591
a0930a69 4592 return addr;
433006a9 4593}
4594
fcdd3ab3 4595/* Return a dummy expression of type TYPE in order to keep going after an
4596 error. */
4597
4598static tree
4599dummy_object (tree type)
4600{
535664e3 4601 tree t = build_int_cst (build_pointer_type (type), 0);
fcdd3ab3 4602 return build1 (INDIRECT_REF, type, t);
4603}
4604
2799a2b7 4605/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
4606 builtin function, but a very special sort of operator. */
fcdd3ab3 4607
4608enum gimplify_status
75a70cf9 4609gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
fcdd3ab3 4610{
5f57a8b1 4611 tree promoted_type, have_va_type;
fcdd3ab3 4612 tree valist = TREE_OPERAND (*expr_p, 0);
4613 tree type = TREE_TYPE (*expr_p);
4614 tree t;
389dd41b 4615 location_t loc = EXPR_LOCATION (*expr_p);
fcdd3ab3 4616
4617 /* Verify that valist is of the proper type. */
fcdd3ab3 4618 have_va_type = TREE_TYPE (valist);
f43dda35 4619 if (have_va_type == error_mark_node)
4620 return GS_ERROR;
5f57a8b1 4621 have_va_type = targetm.canonical_va_list_type (have_va_type);
f43dda35 4622
5f57a8b1 4623 if (have_va_type == NULL_TREE)
fcdd3ab3 4624 {
e60a6f7b 4625 error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>");
e0eca1fa 4626 return GS_ERROR;
fcdd3ab3 4627 }
4628
4629 /* Generate a diagnostic for requesting data of a type that cannot
4630 be passed through `...' due to type promotion at the call site. */
5f57a8b1 4631 if ((promoted_type = lang_hooks.types.type_promotes_to (type))
fcdd3ab3 4632 != type)
4633 {
4634 static bool gave_help;
a52d5726 4635 bool warned;
fcdd3ab3 4636
4637 /* Unfortunately, this is merely undefined, rather than a constraint
4638 violation, so we cannot make this an error. If this call is never
4639 executed, the program is still strictly conforming. */
e60a6f7b 4640 warned = warning_at (loc, 0,
4641 "%qT is promoted to %qT when passed through %<...%>",
4642 type, promoted_type);
a52d5726 4643 if (!gave_help && warned)
fcdd3ab3 4644 {
4645 gave_help = true;
e60a6f7b 4646 inform (loc, "(so you should pass %qT not %qT to %<va_arg%>)",
4647 promoted_type, type);
fcdd3ab3 4648 }
4649
4650 /* We can, however, treat "undefined" any way we please.
4651 Call abort to encourage the user to fix the program. */
a52d5726 4652 if (warned)
e60a6f7b 4653 inform (loc, "if this code is reached, the program will abort");
ad0e7a06 4654 /* Before the abort, allow the evaluation of the va_list
4655 expression to exit or longjmp. */
4656 gimplify_and_add (valist, pre_p);
389dd41b 4657 t = build_call_expr_loc (loc,
4658 implicit_built_in_decls[BUILT_IN_TRAP], 0);
75a70cf9 4659 gimplify_and_add (t, pre_p);
fcdd3ab3 4660
4661 /* This is dead code, but go ahead and finish so that the
4662 mode of the result comes out right. */
4663 *expr_p = dummy_object (type);
4664 return GS_ALL_DONE;
4665 }
4666 else
4667 {
4668 /* Make it easier for the backends by protecting the valist argument
a0c938f0 4669 from multiple evaluations. */
5f57a8b1 4670 if (TREE_CODE (have_va_type) == ARRAY_TYPE)
e0eca1fa 4671 {
4672 /* For this case, the backends will be expecting a pointer to
5f57a8b1 4673 TREE_TYPE (abi), but it's possible we've
4674 actually been given an array (an actual TARGET_FN_ABI_VA_LIST).
e0eca1fa 4675 So fix it. */
4676 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
4677 {
5f57a8b1 4678 tree p1 = build_pointer_type (TREE_TYPE (have_va_type));
389dd41b 4679 valist = fold_convert_loc (loc, p1,
4680 build_fold_addr_expr_loc (loc, valist));
e0eca1fa 4681 }
75a70cf9 4682
e0eca1fa 4683 gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
4684 }
4685 else
4686 gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
fcdd3ab3 4687
17a6380d 4688 if (!targetm.gimplify_va_arg_expr)
75a70cf9 4689 /* FIXME: Once most targets are converted we should merely
89f18f73 4690 assert this is non-null. */
fcdd3ab3 4691 return GS_ALL_DONE;
4692
17a6380d 4693 *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
fcdd3ab3 4694 return GS_OK;
4695 }
4696}
4697
c2f47e15 4698/* Expand EXP, a call to __builtin_va_end. */
f7c44134 4699
a66c9326 4700static rtx
c2f47e15 4701expand_builtin_va_end (tree exp)
a66c9326 4702{
c2f47e15 4703 tree valist = CALL_EXPR_ARG (exp, 0);
8a15c04a 4704
8a15c04a 4705 /* Evaluate for side effects, if needed. I hate macros that don't
4706 do that. */
4707 if (TREE_SIDE_EFFECTS (valist))
4708 expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
a66c9326 4709
4710 return const0_rtx;
4711}
4712
c2f47e15 4713/* Expand EXP, a call to __builtin_va_copy. We do this as a
a66c9326 4714 builtin rather than just as an assignment in stdarg.h because of the
4715 nastiness of array-type va_list types. */
f7c44134 4716
a66c9326 4717static rtx
c2f47e15 4718expand_builtin_va_copy (tree exp)
a66c9326 4719{
4720 tree dst, src, t;
389dd41b 4721 location_t loc = EXPR_LOCATION (exp);
a66c9326 4722
c2f47e15 4723 dst = CALL_EXPR_ARG (exp, 0);
4724 src = CALL_EXPR_ARG (exp, 1);
a66c9326 4725
389dd41b 4726 dst = stabilize_va_list_loc (loc, dst, 1);
4727 src = stabilize_va_list_loc (loc, src, 0);
a66c9326 4728
5f57a8b1 4729 gcc_assert (cfun != NULL && cfun->decl != NULL_TREE);
4730
4731 if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE)
a66c9326 4732 {
5f57a8b1 4733 t = build2 (MODIFY_EXPR, targetm.fn_abi_va_list (cfun->decl), dst, src);
a66c9326 4734 TREE_SIDE_EFFECTS (t) = 1;
4735 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4736 }
4737 else
4738 {
11a61dea 4739 rtx dstb, srcb, size;
4740
4741 /* Evaluate to pointers. */
4742 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
4743 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
5f57a8b1 4744 size = expand_expr (TYPE_SIZE_UNIT (targetm.fn_abi_va_list (cfun->decl)),
4745 NULL_RTX, VOIDmode, EXPAND_NORMAL);
11a61dea 4746
85d654dd 4747 dstb = convert_memory_address (Pmode, dstb);
4748 srcb = convert_memory_address (Pmode, srcb);
726ec87c 4749
11a61dea 4750 /* "Dereference" to BLKmode memories. */
4751 dstb = gen_rtx_MEM (BLKmode, dstb);
ab6ab77e 4752 set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
5f57a8b1 4753 set_mem_align (dstb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 4754 srcb = gen_rtx_MEM (BLKmode, srcb);
ab6ab77e 4755 set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
5f57a8b1 4756 set_mem_align (srcb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 4757
4758 /* Copy. */
0378dbdc 4759 emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
a66c9326 4760 }
4761
4762 return const0_rtx;
4763}
4764
53800dbe 4765/* Expand a call to one of the builtin functions __builtin_frame_address or
4766 __builtin_return_address. */
27d0c333 4767
53800dbe 4768static rtx
c2f47e15 4769expand_builtin_frame_address (tree fndecl, tree exp)
53800dbe 4770{
53800dbe 4771 /* The argument must be a nonnegative integer constant.
4772 It counts the number of frames to scan up the stack.
4773 The value is the return address saved in that frame. */
c2f47e15 4774 if (call_expr_nargs (exp) == 0)
53800dbe 4775 /* Warning about missing arg was already issued. */
4776 return const0_rtx;
c2f47e15 4777 else if (! host_integerp (CALL_EXPR_ARG (exp, 0), 1))
53800dbe 4778 {
4779 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
07e3a3d2 4780 error ("invalid argument to %<__builtin_frame_address%>");
53800dbe 4781 else
07e3a3d2 4782 error ("invalid argument to %<__builtin_return_address%>");
53800dbe 4783 return const0_rtx;
4784 }
4785 else
4786 {
27d0c333 4787 rtx tem
4788 = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
c2f47e15 4789 tree_low_cst (CALL_EXPR_ARG (exp, 0), 1));
53800dbe 4790
4791 /* Some ports cannot access arbitrary stack frames. */
4792 if (tem == NULL)
4793 {
4794 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
c3ceba8e 4795 warning (0, "unsupported argument to %<__builtin_frame_address%>");
53800dbe 4796 else
c3ceba8e 4797 warning (0, "unsupported argument to %<__builtin_return_address%>");
53800dbe 4798 return const0_rtx;
4799 }
4800
4801 /* For __builtin_frame_address, return what we've got. */
4802 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4803 return tem;
4804
8ad4c111 4805 if (!REG_P (tem)
53800dbe 4806 && ! CONSTANT_P (tem))
4807 tem = copy_to_mode_reg (Pmode, tem);
4808 return tem;
4809 }
4810}
4811
c2f47e15 4812/* Expand EXP, a call to the alloca builtin. Return NULL_RTX if
53800dbe 4813 we failed and the caller should emit a normal call, otherwise try to get
4814 the result in TARGET, if convenient. */
15c6cf6b 4815
53800dbe 4816static rtx
c2f47e15 4817expand_builtin_alloca (tree exp, rtx target)
53800dbe 4818{
4819 rtx op0;
15c6cf6b 4820 rtx result;
53800dbe 4821
f9fa0459 4822 /* Emit normal call if marked not-inlineable. */
4823 if (CALL_CANNOT_INLINE_P (exp))
c2f47e15 4824 return NULL_RTX;
4ee9c684 4825
c2f47e15 4826 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4827 return NULL_RTX;
53800dbe 4828
4829 /* Compute the argument. */
c2f47e15 4830 op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
53800dbe 4831
4832 /* Allocate the desired space. */
15c6cf6b 4833 result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
85d654dd 4834 result = convert_memory_address (ptr_mode, result);
15c6cf6b 4835
4836 return result;
53800dbe 4837}
4838
c2f47e15 4839/* Expand a call to a bswap builtin with argument ARG0. MODE
42791117 4840 is the mode to expand with. */
4841
4842static rtx
c2f47e15 4843expand_builtin_bswap (tree exp, rtx target, rtx subtarget)
42791117 4844{
4845 enum machine_mode mode;
4846 tree arg;
4847 rtx op0;
4848
c2f47e15 4849 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4850 return NULL_RTX;
42791117 4851
c2f47e15 4852 arg = CALL_EXPR_ARG (exp, 0);
42791117 4853 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 4854 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
42791117 4855
4856 target = expand_unop (mode, bswap_optab, op0, target, 1);
4857
4858 gcc_assert (target);
4859
4860 return convert_to_mode (mode, target, 0);
4861}
4862
c2f47e15 4863/* Expand a call to a unary builtin in EXP.
4864 Return NULL_RTX if a normal call should be emitted rather than expanding the
53800dbe 4865 function in-line. If convenient, the result should be placed in TARGET.
4866 SUBTARGET may be used as the target for computing one of EXP's operands. */
15c6cf6b 4867
53800dbe 4868static rtx
c2f47e15 4869expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target,
aecda0d6 4870 rtx subtarget, optab op_optab)
53800dbe 4871{
4872 rtx op0;
c2f47e15 4873
4874 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4875 return NULL_RTX;
53800dbe 4876
4877 /* Compute the argument. */
1db6d067 4878 op0 = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
4879 VOIDmode, EXPAND_NORMAL);
6a08d0ab 4880 /* Compute op, into TARGET if possible.
53800dbe 4881 Set TARGET to wherever the result comes back. */
c2f47e15 4882 target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
6a08d0ab 4883 op_optab, op0, target, 1);
64db345d 4884 gcc_assert (target);
7d3f6cc7 4885
efb070c8 4886 return convert_to_mode (target_mode, target, 0);
53800dbe 4887}
89cfe6e5 4888
5a74f77e 4889/* Expand a call to __builtin_expect. We just return our argument
4890 as the builtin_expect semantic should've been already executed by
4891 tree branch prediction pass. */
89cfe6e5 4892
4893static rtx
c2f47e15 4894expand_builtin_expect (tree exp, rtx target)
89cfe6e5 4895{
c2f47e15 4896 tree arg, c;
89cfe6e5 4897
c2f47e15 4898 if (call_expr_nargs (exp) < 2)
89cfe6e5 4899 return const0_rtx;
c2f47e15 4900 arg = CALL_EXPR_ARG (exp, 0);
4901 c = CALL_EXPR_ARG (exp, 1);
89cfe6e5 4902
c2f47e15 4903 target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5a74f77e 4904 /* When guessing was done, the hints should be already stripped away. */
07311427 4905 gcc_assert (!flag_guess_branch_prob
4906 || optimize == 0 || errorcount || sorrycount);
89cfe6e5 4907 return target;
4908}
689df48e 4909
c22de3f0 4910void
aecda0d6 4911expand_builtin_trap (void)
a0ef1725 4912{
4913#ifdef HAVE_trap
4914 if (HAVE_trap)
4915 emit_insn (gen_trap ());
4916 else
4917#endif
4918 emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
4919 emit_barrier ();
4920}
78a74442 4921
d2b48f0c 4922/* Expand a call to __builtin_unreachable. We do nothing except emit
4923 a barrier saying that control flow will not pass here.
4924
4925 It is the responsibility of the program being compiled to ensure
4926 that control flow does never reach __builtin_unreachable. */
4927static void
4928expand_builtin_unreachable (void)
4929{
4930 emit_barrier ();
4931}
4932
c2f47e15 4933/* Expand EXP, a call to fabs, fabsf or fabsl.
4934 Return NULL_RTX if a normal call should be emitted rather than expanding
78a74442 4935 the function inline. If convenient, the result should be placed
4936 in TARGET. SUBTARGET may be used as the target for computing
4937 the operand. */
4938
4939static rtx
c2f47e15 4940expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
78a74442 4941{
4942 enum machine_mode mode;
4943 tree arg;
4944 rtx op0;
4945
c2f47e15 4946 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
4947 return NULL_RTX;
78a74442 4948
c2f47e15 4949 arg = CALL_EXPR_ARG (exp, 0);
c7f617c2 4950 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
78a74442 4951 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 4952 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
78a74442 4953 return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
4954}
4955
c2f47e15 4956/* Expand EXP, a call to copysign, copysignf, or copysignl.
270436f3 4957 Return NULL is a normal call should be emitted rather than expanding the
4958 function inline. If convenient, the result should be placed in TARGET.
4959 SUBTARGET may be used as the target for computing the operand. */
4960
4961static rtx
c2f47e15 4962expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
270436f3 4963{
4964 rtx op0, op1;
4965 tree arg;
4966
c2f47e15 4967 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
4968 return NULL_RTX;
270436f3 4969
c2f47e15 4970 arg = CALL_EXPR_ARG (exp, 0);
8ec3c5c2 4971 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
270436f3 4972
c2f47e15 4973 arg = CALL_EXPR_ARG (exp, 1);
8ec3c5c2 4974 op1 = expand_normal (arg);
270436f3 4975
4976 return expand_copysign (op0, op1, target);
4977}
4978
19bf118a 4979/* Create a new constant string literal and return a char* pointer to it.
4980 The STRING_CST value is the LEN characters at STR. */
1e8e9920 4981tree
19bf118a 4982build_string_literal (int len, const char *str)
4983{
4984 tree t, elem, index, type;
4985
4986 t = build_string (len, str);
4987 elem = build_type_variant (char_type_node, 1, 0);
40238f64 4988 index = build_index_type (size_int (len - 1));
19bf118a 4989 type = build_array_type (elem, index);
4990 TREE_TYPE (t) = type;
4991 TREE_CONSTANT (t) = 1;
4992 TREE_READONLY (t) = 1;
4993 TREE_STATIC (t) = 1;
4994
19bf118a 4995 type = build_pointer_type (elem);
40238f64 4996 t = build1 (ADDR_EXPR, type,
4997 build4 (ARRAY_REF, elem,
4998 t, integer_zero_node, NULL_TREE, NULL_TREE));
19bf118a 4999 return t;
5000}
5001
0b25db21 5002/* Expand EXP, a call to printf or printf_unlocked.
c2f47e15 5003 Return NULL_RTX if a normal call should be emitted rather than transforming
19bf118a 5004 the function inline. If convenient, the result should be placed in
0862b7e9 5005 TARGET with mode MODE. UNLOCKED indicates this is a printf_unlocked
19bf118a 5006 call. */
5007static rtx
0b25db21 5008expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
19bf118a 5009 bool unlocked)
5010{
6d77ed92 5011 /* If we're using an unlocked function, assume the other unlocked
5012 functions exist explicitly. */
5013 tree const fn_putchar = unlocked ? built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
5014 : implicit_built_in_decls[BUILT_IN_PUTCHAR];
5015 tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED]
5016 : implicit_built_in_decls[BUILT_IN_PUTS];
19bf118a 5017 const char *fmt_str;
c2f47e15 5018 tree fn = 0;
5019 tree fmt, arg;
5020 int nargs = call_expr_nargs (exp);
19bf118a 5021
5022 /* If the return value is used, don't do the transformation. */
5023 if (target != const0_rtx)
c2f47e15 5024 return NULL_RTX;
19bf118a 5025
5026 /* Verify the required arguments in the original call. */
c2f47e15 5027 if (nargs == 0)
5028 return NULL_RTX;
5029 fmt = CALL_EXPR_ARG (exp, 0);
552752f7 5030 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
c2f47e15 5031 return NULL_RTX;
19bf118a 5032
5033 /* Check whether the format is a literal string constant. */
5034 fmt_str = c_getstr (fmt);
5035 if (fmt_str == NULL)
c2f47e15 5036 return NULL_RTX;
19bf118a 5037
d4473c84 5038 if (!init_target_chars ())
c2f47e15 5039 return NULL_RTX;
a0c938f0 5040
19bf118a 5041 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
99eabcc1 5042 if (strcmp (fmt_str, target_percent_s_newline) == 0)
19bf118a 5043 {
c2f47e15 5044 if ((nargs != 2)
5045 || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (exp, 1))))
5046 return NULL_RTX;
5047 if (fn_puts)
a65c4d64 5048 fn = build_call_nofold (fn_puts, 1, CALL_EXPR_ARG (exp, 1));
19bf118a 5049 }
5050 /* If the format specifier was "%c", call __builtin_putchar(arg). */
99eabcc1 5051 else if (strcmp (fmt_str, target_percent_c) == 0)
19bf118a 5052 {
c2f47e15 5053 if ((nargs != 2)
5054 || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1))) != INTEGER_TYPE)
5055 return NULL_RTX;
5056 if (fn_putchar)
a65c4d64 5057 fn = build_call_nofold (fn_putchar, 1, CALL_EXPR_ARG (exp, 1));
19bf118a 5058 }
5059 else
5060 {
5061 /* We can't handle anything else with % args or %% ... yet. */
99eabcc1 5062 if (strchr (fmt_str, target_percent))
c2f47e15 5063 return NULL_RTX;
19bf118a 5064
c2f47e15 5065 if (nargs > 1)
5066 return NULL_RTX;
19bf118a 5067
5068 /* If the format specifier was "", printf does nothing. */
5069 if (fmt_str[0] == '\0')
5070 return const0_rtx;
5071 /* If the format specifier has length of 1, call putchar. */
5072 if (fmt_str[1] == '\0')
5073 {
5074 /* Given printf("c"), (where c is any one character,)
5075 convert "c"[0] to an int and pass that to the replacement
5076 function. */
7016c612 5077 arg = build_int_cst (NULL_TREE, fmt_str[0]);
c2f47e15 5078 if (fn_putchar)
a65c4d64 5079 fn = build_call_nofold (fn_putchar, 1, arg);
19bf118a 5080 }
5081 else
5082 {
5083 /* If the format specifier was "string\n", call puts("string"). */
5084 size_t len = strlen (fmt_str);
99eabcc1 5085 if ((unsigned char)fmt_str[len - 1] == target_newline)
19bf118a 5086 {
91c82c20 5087 /* Create a NUL-terminated string that's one char shorter
19bf118a 5088 than the original, stripping off the trailing '\n'. */
364c0c59 5089 char *newstr = XALLOCAVEC (char, len);
19bf118a 5090 memcpy (newstr, fmt_str, len - 1);
5091 newstr[len - 1] = 0;
19bf118a 5092 arg = build_string_literal (len, newstr);
c2f47e15 5093 if (fn_puts)
a65c4d64 5094 fn = build_call_nofold (fn_puts, 1, arg);
19bf118a 5095 }
5096 else
5097 /* We'd like to arrange to call fputs(string,stdout) here,
5098 but we need stdout and don't have a way to get it yet. */
c2f47e15 5099 return NULL_RTX;
19bf118a 5100 }
5101 }
5102
5103 if (!fn)
c2f47e15 5104 return NULL_RTX;
a65c4d64 5105 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
5106 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0b25db21 5107 return expand_expr (fn, target, mode, EXPAND_NORMAL);
19bf118a 5108}
5109
0b25db21 5110/* Expand EXP, a call to fprintf or fprintf_unlocked.
c2f47e15 5111 Return NULL_RTX if a normal call should be emitted rather than transforming
19bf118a 5112 the function inline. If convenient, the result should be placed in
0862b7e9 5113 TARGET with mode MODE. UNLOCKED indicates this is a fprintf_unlocked
19bf118a 5114 call. */
5115static rtx
0b25db21 5116expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
a0c938f0 5117 bool unlocked)
19bf118a 5118{
6d77ed92 5119 /* If we're using an unlocked function, assume the other unlocked
5120 functions exist explicitly. */
5121 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
5122 : implicit_built_in_decls[BUILT_IN_FPUTC];
5123 tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
5124 : implicit_built_in_decls[BUILT_IN_FPUTS];
19bf118a 5125 const char *fmt_str;
c2f47e15 5126 tree fn = 0;
5127 tree fmt, fp, arg;
5128 int nargs = call_expr_nargs (exp);
19bf118a 5129
5130 /* If the return value is used, don't do the transformation. */
5131 if (target != const0_rtx)
c2f47e15 5132 return NULL_RTX;
19bf118a 5133
5134 /* Verify the required arguments in the original call. */
c2f47e15 5135 if (nargs < 2)
5136 return NULL_RTX;
5137 fp = CALL_EXPR_ARG (exp, 0);
552752f7 5138 if (! POINTER_TYPE_P (TREE_TYPE (fp)))
c2f47e15 5139 return NULL_RTX;
5140 fmt = CALL_EXPR_ARG (exp, 1);
552752f7 5141 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
c2f47e15 5142 return NULL_RTX;
19bf118a 5143
5144 /* Check whether the format is a literal string constant. */
5145 fmt_str = c_getstr (fmt);
5146 if (fmt_str == NULL)
c2f47e15 5147 return NULL_RTX;
19bf118a 5148
d4473c84 5149 if (!init_target_chars ())
c2f47e15 5150 return NULL_RTX;
a0c938f0 5151
19bf118a 5152 /* If the format specifier was "%s", call __builtin_fputs(arg,fp). */
99eabcc1 5153 if (strcmp (fmt_str, target_percent_s) == 0)
19bf118a 5154 {
c2f47e15 5155 if ((nargs != 3)
5156 || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (exp, 2))))
5157 return NULL_RTX;
5158 arg = CALL_EXPR_ARG (exp, 2);
5159 if (fn_fputs)
a65c4d64 5160 fn = build_call_nofold (fn_fputs, 2, arg, fp);
19bf118a 5161 }
5162 /* If the format specifier was "%c", call __builtin_fputc(arg,fp). */
99eabcc1 5163 else if (strcmp (fmt_str, target_percent_c) == 0)
19bf118a 5164 {
c2f47e15 5165 if ((nargs != 3)
5166 || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2))) != INTEGER_TYPE)
5167 return NULL_RTX;
5168 arg = CALL_EXPR_ARG (exp, 2);
5169 if (fn_fputc)
a65c4d64 5170 fn = build_call_nofold (fn_fputc, 2, arg, fp);
19bf118a 5171 }
5172 else
5173 {
5174 /* We can't handle anything else with % args or %% ... yet. */
99eabcc1 5175 if (strchr (fmt_str, target_percent))
c2f47e15 5176 return NULL_RTX;
19bf118a 5177
c2f47e15 5178 if (nargs > 2)
5179 return NULL_RTX;
19bf118a 5180
5181 /* If the format specifier was "", fprintf does nothing. */
5182 if (fmt_str[0] == '\0')
5183 {
5184 /* Evaluate and ignore FILE* argument for side-effects. */
5185 expand_expr (fp, const0_rtx, VOIDmode, EXPAND_NORMAL);
5186 return const0_rtx;
5187 }
5188
5189 /* When "string" doesn't contain %, replace all cases of
5190 fprintf(stream,string) with fputs(string,stream). The fputs
5191 builtin will take care of special cases like length == 1. */
c2f47e15 5192 if (fn_fputs)
a65c4d64 5193 fn = build_call_nofold (fn_fputs, 2, fmt, fp);
19bf118a 5194 }
5195
5196 if (!fn)
c2f47e15 5197 return NULL_RTX;
a65c4d64 5198 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
5199 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0b25db21 5200 return expand_expr (fn, target, mode, EXPAND_NORMAL);
19bf118a 5201}
5202
c2f47e15 5203/* Expand a call EXP to sprintf. Return NULL_RTX if
6411575e 5204 a normal call should be emitted rather than expanding the function
5205 inline. If convenient, the result should be placed in TARGET with
5206 mode MODE. */
5207
5208static rtx
c2f47e15 5209expand_builtin_sprintf (tree exp, rtx target, enum machine_mode mode)
6411575e 5210{
c2f47e15 5211 tree dest, fmt;
a7a723f0 5212 const char *fmt_str;
c2f47e15 5213 int nargs = call_expr_nargs (exp);
6411575e 5214
5215 /* Verify the required arguments in the original call. */
c2f47e15 5216 if (nargs < 2)
5217 return NULL_RTX;
5218 dest = CALL_EXPR_ARG (exp, 0);
552752f7 5219 if (! POINTER_TYPE_P (TREE_TYPE (dest)))
c2f47e15 5220 return NULL_RTX;
5221 fmt = CALL_EXPR_ARG (exp, 0);
552752f7 5222 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
c2f47e15 5223 return NULL_RTX;
6411575e 5224
5225 /* Check whether the format is a literal string constant. */
a7a723f0 5226 fmt_str = c_getstr (fmt);
5227 if (fmt_str == NULL)
c2f47e15 5228 return NULL_RTX;
6411575e 5229
d4473c84 5230 if (!init_target_chars ())
c2f47e15 5231 return NULL_RTX;
99eabcc1 5232
6411575e 5233 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 5234 if (strchr (fmt_str, target_percent) == 0)
6411575e 5235 {
5236 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
5237 tree exp;
5238
c2f47e15 5239 if ((nargs > 2) || ! fn)
5240 return NULL_RTX;
a65c4d64 5241 expand_expr (build_call_nofold (fn, 2, dest, fmt),
6411575e 5242 const0_rtx, VOIDmode, EXPAND_NORMAL);
5243 if (target == const0_rtx)
5244 return const0_rtx;
7016c612 5245 exp = build_int_cst (NULL_TREE, strlen (fmt_str));
6411575e 5246 return expand_expr (exp, target, mode, EXPAND_NORMAL);
5247 }
a7a723f0 5248 /* If the format is "%s", use strcpy if the result isn't used. */
99eabcc1 5249 else if (strcmp (fmt_str, target_percent_s) == 0)
6411575e 5250 {
a7a723f0 5251 tree fn, arg, len;
5252 fn = implicit_built_in_decls[BUILT_IN_STRCPY];
6411575e 5253
a7a723f0 5254 if (! fn)
c2f47e15 5255 return NULL_RTX;
5256 if (nargs != 3)
5257 return NULL_RTX;
5258 arg = CALL_EXPR_ARG (exp, 2);
552752f7 5259 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
c2f47e15 5260 return NULL_RTX;
6411575e 5261
5262 if (target != const0_rtx)
5263 {
681fab1e 5264 len = c_strlen (arg, 1);
a7a723f0 5265 if (! len || TREE_CODE (len) != INTEGER_CST)
c2f47e15 5266 return NULL_RTX;
6411575e 5267 }
5268 else
a7a723f0 5269 len = NULL_TREE;
6411575e 5270
a65c4d64 5271 expand_expr (build_call_nofold (fn, 2, dest, arg),
6411575e 5272 const0_rtx, VOIDmode, EXPAND_NORMAL);
5273
5274 if (target == const0_rtx)
5275 return const0_rtx;
a7a723f0 5276 return expand_expr (len, target, mode, EXPAND_NORMAL);
6411575e 5277 }
5278
c2f47e15 5279 return NULL_RTX;
6411575e 5280}
27f261ef 5281
4ee9c684 5282/* Expand a call to either the entry or exit function profiler. */
5283
5284static rtx
5285expand_builtin_profile_func (bool exitp)
5286{
f4e36c33 5287 rtx this_rtx, which;
4ee9c684 5288
f4e36c33 5289 this_rtx = DECL_RTL (current_function_decl);
5290 gcc_assert (MEM_P (this_rtx));
5291 this_rtx = XEXP (this_rtx, 0);
4ee9c684 5292
5293 if (exitp)
5294 which = profile_function_exit_libfunc;
5295 else
5296 which = profile_function_entry_libfunc;
5297
f4e36c33 5298 emit_library_call (which, LCT_NORMAL, VOIDmode, 2, this_rtx, Pmode,
4ee9c684 5299 expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
869d0ef0 5300 0),
4ee9c684 5301 Pmode);
5302
5303 return const0_rtx;
5304}
5305
ac8fb6db 5306/* Expand a call to __builtin___clear_cache. */
5307
5308static rtx
5309expand_builtin___clear_cache (tree exp ATTRIBUTE_UNUSED)
5310{
5311#ifndef HAVE_clear_cache
5312#ifdef CLEAR_INSN_CACHE
5313 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
5314 does something. Just do the default expansion to a call to
5315 __clear_cache(). */
5316 return NULL_RTX;
5317#else
5318 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
5319 does nothing. There is no need to call it. Do nothing. */
5320 return const0_rtx;
5321#endif /* CLEAR_INSN_CACHE */
5322#else
5323 /* We have a "clear_cache" insn, and it will handle everything. */
5324 tree begin, end;
5325 rtx begin_rtx, end_rtx;
5326 enum insn_code icode;
5327
5328 /* We must not expand to a library call. If we did, any
5329 fallback library function in libgcc that might contain a call to
5330 __builtin___clear_cache() would recurse infinitely. */
5331 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
5332 {
5333 error ("both arguments to %<__builtin___clear_cache%> must be pointers");
5334 return const0_rtx;
5335 }
5336
5337 if (HAVE_clear_cache)
5338 {
5339 icode = CODE_FOR_clear_cache;
5340
5341 begin = CALL_EXPR_ARG (exp, 0);
5342 begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
5343 begin_rtx = convert_memory_address (Pmode, begin_rtx);
5344 if (!insn_data[icode].operand[0].predicate (begin_rtx, Pmode))
5345 begin_rtx = copy_to_mode_reg (Pmode, begin_rtx);
5346
5347 end = CALL_EXPR_ARG (exp, 1);
5348 end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
5349 end_rtx = convert_memory_address (Pmode, end_rtx);
5350 if (!insn_data[icode].operand[1].predicate (end_rtx, Pmode))
5351 end_rtx = copy_to_mode_reg (Pmode, end_rtx);
5352
5353 emit_insn (gen_clear_cache (begin_rtx, end_rtx));
5354 }
5355 return const0_rtx;
5356#endif /* HAVE_clear_cache */
5357}
5358
4ee9c684 5359/* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
5360
5361static rtx
5362round_trampoline_addr (rtx tramp)
5363{
5364 rtx temp, addend, mask;
5365
5366 /* If we don't need too much alignment, we'll have been guaranteed
5367 proper alignment by get_trampoline_type. */
5368 if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
5369 return tramp;
5370
5371 /* Round address up to desired boundary. */
5372 temp = gen_reg_rtx (Pmode);
5373 addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
5374 mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
5375
5376 temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
5377 temp, 0, OPTAB_LIB_WIDEN);
5378 tramp = expand_simple_binop (Pmode, AND, temp, mask,
5379 temp, 0, OPTAB_LIB_WIDEN);
5380
5381 return tramp;
5382}
5383
5384static rtx
c2f47e15 5385expand_builtin_init_trampoline (tree exp)
4ee9c684 5386{
5387 tree t_tramp, t_func, t_chain;
82c7907c 5388 rtx m_tramp, r_tramp, r_chain, tmp;
4ee9c684 5389
c2f47e15 5390 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
4ee9c684 5391 POINTER_TYPE, VOID_TYPE))
5392 return NULL_RTX;
5393
c2f47e15 5394 t_tramp = CALL_EXPR_ARG (exp, 0);
5395 t_func = CALL_EXPR_ARG (exp, 1);
5396 t_chain = CALL_EXPR_ARG (exp, 2);
4ee9c684 5397
8ec3c5c2 5398 r_tramp = expand_normal (t_tramp);
82c7907c 5399 m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
5400 MEM_NOTRAP_P (m_tramp) = 1;
5401
5402 /* The TRAMP argument should be the address of a field within the
5403 local function's FRAME decl. Let's see if we can fill in the
5404 to fill in the MEM_ATTRs for this memory. */
5405 if (TREE_CODE (t_tramp) == ADDR_EXPR)
5406 set_mem_attributes_minus_bitpos (m_tramp, TREE_OPERAND (t_tramp, 0),
5407 true, 0);
5408
5409 tmp = round_trampoline_addr (r_tramp);
5410 if (tmp != r_tramp)
5411 {
5412 m_tramp = change_address (m_tramp, BLKmode, tmp);
5413 set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
5414 set_mem_size (m_tramp, GEN_INT (TRAMPOLINE_SIZE));
5415 }
5416
5417 /* The FUNC argument should be the address of the nested function.
5418 Extract the actual function decl to pass to the hook. */
5419 gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
5420 t_func = TREE_OPERAND (t_func, 0);
5421 gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
5422
8ec3c5c2 5423 r_chain = expand_normal (t_chain);
4ee9c684 5424
5425 /* Generate insns to initialize the trampoline. */
82c7907c 5426 targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
4ee9c684 5427
82c7907c 5428 trampolines_created = 1;
4ee9c684 5429 return const0_rtx;
5430}
5431
5432static rtx
c2f47e15 5433expand_builtin_adjust_trampoline (tree exp)
4ee9c684 5434{
5435 rtx tramp;
5436
c2f47e15 5437 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
4ee9c684 5438 return NULL_RTX;
5439
c2f47e15 5440 tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
4ee9c684 5441 tramp = round_trampoline_addr (tramp);
82c7907c 5442 if (targetm.calls.trampoline_adjust_address)
5443 tramp = targetm.calls.trampoline_adjust_address (tramp);
4ee9c684 5444
5445 return tramp;
5446}
5447
93f564d6 5448/* Expand the call EXP to the built-in signbit, signbitf or signbitl
5449 function. The function first checks whether the back end provides
5450 an insn to implement signbit for the respective mode. If not, it
5451 checks whether the floating point format of the value is such that
5452 the sign bit can be extracted. If that is not the case, the
5453 function returns NULL_RTX to indicate that a normal call should be
5454 emitted rather than expanding the function in-line. EXP is the
5455 expression that is a call to the builtin function; if convenient,
5456 the result should be placed in TARGET. */
27f261ef 5457static rtx
5458expand_builtin_signbit (tree exp, rtx target)
5459{
5460 const struct real_format *fmt;
5461 enum machine_mode fmode, imode, rmode;
5462 HOST_WIDE_INT hi, lo;
c2f47e15 5463 tree arg;
ca4f1f5b 5464 int word, bitpos;
27eda240 5465 enum insn_code icode;
27f261ef 5466 rtx temp;
389dd41b 5467 location_t loc = EXPR_LOCATION (exp);
27f261ef 5468
c2f47e15 5469 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
5470 return NULL_RTX;
27f261ef 5471
c2f47e15 5472 arg = CALL_EXPR_ARG (exp, 0);
27f261ef 5473 fmode = TYPE_MODE (TREE_TYPE (arg));
5474 rmode = TYPE_MODE (TREE_TYPE (exp));
5475 fmt = REAL_MODE_FORMAT (fmode);
5476
93f564d6 5477 arg = builtin_save_expr (arg);
5478
5479 /* Expand the argument yielding a RTX expression. */
5480 temp = expand_normal (arg);
5481
5482 /* Check if the back end provides an insn that handles signbit for the
5483 argument's mode. */
27eda240 5484 icode = signbit_optab->handlers [(int) fmode].insn_code;
5485 if (icode != CODE_FOR_nothing)
93f564d6 5486 {
5487 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
27eda240 5488 emit_unop_insn (icode, target, temp, UNKNOWN);
93f564d6 5489 return target;
5490 }
5491
27f261ef 5492 /* For floating point formats without a sign bit, implement signbit
5493 as "ARG < 0.0". */
8d564692 5494 bitpos = fmt->signbit_ro;
ca4f1f5b 5495 if (bitpos < 0)
27f261ef 5496 {
5497 /* But we can't do this if the format supports signed zero. */
5498 if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
c2f47e15 5499 return NULL_RTX;
27f261ef 5500
389dd41b 5501 arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
49d00087 5502 build_real (TREE_TYPE (arg), dconst0));
27f261ef 5503 return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5504 }
5505
ca4f1f5b 5506 if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
27f261ef 5507 {
ca4f1f5b 5508 imode = int_mode_for_mode (fmode);
5509 if (imode == BLKmode)
c2f47e15 5510 return NULL_RTX;
ca4f1f5b 5511 temp = gen_lowpart (imode, temp);
24fd4260 5512 }
5513 else
5514 {
ca4f1f5b 5515 imode = word_mode;
5516 /* Handle targets with different FP word orders. */
5517 if (FLOAT_WORDS_BIG_ENDIAN)
a0c938f0 5518 word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
ca4f1f5b 5519 else
a0c938f0 5520 word = bitpos / BITS_PER_WORD;
ca4f1f5b 5521 temp = operand_subword_force (temp, word, fmode);
5522 bitpos = bitpos % BITS_PER_WORD;
5523 }
5524
44b0f1d0 5525 /* Force the intermediate word_mode (or narrower) result into a
5526 register. This avoids attempting to create paradoxical SUBREGs
5527 of floating point modes below. */
5528 temp = force_reg (imode, temp);
5529
ca4f1f5b 5530 /* If the bitpos is within the "result mode" lowpart, the operation
5531 can be implement with a single bitwise AND. Otherwise, we need
5532 a right shift and an AND. */
5533
5534 if (bitpos < GET_MODE_BITSIZE (rmode))
5535 {
24fd4260 5536 if (bitpos < HOST_BITS_PER_WIDE_INT)
27f261ef 5537 {
24fd4260 5538 hi = 0;
5539 lo = (HOST_WIDE_INT) 1 << bitpos;
27f261ef 5540 }
5541 else
24fd4260 5542 {
5543 hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
5544 lo = 0;
5545 }
27f261ef 5546
4a46f016 5547 if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
ca4f1f5b 5548 temp = gen_lowpart (rmode, temp);
24fd4260 5549 temp = expand_binop (rmode, and_optab, temp,
5550 immed_double_const (lo, hi, rmode),
ca4f1f5b 5551 NULL_RTX, 1, OPTAB_LIB_WIDEN);
27f261ef 5552 }
ca4f1f5b 5553 else
5554 {
5555 /* Perform a logical right shift to place the signbit in the least
a0c938f0 5556 significant bit, then truncate the result to the desired mode
ca4f1f5b 5557 and mask just this bit. */
5558 temp = expand_shift (RSHIFT_EXPR, imode, temp,
5559 build_int_cst (NULL_TREE, bitpos), NULL_RTX, 1);
5560 temp = gen_lowpart (rmode, temp);
5561 temp = expand_binop (rmode, and_optab, temp, const1_rtx,
5562 NULL_RTX, 1, OPTAB_LIB_WIDEN);
5563 }
5564
27f261ef 5565 return temp;
5566}
73673831 5567
5568/* Expand fork or exec calls. TARGET is the desired target of the
c2f47e15 5569 call. EXP is the call. FN is the
73673831 5570 identificator of the actual function. IGNORE is nonzero if the
5571 value is to be ignored. */
5572
5573static rtx
c2f47e15 5574expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
73673831 5575{
5576 tree id, decl;
5577 tree call;
5578
5579 /* If we are not profiling, just call the function. */
5580 if (!profile_arc_flag)
5581 return NULL_RTX;
5582
5583 /* Otherwise call the wrapper. This should be equivalent for the rest of
5584 compiler, so the code does not diverge, and the wrapper may run the
9c9bad97 5585 code necessary for keeping the profiling sane. */
73673831 5586
5587 switch (DECL_FUNCTION_CODE (fn))
5588 {
5589 case BUILT_IN_FORK:
5590 id = get_identifier ("__gcov_fork");
5591 break;
5592
5593 case BUILT_IN_EXECL:
5594 id = get_identifier ("__gcov_execl");
5595 break;
5596
5597 case BUILT_IN_EXECV:
5598 id = get_identifier ("__gcov_execv");
5599 break;
5600
5601 case BUILT_IN_EXECLP:
5602 id = get_identifier ("__gcov_execlp");
5603 break;
5604
5605 case BUILT_IN_EXECLE:
5606 id = get_identifier ("__gcov_execle");
5607 break;
5608
5609 case BUILT_IN_EXECVP:
5610 id = get_identifier ("__gcov_execvp");
5611 break;
5612
5613 case BUILT_IN_EXECVE:
5614 id = get_identifier ("__gcov_execve");
5615 break;
5616
5617 default:
64db345d 5618 gcc_unreachable ();
73673831 5619 }
5620
e60a6f7b 5621 decl = build_decl (DECL_SOURCE_LOCATION (fn),
5622 FUNCTION_DECL, id, TREE_TYPE (fn));
73673831 5623 DECL_EXTERNAL (decl) = 1;
5624 TREE_PUBLIC (decl) = 1;
5625 DECL_ARTIFICIAL (decl) = 1;
5626 TREE_NOTHROW (decl) = 1;
e82d310b 5627 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
5628 DECL_VISIBILITY_SPECIFIED (decl) = 1;
389dd41b 5629 call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0);
73673831 5630 return expand_call (call, target, ignore);
c2f47e15 5631 }
5632
b6a5fc45 5633
5634\f
3e272de8 5635/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
5636 the pointer in these functions is void*, the tree optimizers may remove
5637 casts. The mode computed in expand_builtin isn't reliable either, due
5638 to __sync_bool_compare_and_swap.
5639
5640 FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
5641 group of builtins. This gives us log2 of the mode size. */
5642
5643static inline enum machine_mode
5644get_builtin_sync_mode (int fcode_diff)
5645{
ad3a13b5 5646 /* The size is not negotiable, so ask not to get BLKmode in return
5647 if the target indicates that a smaller size would be better. */
5648 return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
3e272de8 5649}
5650
041e0215 5651/* Expand the memory expression LOC and return the appropriate memory operand
5652 for the builtin_sync operations. */
5653
5654static rtx
5655get_builtin_sync_mem (tree loc, enum machine_mode mode)
5656{
5657 rtx addr, mem;
5658
7f4d56ad 5659 addr = expand_expr (loc, NULL_RTX, ptr_mode, EXPAND_SUM);
5660 addr = convert_memory_address (Pmode, addr);
041e0215 5661
5662 /* Note that we explicitly do not want any alias information for this
5663 memory, so that we kill all other live memories. Otherwise we don't
5664 satisfy the full barrier semantics of the intrinsic. */
5665 mem = validize_mem (gen_rtx_MEM (mode, addr));
5666
5667 set_mem_align (mem, get_pointer_alignment (loc, BIGGEST_ALIGNMENT));
c94cfd1c 5668 set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
041e0215 5669 MEM_VOLATILE_P (mem) = 1;
5670
5671 return mem;
5672}
5673
b6a5fc45 5674/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
c2f47e15 5675 EXP is the CALL_EXPR. CODE is the rtx code
b6a5fc45 5676 that corresponds to the arithmetic or logical operation from the name;
5677 an exception here is that NOT actually means NAND. TARGET is an optional
5678 place for us to store the results; AFTER is true if this is the
5679 fetch_and_xxx form. IGNORE is true if we don't actually care about
5680 the result of the operation at all. */
5681
5682static rtx
c2f47e15 5683expand_builtin_sync_operation (enum machine_mode mode, tree exp,
3e272de8 5684 enum rtx_code code, bool after,
b6a5fc45 5685 rtx target, bool ignore)
5686{
041e0215 5687 rtx val, mem;
a8bb7059 5688 enum machine_mode old_mode;
e60a6f7b 5689 location_t loc = EXPR_LOCATION (exp);
b6a5fc45 5690
cf73e559 5691 if (code == NOT && warn_sync_nand)
5692 {
5693 tree fndecl = get_callee_fndecl (exp);
5694 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
5695
5696 static bool warned_f_a_n, warned_n_a_f;
5697
5698 switch (fcode)
5699 {
5700 case BUILT_IN_FETCH_AND_NAND_1:
5701 case BUILT_IN_FETCH_AND_NAND_2:
5702 case BUILT_IN_FETCH_AND_NAND_4:
5703 case BUILT_IN_FETCH_AND_NAND_8:
5704 case BUILT_IN_FETCH_AND_NAND_16:
5705
5706 if (warned_f_a_n)
5707 break;
5708
5709 fndecl = implicit_built_in_decls[BUILT_IN_FETCH_AND_NAND_N];
e60a6f7b 5710 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
cf73e559 5711 warned_f_a_n = true;
5712 break;
5713
5714 case BUILT_IN_NAND_AND_FETCH_1:
5715 case BUILT_IN_NAND_AND_FETCH_2:
5716 case BUILT_IN_NAND_AND_FETCH_4:
5717 case BUILT_IN_NAND_AND_FETCH_8:
5718 case BUILT_IN_NAND_AND_FETCH_16:
5719
5720 if (warned_n_a_f)
5721 break;
5722
5723 fndecl = implicit_built_in_decls[BUILT_IN_NAND_AND_FETCH_N];
e60a6f7b 5724 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
cf73e559 5725 warned_n_a_f = true;
5726 break;
5727
5728 default:
5729 gcc_unreachable ();
5730 }
5731 }
5732
b6a5fc45 5733 /* Expand the operands. */
c2f47e15 5734 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5735
1db6d067 5736 val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
a8bb7059 5737 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5738 of CONST_INTs, where we know the old_mode only from the call argument. */
5739 old_mode = GET_MODE (val);
5740 if (old_mode == VOIDmode)
5741 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5742 val = convert_modes (mode, old_mode, val, 1);
b6a5fc45 5743
b6a5fc45 5744 if (ignore)
5745 return expand_sync_operation (mem, val, code);
5746 else
5747 return expand_sync_fetch_operation (mem, val, code, after, target);
5748}
5749
5750/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
c2f47e15 5751 intrinsics. EXP is the CALL_EXPR. IS_BOOL is
b6a5fc45 5752 true if this is the boolean form. TARGET is a place for us to store the
5753 results; this is NOT optional if IS_BOOL is true. */
5754
5755static rtx
c2f47e15 5756expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
3e272de8 5757 bool is_bool, rtx target)
b6a5fc45 5758{
041e0215 5759 rtx old_val, new_val, mem;
a8bb7059 5760 enum machine_mode old_mode;
b6a5fc45 5761
5762 /* Expand the operands. */
c2f47e15 5763 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5764
c2f47e15 5765
1db6d067 5766 old_val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX,
5767 mode, EXPAND_NORMAL);
a8bb7059 5768 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5769 of CONST_INTs, where we know the old_mode only from the call argument. */
5770 old_mode = GET_MODE (old_val);
5771 if (old_mode == VOIDmode)
5772 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5773 old_val = convert_modes (mode, old_mode, old_val, 1);
b6a5fc45 5774
1db6d067 5775 new_val = expand_expr (CALL_EXPR_ARG (exp, 2), NULL_RTX,
5776 mode, EXPAND_NORMAL);
a8bb7059 5777 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5778 of CONST_INTs, where we know the old_mode only from the call argument. */
5779 old_mode = GET_MODE (new_val);
5780 if (old_mode == VOIDmode)
5781 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2)));
5782 new_val = convert_modes (mode, old_mode, new_val, 1);
b6a5fc45 5783
b6a5fc45 5784 if (is_bool)
5785 return expand_bool_compare_and_swap (mem, old_val, new_val, target);
5786 else
5787 return expand_val_compare_and_swap (mem, old_val, new_val, target);
5788}
5789
5790/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
5791 general form is actually an atomic exchange, and some targets only
5792 support a reduced form with the second argument being a constant 1.
c2f47e15 5793 EXP is the CALL_EXPR; TARGET is an optional place for us to store
5794 the results. */
b6a5fc45 5795
5796static rtx
c2f47e15 5797expand_builtin_lock_test_and_set (enum machine_mode mode, tree exp,
3e272de8 5798 rtx target)
b6a5fc45 5799{
041e0215 5800 rtx val, mem;
a8bb7059 5801 enum machine_mode old_mode;
b6a5fc45 5802
5803 /* Expand the operands. */
c2f47e15 5804 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1db6d067 5805 val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
a8bb7059 5806 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5807 of CONST_INTs, where we know the old_mode only from the call argument. */
5808 old_mode = GET_MODE (val);
5809 if (old_mode == VOIDmode)
5810 old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
5811 val = convert_modes (mode, old_mode, val, 1);
b6a5fc45 5812
b6a5fc45 5813 return expand_sync_lock_test_and_set (mem, val, target);
5814}
5815
5816/* Expand the __sync_synchronize intrinsic. */
5817
5818static void
5819expand_builtin_synchronize (void)
5820{
16c9337c 5821 gimple x;
78f55ca8 5822 VEC (tree, gc) *v_clobbers;
b6a5fc45 5823
5824#ifdef HAVE_memory_barrier
5825 if (HAVE_memory_barrier)
5826 {
5827 emit_insn (gen_memory_barrier ());
5828 return;
5829 }
5830#endif
5831
047a7e40 5832 if (synchronize_libfunc != NULL_RTX)
5833 {
5834 emit_library_call (synchronize_libfunc, LCT_NORMAL, VOIDmode, 0);
5835 return;
5836 }
5837
82e58396 5838 /* If no explicit memory barrier instruction is available, create an
5839 empty asm stmt with a memory clobber. */
78f55ca8 5840 v_clobbers = VEC_alloc (tree, gc, 1);
5841 VEC_quick_push (tree, v_clobbers,
5842 tree_cons (NULL, build_string (6, "memory"), NULL));
5843 x = gimple_build_asm_vec ("", NULL, NULL, v_clobbers, NULL);
16c9337c 5844 gimple_asm_set_volatile (x, true);
5845 expand_asm_stmt (x);
b6a5fc45 5846}
5847
c2f47e15 5848/* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */
b6a5fc45 5849
5850static void
c2f47e15 5851expand_builtin_lock_release (enum machine_mode mode, tree exp)
b6a5fc45 5852{
b6a5fc45 5853 enum insn_code icode;
041e0215 5854 rtx mem, insn;
3e272de8 5855 rtx val = const0_rtx;
b6a5fc45 5856
5857 /* Expand the operands. */
c2f47e15 5858 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
b6a5fc45 5859
5860 /* If there is an explicit operation in the md file, use it. */
5861 icode = sync_lock_release[mode];
5862 if (icode != CODE_FOR_nothing)
5863 {
5864 if (!insn_data[icode].operand[1].predicate (val, mode))
5865 val = force_reg (mode, val);
5866
5867 insn = GEN_FCN (icode) (mem, val);
5868 if (insn)
5869 {
5870 emit_insn (insn);
5871 return;
5872 }
5873 }
5874
5875 /* Otherwise we can implement this operation by emitting a barrier
5876 followed by a store of zero. */
5877 expand_builtin_synchronize ();
5878 emit_move_insn (mem, val);
5879}
53800dbe 5880\f
5881/* Expand an expression EXP that calls a built-in function,
5882 with result going to TARGET if that's convenient
5883 (and in mode MODE if that's convenient).
5884 SUBTARGET may be used as the target for computing one of EXP's operands.
5885 IGNORE is nonzero if the value is to be ignored. */
5886
5887rtx
aecda0d6 5888expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
5889 int ignore)
53800dbe 5890{
c6e6ecb1 5891 tree fndecl = get_callee_fndecl (exp);
53800dbe 5892 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
efb070c8 5893 enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
53800dbe 5894
8305149e 5895 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
883b2e73 5896 return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
bf8e3599 5897
53800dbe 5898 /* When not optimizing, generate calls to library functions for a certain
5899 set of builtins. */
cd9ff771 5900 if (!optimize
b6a5fc45 5901 && !called_as_built_in (fndecl)
cd9ff771 5902 && DECL_ASSEMBLER_NAME_SET_P (fndecl)
2c281b15 5903 && fcode != BUILT_IN_ALLOCA
5904 && fcode != BUILT_IN_FREE)
cd9ff771 5905 return expand_call (exp, target, ignore);
53800dbe 5906
8d6d7930 5907 /* The built-in function expanders test for target == const0_rtx
5908 to determine whether the function's result will be ignored. */
5909 if (ignore)
5910 target = const0_rtx;
5911
5912 /* If the result of a pure or const built-in function is ignored, and
5913 none of its arguments are volatile, we can avoid expanding the
5914 built-in call and just evaluate the arguments for side-effects. */
5915 if (target == const0_rtx
9c2a0c05 5916 && (DECL_PURE_P (fndecl) || TREE_READONLY (fndecl)))
8d6d7930 5917 {
5918 bool volatilep = false;
5919 tree arg;
c2f47e15 5920 call_expr_arg_iterator iter;
8d6d7930 5921
c2f47e15 5922 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5923 if (TREE_THIS_VOLATILE (arg))
8d6d7930 5924 {
5925 volatilep = true;
5926 break;
5927 }
5928
5929 if (! volatilep)
5930 {
c2f47e15 5931 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5932 expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
8d6d7930 5933 return const0_rtx;
5934 }
5935 }
5936
53800dbe 5937 switch (fcode)
5938 {
4f35b1fc 5939 CASE_FLT_FN (BUILT_IN_FABS):
c2f47e15 5940 target = expand_builtin_fabs (exp, target, subtarget);
78a74442 5941 if (target)
a0c938f0 5942 return target;
78a74442 5943 break;
5944
4f35b1fc 5945 CASE_FLT_FN (BUILT_IN_COPYSIGN):
c2f47e15 5946 target = expand_builtin_copysign (exp, target, subtarget);
270436f3 5947 if (target)
5948 return target;
5949 break;
5950
7d3f6cc7 5951 /* Just do a normal library call if we were unable to fold
5952 the values. */
4f35b1fc 5953 CASE_FLT_FN (BUILT_IN_CABS):
78a74442 5954 break;
53800dbe 5955
4f35b1fc 5956 CASE_FLT_FN (BUILT_IN_EXP):
5957 CASE_FLT_FN (BUILT_IN_EXP10):
5958 CASE_FLT_FN (BUILT_IN_POW10):
5959 CASE_FLT_FN (BUILT_IN_EXP2):
5960 CASE_FLT_FN (BUILT_IN_EXPM1):
5961 CASE_FLT_FN (BUILT_IN_LOGB):
4f35b1fc 5962 CASE_FLT_FN (BUILT_IN_LOG):
5963 CASE_FLT_FN (BUILT_IN_LOG10):
5964 CASE_FLT_FN (BUILT_IN_LOG2):
5965 CASE_FLT_FN (BUILT_IN_LOG1P):
5966 CASE_FLT_FN (BUILT_IN_TAN):
5967 CASE_FLT_FN (BUILT_IN_ASIN):
5968 CASE_FLT_FN (BUILT_IN_ACOS):
5969 CASE_FLT_FN (BUILT_IN_ATAN):
b3154a1f 5970 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
7f3be425 5971 /* Treat these like sqrt only if unsafe math optimizations are allowed,
5972 because of possible accuracy problems. */
5973 if (! flag_unsafe_math_optimizations)
53800dbe 5974 break;
4f35b1fc 5975 CASE_FLT_FN (BUILT_IN_SQRT):
5976 CASE_FLT_FN (BUILT_IN_FLOOR):
5977 CASE_FLT_FN (BUILT_IN_CEIL):
5978 CASE_FLT_FN (BUILT_IN_TRUNC):
5979 CASE_FLT_FN (BUILT_IN_ROUND):
5980 CASE_FLT_FN (BUILT_IN_NEARBYINT):
5981 CASE_FLT_FN (BUILT_IN_RINT):
53800dbe 5982 target = expand_builtin_mathfn (exp, target, subtarget);
5983 if (target)
5984 return target;
5985 break;
5986
a67a90e5 5987 CASE_FLT_FN (BUILT_IN_ILOGB):
5988 if (! flag_unsafe_math_optimizations)
5989 break;
69b779ea 5990 CASE_FLT_FN (BUILT_IN_ISINF):
cde061c1 5991 CASE_FLT_FN (BUILT_IN_FINITE):
5992 case BUILT_IN_ISFINITE:
8a1a9cb7 5993 case BUILT_IN_ISNORMAL:
a67a90e5 5994 target = expand_builtin_interclass_mathfn (exp, target, subtarget);
5995 if (target)
5996 return target;
5997 break;
5998
4f35b1fc 5999 CASE_FLT_FN (BUILT_IN_LCEIL):
6000 CASE_FLT_FN (BUILT_IN_LLCEIL):
6001 CASE_FLT_FN (BUILT_IN_LFLOOR):
6002 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ff1b14e4 6003 target = expand_builtin_int_roundingfn (exp, target);
ad52b9b7 6004 if (target)
6005 return target;
6006 break;
6007
7d3afc77 6008 CASE_FLT_FN (BUILT_IN_LRINT):
6009 CASE_FLT_FN (BUILT_IN_LLRINT):
ef2f1a10 6010 CASE_FLT_FN (BUILT_IN_LROUND):
6011 CASE_FLT_FN (BUILT_IN_LLROUND):
ff1b14e4 6012 target = expand_builtin_int_roundingfn_2 (exp, target);
7d3afc77 6013 if (target)
6014 return target;
6015 break;
6016
4f35b1fc 6017 CASE_FLT_FN (BUILT_IN_POW):
f1b844c6 6018 target = expand_builtin_pow (exp, target, subtarget);
6019 if (target)
6020 return target;
6021 break;
6022
4f35b1fc 6023 CASE_FLT_FN (BUILT_IN_POWI):
757c219d 6024 target = expand_builtin_powi (exp, target, subtarget);
6025 if (target)
6026 return target;
6027 break;
6028
4f35b1fc 6029 CASE_FLT_FN (BUILT_IN_ATAN2):
6030 CASE_FLT_FN (BUILT_IN_LDEXP):
73a954a1 6031 CASE_FLT_FN (BUILT_IN_SCALB):
6032 CASE_FLT_FN (BUILT_IN_SCALBN):
6033 CASE_FLT_FN (BUILT_IN_SCALBLN):
0fd605a5 6034 if (! flag_unsafe_math_optimizations)
6035 break;
ef722005 6036
6037 CASE_FLT_FN (BUILT_IN_FMOD):
6038 CASE_FLT_FN (BUILT_IN_REMAINDER):
6039 CASE_FLT_FN (BUILT_IN_DREM):
0fd605a5 6040 target = expand_builtin_mathfn_2 (exp, target, subtarget);
6041 if (target)
6042 return target;
6043 break;
6044
d735c391 6045 CASE_FLT_FN (BUILT_IN_CEXPI):
6046 target = expand_builtin_cexpi (exp, target, subtarget);
6047 gcc_assert (target);
6048 return target;
6049
4f35b1fc 6050 CASE_FLT_FN (BUILT_IN_SIN):
6051 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 6052 if (! flag_unsafe_math_optimizations)
6053 break;
6054 target = expand_builtin_mathfn_3 (exp, target, subtarget);
6055 if (target)
6056 return target;
6057 break;
6058
c3147c1a 6059 CASE_FLT_FN (BUILT_IN_SINCOS):
6060 if (! flag_unsafe_math_optimizations)
6061 break;
6062 target = expand_builtin_sincos (exp);
6063 if (target)
6064 return target;
6065 break;
6066
53800dbe 6067 case BUILT_IN_APPLY_ARGS:
6068 return expand_builtin_apply_args ();
6069
6070 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
6071 FUNCTION with a copy of the parameters described by
6072 ARGUMENTS, and ARGSIZE. It returns a block of memory
6073 allocated on the stack into which is stored all the registers
6074 that might possibly be used for returning the result of a
6075 function. ARGUMENTS is the value returned by
6076 __builtin_apply_args. ARGSIZE is the number of bytes of
6077 arguments that must be copied. ??? How should this value be
6078 computed? We'll also need a safe worst case value for varargs
6079 functions. */
6080 case BUILT_IN_APPLY:
c2f47e15 6081 if (!validate_arglist (exp, POINTER_TYPE,
0eb671f7 6082 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
c2f47e15 6083 && !validate_arglist (exp, REFERENCE_TYPE,
0eb671f7 6084 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 6085 return const0_rtx;
6086 else
6087 {
53800dbe 6088 rtx ops[3];
6089
c2f47e15 6090 ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
6091 ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
6092 ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
53800dbe 6093
6094 return expand_builtin_apply (ops[0], ops[1], ops[2]);
6095 }
6096
6097 /* __builtin_return (RESULT) causes the function to return the
6098 value described by RESULT. RESULT is address of the block of
6099 memory returned by __builtin_apply. */
6100 case BUILT_IN_RETURN:
c2f47e15 6101 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
6102 expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
53800dbe 6103 return const0_rtx;
6104
6105 case BUILT_IN_SAVEREGS:
a66c9326 6106 return expand_builtin_saveregs ();
53800dbe 6107
6108 case BUILT_IN_ARGS_INFO:
c2f47e15 6109 return expand_builtin_args_info (exp);
53800dbe 6110
48dc2227 6111 case BUILT_IN_VA_ARG_PACK:
6112 /* All valid uses of __builtin_va_arg_pack () are removed during
6113 inlining. */
b8c23db3 6114 error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
48dc2227 6115 return const0_rtx;
6116
4e1d7ea4 6117 case BUILT_IN_VA_ARG_PACK_LEN:
6118 /* All valid uses of __builtin_va_arg_pack_len () are removed during
6119 inlining. */
b8c23db3 6120 error ("%Kinvalid use of %<__builtin_va_arg_pack_len ()%>", exp);
4e1d7ea4 6121 return const0_rtx;
6122
53800dbe 6123 /* Return the address of the first anonymous stack arg. */
6124 case BUILT_IN_NEXT_ARG:
c2f47e15 6125 if (fold_builtin_next_arg (exp, false))
a0c938f0 6126 return const0_rtx;
79012a9d 6127 return expand_builtin_next_arg ();
53800dbe 6128
ac8fb6db 6129 case BUILT_IN_CLEAR_CACHE:
6130 target = expand_builtin___clear_cache (exp);
6131 if (target)
6132 return target;
6133 break;
6134
53800dbe 6135 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 6136 return expand_builtin_classify_type (exp);
53800dbe 6137
6138 case BUILT_IN_CONSTANT_P:
4ee9c684 6139 return const0_rtx;
53800dbe 6140
6141 case BUILT_IN_FRAME_ADDRESS:
6142 case BUILT_IN_RETURN_ADDRESS:
c2f47e15 6143 return expand_builtin_frame_address (fndecl, exp);
53800dbe 6144
6145 /* Returns the address of the area where the structure is returned.
6146 0 otherwise. */
6147 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
c2f47e15 6148 if (call_expr_nargs (exp) != 0
9342ee68 6149 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
e16ceb8e 6150 || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
9342ee68 6151 return const0_rtx;
53800dbe 6152 else
9342ee68 6153 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
53800dbe 6154
6155 case BUILT_IN_ALLOCA:
c2f47e15 6156 target = expand_builtin_alloca (exp, target);
53800dbe 6157 if (target)
6158 return target;
6159 break;
6160
4ee9c684 6161 case BUILT_IN_STACK_SAVE:
6162 return expand_stack_save ();
6163
6164 case BUILT_IN_STACK_RESTORE:
c2f47e15 6165 expand_stack_restore (CALL_EXPR_ARG (exp, 0));
4ee9c684 6166 return const0_rtx;
6167
42791117 6168 case BUILT_IN_BSWAP32:
6169 case BUILT_IN_BSWAP64:
c2f47e15 6170 target = expand_builtin_bswap (exp, target, subtarget);
42791117 6171
6172 if (target)
6173 return target;
6174 break;
6175
4f35b1fc 6176 CASE_INT_FN (BUILT_IN_FFS):
5053259b 6177 case BUILT_IN_FFSIMAX:
c2f47e15 6178 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6179 subtarget, ffs_optab);
6a08d0ab 6180 if (target)
6181 return target;
6182 break;
6183
4f35b1fc 6184 CASE_INT_FN (BUILT_IN_CLZ):
5053259b 6185 case BUILT_IN_CLZIMAX:
c2f47e15 6186 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6187 subtarget, clz_optab);
6a08d0ab 6188 if (target)
6189 return target;
6190 break;
6191
4f35b1fc 6192 CASE_INT_FN (BUILT_IN_CTZ):
5053259b 6193 case BUILT_IN_CTZIMAX:
c2f47e15 6194 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6195 subtarget, ctz_optab);
6a08d0ab 6196 if (target)
6197 return target;
6198 break;
6199
4f35b1fc 6200 CASE_INT_FN (BUILT_IN_POPCOUNT):
5053259b 6201 case BUILT_IN_POPCOUNTIMAX:
c2f47e15 6202 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6203 subtarget, popcount_optab);
6a08d0ab 6204 if (target)
6205 return target;
6206 break;
6207
4f35b1fc 6208 CASE_INT_FN (BUILT_IN_PARITY):
5053259b 6209 case BUILT_IN_PARITYIMAX:
c2f47e15 6210 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6211 subtarget, parity_optab);
53800dbe 6212 if (target)
6213 return target;
6214 break;
6215
6216 case BUILT_IN_STRLEN:
c2f47e15 6217 target = expand_builtin_strlen (exp, target, target_mode);
53800dbe 6218 if (target)
6219 return target;
6220 break;
6221
6222 case BUILT_IN_STRCPY:
a65c4d64 6223 target = expand_builtin_strcpy (exp, target);
53800dbe 6224 if (target)
6225 return target;
6226 break;
bf8e3599 6227
ed09096d 6228 case BUILT_IN_STRNCPY:
a65c4d64 6229 target = expand_builtin_strncpy (exp, target);
ed09096d 6230 if (target)
6231 return target;
6232 break;
bf8e3599 6233
3b824fa6 6234 case BUILT_IN_STPCPY:
dc369150 6235 target = expand_builtin_stpcpy (exp, target, mode);
3b824fa6 6236 if (target)
6237 return target;
6238 break;
6239
53800dbe 6240 case BUILT_IN_MEMCPY:
a65c4d64 6241 target = expand_builtin_memcpy (exp, target);
3b824fa6 6242 if (target)
6243 return target;
6244 break;
6245
6246 case BUILT_IN_MEMPCPY:
c2f47e15 6247 target = expand_builtin_mempcpy (exp, target, mode);
53800dbe 6248 if (target)
6249 return target;
6250 break;
6251
6252 case BUILT_IN_MEMSET:
c2f47e15 6253 target = expand_builtin_memset (exp, target, mode);
53800dbe 6254 if (target)
6255 return target;
6256 break;
6257
ffc83088 6258 case BUILT_IN_BZERO:
0b25db21 6259 target = expand_builtin_bzero (exp);
ffc83088 6260 if (target)
6261 return target;
6262 break;
6263
53800dbe 6264 case BUILT_IN_STRCMP:
a65c4d64 6265 target = expand_builtin_strcmp (exp, target);
53800dbe 6266 if (target)
6267 return target;
6268 break;
6269
ed09096d 6270 case BUILT_IN_STRNCMP:
6271 target = expand_builtin_strncmp (exp, target, mode);
6272 if (target)
6273 return target;
6274 break;
6275
071f1696 6276 case BUILT_IN_BCMP:
53800dbe 6277 case BUILT_IN_MEMCMP:
c2f47e15 6278 target = expand_builtin_memcmp (exp, target, mode);
53800dbe 6279 if (target)
6280 return target;
6281 break;
53800dbe 6282
6283 case BUILT_IN_SETJMP:
2c8a1497 6284 /* This should have been lowered to the builtins below. */
6285 gcc_unreachable ();
6286
6287 case BUILT_IN_SETJMP_SETUP:
6288 /* __builtin_setjmp_setup is passed a pointer to an array of five words
6289 and the receiver label. */
c2f47e15 6290 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2c8a1497 6291 {
c2f47e15 6292 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
2c8a1497 6293 VOIDmode, EXPAND_NORMAL);
c2f47e15 6294 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
2c8a1497 6295 rtx label_r = label_rtx (label);
6296
6297 /* This is copied from the handling of non-local gotos. */
6298 expand_builtin_setjmp_setup (buf_addr, label_r);
6299 nonlocal_goto_handler_labels
6300 = gen_rtx_EXPR_LIST (VOIDmode, label_r,
6301 nonlocal_goto_handler_labels);
6302 /* ??? Do not let expand_label treat us as such since we would
6303 not want to be both on the list of non-local labels and on
6304 the list of forced labels. */
6305 FORCED_LABEL (label) = 0;
6306 return const0_rtx;
6307 }
6308 break;
6309
6310 case BUILT_IN_SETJMP_DISPATCHER:
6311 /* __builtin_setjmp_dispatcher is passed the dispatcher label. */
c2f47e15 6312 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6313 {
c2f47e15 6314 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6315 rtx label_r = label_rtx (label);
6316
6317 /* Remove the dispatcher label from the list of non-local labels
6318 since the receiver labels have been added to it above. */
6319 remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels);
6320 return const0_rtx;
6321 }
6322 break;
6323
6324 case BUILT_IN_SETJMP_RECEIVER:
6325 /* __builtin_setjmp_receiver is passed the receiver label. */
c2f47e15 6326 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6327 {
c2f47e15 6328 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6329 rtx label_r = label_rtx (label);
6330
6331 expand_builtin_setjmp_receiver (label_r);
6332 return const0_rtx;
6333 }
6b7f6858 6334 break;
53800dbe 6335
6336 /* __builtin_longjmp is passed a pointer to an array of five words.
6337 It's similar to the C library longjmp function but works with
6338 __builtin_setjmp above. */
6339 case BUILT_IN_LONGJMP:
c2f47e15 6340 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 6341 {
c2f47e15 6342 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
8ec3c5c2 6343 VOIDmode, EXPAND_NORMAL);
c2f47e15 6344 rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
53800dbe 6345
6346 if (value != const1_rtx)
6347 {
1e5fcbe2 6348 error ("%<__builtin_longjmp%> second argument must be 1");
53800dbe 6349 return const0_rtx;
6350 }
6351
6352 expand_builtin_longjmp (buf_addr, value);
6353 return const0_rtx;
6354 }
2c8a1497 6355 break;
53800dbe 6356
4ee9c684 6357 case BUILT_IN_NONLOCAL_GOTO:
c2f47e15 6358 target = expand_builtin_nonlocal_goto (exp);
4ee9c684 6359 if (target)
6360 return target;
6361 break;
6362
843d08a9 6363 /* This updates the setjmp buffer that is its argument with the value
6364 of the current stack pointer. */
6365 case BUILT_IN_UPDATE_SETJMP_BUF:
c2f47e15 6366 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
843d08a9 6367 {
6368 rtx buf_addr
c2f47e15 6369 = expand_normal (CALL_EXPR_ARG (exp, 0));
843d08a9 6370
6371 expand_builtin_update_setjmp_buf (buf_addr);
6372 return const0_rtx;
6373 }
6374 break;
6375
53800dbe 6376 case BUILT_IN_TRAP:
a0ef1725 6377 expand_builtin_trap ();
53800dbe 6378 return const0_rtx;
6379
d2b48f0c 6380 case BUILT_IN_UNREACHABLE:
6381 expand_builtin_unreachable ();
6382 return const0_rtx;
6383
19bf118a 6384 case BUILT_IN_PRINTF:
0b25db21 6385 target = expand_builtin_printf (exp, target, mode, false);
19bf118a 6386 if (target)
6387 return target;
6388 break;
6389
6390 case BUILT_IN_PRINTF_UNLOCKED:
0b25db21 6391 target = expand_builtin_printf (exp, target, mode, true);
19bf118a 6392 if (target)
6393 return target;
6394 break;
6395
19bf118a 6396 case BUILT_IN_FPRINTF:
0b25db21 6397 target = expand_builtin_fprintf (exp, target, mode, false);
19bf118a 6398 if (target)
6399 return target;
6400 break;
6401
6402 case BUILT_IN_FPRINTF_UNLOCKED:
0b25db21 6403 target = expand_builtin_fprintf (exp, target, mode, true);
df94cd3b 6404 if (target)
6405 return target;
6406 break;
bf8e3599 6407
6411575e 6408 case BUILT_IN_SPRINTF:
c2f47e15 6409 target = expand_builtin_sprintf (exp, target, mode);
6411575e 6410 if (target)
6411 return target;
6412 break;
6413
4f35b1fc 6414 CASE_FLT_FN (BUILT_IN_SIGNBIT):
004e23c4 6415 case BUILT_IN_SIGNBITD32:
6416 case BUILT_IN_SIGNBITD64:
6417 case BUILT_IN_SIGNBITD128:
27f261ef 6418 target = expand_builtin_signbit (exp, target);
6419 if (target)
6420 return target;
6421 break;
6422
53800dbe 6423 /* Various hooks for the DWARF 2 __throw routine. */
6424 case BUILT_IN_UNWIND_INIT:
6425 expand_builtin_unwind_init ();
6426 return const0_rtx;
6427 case BUILT_IN_DWARF_CFA:
6428 return virtual_cfa_rtx;
6429#ifdef DWARF2_UNWIND_INFO
f8f023a5 6430 case BUILT_IN_DWARF_SP_COLUMN:
6431 return expand_builtin_dwarf_sp_column ();
695e919b 6432 case BUILT_IN_INIT_DWARF_REG_SIZES:
c2f47e15 6433 expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
695e919b 6434 return const0_rtx;
53800dbe 6435#endif
6436 case BUILT_IN_FROB_RETURN_ADDR:
c2f47e15 6437 return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6438 case BUILT_IN_EXTRACT_RETURN_ADDR:
c2f47e15 6439 return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6440 case BUILT_IN_EH_RETURN:
c2f47e15 6441 expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
6442 CALL_EXPR_ARG (exp, 1));
53800dbe 6443 return const0_rtx;
df4b504c 6444#ifdef EH_RETURN_DATA_REGNO
6445 case BUILT_IN_EH_RETURN_DATA_REGNO:
c2f47e15 6446 return expand_builtin_eh_return_data_regno (exp);
df4b504c 6447#endif
26093bf4 6448 case BUILT_IN_EXTEND_POINTER:
c2f47e15 6449 return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
e38def9c 6450 case BUILT_IN_EH_POINTER:
6451 return expand_builtin_eh_pointer (exp);
6452 case BUILT_IN_EH_FILTER:
6453 return expand_builtin_eh_filter (exp);
6454 case BUILT_IN_EH_COPY_VALUES:
6455 return expand_builtin_eh_copy_values (exp);
26093bf4 6456
7ccc713a 6457 case BUILT_IN_VA_START:
c2f47e15 6458 return expand_builtin_va_start (exp);
a66c9326 6459 case BUILT_IN_VA_END:
c2f47e15 6460 return expand_builtin_va_end (exp);
a66c9326 6461 case BUILT_IN_VA_COPY:
c2f47e15 6462 return expand_builtin_va_copy (exp);
89cfe6e5 6463 case BUILT_IN_EXPECT:
c2f47e15 6464 return expand_builtin_expect (exp, target);
5e3608d8 6465 case BUILT_IN_PREFETCH:
c2f47e15 6466 expand_builtin_prefetch (exp);
5e3608d8 6467 return const0_rtx;
6468
4ee9c684 6469 case BUILT_IN_PROFILE_FUNC_ENTER:
6470 return expand_builtin_profile_func (false);
6471 case BUILT_IN_PROFILE_FUNC_EXIT:
6472 return expand_builtin_profile_func (true);
6473
6474 case BUILT_IN_INIT_TRAMPOLINE:
c2f47e15 6475 return expand_builtin_init_trampoline (exp);
4ee9c684 6476 case BUILT_IN_ADJUST_TRAMPOLINE:
c2f47e15 6477 return expand_builtin_adjust_trampoline (exp);
4ee9c684 6478
73673831 6479 case BUILT_IN_FORK:
6480 case BUILT_IN_EXECL:
6481 case BUILT_IN_EXECV:
6482 case BUILT_IN_EXECLP:
6483 case BUILT_IN_EXECLE:
6484 case BUILT_IN_EXECVP:
6485 case BUILT_IN_EXECVE:
c2f47e15 6486 target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
73673831 6487 if (target)
6488 return target;
6489 break;
53800dbe 6490
b6a5fc45 6491 case BUILT_IN_FETCH_AND_ADD_1:
6492 case BUILT_IN_FETCH_AND_ADD_2:
6493 case BUILT_IN_FETCH_AND_ADD_4:
6494 case BUILT_IN_FETCH_AND_ADD_8:
27213ba3 6495 case BUILT_IN_FETCH_AND_ADD_16:
3e272de8 6496 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_ADD_1);
c2f47e15 6497 target = expand_builtin_sync_operation (mode, exp, PLUS,
b6a5fc45 6498 false, target, ignore);
6499 if (target)
6500 return target;
6501 break;
6502
6503 case BUILT_IN_FETCH_AND_SUB_1:
6504 case BUILT_IN_FETCH_AND_SUB_2:
6505 case BUILT_IN_FETCH_AND_SUB_4:
6506 case BUILT_IN_FETCH_AND_SUB_8:
27213ba3 6507 case BUILT_IN_FETCH_AND_SUB_16:
3e272de8 6508 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_SUB_1);
c2f47e15 6509 target = expand_builtin_sync_operation (mode, exp, MINUS,
b6a5fc45 6510 false, target, ignore);
6511 if (target)
6512 return target;
6513 break;
6514
6515 case BUILT_IN_FETCH_AND_OR_1:
6516 case BUILT_IN_FETCH_AND_OR_2:
6517 case BUILT_IN_FETCH_AND_OR_4:
6518 case BUILT_IN_FETCH_AND_OR_8:
27213ba3 6519 case BUILT_IN_FETCH_AND_OR_16:
3e272de8 6520 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_OR_1);
c2f47e15 6521 target = expand_builtin_sync_operation (mode, exp, IOR,
b6a5fc45 6522 false, target, ignore);
6523 if (target)
6524 return target;
6525 break;
6526
6527 case BUILT_IN_FETCH_AND_AND_1:
6528 case BUILT_IN_FETCH_AND_AND_2:
6529 case BUILT_IN_FETCH_AND_AND_4:
6530 case BUILT_IN_FETCH_AND_AND_8:
27213ba3 6531 case BUILT_IN_FETCH_AND_AND_16:
3e272de8 6532 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_AND_1);
c2f47e15 6533 target = expand_builtin_sync_operation (mode, exp, AND,
b6a5fc45 6534 false, target, ignore);
6535 if (target)
6536 return target;
6537 break;
6538
6539 case BUILT_IN_FETCH_AND_XOR_1:
6540 case BUILT_IN_FETCH_AND_XOR_2:
6541 case BUILT_IN_FETCH_AND_XOR_4:
6542 case BUILT_IN_FETCH_AND_XOR_8:
27213ba3 6543 case BUILT_IN_FETCH_AND_XOR_16:
3e272de8 6544 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_XOR_1);
c2f47e15 6545 target = expand_builtin_sync_operation (mode, exp, XOR,
b6a5fc45 6546 false, target, ignore);
6547 if (target)
6548 return target;
6549 break;
6550
6551 case BUILT_IN_FETCH_AND_NAND_1:
6552 case BUILT_IN_FETCH_AND_NAND_2:
6553 case BUILT_IN_FETCH_AND_NAND_4:
6554 case BUILT_IN_FETCH_AND_NAND_8:
27213ba3 6555 case BUILT_IN_FETCH_AND_NAND_16:
3e272de8 6556 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_NAND_1);
c2f47e15 6557 target = expand_builtin_sync_operation (mode, exp, NOT,
b6a5fc45 6558 false, target, ignore);
6559 if (target)
6560 return target;
6561 break;
6562
6563 case BUILT_IN_ADD_AND_FETCH_1:
6564 case BUILT_IN_ADD_AND_FETCH_2:
6565 case BUILT_IN_ADD_AND_FETCH_4:
6566 case BUILT_IN_ADD_AND_FETCH_8:
27213ba3 6567 case BUILT_IN_ADD_AND_FETCH_16:
3e272de8 6568 mode = get_builtin_sync_mode (fcode - BUILT_IN_ADD_AND_FETCH_1);
c2f47e15 6569 target = expand_builtin_sync_operation (mode, exp, PLUS,
b6a5fc45 6570 true, target, ignore);
6571 if (target)
6572 return target;
6573 break;
6574
6575 case BUILT_IN_SUB_AND_FETCH_1:
6576 case BUILT_IN_SUB_AND_FETCH_2:
6577 case BUILT_IN_SUB_AND_FETCH_4:
6578 case BUILT_IN_SUB_AND_FETCH_8:
27213ba3 6579 case BUILT_IN_SUB_AND_FETCH_16:
3e272de8 6580 mode = get_builtin_sync_mode (fcode - BUILT_IN_SUB_AND_FETCH_1);
c2f47e15 6581 target = expand_builtin_sync_operation (mode, exp, MINUS,
b6a5fc45 6582 true, target, ignore);
6583 if (target)
6584 return target;
6585 break;
6586
6587 case BUILT_IN_OR_AND_FETCH_1:
6588 case BUILT_IN_OR_AND_FETCH_2:
6589 case BUILT_IN_OR_AND_FETCH_4:
6590 case BUILT_IN_OR_AND_FETCH_8:
27213ba3 6591 case BUILT_IN_OR_AND_FETCH_16:
3e272de8 6592 mode = get_builtin_sync_mode (fcode - BUILT_IN_OR_AND_FETCH_1);
c2f47e15 6593 target = expand_builtin_sync_operation (mode, exp, IOR,
b6a5fc45 6594 true, target, ignore);
6595 if (target)
6596 return target;
6597 break;
6598
6599 case BUILT_IN_AND_AND_FETCH_1:
6600 case BUILT_IN_AND_AND_FETCH_2:
6601 case BUILT_IN_AND_AND_FETCH_4:
6602 case BUILT_IN_AND_AND_FETCH_8:
27213ba3 6603 case BUILT_IN_AND_AND_FETCH_16:
3e272de8 6604 mode = get_builtin_sync_mode (fcode - BUILT_IN_AND_AND_FETCH_1);
c2f47e15 6605 target = expand_builtin_sync_operation (mode, exp, AND,
b6a5fc45 6606 true, target, ignore);
6607 if (target)
6608 return target;
6609 break;
6610
6611 case BUILT_IN_XOR_AND_FETCH_1:
6612 case BUILT_IN_XOR_AND_FETCH_2:
6613 case BUILT_IN_XOR_AND_FETCH_4:
6614 case BUILT_IN_XOR_AND_FETCH_8:
27213ba3 6615 case BUILT_IN_XOR_AND_FETCH_16:
3e272de8 6616 mode = get_builtin_sync_mode (fcode - BUILT_IN_XOR_AND_FETCH_1);
c2f47e15 6617 target = expand_builtin_sync_operation (mode, exp, XOR,
b6a5fc45 6618 true, target, ignore);
6619 if (target)
6620 return target;
6621 break;
6622
6623 case BUILT_IN_NAND_AND_FETCH_1:
6624 case BUILT_IN_NAND_AND_FETCH_2:
6625 case BUILT_IN_NAND_AND_FETCH_4:
6626 case BUILT_IN_NAND_AND_FETCH_8:
27213ba3 6627 case BUILT_IN_NAND_AND_FETCH_16:
3e272de8 6628 mode = get_builtin_sync_mode (fcode - BUILT_IN_NAND_AND_FETCH_1);
c2f47e15 6629 target = expand_builtin_sync_operation (mode, exp, NOT,
b6a5fc45 6630 true, target, ignore);
6631 if (target)
6632 return target;
6633 break;
6634
6635 case BUILT_IN_BOOL_COMPARE_AND_SWAP_1:
6636 case BUILT_IN_BOOL_COMPARE_AND_SWAP_2:
6637 case BUILT_IN_BOOL_COMPARE_AND_SWAP_4:
6638 case BUILT_IN_BOOL_COMPARE_AND_SWAP_8:
27213ba3 6639 case BUILT_IN_BOOL_COMPARE_AND_SWAP_16:
a601d32a 6640 if (mode == VOIDmode)
6641 mode = TYPE_MODE (boolean_type_node);
b6a5fc45 6642 if (!target || !register_operand (target, mode))
6643 target = gen_reg_rtx (mode);
3e272de8 6644
6645 mode = get_builtin_sync_mode (fcode - BUILT_IN_BOOL_COMPARE_AND_SWAP_1);
c2f47e15 6646 target = expand_builtin_compare_and_swap (mode, exp, true, target);
b6a5fc45 6647 if (target)
6648 return target;
6649 break;
6650
6651 case BUILT_IN_VAL_COMPARE_AND_SWAP_1:
6652 case BUILT_IN_VAL_COMPARE_AND_SWAP_2:
6653 case BUILT_IN_VAL_COMPARE_AND_SWAP_4:
6654 case BUILT_IN_VAL_COMPARE_AND_SWAP_8:
27213ba3 6655 case BUILT_IN_VAL_COMPARE_AND_SWAP_16:
3e272de8 6656 mode = get_builtin_sync_mode (fcode - BUILT_IN_VAL_COMPARE_AND_SWAP_1);
c2f47e15 6657 target = expand_builtin_compare_and_swap (mode, exp, false, target);
b6a5fc45 6658 if (target)
6659 return target;
6660 break;
6661
6662 case BUILT_IN_LOCK_TEST_AND_SET_1:
6663 case BUILT_IN_LOCK_TEST_AND_SET_2:
6664 case BUILT_IN_LOCK_TEST_AND_SET_4:
6665 case BUILT_IN_LOCK_TEST_AND_SET_8:
27213ba3 6666 case BUILT_IN_LOCK_TEST_AND_SET_16:
3e272de8 6667 mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_TEST_AND_SET_1);
c2f47e15 6668 target = expand_builtin_lock_test_and_set (mode, exp, target);
b6a5fc45 6669 if (target)
6670 return target;
6671 break;
6672
6673 case BUILT_IN_LOCK_RELEASE_1:
6674 case BUILT_IN_LOCK_RELEASE_2:
6675 case BUILT_IN_LOCK_RELEASE_4:
6676 case BUILT_IN_LOCK_RELEASE_8:
27213ba3 6677 case BUILT_IN_LOCK_RELEASE_16:
3e272de8 6678 mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_RELEASE_1);
c2f47e15 6679 expand_builtin_lock_release (mode, exp);
b6a5fc45 6680 return const0_rtx;
6681
6682 case BUILT_IN_SYNCHRONIZE:
6683 expand_builtin_synchronize ();
6684 return const0_rtx;
6685
0a39fd54 6686 case BUILT_IN_OBJECT_SIZE:
6687 return expand_builtin_object_size (exp);
6688
6689 case BUILT_IN_MEMCPY_CHK:
6690 case BUILT_IN_MEMPCPY_CHK:
6691 case BUILT_IN_MEMMOVE_CHK:
6692 case BUILT_IN_MEMSET_CHK:
6693 target = expand_builtin_memory_chk (exp, target, mode, fcode);
6694 if (target)
6695 return target;
6696 break;
6697
6698 case BUILT_IN_STRCPY_CHK:
6699 case BUILT_IN_STPCPY_CHK:
6700 case BUILT_IN_STRNCPY_CHK:
6701 case BUILT_IN_STRCAT_CHK:
b356dfef 6702 case BUILT_IN_STRNCAT_CHK:
0a39fd54 6703 case BUILT_IN_SNPRINTF_CHK:
6704 case BUILT_IN_VSNPRINTF_CHK:
6705 maybe_emit_chk_warning (exp, fcode);
6706 break;
6707
6708 case BUILT_IN_SPRINTF_CHK:
6709 case BUILT_IN_VSPRINTF_CHK:
6710 maybe_emit_sprintf_chk_warning (exp, fcode);
6711 break;
6712
2c281b15 6713 case BUILT_IN_FREE:
6714 maybe_emit_free_warning (exp);
6715 break;
6716
92482ee0 6717 default: /* just do library call, if unknown builtin */
146c1b4f 6718 break;
53800dbe 6719 }
6720
6721 /* The switch statement above can drop through to cause the function
6722 to be called normally. */
6723 return expand_call (exp, target, ignore);
6724}
650e4c94 6725
805e22b2 6726/* Determine whether a tree node represents a call to a built-in
52203a9d 6727 function. If the tree T is a call to a built-in function with
6728 the right number of arguments of the appropriate types, return
6729 the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
6730 Otherwise the return value is END_BUILTINS. */
aecda0d6 6731
805e22b2 6732enum built_in_function
b7bf20db 6733builtin_mathfn_code (const_tree t)
805e22b2 6734{
b7bf20db 6735 const_tree fndecl, arg, parmlist;
6736 const_tree argtype, parmtype;
6737 const_call_expr_arg_iterator iter;
805e22b2 6738
6739 if (TREE_CODE (t) != CALL_EXPR
c2f47e15 6740 || TREE_CODE (CALL_EXPR_FN (t)) != ADDR_EXPR)
805e22b2 6741 return END_BUILTINS;
6742
c6e6ecb1 6743 fndecl = get_callee_fndecl (t);
6744 if (fndecl == NULL_TREE
52203a9d 6745 || TREE_CODE (fndecl) != FUNCTION_DECL
805e22b2 6746 || ! DECL_BUILT_IN (fndecl)
6747 || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
6748 return END_BUILTINS;
6749
52203a9d 6750 parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
b7bf20db 6751 init_const_call_expr_arg_iterator (t, &iter);
52203a9d 6752 for (; parmlist; parmlist = TREE_CHAIN (parmlist))
e9f80ff5 6753 {
52203a9d 6754 /* If a function doesn't take a variable number of arguments,
6755 the last element in the list will have type `void'. */
6756 parmtype = TREE_VALUE (parmlist);
6757 if (VOID_TYPE_P (parmtype))
6758 {
b7bf20db 6759 if (more_const_call_expr_args_p (&iter))
52203a9d 6760 return END_BUILTINS;
6761 return DECL_FUNCTION_CODE (fndecl);
6762 }
6763
b7bf20db 6764 if (! more_const_call_expr_args_p (&iter))
e9f80ff5 6765 return END_BUILTINS;
c2f47e15 6766
b7bf20db 6767 arg = next_const_call_expr_arg (&iter);
c2f47e15 6768 argtype = TREE_TYPE (arg);
52203a9d 6769
6770 if (SCALAR_FLOAT_TYPE_P (parmtype))
6771 {
6772 if (! SCALAR_FLOAT_TYPE_P (argtype))
6773 return END_BUILTINS;
6774 }
6775 else if (COMPLEX_FLOAT_TYPE_P (parmtype))
6776 {
6777 if (! COMPLEX_FLOAT_TYPE_P (argtype))
6778 return END_BUILTINS;
6779 }
6780 else if (POINTER_TYPE_P (parmtype))
6781 {
6782 if (! POINTER_TYPE_P (argtype))
6783 return END_BUILTINS;
6784 }
6785 else if (INTEGRAL_TYPE_P (parmtype))
6786 {
6787 if (! INTEGRAL_TYPE_P (argtype))
6788 return END_BUILTINS;
6789 }
6790 else
e9f80ff5 6791 return END_BUILTINS;
e9f80ff5 6792 }
6793
52203a9d 6794 /* Variable-length argument list. */
805e22b2 6795 return DECL_FUNCTION_CODE (fndecl);
6796}
6797
c2f47e15 6798/* Fold a call to __builtin_constant_p, if we know its argument ARG will
6799 evaluate to a constant. */
650e4c94 6800
6801static tree
c2f47e15 6802fold_builtin_constant_p (tree arg)
650e4c94 6803{
650e4c94 6804 /* We return 1 for a numeric type that's known to be a constant
6805 value at compile-time or for an aggregate type that's a
6806 literal constant. */
c2f47e15 6807 STRIP_NOPS (arg);
650e4c94 6808
6809 /* If we know this is a constant, emit the constant of one. */
c2f47e15 6810 if (CONSTANT_CLASS_P (arg)
6811 || (TREE_CODE (arg) == CONSTRUCTOR
6812 && TREE_CONSTANT (arg)))
650e4c94 6813 return integer_one_node;
c2f47e15 6814 if (TREE_CODE (arg) == ADDR_EXPR)
adcfa3a3 6815 {
c2f47e15 6816 tree op = TREE_OPERAND (arg, 0);
adcfa3a3 6817 if (TREE_CODE (op) == STRING_CST
6818 || (TREE_CODE (op) == ARRAY_REF
6819 && integer_zerop (TREE_OPERAND (op, 1))
6820 && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
6821 return integer_one_node;
6822 }
650e4c94 6823
1fb4300c 6824 /* If this expression has side effects, show we don't know it to be a
6825 constant. Likewise if it's a pointer or aggregate type since in
6826 those case we only want literals, since those are only optimized
f97c71a1 6827 when generating RTL, not later.
6828 And finally, if we are compiling an initializer, not code, we
6829 need to return a definite result now; there's not going to be any
6830 more optimization done. */
c2f47e15 6831 if (TREE_SIDE_EFFECTS (arg)
6832 || AGGREGATE_TYPE_P (TREE_TYPE (arg))
6833 || POINTER_TYPE_P (TREE_TYPE (arg))
47be647d 6834 || cfun == 0
6835 || folding_initializer)
650e4c94 6836 return integer_zero_node;
6837
c2f47e15 6838 return NULL_TREE;
650e4c94 6839}
6840
76f5a783 6841/* Create builtin_expect with PRED and EXPECTED as its arguments and
6842 return it as a truthvalue. */
4ee9c684 6843
6844static tree
389dd41b 6845build_builtin_expect_predicate (location_t loc, tree pred, tree expected)
4ee9c684 6846{
76f5a783 6847 tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
4ee9c684 6848
76f5a783 6849 fn = built_in_decls[BUILT_IN_EXPECT];
6850 arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
6851 ret_type = TREE_TYPE (TREE_TYPE (fn));
6852 pred_type = TREE_VALUE (arg_types);
6853 expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
6854
389dd41b 6855 pred = fold_convert_loc (loc, pred_type, pred);
6856 expected = fold_convert_loc (loc, expected_type, expected);
6857 call_expr = build_call_expr_loc (loc, fn, 2, pred, expected);
76f5a783 6858
6859 return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
6860 build_int_cst (ret_type, 0));
6861}
6862
6863/* Fold a call to builtin_expect with arguments ARG0 and ARG1. Return
6864 NULL_TREE if no simplification is possible. */
6865
6866static tree
389dd41b 6867fold_builtin_expect (location_t loc, tree arg0, tree arg1)
76f5a783 6868{
6869 tree inner, fndecl;
6870 enum tree_code code;
6871
6872 /* If this is a builtin_expect within a builtin_expect keep the
6873 inner one. See through a comparison against a constant. It
6874 might have been added to create a thruthvalue. */
6875 inner = arg0;
6876 if (COMPARISON_CLASS_P (inner)
6877 && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST)
6878 inner = TREE_OPERAND (inner, 0);
6879
6880 if (TREE_CODE (inner) == CALL_EXPR
6881 && (fndecl = get_callee_fndecl (inner))
6882 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
6883 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT)
6884 return arg0;
6885
6886 /* Distribute the expected value over short-circuiting operators.
6887 See through the cast from truthvalue_type_node to long. */
6888 inner = arg0;
6889 while (TREE_CODE (inner) == NOP_EXPR
6890 && INTEGRAL_TYPE_P (TREE_TYPE (inner))
6891 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner, 0))))
6892 inner = TREE_OPERAND (inner, 0);
6893
6894 code = TREE_CODE (inner);
6895 if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
6896 {
6897 tree op0 = TREE_OPERAND (inner, 0);
6898 tree op1 = TREE_OPERAND (inner, 1);
6899
389dd41b 6900 op0 = build_builtin_expect_predicate (loc, op0, arg1);
6901 op1 = build_builtin_expect_predicate (loc, op1, arg1);
76f5a783 6902 inner = build2 (code, TREE_TYPE (inner), op0, op1);
6903
389dd41b 6904 return fold_convert_loc (loc, TREE_TYPE (arg0), inner);
76f5a783 6905 }
6906
6907 /* If the argument isn't invariant then there's nothing else we can do. */
c7d4e749 6908 if (!TREE_CONSTANT (arg0))
c2f47e15 6909 return NULL_TREE;
4ee9c684 6910
76f5a783 6911 /* If we expect that a comparison against the argument will fold to
6912 a constant return the constant. In practice, this means a true
6913 constant or the address of a non-weak symbol. */
6914 inner = arg0;
4ee9c684 6915 STRIP_NOPS (inner);
6916 if (TREE_CODE (inner) == ADDR_EXPR)
6917 {
6918 do
6919 {
6920 inner = TREE_OPERAND (inner, 0);
6921 }
6922 while (TREE_CODE (inner) == COMPONENT_REF
6923 || TREE_CODE (inner) == ARRAY_REF);
062b4460 6924 if ((TREE_CODE (inner) == VAR_DECL
6925 || TREE_CODE (inner) == FUNCTION_DECL)
6926 && DECL_WEAK (inner))
c2f47e15 6927 return NULL_TREE;
4ee9c684 6928 }
6929
76f5a783 6930 /* Otherwise, ARG0 already has the proper type for the return value. */
6931 return arg0;
4ee9c684 6932}
6933
c2f47e15 6934/* Fold a call to __builtin_classify_type with argument ARG. */
27d0c333 6935
539a3a92 6936static tree
c2f47e15 6937fold_builtin_classify_type (tree arg)
539a3a92 6938{
c2f47e15 6939 if (arg == 0)
7016c612 6940 return build_int_cst (NULL_TREE, no_type_class);
539a3a92 6941
c2f47e15 6942 return build_int_cst (NULL_TREE, type_to_class (TREE_TYPE (arg)));
539a3a92 6943}
6944
c2f47e15 6945/* Fold a call to __builtin_strlen with argument ARG. */
e6e27594 6946
6947static tree
389dd41b 6948fold_builtin_strlen (location_t loc, tree arg)
e6e27594 6949{
c2f47e15 6950 if (!validate_arg (arg, POINTER_TYPE))
e6e27594 6951 return NULL_TREE;
6952 else
6953 {
c2f47e15 6954 tree len = c_strlen (arg, 0);
e6e27594 6955
6956 if (len)
6957 {
6958 /* Convert from the internal "sizetype" type to "size_t". */
6959 if (size_type_node)
389dd41b 6960 len = fold_convert_loc (loc, size_type_node, len);
e6e27594 6961 return len;
6962 }
6963
6964 return NULL_TREE;
6965 }
6966}
6967
92c43e3c 6968/* Fold a call to __builtin_inf or __builtin_huge_val. */
6969
6970static tree
389dd41b 6971fold_builtin_inf (location_t loc, tree type, int warn)
92c43e3c 6972{
aa870c1b 6973 REAL_VALUE_TYPE real;
6974
40f4dbd5 6975 /* __builtin_inff is intended to be usable to define INFINITY on all
6976 targets. If an infinity is not available, INFINITY expands "to a
6977 positive constant of type float that overflows at translation
6978 time", footnote "In this case, using INFINITY will violate the
6979 constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
6980 Thus we pedwarn to ensure this constraint violation is
6981 diagnosed. */
92c43e3c 6982 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
389dd41b 6983 pedwarn (loc, 0, "target format does not support infinity");
92c43e3c 6984
aa870c1b 6985 real_inf (&real);
6986 return build_real (type, real);
92c43e3c 6987}
6988
c2f47e15 6989/* Fold a call to __builtin_nan or __builtin_nans with argument ARG. */
b0db7939 6990
6991static tree
c2f47e15 6992fold_builtin_nan (tree arg, tree type, int quiet)
b0db7939 6993{
6994 REAL_VALUE_TYPE real;
6995 const char *str;
6996
c2f47e15 6997 if (!validate_arg (arg, POINTER_TYPE))
6998 return NULL_TREE;
6999 str = c_getstr (arg);
b0db7939 7000 if (!str)
c2f47e15 7001 return NULL_TREE;
b0db7939 7002
7003 if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
c2f47e15 7004 return NULL_TREE;
b0db7939 7005
7006 return build_real (type, real);
7007}
7008
277f8dd2 7009/* Return true if the floating point expression T has an integer value.
7010 We also allow +Inf, -Inf and NaN to be considered integer values. */
7011
7012static bool
7013integer_valued_real_p (tree t)
7014{
7015 switch (TREE_CODE (t))
7016 {
7017 case FLOAT_EXPR:
7018 return true;
7019
7020 case ABS_EXPR:
7021 case SAVE_EXPR:
277f8dd2 7022 return integer_valued_real_p (TREE_OPERAND (t, 0));
7023
7024 case COMPOUND_EXPR:
41076ef6 7025 case MODIFY_EXPR:
277f8dd2 7026 case BIND_EXPR:
75a70cf9 7027 return integer_valued_real_p (TREE_OPERAND (t, 1));
277f8dd2 7028
7029 case PLUS_EXPR:
7030 case MINUS_EXPR:
7031 case MULT_EXPR:
7032 case MIN_EXPR:
7033 case MAX_EXPR:
7034 return integer_valued_real_p (TREE_OPERAND (t, 0))
7035 && integer_valued_real_p (TREE_OPERAND (t, 1));
7036
7037 case COND_EXPR:
7038 return integer_valued_real_p (TREE_OPERAND (t, 1))
7039 && integer_valued_real_p (TREE_OPERAND (t, 2));
7040
7041 case REAL_CST:
0570334c 7042 return real_isinteger (TREE_REAL_CST_PTR (t), TYPE_MODE (TREE_TYPE (t)));
277f8dd2 7043
7044 case NOP_EXPR:
7045 {
7046 tree type = TREE_TYPE (TREE_OPERAND (t, 0));
7047 if (TREE_CODE (type) == INTEGER_TYPE)
7048 return true;
7049 if (TREE_CODE (type) == REAL_TYPE)
7050 return integer_valued_real_p (TREE_OPERAND (t, 0));
7051 break;
7052 }
7053
7054 case CALL_EXPR:
7055 switch (builtin_mathfn_code (t))
7056 {
4f35b1fc 7057 CASE_FLT_FN (BUILT_IN_CEIL):
7058 CASE_FLT_FN (BUILT_IN_FLOOR):
7059 CASE_FLT_FN (BUILT_IN_NEARBYINT):
7060 CASE_FLT_FN (BUILT_IN_RINT):
7061 CASE_FLT_FN (BUILT_IN_ROUND):
7062 CASE_FLT_FN (BUILT_IN_TRUNC):
277f8dd2 7063 return true;
7064
d4a43a03 7065 CASE_FLT_FN (BUILT_IN_FMIN):
7066 CASE_FLT_FN (BUILT_IN_FMAX):
c2f47e15 7067 return integer_valued_real_p (CALL_EXPR_ARG (t, 0))
7068 && integer_valued_real_p (CALL_EXPR_ARG (t, 1));
d4a43a03 7069
277f8dd2 7070 default:
7071 break;
7072 }
7073 break;
7074
7075 default:
7076 break;
7077 }
7078 return false;
7079}
7080
c2f47e15 7081/* FNDECL is assumed to be a builtin where truncation can be propagated
6528f4f4 7082 across (for instance floor((double)f) == (double)floorf (f).
c2f47e15 7083 Do the transformation for a call with argument ARG. */
277f8dd2 7084
6528f4f4 7085static tree
389dd41b 7086fold_trunc_transparent_mathfn (location_t loc, tree fndecl, tree arg)
6528f4f4 7087{
6528f4f4 7088 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
277f8dd2 7089
c2f47e15 7090 if (!validate_arg (arg, REAL_TYPE))
7091 return NULL_TREE;
6528f4f4 7092
277f8dd2 7093 /* Integer rounding functions are idempotent. */
7094 if (fcode == builtin_mathfn_code (arg))
7095 return arg;
7096
7097 /* If argument is already integer valued, and we don't need to worry
7098 about setting errno, there's no need to perform rounding. */
7099 if (! flag_errno_math && integer_valued_real_p (arg))
7100 return arg;
7101
7102 if (optimize)
6528f4f4 7103 {
277f8dd2 7104 tree arg0 = strip_float_extensions (arg);
2426241c 7105 tree ftype = TREE_TYPE (TREE_TYPE (fndecl));
6528f4f4 7106 tree newtype = TREE_TYPE (arg0);
7107 tree decl;
7108
7109 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7110 && (decl = mathfn_built_in (newtype, fcode)))
389dd41b 7111 return fold_convert_loc (loc, ftype,
7112 build_call_expr_loc (loc, decl, 1,
7113 fold_convert_loc (loc,
7114 newtype,
7115 arg0)));
6528f4f4 7116 }
c2f47e15 7117 return NULL_TREE;
6528f4f4 7118}
7119
c2f47e15 7120/* FNDECL is assumed to be builtin which can narrow the FP type of
7121 the argument, for instance lround((double)f) -> lroundf (f).
7122 Do the transformation for a call with argument ARG. */
9ed65c7f 7123
7124static tree
389dd41b 7125fold_fixed_mathfn (location_t loc, tree fndecl, tree arg)
9ed65c7f 7126{
9ed65c7f 7127 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9ed65c7f 7128
c2f47e15 7129 if (!validate_arg (arg, REAL_TYPE))
7130 return NULL_TREE;
9ed65c7f 7131
7132 /* If argument is already integer valued, and we don't need to worry
7133 about setting errno, there's no need to perform rounding. */
7134 if (! flag_errno_math && integer_valued_real_p (arg))
389dd41b 7135 return fold_build1_loc (loc, FIX_TRUNC_EXPR,
7136 TREE_TYPE (TREE_TYPE (fndecl)), arg);
9ed65c7f 7137
7138 if (optimize)
7139 {
7140 tree ftype = TREE_TYPE (arg);
7141 tree arg0 = strip_float_extensions (arg);
7142 tree newtype = TREE_TYPE (arg0);
7143 tree decl;
7144
7145 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7146 && (decl = mathfn_built_in (newtype, fcode)))
389dd41b 7147 return build_call_expr_loc (loc, decl, 1,
7148 fold_convert_loc (loc, newtype, arg0));
9ed65c7f 7149 }
73a0da56 7150
7151 /* Canonicalize llround (x) to lround (x) on LP64 targets where
7152 sizeof (long long) == sizeof (long). */
7153 if (TYPE_PRECISION (long_long_integer_type_node)
7154 == TYPE_PRECISION (long_integer_type_node))
7155 {
7156 tree newfn = NULL_TREE;
7157 switch (fcode)
7158 {
7159 CASE_FLT_FN (BUILT_IN_LLCEIL):
7160 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
7161 break;
7162
7163 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7164 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
7165 break;
7166
7167 CASE_FLT_FN (BUILT_IN_LLROUND):
7168 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
7169 break;
7170
7171 CASE_FLT_FN (BUILT_IN_LLRINT):
7172 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
7173 break;
7174
7175 default:
7176 break;
7177 }
7178
7179 if (newfn)
7180 {
389dd41b 7181 tree newcall = build_call_expr_loc (loc, newfn, 1, arg);
7182 return fold_convert_loc (loc,
7183 TREE_TYPE (TREE_TYPE (fndecl)), newcall);
73a0da56 7184 }
7185 }
7186
c2f47e15 7187 return NULL_TREE;
9ed65c7f 7188}
7189
c2f47e15 7190/* Fold call to builtin cabs, cabsf or cabsl with argument ARG. TYPE is the
7191 return type. Return NULL_TREE if no simplification can be made. */
c63f4ad3 7192
7193static tree
389dd41b 7194fold_builtin_cabs (location_t loc, tree arg, tree type, tree fndecl)
c63f4ad3 7195{
c2f47e15 7196 tree res;
c63f4ad3 7197
b0ce8887 7198 if (!validate_arg (arg, COMPLEX_TYPE)
c63f4ad3 7199 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
7200 return NULL_TREE;
7201
b4725390 7202 /* Calculate the result when the argument is a constant. */
7203 if (TREE_CODE (arg) == COMPLEX_CST
7204 && (res = do_mpfr_arg2 (TREE_REALPART (arg), TREE_IMAGPART (arg),
7205 type, mpfr_hypot)))
7206 return res;
7207
1af0d139 7208 if (TREE_CODE (arg) == COMPLEX_EXPR)
7209 {
7210 tree real = TREE_OPERAND (arg, 0);
7211 tree imag = TREE_OPERAND (arg, 1);
7212
7213 /* If either part is zero, cabs is fabs of the other. */
7214 if (real_zerop (real))
389dd41b 7215 return fold_build1_loc (loc, ABS_EXPR, type, imag);
1af0d139 7216 if (real_zerop (imag))
389dd41b 7217 return fold_build1_loc (loc, ABS_EXPR, type, real);
1af0d139 7218
7219 /* cabs(x+xi) -> fabs(x)*sqrt(2). */
7220 if (flag_unsafe_math_optimizations
7221 && operand_equal_p (real, imag, OEP_PURE_SAME))
7222 {
2e7ca27b 7223 const REAL_VALUE_TYPE sqrt2_trunc
7910b2fb 7224 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
1af0d139 7225 STRIP_NOPS (real);
389dd41b 7226 return fold_build2_loc (loc, MULT_EXPR, type,
7227 fold_build1_loc (loc, ABS_EXPR, type, real),
2e7ca27b 7228 build_real (type, sqrt2_trunc));
1af0d139 7229 }
7230 }
c63f4ad3 7231
749891b2 7232 /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */
7233 if (TREE_CODE (arg) == NEGATE_EXPR
7234 || TREE_CODE (arg) == CONJ_EXPR)
389dd41b 7235 return build_call_expr_loc (loc, fndecl, 1, TREE_OPERAND (arg, 0));
749891b2 7236
7d3f6cc7 7237 /* Don't do this when optimizing for size. */
7238 if (flag_unsafe_math_optimizations
0bfd8d5c 7239 && optimize && optimize_function_for_speed_p (cfun))
c63f4ad3 7240 {
0da0dbfa 7241 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
c63f4ad3 7242
7243 if (sqrtfn != NULL_TREE)
7244 {
c2f47e15 7245 tree rpart, ipart, result;
c63f4ad3 7246
4ee9c684 7247 arg = builtin_save_expr (arg);
29a6518e 7248
389dd41b 7249 rpart = fold_build1_loc (loc, REALPART_EXPR, type, arg);
7250 ipart = fold_build1_loc (loc, IMAGPART_EXPR, type, arg);
c63f4ad3 7251
4ee9c684 7252 rpart = builtin_save_expr (rpart);
7253 ipart = builtin_save_expr (ipart);
c63f4ad3 7254
389dd41b 7255 result = fold_build2_loc (loc, PLUS_EXPR, type,
7256 fold_build2_loc (loc, MULT_EXPR, type,
49d00087 7257 rpart, rpart),
389dd41b 7258 fold_build2_loc (loc, MULT_EXPR, type,
49d00087 7259 ipart, ipart));
c63f4ad3 7260
389dd41b 7261 return build_call_expr_loc (loc, sqrtfn, 1, result);
c63f4ad3 7262 }
7263 }
7264
7265 return NULL_TREE;
7266}
7267
c2f47e15 7268/* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG.
7269 Return NULL_TREE if no simplification can be made. */
e6e27594 7270
7271static tree
389dd41b 7272fold_builtin_sqrt (location_t loc, tree arg, tree type)
e6e27594 7273{
7274
7275 enum built_in_function fcode;
b4e8ab0c 7276 tree res;
c2f47e15 7277
7278 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7279 return NULL_TREE;
7280
b4e8ab0c 7281 /* Calculate the result when the argument is a constant. */
7282 if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
7283 return res;
7284
e6e27594 7285 /* Optimize sqrt(expN(x)) = expN(x*0.5). */
7286 fcode = builtin_mathfn_code (arg);
7287 if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
7288 {
c2f47e15 7289 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
389dd41b 7290 arg = fold_build2_loc (loc, MULT_EXPR, type,
c2f47e15 7291 CALL_EXPR_ARG (arg, 0),
49d00087 7292 build_real (type, dconsthalf));
389dd41b 7293 return build_call_expr_loc (loc, expfn, 1, arg);
e6e27594 7294 }
7295
7296 /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */
7297 if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
7298 {
7299 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7300
7301 if (powfn)
7302 {
c2f47e15 7303 tree arg0 = CALL_EXPR_ARG (arg, 0);
e6e27594 7304 tree tree_root;
7305 /* The inner root was either sqrt or cbrt. */
57510da6 7306 /* This was a conditional expression but it triggered a bug
18381619 7307 in Sun C 5.5. */
ce6cd837 7308 REAL_VALUE_TYPE dconstroot;
7309 if (BUILTIN_SQRT_P (fcode))
7310 dconstroot = dconsthalf;
7311 else
7312 dconstroot = dconst_third ();
e6e27594 7313
7314 /* Adjust for the outer root. */
7315 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7316 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7317 tree_root = build_real (type, dconstroot);
389dd41b 7318 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
e6e27594 7319 }
7320 }
7321
bc33117f 7322 /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
e6e27594 7323 if (flag_unsafe_math_optimizations
7324 && (fcode == BUILT_IN_POW
7325 || fcode == BUILT_IN_POWF
7326 || fcode == BUILT_IN_POWL))
7327 {
c2f47e15 7328 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
7329 tree arg0 = CALL_EXPR_ARG (arg, 0);
7330 tree arg1 = CALL_EXPR_ARG (arg, 1);
bc33117f 7331 tree narg1;
7332 if (!tree_expr_nonnegative_p (arg0))
7333 arg0 = build1 (ABS_EXPR, type, arg0);
389dd41b 7334 narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 7335 build_real (type, dconsthalf));
389dd41b 7336 return build_call_expr_loc (loc, powfn, 2, arg0, narg1);
e6e27594 7337 }
7338
7339 return NULL_TREE;
7340}
7341
c2f47e15 7342/* Fold a builtin function call to cbrt, cbrtf, or cbrtl with argument ARG.
7343 Return NULL_TREE if no simplification can be made. */
7344
e6e27594 7345static tree
389dd41b 7346fold_builtin_cbrt (location_t loc, tree arg, tree type)
e6e27594 7347{
e6e27594 7348 const enum built_in_function fcode = builtin_mathfn_code (arg);
29f4cd78 7349 tree res;
e6e27594 7350
c2f47e15 7351 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7352 return NULL_TREE;
7353
29f4cd78 7354 /* Calculate the result when the argument is a constant. */
7355 if ((res = do_mpfr_arg1 (arg, type, mpfr_cbrt, NULL, NULL, 0)))
7356 return res;
e6e27594 7357
cdfeb715 7358 if (flag_unsafe_math_optimizations)
e6e27594 7359 {
cdfeb715 7360 /* Optimize cbrt(expN(x)) -> expN(x/3). */
7361 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 7362 {
c2f47e15 7363 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7364 const REAL_VALUE_TYPE third_trunc =
7910b2fb 7365 real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 7366 arg = fold_build2_loc (loc, MULT_EXPR, type,
c2f47e15 7367 CALL_EXPR_ARG (arg, 0),
49d00087 7368 build_real (type, third_trunc));
389dd41b 7369 return build_call_expr_loc (loc, expfn, 1, arg);
cdfeb715 7370 }
e6e27594 7371
cdfeb715 7372 /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */
7373 if (BUILTIN_SQRT_P (fcode))
a0c938f0 7374 {
cdfeb715 7375 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
e6e27594 7376
cdfeb715 7377 if (powfn)
7378 {
c2f47e15 7379 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7380 tree tree_root;
7910b2fb 7381 REAL_VALUE_TYPE dconstroot = dconst_third ();
cdfeb715 7382
7383 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7384 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7385 tree_root = build_real (type, dconstroot);
389dd41b 7386 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
cdfeb715 7387 }
e6e27594 7388 }
7389
cdfeb715 7390 /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */
7391 if (BUILTIN_CBRT_P (fcode))
a0c938f0 7392 {
c2f47e15 7393 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7394 if (tree_expr_nonnegative_p (arg0))
7395 {
7396 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7397
7398 if (powfn)
a0c938f0 7399 {
cdfeb715 7400 tree tree_root;
7401 REAL_VALUE_TYPE dconstroot;
a0c938f0 7402
3fa759a9 7403 real_arithmetic (&dconstroot, MULT_EXPR,
7910b2fb 7404 dconst_third_ptr (), dconst_third_ptr ());
cdfeb715 7405 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7406 tree_root = build_real (type, dconstroot);
389dd41b 7407 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
cdfeb715 7408 }
7409 }
7410 }
a0c938f0 7411
cdfeb715 7412 /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */
c2f47e15 7413 if (fcode == BUILT_IN_POW
7414 || fcode == BUILT_IN_POWF
cdfeb715 7415 || fcode == BUILT_IN_POWL)
a0c938f0 7416 {
c2f47e15 7417 tree arg00 = CALL_EXPR_ARG (arg, 0);
7418 tree arg01 = CALL_EXPR_ARG (arg, 1);
cdfeb715 7419 if (tree_expr_nonnegative_p (arg00))
7420 {
c2f47e15 7421 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7422 const REAL_VALUE_TYPE dconstroot
7910b2fb 7423 = real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 7424 tree narg01 = fold_build2_loc (loc, MULT_EXPR, type, arg01,
49d00087 7425 build_real (type, dconstroot));
389dd41b 7426 return build_call_expr_loc (loc, powfn, 2, arg00, narg01);
cdfeb715 7427 }
7428 }
e6e27594 7429 }
7430 return NULL_TREE;
7431}
7432
c2f47e15 7433/* Fold function call to builtin cos, cosf, or cosl with argument ARG.
7434 TYPE is the type of the return value. Return NULL_TREE if no
7435 simplification can be made. */
7436
e6e27594 7437static tree
389dd41b 7438fold_builtin_cos (location_t loc,
7439 tree arg, tree type, tree fndecl)
e6e27594 7440{
e6ab33d8 7441 tree res, narg;
e6e27594 7442
c2f47e15 7443 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7444 return NULL_TREE;
7445
bffb7645 7446 /* Calculate the result when the argument is a constant. */
728bac60 7447 if ((res = do_mpfr_arg1 (arg, type, mpfr_cos, NULL, NULL, 0)))
bffb7645 7448 return res;
7449
e6e27594 7450 /* Optimize cos(-x) into cos (x). */
e6ab33d8 7451 if ((narg = fold_strip_sign_ops (arg)))
389dd41b 7452 return build_call_expr_loc (loc, fndecl, 1, narg);
e6e27594 7453
7454 return NULL_TREE;
7455}
7456
c2f47e15 7457/* Fold function call to builtin cosh, coshf, or coshl with argument ARG.
7458 Return NULL_TREE if no simplification can be made. */
7459
cacdc1af 7460static tree
389dd41b 7461fold_builtin_cosh (location_t loc, tree arg, tree type, tree fndecl)
cacdc1af 7462{
c2f47e15 7463 if (validate_arg (arg, REAL_TYPE))
cacdc1af 7464 {
cacdc1af 7465 tree res, narg;
7466
7467 /* Calculate the result when the argument is a constant. */
7468 if ((res = do_mpfr_arg1 (arg, type, mpfr_cosh, NULL, NULL, 0)))
7469 return res;
7470
7471 /* Optimize cosh(-x) into cosh (x). */
7472 if ((narg = fold_strip_sign_ops (arg)))
389dd41b 7473 return build_call_expr_loc (loc, fndecl, 1, narg);
cacdc1af 7474 }
7475
7476 return NULL_TREE;
7477}
7478
239d491a 7479/* Fold function call to builtin ccos (or ccosh if HYPER is TRUE) with
7480 argument ARG. TYPE is the type of the return value. Return
7481 NULL_TREE if no simplification can be made. */
7482
7483static tree
389dd41b 7484fold_builtin_ccos (location_t loc,
7485 tree arg, tree type ATTRIBUTE_UNUSED, tree fndecl,
239d491a 7486 bool hyper ATTRIBUTE_UNUSED)
7487{
7488 if (validate_arg (arg, COMPLEX_TYPE)
7489 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
7490 {
7491 tree tmp;
7492
7493#ifdef HAVE_mpc
7494 /* Calculate the result when the argument is a constant. */
7495 if ((tmp = do_mpc_arg1 (arg, type, (hyper ? mpc_cosh : mpc_cos))))
7496 return tmp;
7497#endif
7498
7499 /* Optimize fn(-x) into fn(x). */
7500 if ((tmp = fold_strip_sign_ops (arg)))
389dd41b 7501 return build_call_expr_loc (loc, fndecl, 1, tmp);
239d491a 7502 }
7503
7504 return NULL_TREE;
7505}
7506
c2f47e15 7507/* Fold function call to builtin tan, tanf, or tanl with argument ARG.
7508 Return NULL_TREE if no simplification can be made. */
7509
e6e27594 7510static tree
c2f47e15 7511fold_builtin_tan (tree arg, tree type)
e6e27594 7512{
7513 enum built_in_function fcode;
29f4cd78 7514 tree res;
e6e27594 7515
c2f47e15 7516 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7517 return NULL_TREE;
7518
bffb7645 7519 /* Calculate the result when the argument is a constant. */
728bac60 7520 if ((res = do_mpfr_arg1 (arg, type, mpfr_tan, NULL, NULL, 0)))
bffb7645 7521 return res;
7522
e6e27594 7523 /* Optimize tan(atan(x)) = x. */
7524 fcode = builtin_mathfn_code (arg);
7525 if (flag_unsafe_math_optimizations
7526 && (fcode == BUILT_IN_ATAN
7527 || fcode == BUILT_IN_ATANF
7528 || fcode == BUILT_IN_ATANL))
c2f47e15 7529 return CALL_EXPR_ARG (arg, 0);
e6e27594 7530
7531 return NULL_TREE;
7532}
7533
d735c391 7534/* Fold function call to builtin sincos, sincosf, or sincosl. Return
7535 NULL_TREE if no simplification can be made. */
7536
7537static tree
389dd41b 7538fold_builtin_sincos (location_t loc,
7539 tree arg0, tree arg1, tree arg2)
d735c391 7540{
c2f47e15 7541 tree type;
d735c391 7542 tree res, fn, call;
7543
c2f47e15 7544 if (!validate_arg (arg0, REAL_TYPE)
7545 || !validate_arg (arg1, POINTER_TYPE)
7546 || !validate_arg (arg2, POINTER_TYPE))
d735c391 7547 return NULL_TREE;
7548
d735c391 7549 type = TREE_TYPE (arg0);
d735c391 7550
7551 /* Calculate the result when the argument is a constant. */
7552 if ((res = do_mpfr_sincos (arg0, arg1, arg2)))
7553 return res;
7554
7555 /* Canonicalize sincos to cexpi. */
2a6b4c77 7556 if (!TARGET_C99_FUNCTIONS)
7557 return NULL_TREE;
d735c391 7558 fn = mathfn_built_in (type, BUILT_IN_CEXPI);
7559 if (!fn)
7560 return NULL_TREE;
7561
389dd41b 7562 call = build_call_expr_loc (loc, fn, 1, arg0);
d735c391 7563 call = builtin_save_expr (call);
7564
a75b1c71 7565 return build2 (COMPOUND_EXPR, void_type_node,
d735c391 7566 build2 (MODIFY_EXPR, void_type_node,
389dd41b 7567 build_fold_indirect_ref_loc (loc, arg1),
d735c391 7568 build1 (IMAGPART_EXPR, type, call)),
7569 build2 (MODIFY_EXPR, void_type_node,
389dd41b 7570 build_fold_indirect_ref_loc (loc, arg2),
d735c391 7571 build1 (REALPART_EXPR, type, call)));
7572}
7573
c5bb2c4b 7574/* Fold function call to builtin cexp, cexpf, or cexpl. Return
7575 NULL_TREE if no simplification can be made. */
7576
7577static tree
389dd41b 7578fold_builtin_cexp (location_t loc, tree arg0, tree type)
c5bb2c4b 7579{
c2f47e15 7580 tree rtype;
c5bb2c4b 7581 tree realp, imagp, ifn;
239d491a 7582#ifdef HAVE_mpc
7583 tree res;
7584#endif
c5bb2c4b 7585
239d491a 7586 if (!validate_arg (arg0, COMPLEX_TYPE)
b0ce8887 7587 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) != REAL_TYPE)
c5bb2c4b 7588 return NULL_TREE;
7589
239d491a 7590#ifdef HAVE_mpc
7591 /* Calculate the result when the argument is a constant. */
7592 if ((res = do_mpc_arg1 (arg0, type, mpc_exp)))
7593 return res;
7594#endif
7595
c5bb2c4b 7596 rtype = TREE_TYPE (TREE_TYPE (arg0));
7597
7598 /* In case we can figure out the real part of arg0 and it is constant zero
7599 fold to cexpi. */
2a6b4c77 7600 if (!TARGET_C99_FUNCTIONS)
7601 return NULL_TREE;
c5bb2c4b 7602 ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI);
7603 if (!ifn)
7604 return NULL_TREE;
7605
389dd41b 7606 if ((realp = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0))
c5bb2c4b 7607 && real_zerop (realp))
7608 {
389dd41b 7609 tree narg = fold_build1_loc (loc, IMAGPART_EXPR, rtype, arg0);
7610 return build_call_expr_loc (loc, ifn, 1, narg);
c5bb2c4b 7611 }
7612
7613 /* In case we can easily decompose real and imaginary parts split cexp
7614 to exp (r) * cexpi (i). */
7615 if (flag_unsafe_math_optimizations
7616 && realp)
7617 {
7618 tree rfn, rcall, icall;
7619
7620 rfn = mathfn_built_in (rtype, BUILT_IN_EXP);
7621 if (!rfn)
7622 return NULL_TREE;
7623
389dd41b 7624 imagp = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
c5bb2c4b 7625 if (!imagp)
7626 return NULL_TREE;
7627
389dd41b 7628 icall = build_call_expr_loc (loc, ifn, 1, imagp);
c5bb2c4b 7629 icall = builtin_save_expr (icall);
389dd41b 7630 rcall = build_call_expr_loc (loc, rfn, 1, realp);
c5bb2c4b 7631 rcall = builtin_save_expr (rcall);
389dd41b 7632 return fold_build2_loc (loc, COMPLEX_EXPR, type,
7633 fold_build2_loc (loc, MULT_EXPR, rtype,
71bf42bb 7634 rcall,
389dd41b 7635 fold_build1_loc (loc, REALPART_EXPR,
7636 rtype, icall)),
7637 fold_build2_loc (loc, MULT_EXPR, rtype,
71bf42bb 7638 rcall,
389dd41b 7639 fold_build1_loc (loc, IMAGPART_EXPR,
7640 rtype, icall)));
c5bb2c4b 7641 }
7642
7643 return NULL_TREE;
7644}
7645
c2f47e15 7646/* Fold function call to builtin trunc, truncf or truncl with argument ARG.
7647 Return NULL_TREE if no simplification can be made. */
277f8dd2 7648
7649static tree
389dd41b 7650fold_builtin_trunc (location_t loc, tree fndecl, tree arg)
277f8dd2 7651{
c2f47e15 7652 if (!validate_arg (arg, REAL_TYPE))
7653 return NULL_TREE;
277f8dd2 7654
7655 /* Optimize trunc of constant value. */
f96bd2bf 7656 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7657 {
7658 REAL_VALUE_TYPE r, x;
2426241c 7659 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7660
7661 x = TREE_REAL_CST (arg);
7662 real_trunc (&r, TYPE_MODE (type), &x);
7663 return build_real (type, r);
7664 }
7665
389dd41b 7666 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7667}
7668
c2f47e15 7669/* Fold function call to builtin floor, floorf or floorl with argument ARG.
7670 Return NULL_TREE if no simplification can be made. */
277f8dd2 7671
7672static tree
389dd41b 7673fold_builtin_floor (location_t loc, tree fndecl, tree arg)
277f8dd2 7674{
c2f47e15 7675 if (!validate_arg (arg, REAL_TYPE))
7676 return NULL_TREE;
277f8dd2 7677
7678 /* Optimize floor of constant value. */
f96bd2bf 7679 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7680 {
7681 REAL_VALUE_TYPE x;
7682
7683 x = TREE_REAL_CST (arg);
7684 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7685 {
2426241c 7686 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7687 REAL_VALUE_TYPE r;
7688
7689 real_floor (&r, TYPE_MODE (type), &x);
7690 return build_real (type, r);
7691 }
7692 }
7693
acc2b92e 7694 /* Fold floor (x) where x is nonnegative to trunc (x). */
7695 if (tree_expr_nonnegative_p (arg))
30fe8286 7696 {
7697 tree truncfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_TRUNC);
7698 if (truncfn)
389dd41b 7699 return build_call_expr_loc (loc, truncfn, 1, arg);
30fe8286 7700 }
acc2b92e 7701
389dd41b 7702 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7703}
7704
c2f47e15 7705/* Fold function call to builtin ceil, ceilf or ceill with argument ARG.
7706 Return NULL_TREE if no simplification can be made. */
277f8dd2 7707
7708static tree
389dd41b 7709fold_builtin_ceil (location_t loc, tree fndecl, tree arg)
277f8dd2 7710{
c2f47e15 7711 if (!validate_arg (arg, REAL_TYPE))
7712 return NULL_TREE;
277f8dd2 7713
7714 /* Optimize ceil of constant value. */
f96bd2bf 7715 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7716 {
7717 REAL_VALUE_TYPE x;
7718
7719 x = TREE_REAL_CST (arg);
7720 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7721 {
2426241c 7722 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7723 REAL_VALUE_TYPE r;
7724
7725 real_ceil (&r, TYPE_MODE (type), &x);
7726 return build_real (type, r);
7727 }
7728 }
7729
389dd41b 7730 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7731}
7732
c2f47e15 7733/* Fold function call to builtin round, roundf or roundl with argument ARG.
7734 Return NULL_TREE if no simplification can be made. */
89ab3887 7735
7736static tree
389dd41b 7737fold_builtin_round (location_t loc, tree fndecl, tree arg)
89ab3887 7738{
c2f47e15 7739 if (!validate_arg (arg, REAL_TYPE))
7740 return NULL_TREE;
89ab3887 7741
34f17811 7742 /* Optimize round of constant value. */
f96bd2bf 7743 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
89ab3887 7744 {
7745 REAL_VALUE_TYPE x;
7746
7747 x = TREE_REAL_CST (arg);
7748 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7749 {
2426241c 7750 tree type = TREE_TYPE (TREE_TYPE (fndecl));
89ab3887 7751 REAL_VALUE_TYPE r;
7752
7753 real_round (&r, TYPE_MODE (type), &x);
7754 return build_real (type, r);
7755 }
7756 }
7757
389dd41b 7758 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
89ab3887 7759}
7760
34f17811 7761/* Fold function call to builtin lround, lroundf or lroundl (or the
c2f47e15 7762 corresponding long long versions) and other rounding functions. ARG
7763 is the argument to the call. Return NULL_TREE if no simplification
7764 can be made. */
34f17811 7765
7766static tree
389dd41b 7767fold_builtin_int_roundingfn (location_t loc, tree fndecl, tree arg)
34f17811 7768{
c2f47e15 7769 if (!validate_arg (arg, REAL_TYPE))
7770 return NULL_TREE;
34f17811 7771
7772 /* Optimize lround of constant value. */
f96bd2bf 7773 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
34f17811 7774 {
7775 const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
7776
776a7bab 7777 if (real_isfinite (&x))
34f17811 7778 {
2426241c 7779 tree itype = TREE_TYPE (TREE_TYPE (fndecl));
ca9b061d 7780 tree ftype = TREE_TYPE (arg);
7781 unsigned HOST_WIDE_INT lo2;
34f17811 7782 HOST_WIDE_INT hi, lo;
7783 REAL_VALUE_TYPE r;
7784
ad52b9b7 7785 switch (DECL_FUNCTION_CODE (fndecl))
7786 {
4f35b1fc 7787 CASE_FLT_FN (BUILT_IN_LFLOOR):
7788 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 7789 real_floor (&r, TYPE_MODE (ftype), &x);
7790 break;
7791
4f35b1fc 7792 CASE_FLT_FN (BUILT_IN_LCEIL):
7793 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 7794 real_ceil (&r, TYPE_MODE (ftype), &x);
7795 break;
7796
4f35b1fc 7797 CASE_FLT_FN (BUILT_IN_LROUND):
7798 CASE_FLT_FN (BUILT_IN_LLROUND):
ad52b9b7 7799 real_round (&r, TYPE_MODE (ftype), &x);
7800 break;
7801
7802 default:
7803 gcc_unreachable ();
7804 }
7805
34f17811 7806 REAL_VALUE_TO_INT (&lo, &hi, r);
ca9b061d 7807 if (!fit_double_type (lo, hi, &lo2, &hi, itype))
7808 return build_int_cst_wide (itype, lo2, hi);
34f17811 7809 }
7810 }
7811
acc2b92e 7812 switch (DECL_FUNCTION_CODE (fndecl))
7813 {
7814 CASE_FLT_FN (BUILT_IN_LFLOOR):
7815 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7816 /* Fold lfloor (x) where x is nonnegative to FIX_TRUNC (x). */
7817 if (tree_expr_nonnegative_p (arg))
389dd41b 7818 return fold_build1_loc (loc, FIX_TRUNC_EXPR,
7819 TREE_TYPE (TREE_TYPE (fndecl)), arg);
acc2b92e 7820 break;
7821 default:;
7822 }
7823
389dd41b 7824 return fold_fixed_mathfn (loc, fndecl, arg);
34f17811 7825}
7826
70fb4c07 7827/* Fold function call to builtin ffs, clz, ctz, popcount and parity
c2f47e15 7828 and their long and long long variants (i.e. ffsl and ffsll). ARG is
7829 the argument to the call. Return NULL_TREE if no simplification can
7830 be made. */
70fb4c07 7831
7832static tree
c2f47e15 7833fold_builtin_bitop (tree fndecl, tree arg)
70fb4c07 7834{
c2f47e15 7835 if (!validate_arg (arg, INTEGER_TYPE))
70fb4c07 7836 return NULL_TREE;
7837
7838 /* Optimize for constant argument. */
f96bd2bf 7839 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
70fb4c07 7840 {
7841 HOST_WIDE_INT hi, width, result;
7842 unsigned HOST_WIDE_INT lo;
7c446c95 7843 tree type;
70fb4c07 7844
7845 type = TREE_TYPE (arg);
7846 width = TYPE_PRECISION (type);
7847 lo = TREE_INT_CST_LOW (arg);
7848
7849 /* Clear all the bits that are beyond the type's precision. */
7850 if (width > HOST_BITS_PER_WIDE_INT)
7851 {
7852 hi = TREE_INT_CST_HIGH (arg);
7853 if (width < 2 * HOST_BITS_PER_WIDE_INT)
7854 hi &= ~((HOST_WIDE_INT) (-1) >> (width - HOST_BITS_PER_WIDE_INT));
7855 }
7856 else
7857 {
7858 hi = 0;
7859 if (width < HOST_BITS_PER_WIDE_INT)
7860 lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
7861 }
7862
7863 switch (DECL_FUNCTION_CODE (fndecl))
7864 {
4f35b1fc 7865 CASE_INT_FN (BUILT_IN_FFS):
70fb4c07 7866 if (lo != 0)
7867 result = exact_log2 (lo & -lo) + 1;
7868 else if (hi != 0)
7869 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi) + 1;
7870 else
7871 result = 0;
7872 break;
7873
4f35b1fc 7874 CASE_INT_FN (BUILT_IN_CLZ):
70fb4c07 7875 if (hi != 0)
7876 result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
7877 else if (lo != 0)
7878 result = width - floor_log2 (lo) - 1;
7879 else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
7880 result = width;
7881 break;
7882
4f35b1fc 7883 CASE_INT_FN (BUILT_IN_CTZ):
70fb4c07 7884 if (lo != 0)
7885 result = exact_log2 (lo & -lo);
7886 else if (hi != 0)
7887 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi);
7888 else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
7889 result = width;
7890 break;
7891
4f35b1fc 7892 CASE_INT_FN (BUILT_IN_POPCOUNT):
70fb4c07 7893 result = 0;
7894 while (lo)
7895 result++, lo &= lo - 1;
7896 while (hi)
7897 result++, hi &= hi - 1;
7898 break;
7899
4f35b1fc 7900 CASE_INT_FN (BUILT_IN_PARITY):
70fb4c07 7901 result = 0;
7902 while (lo)
7903 result++, lo &= lo - 1;
7904 while (hi)
7905 result++, hi &= hi - 1;
7906 result &= 1;
7907 break;
7908
7909 default:
64db345d 7910 gcc_unreachable ();
70fb4c07 7911 }
7912
2426241c 7913 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
70fb4c07 7914 }
7915
7916 return NULL_TREE;
7917}
7918
42791117 7919/* Fold function call to builtin_bswap and the long and long long
7920 variants. Return NULL_TREE if no simplification can be made. */
7921static tree
c2f47e15 7922fold_builtin_bswap (tree fndecl, tree arg)
42791117 7923{
c2f47e15 7924 if (! validate_arg (arg, INTEGER_TYPE))
7925 return NULL_TREE;
42791117 7926
7927 /* Optimize constant value. */
f96bd2bf 7928 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
42791117 7929 {
7930 HOST_WIDE_INT hi, width, r_hi = 0;
7931 unsigned HOST_WIDE_INT lo, r_lo = 0;
7932 tree type;
7933
7934 type = TREE_TYPE (arg);
7935 width = TYPE_PRECISION (type);
7936 lo = TREE_INT_CST_LOW (arg);
7937 hi = TREE_INT_CST_HIGH (arg);
7938
7939 switch (DECL_FUNCTION_CODE (fndecl))
7940 {
7941 case BUILT_IN_BSWAP32:
7942 case BUILT_IN_BSWAP64:
7943 {
7944 int s;
7945
7946 for (s = 0; s < width; s += 8)
7947 {
7948 int d = width - s - 8;
7949 unsigned HOST_WIDE_INT byte;
7950
7951 if (s < HOST_BITS_PER_WIDE_INT)
7952 byte = (lo >> s) & 0xff;
7953 else
7954 byte = (hi >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff;
7955
7956 if (d < HOST_BITS_PER_WIDE_INT)
7957 r_lo |= byte << d;
7958 else
7959 r_hi |= byte << (d - HOST_BITS_PER_WIDE_INT);
7960 }
7961 }
7962
7963 break;
7964
7965 default:
7966 gcc_unreachable ();
7967 }
7968
7969 if (width < HOST_BITS_PER_WIDE_INT)
7970 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), r_lo);
7971 else
7972 return build_int_cst_wide (TREE_TYPE (TREE_TYPE (fndecl)), r_lo, r_hi);
7973 }
7974
7975 return NULL_TREE;
7976}
c2f47e15 7977
8918c507 7978/* A subroutine of fold_builtin to fold the various logarithmic
29f4cd78 7979 functions. Return NULL_TREE if no simplification can me made.
7980 FUNC is the corresponding MPFR logarithm function. */
8918c507 7981
7982static tree
389dd41b 7983fold_builtin_logarithm (location_t loc, tree fndecl, tree arg,
29f4cd78 7984 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 7985{
c2f47e15 7986 if (validate_arg (arg, REAL_TYPE))
8918c507 7987 {
8918c507 7988 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 7989 tree res;
8918c507 7990 const enum built_in_function fcode = builtin_mathfn_code (arg);
0862b7e9 7991
29f4cd78 7992 /* Calculate the result when the argument is a constant. */
7993 if ((res = do_mpfr_arg1 (arg, type, func, &dconst0, NULL, false)))
7994 return res;
7995
8918c507 7996 /* Special case, optimize logN(expN(x)) = x. */
7997 if (flag_unsafe_math_optimizations
29f4cd78 7998 && ((func == mpfr_log
8918c507 7999 && (fcode == BUILT_IN_EXP
8000 || fcode == BUILT_IN_EXPF
8001 || fcode == BUILT_IN_EXPL))
29f4cd78 8002 || (func == mpfr_log2
8918c507 8003 && (fcode == BUILT_IN_EXP2
8004 || fcode == BUILT_IN_EXP2F
8005 || fcode == BUILT_IN_EXP2L))
29f4cd78 8006 || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode)))))
389dd41b 8007 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
8918c507 8008
ca273d4a 8009 /* Optimize logN(func()) for various exponential functions. We
a0c938f0 8010 want to determine the value "x" and the power "exponent" in
8011 order to transform logN(x**exponent) into exponent*logN(x). */
8918c507 8012 if (flag_unsafe_math_optimizations)
a0c938f0 8013 {
8918c507 8014 tree exponent = 0, x = 0;
0862b7e9 8015
8918c507 8016 switch (fcode)
8017 {
4f35b1fc 8018 CASE_FLT_FN (BUILT_IN_EXP):
8918c507 8019 /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
7910b2fb 8020 x = build_real (type, real_value_truncate (TYPE_MODE (type),
8021 dconst_e ()));
c2f47e15 8022 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8023 break;
4f35b1fc 8024 CASE_FLT_FN (BUILT_IN_EXP2):
8918c507 8025 /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */
8026 x = build_real (type, dconst2);
c2f47e15 8027 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8028 break;
4f35b1fc 8029 CASE_FLT_FN (BUILT_IN_EXP10):
8030 CASE_FLT_FN (BUILT_IN_POW10):
8918c507 8031 /* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */
3fa759a9 8032 {
8033 REAL_VALUE_TYPE dconst10;
8034 real_from_integer (&dconst10, VOIDmode, 10, 0, 0);
8035 x = build_real (type, dconst10);
8036 }
c2f47e15 8037 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8038 break;
4f35b1fc 8039 CASE_FLT_FN (BUILT_IN_SQRT):
8918c507 8040 /* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */
c2f47e15 8041 x = CALL_EXPR_ARG (arg, 0);
8918c507 8042 exponent = build_real (type, dconsthalf);
8043 break;
4f35b1fc 8044 CASE_FLT_FN (BUILT_IN_CBRT):
8918c507 8045 /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */
c2f47e15 8046 x = CALL_EXPR_ARG (arg, 0);
8918c507 8047 exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
7910b2fb 8048 dconst_third ()));
8918c507 8049 break;
4f35b1fc 8050 CASE_FLT_FN (BUILT_IN_POW):
8918c507 8051 /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x). */
c2f47e15 8052 x = CALL_EXPR_ARG (arg, 0);
8053 exponent = CALL_EXPR_ARG (arg, 1);
8918c507 8054 break;
8055 default:
8056 break;
8057 }
8058
8059 /* Now perform the optimization. */
8060 if (x && exponent)
8061 {
389dd41b 8062 tree logfn = build_call_expr_loc (loc, fndecl, 1, x);
8063 return fold_build2_loc (loc, MULT_EXPR, type, exponent, logfn);
8918c507 8064 }
8065 }
8066 }
8067
c2f47e15 8068 return NULL_TREE;
8918c507 8069}
0862b7e9 8070
f0c477f2 8071/* Fold a builtin function call to hypot, hypotf, or hypotl. Return
8072 NULL_TREE if no simplification can be made. */
8073
8074static tree
389dd41b 8075fold_builtin_hypot (location_t loc, tree fndecl,
8076 tree arg0, tree arg1, tree type)
f0c477f2 8077{
e6ab33d8 8078 tree res, narg0, narg1;
f0c477f2 8079
c2f47e15 8080 if (!validate_arg (arg0, REAL_TYPE)
8081 || !validate_arg (arg1, REAL_TYPE))
f0c477f2 8082 return NULL_TREE;
8083
8084 /* Calculate the result when the argument is a constant. */
8085 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot)))
8086 return res;
8087
6c95f21c 8088 /* If either argument to hypot has a negate or abs, strip that off.
8089 E.g. hypot(-x,fabs(y)) -> hypot(x,y). */
e6ab33d8 8090 narg0 = fold_strip_sign_ops (arg0);
8091 narg1 = fold_strip_sign_ops (arg1);
8092 if (narg0 || narg1)
8093 {
389dd41b 8094 return build_call_expr_loc (loc, fndecl, 2, narg0 ? narg0 : arg0,
c2f47e15 8095 narg1 ? narg1 : arg1);
6c95f21c 8096 }
8097
f0c477f2 8098 /* If either argument is zero, hypot is fabs of the other. */
8099 if (real_zerop (arg0))
389dd41b 8100 return fold_build1_loc (loc, ABS_EXPR, type, arg1);
f0c477f2 8101 else if (real_zerop (arg1))
389dd41b 8102 return fold_build1_loc (loc, ABS_EXPR, type, arg0);
f0c477f2 8103
6c95f21c 8104 /* hypot(x,x) -> fabs(x)*sqrt(2). */
8105 if (flag_unsafe_math_optimizations
8106 && operand_equal_p (arg0, arg1, OEP_PURE_SAME))
f0c477f2 8107 {
2e7ca27b 8108 const REAL_VALUE_TYPE sqrt2_trunc
7910b2fb 8109 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
389dd41b 8110 return fold_build2_loc (loc, MULT_EXPR, type,
8111 fold_build1_loc (loc, ABS_EXPR, type, arg0),
2e7ca27b 8112 build_real (type, sqrt2_trunc));
f0c477f2 8113 }
8114
f0c477f2 8115 return NULL_TREE;
8116}
8117
8118
e6e27594 8119/* Fold a builtin function call to pow, powf, or powl. Return
8120 NULL_TREE if no simplification can be made. */
8121static tree
389dd41b 8122fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
e6e27594 8123{
f0c477f2 8124 tree res;
e6e27594 8125
c2f47e15 8126 if (!validate_arg (arg0, REAL_TYPE)
8127 || !validate_arg (arg1, REAL_TYPE))
e6e27594 8128 return NULL_TREE;
8129
f0c477f2 8130 /* Calculate the result when the argument is a constant. */
8131 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_pow)))
8132 return res;
8133
e6e27594 8134 /* Optimize pow(1.0,y) = 1.0. */
8135 if (real_onep (arg0))
389dd41b 8136 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
e6e27594 8137
8138 if (TREE_CODE (arg1) == REAL_CST
f96bd2bf 8139 && !TREE_OVERFLOW (arg1))
e6e27594 8140 {
198d9bbe 8141 REAL_VALUE_TYPE cint;
e6e27594 8142 REAL_VALUE_TYPE c;
198d9bbe 8143 HOST_WIDE_INT n;
8144
e6e27594 8145 c = TREE_REAL_CST (arg1);
8146
8147 /* Optimize pow(x,0.0) = 1.0. */
8148 if (REAL_VALUES_EQUAL (c, dconst0))
389dd41b 8149 return omit_one_operand_loc (loc, type, build_real (type, dconst1),
e6e27594 8150 arg0);
8151
8152 /* Optimize pow(x,1.0) = x. */
8153 if (REAL_VALUES_EQUAL (c, dconst1))
8154 return arg0;
8155
8156 /* Optimize pow(x,-1.0) = 1.0/x. */
8157 if (REAL_VALUES_EQUAL (c, dconstm1))
389dd41b 8158 return fold_build2_loc (loc, RDIV_EXPR, type,
49d00087 8159 build_real (type, dconst1), arg0);
e6e27594 8160
8161 /* Optimize pow(x,0.5) = sqrt(x). */
8162 if (flag_unsafe_math_optimizations
8163 && REAL_VALUES_EQUAL (c, dconsthalf))
8164 {
8165 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
8166
8167 if (sqrtfn != NULL_TREE)
389dd41b 8168 return build_call_expr_loc (loc, sqrtfn, 1, arg0);
e6e27594 8169 }
8170
feb5b3eb 8171 /* Optimize pow(x,1.0/3.0) = cbrt(x). */
8172 if (flag_unsafe_math_optimizations)
8173 {
8174 const REAL_VALUE_TYPE dconstroot
7910b2fb 8175 = real_value_truncate (TYPE_MODE (type), dconst_third ());
feb5b3eb 8176
8177 if (REAL_VALUES_EQUAL (c, dconstroot))
8178 {
8179 tree cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT);
8180 if (cbrtfn != NULL_TREE)
389dd41b 8181 return build_call_expr_loc (loc, cbrtfn, 1, arg0);
feb5b3eb 8182 }
8183 }
8184
198d9bbe 8185 /* Check for an integer exponent. */
8186 n = real_to_integer (&c);
8187 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
8188 if (real_identical (&c, &cint))
e6e27594 8189 {
a2b30b48 8190 /* Attempt to evaluate pow at compile-time, unless this should
8191 raise an exception. */
198d9bbe 8192 if (TREE_CODE (arg0) == REAL_CST
a2b30b48 8193 && !TREE_OVERFLOW (arg0)
8194 && (n > 0
8195 || (!flag_trapping_math && !flag_errno_math)
8196 || !REAL_VALUES_EQUAL (TREE_REAL_CST (arg0), dconst0)))
e6e27594 8197 {
8198 REAL_VALUE_TYPE x;
8199 bool inexact;
8200
8201 x = TREE_REAL_CST (arg0);
8202 inexact = real_powi (&x, TYPE_MODE (type), &x, n);
8203 if (flag_unsafe_math_optimizations || !inexact)
8204 return build_real (type, x);
8205 }
198d9bbe 8206
8207 /* Strip sign ops from even integer powers. */
8208 if ((n & 1) == 0 && flag_unsafe_math_optimizations)
8209 {
8210 tree narg0 = fold_strip_sign_ops (arg0);
8211 if (narg0)
389dd41b 8212 return build_call_expr_loc (loc, fndecl, 2, narg0, arg1);
198d9bbe 8213 }
e6e27594 8214 }
8215 }
8216
cdfeb715 8217 if (flag_unsafe_math_optimizations)
e6e27594 8218 {
cdfeb715 8219 const enum built_in_function fcode = builtin_mathfn_code (arg0);
e6e27594 8220
cdfeb715 8221 /* Optimize pow(expN(x),y) = expN(x*y). */
8222 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 8223 {
c2f47e15 8224 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
8225 tree arg = CALL_EXPR_ARG (arg0, 0);
389dd41b 8226 arg = fold_build2_loc (loc, MULT_EXPR, type, arg, arg1);
8227 return build_call_expr_loc (loc, expfn, 1, arg);
cdfeb715 8228 }
e6e27594 8229
cdfeb715 8230 /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
8231 if (BUILTIN_SQRT_P (fcode))
a0c938f0 8232 {
c2f47e15 8233 tree narg0 = CALL_EXPR_ARG (arg0, 0);
389dd41b 8234 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 8235 build_real (type, dconsthalf));
389dd41b 8236 return build_call_expr_loc (loc, fndecl, 2, narg0, narg1);
cdfeb715 8237 }
8238
8239 /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */
8240 if (BUILTIN_CBRT_P (fcode))
a0c938f0 8241 {
c2f47e15 8242 tree arg = CALL_EXPR_ARG (arg0, 0);
cdfeb715 8243 if (tree_expr_nonnegative_p (arg))
8244 {
8245 const REAL_VALUE_TYPE dconstroot
7910b2fb 8246 = real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 8247 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 8248 build_real (type, dconstroot));
389dd41b 8249 return build_call_expr_loc (loc, fndecl, 2, arg, narg1);
cdfeb715 8250 }
8251 }
a0c938f0 8252
49e436b5 8253 /* Optimize pow(pow(x,y),z) = pow(x,y*z) iff x is nonnegative. */
c2f47e15 8254 if (fcode == BUILT_IN_POW
8255 || fcode == BUILT_IN_POWF
8256 || fcode == BUILT_IN_POWL)
a0c938f0 8257 {
c2f47e15 8258 tree arg00 = CALL_EXPR_ARG (arg0, 0);
49e436b5 8259 if (tree_expr_nonnegative_p (arg00))
8260 {
8261 tree arg01 = CALL_EXPR_ARG (arg0, 1);
8262 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg01, arg1);
8263 return build_call_expr_loc (loc, fndecl, 2, arg00, narg1);
8264 }
cdfeb715 8265 }
e6e27594 8266 }
cdfeb715 8267
e6e27594 8268 return NULL_TREE;
8269}
8270
c2f47e15 8271/* Fold a builtin function call to powi, powif, or powil with argument ARG.
8272 Return NULL_TREE if no simplification can be made. */
b4d0c20c 8273static tree
389dd41b 8274fold_builtin_powi (location_t loc, tree fndecl ATTRIBUTE_UNUSED,
c2f47e15 8275 tree arg0, tree arg1, tree type)
b4d0c20c 8276{
c2f47e15 8277 if (!validate_arg (arg0, REAL_TYPE)
8278 || !validate_arg (arg1, INTEGER_TYPE))
b4d0c20c 8279 return NULL_TREE;
8280
8281 /* Optimize pow(1.0,y) = 1.0. */
8282 if (real_onep (arg0))
389dd41b 8283 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
b4d0c20c 8284
8285 if (host_integerp (arg1, 0))
8286 {
8287 HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
8288
8289 /* Evaluate powi at compile-time. */
8290 if (TREE_CODE (arg0) == REAL_CST
f96bd2bf 8291 && !TREE_OVERFLOW (arg0))
b4d0c20c 8292 {
8293 REAL_VALUE_TYPE x;
8294 x = TREE_REAL_CST (arg0);
8295 real_powi (&x, TYPE_MODE (type), &x, c);
8296 return build_real (type, x);
8297 }
8298
8299 /* Optimize pow(x,0) = 1.0. */
8300 if (c == 0)
389dd41b 8301 return omit_one_operand_loc (loc, type, build_real (type, dconst1),
b4d0c20c 8302 arg0);
8303
8304 /* Optimize pow(x,1) = x. */
8305 if (c == 1)
8306 return arg0;
8307
8308 /* Optimize pow(x,-1) = 1.0/x. */
8309 if (c == -1)
389dd41b 8310 return fold_build2_loc (loc, RDIV_EXPR, type,
49d00087 8311 build_real (type, dconst1), arg0);
b4d0c20c 8312 }
8313
8314 return NULL_TREE;
8315}
8316
8918c507 8317/* A subroutine of fold_builtin to fold the various exponent
c2f47e15 8318 functions. Return NULL_TREE if no simplification can be made.
debf9994 8319 FUNC is the corresponding MPFR exponent function. */
8918c507 8320
8321static tree
389dd41b 8322fold_builtin_exponent (location_t loc, tree fndecl, tree arg,
debf9994 8323 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8324{
c2f47e15 8325 if (validate_arg (arg, REAL_TYPE))
8918c507 8326 {
8918c507 8327 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8328 tree res;
debf9994 8329
8330 /* Calculate the result when the argument is a constant. */
728bac60 8331 if ((res = do_mpfr_arg1 (arg, type, func, NULL, NULL, 0)))
debf9994 8332 return res;
8918c507 8333
8334 /* Optimize expN(logN(x)) = x. */
8335 if (flag_unsafe_math_optimizations)
a0c938f0 8336 {
8918c507 8337 const enum built_in_function fcode = builtin_mathfn_code (arg);
8338
debf9994 8339 if ((func == mpfr_exp
8918c507 8340 && (fcode == BUILT_IN_LOG
8341 || fcode == BUILT_IN_LOGF
8342 || fcode == BUILT_IN_LOGL))
debf9994 8343 || (func == mpfr_exp2
8918c507 8344 && (fcode == BUILT_IN_LOG2
8345 || fcode == BUILT_IN_LOG2F
8346 || fcode == BUILT_IN_LOG2L))
debf9994 8347 || (func == mpfr_exp10
8918c507 8348 && (fcode == BUILT_IN_LOG10
8349 || fcode == BUILT_IN_LOG10F
8350 || fcode == BUILT_IN_LOG10L)))
389dd41b 8351 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
8918c507 8352 }
8353 }
8354
c2f47e15 8355 return NULL_TREE;
8918c507 8356}
8357
e973ffcc 8358/* Return true if VAR is a VAR_DECL or a component thereof. */
8359
8360static bool
8361var_decl_component_p (tree var)
8362{
8363 tree inner = var;
8364 while (handled_component_p (inner))
8365 inner = TREE_OPERAND (inner, 0);
8366 return SSA_VAR_P (inner);
8367}
8368
4f46f2b9 8369/* Fold function call to builtin memset. Return
9c8a1629 8370 NULL_TREE if no simplification can be made. */
8371
8372static tree
389dd41b 8373fold_builtin_memset (location_t loc, tree dest, tree c, tree len,
8374 tree type, bool ignore)
9c8a1629 8375{
45bb3afb 8376 tree var, ret, etype;
4f46f2b9 8377 unsigned HOST_WIDE_INT length, cval;
9c8a1629 8378
c2f47e15 8379 if (! validate_arg (dest, POINTER_TYPE)
8380 || ! validate_arg (c, INTEGER_TYPE)
8381 || ! validate_arg (len, INTEGER_TYPE))
8382 return NULL_TREE;
9c8a1629 8383
4f46f2b9 8384 if (! host_integerp (len, 1))
c2f47e15 8385 return NULL_TREE;
4f46f2b9 8386
9c8a1629 8387 /* If the LEN parameter is zero, return DEST. */
8388 if (integer_zerop (len))
389dd41b 8389 return omit_one_operand_loc (loc, type, dest, c);
9c8a1629 8390
4f46f2b9 8391 if (! host_integerp (c, 1) || TREE_SIDE_EFFECTS (dest))
c2f47e15 8392 return NULL_TREE;
9c8a1629 8393
4f46f2b9 8394 var = dest;
8395 STRIP_NOPS (var);
8396 if (TREE_CODE (var) != ADDR_EXPR)
c2f47e15 8397 return NULL_TREE;
4f46f2b9 8398
8399 var = TREE_OPERAND (var, 0);
8400 if (TREE_THIS_VOLATILE (var))
c2f47e15 8401 return NULL_TREE;
4f46f2b9 8402
45bb3afb 8403 etype = TREE_TYPE (var);
8404 if (TREE_CODE (etype) == ARRAY_TYPE)
8405 etype = TREE_TYPE (etype);
8406
8407 if (!INTEGRAL_TYPE_P (etype)
8408 && !POINTER_TYPE_P (etype))
c2f47e15 8409 return NULL_TREE;
4f46f2b9 8410
e973ffcc 8411 if (! var_decl_component_p (var))
c2f47e15 8412 return NULL_TREE;
e973ffcc 8413
4f46f2b9 8414 length = tree_low_cst (len, 1);
45bb3afb 8415 if (GET_MODE_SIZE (TYPE_MODE (etype)) != length
4f46f2b9 8416 || get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
8417 < (int) length)
c2f47e15 8418 return NULL_TREE;
4f46f2b9 8419
8420 if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT)
c2f47e15 8421 return NULL_TREE;
4f46f2b9 8422
8423 if (integer_zerop (c))
8424 cval = 0;
8425 else
8426 {
8427 if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64)
c2f47e15 8428 return NULL_TREE;
4f46f2b9 8429
8430 cval = tree_low_cst (c, 1);
8431 cval &= 0xff;
8432 cval |= cval << 8;
8433 cval |= cval << 16;
8434 cval |= (cval << 31) << 1;
8435 }
8436
45bb3afb 8437 ret = build_int_cst_type (etype, cval);
389dd41b 8438 var = build_fold_indirect_ref_loc (loc,
8439 fold_convert_loc (loc,
8440 build_pointer_type (etype),
8441 dest));
45bb3afb 8442 ret = build2 (MODIFY_EXPR, etype, var, ret);
4f46f2b9 8443 if (ignore)
8444 return ret;
8445
389dd41b 8446 return omit_one_operand_loc (loc, type, dest, ret);
9c8a1629 8447}
8448
4f46f2b9 8449/* Fold function call to builtin memset. Return
9c8a1629 8450 NULL_TREE if no simplification can be made. */
8451
8452static tree
389dd41b 8453fold_builtin_bzero (location_t loc, tree dest, tree size, bool ignore)
9c8a1629 8454{
c2f47e15 8455 if (! validate_arg (dest, POINTER_TYPE)
8456 || ! validate_arg (size, INTEGER_TYPE))
8457 return NULL_TREE;
9c8a1629 8458
4f46f2b9 8459 if (!ignore)
c2f47e15 8460 return NULL_TREE;
a0c938f0 8461
4f46f2b9 8462 /* New argument list transforming bzero(ptr x, int y) to
8463 memset(ptr x, int 0, size_t y). This is done this way
8464 so that if it isn't expanded inline, we fallback to
8465 calling bzero instead of memset. */
8466
389dd41b 8467 return fold_builtin_memset (loc, dest, integer_zero_node,
8468 fold_convert_loc (loc, sizetype, size),
c2f47e15 8469 void_type_node, ignore);
9c8a1629 8470}
8471
4f46f2b9 8472/* Fold function call to builtin mem{{,p}cpy,move}. Return
8473 NULL_TREE if no simplification can be made.
8474 If ENDP is 0, return DEST (like memcpy).
8475 If ENDP is 1, return DEST+LEN (like mempcpy).
8476 If ENDP is 2, return DEST+LEN-1 (like stpcpy).
8477 If ENDP is 3, return DEST, additionally *SRC and *DEST may overlap
8478 (memmove). */
9c8a1629 8479
8480static tree
389dd41b 8481fold_builtin_memory_op (location_t loc, tree dest, tree src,
8482 tree len, tree type, bool ignore, int endp)
9c8a1629 8483{
c2f47e15 8484 tree destvar, srcvar, expr;
9c8a1629 8485
c2f47e15 8486 if (! validate_arg (dest, POINTER_TYPE)
8487 || ! validate_arg (src, POINTER_TYPE)
8488 || ! validate_arg (len, INTEGER_TYPE))
8489 return NULL_TREE;
9c8a1629 8490
8491 /* If the LEN parameter is zero, return DEST. */
8492 if (integer_zerop (len))
389dd41b 8493 return omit_one_operand_loc (loc, type, dest, src);
9c8a1629 8494
4f46f2b9 8495 /* If SRC and DEST are the same (and not volatile), return
8496 DEST{,+LEN,+LEN-1}. */
9c8a1629 8497 if (operand_equal_p (src, dest, 0))
4f46f2b9 8498 expr = len;
8499 else
8500 {
5a84fdd6 8501 tree srctype, desttype;
5383fb56 8502 int src_align, dest_align;
8503
3b1757a2 8504 if (endp == 3)
8505 {
5383fb56 8506 src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
8507 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
5a84fdd6 8508
3b1757a2 8509 /* Both DEST and SRC must be pointer types.
8510 ??? This is what old code did. Is the testing for pointer types
8511 really mandatory?
8512
8513 If either SRC is readonly or length is 1, we can use memcpy. */
3f95c690 8514 if (!dest_align || !src_align)
8515 return NULL_TREE;
8516 if (readonly_data_expr (src)
8517 || (host_integerp (len, 1)
8518 && (MIN (src_align, dest_align) / BITS_PER_UNIT
8519 >= tree_low_cst (len, 1))))
3b1757a2 8520 {
8521 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8522 if (!fn)
c2f47e15 8523 return NULL_TREE;
389dd41b 8524 return build_call_expr_loc (loc, fn, 3, dest, src, len);
3b1757a2 8525 }
3f95c690 8526
8527 /* If *src and *dest can't overlap, optimize into memcpy as well. */
f85fb819 8528 srcvar = build_fold_indirect_ref_loc (loc, src);
8529 destvar = build_fold_indirect_ref_loc (loc, dest);
8530 if (srcvar
8531 && !TREE_THIS_VOLATILE (srcvar)
8532 && destvar
8533 && !TREE_THIS_VOLATILE (destvar))
3f95c690 8534 {
f85fb819 8535 tree src_base, dest_base, fn;
8536 HOST_WIDE_INT src_offset = 0, dest_offset = 0;
8537 HOST_WIDE_INT size = -1;
8538 HOST_WIDE_INT maxsize = -1;
8539
8540 src_base = srcvar;
8541 if (handled_component_p (src_base))
8542 src_base = get_ref_base_and_extent (src_base, &src_offset,
8543 &size, &maxsize);
8544 dest_base = destvar;
8545 if (handled_component_p (dest_base))
8546 dest_base = get_ref_base_and_extent (dest_base, &dest_offset,
8547 &size, &maxsize);
8548 if (host_integerp (len, 1))
8549 {
8550 maxsize = tree_low_cst (len, 1);
8551 if (maxsize
8552 > INTTYPE_MAXIMUM (HOST_WIDE_INT) / BITS_PER_UNIT)
8553 maxsize = -1;
8554 else
8555 maxsize *= BITS_PER_UNIT;
8556 }
8557 else
8558 maxsize = -1;
8559 if (SSA_VAR_P (src_base)
8560 && SSA_VAR_P (dest_base))
8561 {
8562 if (operand_equal_p (src_base, dest_base, 0)
8563 && ranges_overlap_p (src_offset, maxsize,
8564 dest_offset, maxsize))
8565 return NULL_TREE;
8566 }
8567 else if (TREE_CODE (src_base) == INDIRECT_REF
8568 && TREE_CODE (dest_base) == INDIRECT_REF)
8569 {
8570 if (! operand_equal_p (TREE_OPERAND (src_base, 0),
8571 TREE_OPERAND (dest_base, 0), 0)
8572 || ranges_overlap_p (src_offset, maxsize,
8573 dest_offset, maxsize))
8574 return NULL_TREE;
8575 }
8576 else
8577 return NULL_TREE;
8578
8579 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
3f95c690 8580 if (!fn)
8581 return NULL_TREE;
389dd41b 8582 return build_call_expr_loc (loc, fn, 3, dest, src, len);
3f95c690 8583 }
c2f47e15 8584 return NULL_TREE;
3b1757a2 8585 }
4f46f2b9 8586
5a84fdd6 8587 if (!host_integerp (len, 0))
c2f47e15 8588 return NULL_TREE;
5a84fdd6 8589 /* FIXME:
8590 This logic lose for arguments like (type *)malloc (sizeof (type)),
8591 since we strip the casts of up to VOID return value from malloc.
8592 Perhaps we ought to inherit type from non-VOID argument here? */
8593 STRIP_NOPS (src);
8594 STRIP_NOPS (dest);
45bb3afb 8595 /* As we fold (void *)(p + CST) to (void *)p + CST undo this here. */
8596 if (TREE_CODE (src) == POINTER_PLUS_EXPR)
8597 {
8598 tree tem = TREE_OPERAND (src, 0);
8599 STRIP_NOPS (tem);
8600 if (tem != TREE_OPERAND (src, 0))
8601 src = build1 (NOP_EXPR, TREE_TYPE (tem), src);
8602 }
8603 if (TREE_CODE (dest) == POINTER_PLUS_EXPR)
8604 {
8605 tree tem = TREE_OPERAND (dest, 0);
8606 STRIP_NOPS (tem);
8607 if (tem != TREE_OPERAND (dest, 0))
8608 dest = build1 (NOP_EXPR, TREE_TYPE (tem), dest);
8609 }
5a84fdd6 8610 srctype = TREE_TYPE (TREE_TYPE (src));
45bb3afb 8611 if (srctype
97d4c6a6 8612 && TREE_CODE (srctype) == ARRAY_TYPE
8613 && !tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
45bb3afb 8614 {
8615 srctype = TREE_TYPE (srctype);
8616 STRIP_NOPS (src);
8617 src = build1 (NOP_EXPR, build_pointer_type (srctype), src);
8618 }
5a84fdd6 8619 desttype = TREE_TYPE (TREE_TYPE (dest));
45bb3afb 8620 if (desttype
97d4c6a6 8621 && TREE_CODE (desttype) == ARRAY_TYPE
8622 && !tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
45bb3afb 8623 {
8624 desttype = TREE_TYPE (desttype);
8625 STRIP_NOPS (dest);
8626 dest = build1 (NOP_EXPR, build_pointer_type (desttype), dest);
8627 }
5a84fdd6 8628 if (!srctype || !desttype
8629 || !TYPE_SIZE_UNIT (srctype)
8630 || !TYPE_SIZE_UNIT (desttype)
8631 || TREE_CODE (TYPE_SIZE_UNIT (srctype)) != INTEGER_CST
6f52ebeb 8632 || TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST
8633 || TYPE_VOLATILE (srctype)
8634 || TYPE_VOLATILE (desttype))
c2f47e15 8635 return NULL_TREE;
4f46f2b9 8636
5383fb56 8637 src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
8638 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
8639 if (dest_align < (int) TYPE_ALIGN (desttype)
8640 || src_align < (int) TYPE_ALIGN (srctype))
c2f47e15 8641 return NULL_TREE;
e973ffcc 8642
5a84fdd6 8643 if (!ignore)
8644 dest = builtin_save_expr (dest);
4f46f2b9 8645
5383fb56 8646 srcvar = NULL_TREE;
8647 if (tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
8648 {
389dd41b 8649 srcvar = build_fold_indirect_ref_loc (loc, src);
5383fb56 8650 if (TREE_THIS_VOLATILE (srcvar))
6f52ebeb 8651 return NULL_TREE;
92ddcd97 8652 else if (!tree_int_cst_equal (tree_expr_size (srcvar), len))
5383fb56 8653 srcvar = NULL_TREE;
8654 /* With memcpy, it is possible to bypass aliasing rules, so without
8655 this check i.e. execute/20060930-2.c would be misoptimized,
8656 because it use conflicting alias set to hold argument for the
8657 memcpy call. This check is probably unnecessary with
8658 -fno-strict-aliasing. Similarly for destvar. See also
8659 PR29286. */
8660 else if (!var_decl_component_p (srcvar))
8661 srcvar = NULL_TREE;
8662 }
4f46f2b9 8663
5383fb56 8664 destvar = NULL_TREE;
8665 if (tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
8666 {
389dd41b 8667 destvar = build_fold_indirect_ref_loc (loc, dest);
5383fb56 8668 if (TREE_THIS_VOLATILE (destvar))
6f52ebeb 8669 return NULL_TREE;
92ddcd97 8670 else if (!tree_int_cst_equal (tree_expr_size (destvar), len))
5383fb56 8671 destvar = NULL_TREE;
8672 else if (!var_decl_component_p (destvar))
8673 destvar = NULL_TREE;
8674 }
8675
8676 if (srcvar == NULL_TREE && destvar == NULL_TREE)
c2f47e15 8677 return NULL_TREE;
4f46f2b9 8678
5383fb56 8679 if (srcvar == NULL_TREE)
8680 {
8681 tree srcptype;
8682 if (TREE_ADDRESSABLE (TREE_TYPE (destvar)))
8683 return NULL_TREE;
8684
6f52ebeb 8685 srctype = build_qualified_type (desttype, 0);
5383fb56 8686 if (src_align < (int) TYPE_ALIGN (srctype))
8687 {
8688 if (AGGREGATE_TYPE_P (srctype)
8689 || SLOW_UNALIGNED_ACCESS (TYPE_MODE (srctype), src_align))
8690 return NULL_TREE;
8691
8692 srctype = build_variant_type_copy (srctype);
8693 TYPE_ALIGN (srctype) = src_align;
8694 TYPE_USER_ALIGN (srctype) = 1;
8695 TYPE_PACKED (srctype) = 1;
8696 }
8697 srcptype = build_pointer_type_for_mode (srctype, ptr_mode, true);
389dd41b 8698 src = fold_convert_loc (loc, srcptype, src);
8699 srcvar = build_fold_indirect_ref_loc (loc, src);
5383fb56 8700 }
8701 else if (destvar == NULL_TREE)
8702 {
8703 tree destptype;
8704 if (TREE_ADDRESSABLE (TREE_TYPE (srcvar)))
8705 return NULL_TREE;
8706
6f52ebeb 8707 desttype = build_qualified_type (srctype, 0);
5383fb56 8708 if (dest_align < (int) TYPE_ALIGN (desttype))
8709 {
8710 if (AGGREGATE_TYPE_P (desttype)
8711 || SLOW_UNALIGNED_ACCESS (TYPE_MODE (desttype), dest_align))
8712 return NULL_TREE;
8713
8714 desttype = build_variant_type_copy (desttype);
8715 TYPE_ALIGN (desttype) = dest_align;
8716 TYPE_USER_ALIGN (desttype) = 1;
8717 TYPE_PACKED (desttype) = 1;
8718 }
8719 destptype = build_pointer_type_for_mode (desttype, ptr_mode, true);
389dd41b 8720 dest = fold_convert_loc (loc, destptype, dest);
8721 destvar = build_fold_indirect_ref_loc (loc, dest);
5383fb56 8722 }
8723
5a84fdd6 8724 if (srctype == desttype
2d04fd8d 8725 || (gimple_in_ssa_p (cfun)
548044d8 8726 && useless_type_conversion_p (desttype, srctype)))
5a84fdd6 8727 expr = srcvar;
8728 else if ((INTEGRAL_TYPE_P (TREE_TYPE (srcvar))
4f46f2b9 8729 || POINTER_TYPE_P (TREE_TYPE (srcvar)))
8730 && (INTEGRAL_TYPE_P (TREE_TYPE (destvar))
8731 || POINTER_TYPE_P (TREE_TYPE (destvar))))
389dd41b 8732 expr = fold_convert_loc (loc, TREE_TYPE (destvar), srcvar);
4f46f2b9 8733 else
389dd41b 8734 expr = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
8735 TREE_TYPE (destvar), srcvar);
41076ef6 8736 expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, expr);
4f46f2b9 8737 }
8738
8739 if (ignore)
8740 return expr;
8741
8742 if (endp == 0 || endp == 3)
389dd41b 8743 return omit_one_operand_loc (loc, type, dest, expr);
4f46f2b9 8744
8745 if (expr == len)
c2f47e15 8746 expr = NULL_TREE;
4f46f2b9 8747
8748 if (endp == 2)
389dd41b 8749 len = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (len), len,
4f46f2b9 8750 ssize_int (1));
8751
389dd41b 8752 len = fold_convert_loc (loc, sizetype, len);
8753 dest = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
8754 dest = fold_convert_loc (loc, type, dest);
4f46f2b9 8755 if (expr)
389dd41b 8756 dest = omit_one_operand_loc (loc, type, dest, expr);
4f46f2b9 8757 return dest;
8758}
8759
c2f47e15 8760/* Fold function call to builtin strcpy with arguments DEST and SRC.
8761 If LEN is not NULL, it represents the length of the string to be
8762 copied. Return NULL_TREE if no simplification can be made. */
9c8a1629 8763
f0613857 8764tree
389dd41b 8765fold_builtin_strcpy (location_t loc, tree fndecl, tree dest, tree src, tree len)
9c8a1629 8766{
c2f47e15 8767 tree fn;
9c8a1629 8768
c2f47e15 8769 if (!validate_arg (dest, POINTER_TYPE)
8770 || !validate_arg (src, POINTER_TYPE))
8771 return NULL_TREE;
9c8a1629 8772
8773 /* If SRC and DEST are the same (and not volatile), return DEST. */
8774 if (operand_equal_p (src, dest, 0))
389dd41b 8775 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
9c8a1629 8776
0bfd8d5c 8777 if (optimize_function_for_size_p (cfun))
c2f47e15 8778 return NULL_TREE;
f0613857 8779
8780 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8781 if (!fn)
c2f47e15 8782 return NULL_TREE;
f0613857 8783
8784 if (!len)
8785 {
8786 len = c_strlen (src, 1);
8787 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 8788 return NULL_TREE;
f0613857 8789 }
8790
389dd41b 8791 len = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
8792 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
8793 build_call_expr_loc (loc, fn, 3, dest, src, len));
9c8a1629 8794}
8795
a65c4d64 8796/* Fold function call to builtin stpcpy with arguments DEST and SRC.
8797 Return NULL_TREE if no simplification can be made. */
8798
8799static tree
8800fold_builtin_stpcpy (location_t loc, tree fndecl, tree dest, tree src)
8801{
8802 tree fn, len, lenp1, call, type;
8803
8804 if (!validate_arg (dest, POINTER_TYPE)
8805 || !validate_arg (src, POINTER_TYPE))
8806 return NULL_TREE;
8807
8808 len = c_strlen (src, 1);
8809 if (!len
8810 || TREE_CODE (len) != INTEGER_CST)
8811 return NULL_TREE;
8812
8813 if (optimize_function_for_size_p (cfun)
8814 /* If length is zero it's small enough. */
8815 && !integer_zerop (len))
8816 return NULL_TREE;
8817
8818 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8819 if (!fn)
8820 return NULL_TREE;
8821
8822 lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
8823 /* We use dest twice in building our expression. Save it from
8824 multiple expansions. */
8825 dest = builtin_save_expr (dest);
8826 call = build_call_expr_loc (loc, fn, 3, dest, src, lenp1);
8827
8828 type = TREE_TYPE (TREE_TYPE (fndecl));
8829 len = fold_convert_loc (loc, sizetype, len);
8830 dest = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
8831 dest = fold_convert_loc (loc, type, dest);
8832 dest = omit_one_operand_loc (loc, type, dest, call);
8833 return dest;
8834}
8835
c2f47e15 8836/* Fold function call to builtin strncpy with arguments DEST, SRC, and LEN.
8837 If SLEN is not NULL, it represents the length of the source string.
8838 Return NULL_TREE if no simplification can be made. */
9c8a1629 8839
f0613857 8840tree
389dd41b 8841fold_builtin_strncpy (location_t loc, tree fndecl, tree dest,
8842 tree src, tree len, tree slen)
9c8a1629 8843{
c2f47e15 8844 tree fn;
9c8a1629 8845
c2f47e15 8846 if (!validate_arg (dest, POINTER_TYPE)
8847 || !validate_arg (src, POINTER_TYPE)
8848 || !validate_arg (len, INTEGER_TYPE))
8849 return NULL_TREE;
9c8a1629 8850
8851 /* If the LEN parameter is zero, return DEST. */
8852 if (integer_zerop (len))
389dd41b 8853 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
9c8a1629 8854
19226313 8855 /* We can't compare slen with len as constants below if len is not a
8856 constant. */
8857 if (len == 0 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 8858 return NULL_TREE;
19226313 8859
f0613857 8860 if (!slen)
8861 slen = c_strlen (src, 1);
8862
8863 /* Now, we must be passed a constant src ptr parameter. */
8864 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
c2f47e15 8865 return NULL_TREE;
f0613857 8866
389dd41b 8867 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
f0613857 8868
8869 /* We do not support simplification of this case, though we do
8870 support it when expanding trees into RTL. */
8871 /* FIXME: generate a call to __builtin_memset. */
8872 if (tree_int_cst_lt (slen, len))
c2f47e15 8873 return NULL_TREE;
f0613857 8874
8875 /* OK transform into builtin memcpy. */
8876 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8877 if (!fn)
c2f47e15 8878 return NULL_TREE;
389dd41b 8879 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
8880 build_call_expr_loc (loc, fn, 3, dest, src, len));
9c8a1629 8881}
8882
7959b13b 8883/* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the
8884 arguments to the call, and TYPE is its return type.
8885 Return NULL_TREE if no simplification can be made. */
8886
8887static tree
389dd41b 8888fold_builtin_memchr (location_t loc, tree arg1, tree arg2, tree len, tree type)
7959b13b 8889{
8890 if (!validate_arg (arg1, POINTER_TYPE)
8891 || !validate_arg (arg2, INTEGER_TYPE)
8892 || !validate_arg (len, INTEGER_TYPE))
8893 return NULL_TREE;
8894 else
8895 {
8896 const char *p1;
8897
8898 if (TREE_CODE (arg2) != INTEGER_CST
8899 || !host_integerp (len, 1))
8900 return NULL_TREE;
8901
8902 p1 = c_getstr (arg1);
8903 if (p1 && compare_tree_int (len, strlen (p1) + 1) <= 0)
8904 {
8905 char c;
8906 const char *r;
8907 tree tem;
8908
8909 if (target_char_cast (arg2, &c))
8910 return NULL_TREE;
8911
364c0c59 8912 r = (char *) memchr (p1, c, tree_low_cst (len, 1));
7959b13b 8913
8914 if (r == NULL)
8915 return build_int_cst (TREE_TYPE (arg1), 0);
8916
389dd41b 8917 tem = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (arg1), arg1,
0de36bdb 8918 size_int (r - p1));
389dd41b 8919 return fold_convert_loc (loc, type, tem);
7959b13b 8920 }
8921 return NULL_TREE;
8922 }
8923}
8924
c2f47e15 8925/* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
8926 Return NULL_TREE if no simplification can be made. */
9c8a1629 8927
8928static tree
389dd41b 8929fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
9c8a1629 8930{
c4fef134 8931 const char *p1, *p2;
9c8a1629 8932
c2f47e15 8933 if (!validate_arg (arg1, POINTER_TYPE)
8934 || !validate_arg (arg2, POINTER_TYPE)
8935 || !validate_arg (len, INTEGER_TYPE))
8936 return NULL_TREE;
9c8a1629 8937
8938 /* If the LEN parameter is zero, return zero. */
8939 if (integer_zerop (len))
389dd41b 8940 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
c4fef134 8941 arg1, arg2);
9c8a1629 8942
8943 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8944 if (operand_equal_p (arg1, arg2, 0))
389dd41b 8945 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
c4fef134 8946
8947 p1 = c_getstr (arg1);
8948 p2 = c_getstr (arg2);
8949
8950 /* If all arguments are constant, and the value of len is not greater
8951 than the lengths of arg1 and arg2, evaluate at compile-time. */
8952 if (host_integerp (len, 1) && p1 && p2
8953 && compare_tree_int (len, strlen (p1) + 1) <= 0
8954 && compare_tree_int (len, strlen (p2) + 1) <= 0)
8955 {
8956 const int r = memcmp (p1, p2, tree_low_cst (len, 1));
8957
8958 if (r > 0)
8959 return integer_one_node;
8960 else if (r < 0)
8961 return integer_minus_one_node;
8962 else
8963 return integer_zero_node;
8964 }
8965
8966 /* If len parameter is one, return an expression corresponding to
8967 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
8968 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
8969 {
8970 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 8971 tree cst_uchar_ptr_node
8972 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8973
389dd41b 8974 tree ind1
8975 = fold_convert_loc (loc, integer_type_node,
8976 build1 (INDIRECT_REF, cst_uchar_node,
8977 fold_convert_loc (loc,
8978 cst_uchar_ptr_node,
c4fef134 8979 arg1)));
389dd41b 8980 tree ind2
8981 = fold_convert_loc (loc, integer_type_node,
8982 build1 (INDIRECT_REF, cst_uchar_node,
8983 fold_convert_loc (loc,
8984 cst_uchar_ptr_node,
c4fef134 8985 arg2)));
389dd41b 8986 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
c4fef134 8987 }
9c8a1629 8988
c2f47e15 8989 return NULL_TREE;
9c8a1629 8990}
8991
c2f47e15 8992/* Fold function call to builtin strcmp with arguments ARG1 and ARG2.
8993 Return NULL_TREE if no simplification can be made. */
9c8a1629 8994
8995static tree
389dd41b 8996fold_builtin_strcmp (location_t loc, tree arg1, tree arg2)
9c8a1629 8997{
9c8a1629 8998 const char *p1, *p2;
8999
c2f47e15 9000 if (!validate_arg (arg1, POINTER_TYPE)
9001 || !validate_arg (arg2, POINTER_TYPE))
9002 return NULL_TREE;
9c8a1629 9003
9004 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9005 if (operand_equal_p (arg1, arg2, 0))
c4fef134 9006 return integer_zero_node;
9c8a1629 9007
9008 p1 = c_getstr (arg1);
9009 p2 = c_getstr (arg2);
9010
9011 if (p1 && p2)
9012 {
9c8a1629 9013 const int i = strcmp (p1, p2);
9014 if (i < 0)
c4fef134 9015 return integer_minus_one_node;
9c8a1629 9016 else if (i > 0)
c4fef134 9017 return integer_one_node;
9c8a1629 9018 else
c4fef134 9019 return integer_zero_node;
9020 }
9021
9022 /* If the second arg is "", return *(const unsigned char*)arg1. */
9023 if (p2 && *p2 == '\0')
9024 {
9025 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9026 tree cst_uchar_ptr_node
9027 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9028
389dd41b 9029 return fold_convert_loc (loc, integer_type_node,
9030 build1 (INDIRECT_REF, cst_uchar_node,
9031 fold_convert_loc (loc,
9032 cst_uchar_ptr_node,
9033 arg1)));
c4fef134 9034 }
9035
9036 /* If the first arg is "", return -*(const unsigned char*)arg2. */
9037 if (p1 && *p1 == '\0')
9038 {
9039 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9040 tree cst_uchar_ptr_node
9041 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9042
389dd41b 9043 tree temp
9044 = fold_convert_loc (loc, integer_type_node,
9045 build1 (INDIRECT_REF, cst_uchar_node,
9046 fold_convert_loc (loc,
9047 cst_uchar_ptr_node,
c4fef134 9048 arg2)));
389dd41b 9049 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp);
9c8a1629 9050 }
9051
c2f47e15 9052 return NULL_TREE;
9c8a1629 9053}
9054
c2f47e15 9055/* Fold function call to builtin strncmp with arguments ARG1, ARG2, and LEN.
9056 Return NULL_TREE if no simplification can be made. */
9c8a1629 9057
9058static tree
389dd41b 9059fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len)
9c8a1629 9060{
9c8a1629 9061 const char *p1, *p2;
9062
c2f47e15 9063 if (!validate_arg (arg1, POINTER_TYPE)
9064 || !validate_arg (arg2, POINTER_TYPE)
9065 || !validate_arg (len, INTEGER_TYPE))
9066 return NULL_TREE;
9c8a1629 9067
9068 /* If the LEN parameter is zero, return zero. */
9069 if (integer_zerop (len))
389dd41b 9070 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
c4fef134 9071 arg1, arg2);
9c8a1629 9072
9073 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9074 if (operand_equal_p (arg1, arg2, 0))
389dd41b 9075 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
9c8a1629 9076
9077 p1 = c_getstr (arg1);
9078 p2 = c_getstr (arg2);
9079
9080 if (host_integerp (len, 1) && p1 && p2)
9081 {
9c8a1629 9082 const int i = strncmp (p1, p2, tree_low_cst (len, 1));
c4fef134 9083 if (i > 0)
9084 return integer_one_node;
9085 else if (i < 0)
9086 return integer_minus_one_node;
9c8a1629 9087 else
c4fef134 9088 return integer_zero_node;
9089 }
9090
9091 /* If the second arg is "", and the length is greater than zero,
9092 return *(const unsigned char*)arg1. */
9093 if (p2 && *p2 == '\0'
9094 && TREE_CODE (len) == INTEGER_CST
9095 && tree_int_cst_sgn (len) == 1)
9096 {
9097 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9098 tree cst_uchar_ptr_node
9099 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9100
389dd41b 9101 return fold_convert_loc (loc, integer_type_node,
9102 build1 (INDIRECT_REF, cst_uchar_node,
9103 fold_convert_loc (loc,
9104 cst_uchar_ptr_node,
9105 arg1)));
c4fef134 9106 }
9107
9108 /* If the first arg is "", and the length is greater than zero,
9109 return -*(const unsigned char*)arg2. */
9110 if (p1 && *p1 == '\0'
9111 && TREE_CODE (len) == INTEGER_CST
9112 && tree_int_cst_sgn (len) == 1)
9113 {
9114 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9115 tree cst_uchar_ptr_node
9116 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9117
389dd41b 9118 tree temp = fold_convert_loc (loc, integer_type_node,
9119 build1 (INDIRECT_REF, cst_uchar_node,
9120 fold_convert_loc (loc,
9121 cst_uchar_ptr_node,
9122 arg2)));
9123 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp);
c4fef134 9124 }
9125
9126 /* If len parameter is one, return an expression corresponding to
9127 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
9128 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
9129 {
9130 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9131 tree cst_uchar_ptr_node
9132 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9133
389dd41b 9134 tree ind1 = fold_convert_loc (loc, integer_type_node,
9135 build1 (INDIRECT_REF, cst_uchar_node,
9136 fold_convert_loc (loc,
9137 cst_uchar_ptr_node,
9138 arg1)));
9139 tree ind2 = fold_convert_loc (loc, integer_type_node,
9140 build1 (INDIRECT_REF, cst_uchar_node,
9141 fold_convert_loc (loc,
9142 cst_uchar_ptr_node,
9143 arg2)));
9144 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
9c8a1629 9145 }
9146
c2f47e15 9147 return NULL_TREE;
9c8a1629 9148}
9149
c2f47e15 9150/* Fold function call to builtin signbit, signbitf or signbitl with argument
9151 ARG. Return NULL_TREE if no simplification can be made. */
27f261ef 9152
9153static tree
389dd41b 9154fold_builtin_signbit (location_t loc, tree arg, tree type)
27f261ef 9155{
c2f47e15 9156 tree temp;
27f261ef 9157
c2f47e15 9158 if (!validate_arg (arg, REAL_TYPE))
27f261ef 9159 return NULL_TREE;
9160
27f261ef 9161 /* If ARG is a compile-time constant, determine the result. */
9162 if (TREE_CODE (arg) == REAL_CST
f96bd2bf 9163 && !TREE_OVERFLOW (arg))
27f261ef 9164 {
9165 REAL_VALUE_TYPE c;
9166
9167 c = TREE_REAL_CST (arg);
9168 temp = REAL_VALUE_NEGATIVE (c) ? integer_one_node : integer_zero_node;
389dd41b 9169 return fold_convert_loc (loc, type, temp);
27f261ef 9170 }
9171
9172 /* If ARG is non-negative, the result is always zero. */
9173 if (tree_expr_nonnegative_p (arg))
389dd41b 9174 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
27f261ef 9175
9176 /* If ARG's format doesn't have signed zeros, return "arg < 0.0". */
9177 if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 9178 return fold_build2_loc (loc, LT_EXPR, type, arg,
49d00087 9179 build_real (TREE_TYPE (arg), dconst0));
27f261ef 9180
9181 return NULL_TREE;
9182}
9183
c2f47e15 9184/* Fold function call to builtin copysign, copysignf or copysignl with
9185 arguments ARG1 and ARG2. Return NULL_TREE if no simplification can
9186 be made. */
467214fd 9187
9188static tree
389dd41b 9189fold_builtin_copysign (location_t loc, tree fndecl,
9190 tree arg1, tree arg2, tree type)
467214fd 9191{
c2f47e15 9192 tree tem;
467214fd 9193
c2f47e15 9194 if (!validate_arg (arg1, REAL_TYPE)
9195 || !validate_arg (arg2, REAL_TYPE))
467214fd 9196 return NULL_TREE;
9197
467214fd 9198 /* copysign(X,X) is X. */
9199 if (operand_equal_p (arg1, arg2, 0))
389dd41b 9200 return fold_convert_loc (loc, type, arg1);
467214fd 9201
9202 /* If ARG1 and ARG2 are compile-time constants, determine the result. */
9203 if (TREE_CODE (arg1) == REAL_CST
9204 && TREE_CODE (arg2) == REAL_CST
f96bd2bf 9205 && !TREE_OVERFLOW (arg1)
9206 && !TREE_OVERFLOW (arg2))
467214fd 9207 {
9208 REAL_VALUE_TYPE c1, c2;
9209
9210 c1 = TREE_REAL_CST (arg1);
9211 c2 = TREE_REAL_CST (arg2);
749680e2 9212 /* c1.sign := c2.sign. */
467214fd 9213 real_copysign (&c1, &c2);
9214 return build_real (type, c1);
467214fd 9215 }
9216
9217 /* copysign(X, Y) is fabs(X) when Y is always non-negative.
9218 Remember to evaluate Y for side-effects. */
9219 if (tree_expr_nonnegative_p (arg2))
389dd41b 9220 return omit_one_operand_loc (loc, type,
9221 fold_build1_loc (loc, ABS_EXPR, type, arg1),
467214fd 9222 arg2);
9223
198d9bbe 9224 /* Strip sign changing operations for the first argument. */
9225 tem = fold_strip_sign_ops (arg1);
9226 if (tem)
389dd41b 9227 return build_call_expr_loc (loc, fndecl, 2, tem, arg2);
198d9bbe 9228
467214fd 9229 return NULL_TREE;
9230}
9231
c2f47e15 9232/* Fold a call to builtin isascii with argument ARG. */
d49367d4 9233
9234static tree
389dd41b 9235fold_builtin_isascii (location_t loc, tree arg)
d49367d4 9236{
c2f47e15 9237 if (!validate_arg (arg, INTEGER_TYPE))
9238 return NULL_TREE;
d49367d4 9239 else
9240 {
9241 /* Transform isascii(c) -> ((c & ~0x7f) == 0). */
c90b5d40 9242 arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
9243 build_int_cst (NULL_TREE,
9244 ~ (unsigned HOST_WIDE_INT) 0x7f));
389dd41b 9245 return fold_build2_loc (loc, EQ_EXPR, integer_type_node,
f2532264 9246 arg, integer_zero_node);
d49367d4 9247 }
9248}
9249
c2f47e15 9250/* Fold a call to builtin toascii with argument ARG. */
d49367d4 9251
9252static tree
389dd41b 9253fold_builtin_toascii (location_t loc, tree arg)
d49367d4 9254{
c2f47e15 9255 if (!validate_arg (arg, INTEGER_TYPE))
9256 return NULL_TREE;
9257
9258 /* Transform toascii(c) -> (c & 0x7f). */
389dd41b 9259 return fold_build2_loc (loc, BIT_AND_EXPR, integer_type_node, arg,
c2f47e15 9260 build_int_cst (NULL_TREE, 0x7f));
d49367d4 9261}
9262
c2f47e15 9263/* Fold a call to builtin isdigit with argument ARG. */
df1cf42e 9264
9265static tree
389dd41b 9266fold_builtin_isdigit (location_t loc, tree arg)
df1cf42e 9267{
c2f47e15 9268 if (!validate_arg (arg, INTEGER_TYPE))
9269 return NULL_TREE;
df1cf42e 9270 else
9271 {
9272 /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */
624d37a6 9273 /* According to the C standard, isdigit is unaffected by locale.
9274 However, it definitely is affected by the target character set. */
624d37a6 9275 unsigned HOST_WIDE_INT target_digit0
9276 = lang_hooks.to_target_charset ('0');
9277
9278 if (target_digit0 == 0)
9279 return NULL_TREE;
9280
389dd41b 9281 arg = fold_convert_loc (loc, unsigned_type_node, arg);
c90b5d40 9282 arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg,
9283 build_int_cst (unsigned_type_node, target_digit0));
389dd41b 9284 return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg,
f2532264 9285 build_int_cst (unsigned_type_node, 9));
df1cf42e 9286 }
9287}
27f261ef 9288
c2f47e15 9289/* Fold a call to fabs, fabsf or fabsl with argument ARG. */
d1aade50 9290
9291static tree
389dd41b 9292fold_builtin_fabs (location_t loc, tree arg, tree type)
d1aade50 9293{
c2f47e15 9294 if (!validate_arg (arg, REAL_TYPE))
9295 return NULL_TREE;
d1aade50 9296
389dd41b 9297 arg = fold_convert_loc (loc, type, arg);
d1aade50 9298 if (TREE_CODE (arg) == REAL_CST)
9299 return fold_abs_const (arg, type);
389dd41b 9300 return fold_build1_loc (loc, ABS_EXPR, type, arg);
d1aade50 9301}
9302
c2f47e15 9303/* Fold a call to abs, labs, llabs or imaxabs with argument ARG. */
d1aade50 9304
9305static tree
389dd41b 9306fold_builtin_abs (location_t loc, tree arg, tree type)
d1aade50 9307{
c2f47e15 9308 if (!validate_arg (arg, INTEGER_TYPE))
9309 return NULL_TREE;
d1aade50 9310
389dd41b 9311 arg = fold_convert_loc (loc, type, arg);
d1aade50 9312 if (TREE_CODE (arg) == INTEGER_CST)
9313 return fold_abs_const (arg, type);
389dd41b 9314 return fold_build1_loc (loc, ABS_EXPR, type, arg);
d1aade50 9315}
9316
d4a43a03 9317/* Fold a call to builtin fmin or fmax. */
9318
9319static tree
389dd41b 9320fold_builtin_fmin_fmax (location_t loc, tree arg0, tree arg1,
9321 tree type, bool max)
d4a43a03 9322{
c2f47e15 9323 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, REAL_TYPE))
d4a43a03 9324 {
d4a43a03 9325 /* Calculate the result when the argument is a constant. */
9326 tree res = do_mpfr_arg2 (arg0, arg1, type, (max ? mpfr_max : mpfr_min));
9327
9328 if (res)
9329 return res;
9330
61fe3555 9331 /* If either argument is NaN, return the other one. Avoid the
9332 transformation if we get (and honor) a signalling NaN. Using
9333 omit_one_operand() ensures we create a non-lvalue. */
9334 if (TREE_CODE (arg0) == REAL_CST
9335 && real_isnan (&TREE_REAL_CST (arg0))
9336 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
9337 || ! TREE_REAL_CST (arg0).signalling))
389dd41b 9338 return omit_one_operand_loc (loc, type, arg1, arg0);
61fe3555 9339 if (TREE_CODE (arg1) == REAL_CST
9340 && real_isnan (&TREE_REAL_CST (arg1))
9341 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
9342 || ! TREE_REAL_CST (arg1).signalling))
389dd41b 9343 return omit_one_operand_loc (loc, type, arg0, arg1);
61fe3555 9344
d4a43a03 9345 /* Transform fmin/fmax(x,x) -> x. */
9346 if (operand_equal_p (arg0, arg1, OEP_PURE_SAME))
389dd41b 9347 return omit_one_operand_loc (loc, type, arg0, arg1);
d4a43a03 9348
9349 /* Convert fmin/fmax to MIN_EXPR/MAX_EXPR. C99 requires these
9350 functions to return the numeric arg if the other one is NaN.
9351 These tree codes don't honor that, so only transform if
9352 -ffinite-math-only is set. C99 doesn't require -0.0 to be
9353 handled, so we don't have to worry about it either. */
9354 if (flag_finite_math_only)
389dd41b 9355 return fold_build2_loc (loc, (max ? MAX_EXPR : MIN_EXPR), type,
9356 fold_convert_loc (loc, type, arg0),
9357 fold_convert_loc (loc, type, arg1));
d4a43a03 9358 }
9359 return NULL_TREE;
9360}
9361
abe4dcf6 9362/* Fold a call to builtin carg(a+bi) -> atan2(b,a). */
9363
9364static tree
389dd41b 9365fold_builtin_carg (location_t loc, tree arg, tree type)
abe4dcf6 9366{
239d491a 9367 if (validate_arg (arg, COMPLEX_TYPE)
9368 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
abe4dcf6 9369 {
9370 tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
9371
9372 if (atan2_fn)
9373 {
c2f47e15 9374 tree new_arg = builtin_save_expr (arg);
389dd41b 9375 tree r_arg = fold_build1_loc (loc, REALPART_EXPR, type, new_arg);
9376 tree i_arg = fold_build1_loc (loc, IMAGPART_EXPR, type, new_arg);
9377 return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg);
abe4dcf6 9378 }
9379 }
9380
9381 return NULL_TREE;
9382}
9383
cb2b9385 9384/* Fold a call to builtin logb/ilogb. */
9385
9386static tree
389dd41b 9387fold_builtin_logb (location_t loc, tree arg, tree rettype)
cb2b9385 9388{
9389 if (! validate_arg (arg, REAL_TYPE))
9390 return NULL_TREE;
9391
9392 STRIP_NOPS (arg);
9393
9394 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9395 {
9396 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
9397
9398 switch (value->cl)
9399 {
9400 case rvc_nan:
9401 case rvc_inf:
9402 /* If arg is Inf or NaN and we're logb, return it. */
9403 if (TREE_CODE (rettype) == REAL_TYPE)
389dd41b 9404 return fold_convert_loc (loc, rettype, arg);
cb2b9385 9405 /* Fall through... */
9406 case rvc_zero:
9407 /* Zero may set errno and/or raise an exception for logb, also
9408 for ilogb we don't know FP_ILOGB0. */
9409 return NULL_TREE;
9410 case rvc_normal:
9411 /* For normal numbers, proceed iff radix == 2. In GCC,
9412 normalized significands are in the range [0.5, 1.0). We
9413 want the exponent as if they were [1.0, 2.0) so get the
9414 exponent and subtract 1. */
9415 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
389dd41b 9416 return fold_convert_loc (loc, rettype,
9417 build_int_cst (NULL_TREE,
9418 REAL_EXP (value)-1));
cb2b9385 9419 break;
9420 }
9421 }
9422
9423 return NULL_TREE;
9424}
9425
9426/* Fold a call to builtin significand, if radix == 2. */
9427
9428static tree
389dd41b 9429fold_builtin_significand (location_t loc, tree arg, tree rettype)
cb2b9385 9430{
9431 if (! validate_arg (arg, REAL_TYPE))
9432 return NULL_TREE;
9433
9434 STRIP_NOPS (arg);
9435
9436 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9437 {
9438 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
9439
9440 switch (value->cl)
9441 {
9442 case rvc_zero:
9443 case rvc_nan:
9444 case rvc_inf:
9445 /* If arg is +-0, +-Inf or +-NaN, then return it. */
389dd41b 9446 return fold_convert_loc (loc, rettype, arg);
cb2b9385 9447 case rvc_normal:
9448 /* For normal numbers, proceed iff radix == 2. */
9449 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
9450 {
9451 REAL_VALUE_TYPE result = *value;
9452 /* In GCC, normalized significands are in the range [0.5,
9453 1.0). We want them to be [1.0, 2.0) so set the
9454 exponent to 1. */
9455 SET_REAL_EXP (&result, 1);
9456 return build_real (rettype, result);
9457 }
9458 break;
9459 }
9460 }
9461
9462 return NULL_TREE;
9463}
9464
3838b9ae 9465/* Fold a call to builtin frexp, we can assume the base is 2. */
9466
9467static tree
389dd41b 9468fold_builtin_frexp (location_t loc, tree arg0, tree arg1, tree rettype)
3838b9ae 9469{
9470 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9471 return NULL_TREE;
9472
9473 STRIP_NOPS (arg0);
9474
9475 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9476 return NULL_TREE;
9477
389dd41b 9478 arg1 = build_fold_indirect_ref_loc (loc, arg1);
3838b9ae 9479
9480 /* Proceed if a valid pointer type was passed in. */
9481 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
9482 {
9483 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9484 tree frac, exp;
9485
9486 switch (value->cl)
9487 {
9488 case rvc_zero:
9489 /* For +-0, return (*exp = 0, +-0). */
9490 exp = integer_zero_node;
9491 frac = arg0;
9492 break;
9493 case rvc_nan:
9494 case rvc_inf:
9495 /* For +-NaN or +-Inf, *exp is unspecified, return arg0. */
389dd41b 9496 return omit_one_operand_loc (loc, rettype, arg0, arg1);
3838b9ae 9497 case rvc_normal:
9498 {
9499 /* Since the frexp function always expects base 2, and in
9500 GCC normalized significands are already in the range
9501 [0.5, 1.0), we have exactly what frexp wants. */
9502 REAL_VALUE_TYPE frac_rvt = *value;
9503 SET_REAL_EXP (&frac_rvt, 0);
9504 frac = build_real (rettype, frac_rvt);
9505 exp = build_int_cst (NULL_TREE, REAL_EXP (value));
9506 }
9507 break;
9508 default:
9509 gcc_unreachable ();
9510 }
9511
9512 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
389dd41b 9513 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, exp);
3838b9ae 9514 TREE_SIDE_EFFECTS (arg1) = 1;
389dd41b 9515 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1, frac);
3838b9ae 9516 }
9517
9518 return NULL_TREE;
9519}
9520
7587301b 9521/* Fold a call to builtin ldexp or scalbn/scalbln. If LDEXP is true
9522 then we can assume the base is two. If it's false, then we have to
9523 check the mode of the TYPE parameter in certain cases. */
9524
9525static tree
389dd41b 9526fold_builtin_load_exponent (location_t loc, tree arg0, tree arg1,
9527 tree type, bool ldexp)
7587301b 9528{
9529 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, INTEGER_TYPE))
9530 {
9531 STRIP_NOPS (arg0);
9532 STRIP_NOPS (arg1);
9533
9534 /* If arg0 is 0, Inf or NaN, or if arg1 is 0, then return arg0. */
9535 if (real_zerop (arg0) || integer_zerop (arg1)
9536 || (TREE_CODE (arg0) == REAL_CST
776a7bab 9537 && !real_isfinite (&TREE_REAL_CST (arg0))))
389dd41b 9538 return omit_one_operand_loc (loc, type, arg0, arg1);
7587301b 9539
9540 /* If both arguments are constant, then try to evaluate it. */
9541 if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2)
9542 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
9543 && host_integerp (arg1, 0))
9544 {
9545 /* Bound the maximum adjustment to twice the range of the
9546 mode's valid exponents. Use abs to ensure the range is
9547 positive as a sanity check. */
9548 const long max_exp_adj = 2 *
9549 labs (REAL_MODE_FORMAT (TYPE_MODE (type))->emax
9550 - REAL_MODE_FORMAT (TYPE_MODE (type))->emin);
9551
9552 /* Get the user-requested adjustment. */
9553 const HOST_WIDE_INT req_exp_adj = tree_low_cst (arg1, 0);
9554
9555 /* The requested adjustment must be inside this range. This
9556 is a preliminary cap to avoid things like overflow, we
9557 may still fail to compute the result for other reasons. */
9558 if (-max_exp_adj < req_exp_adj && req_exp_adj < max_exp_adj)
9559 {
9560 REAL_VALUE_TYPE initial_result;
9561
9562 real_ldexp (&initial_result, &TREE_REAL_CST (arg0), req_exp_adj);
9563
9564 /* Ensure we didn't overflow. */
9565 if (! real_isinf (&initial_result))
9566 {
9567 const REAL_VALUE_TYPE trunc_result
9568 = real_value_truncate (TYPE_MODE (type), initial_result);
9569
9570 /* Only proceed if the target mode can hold the
9571 resulting value. */
9572 if (REAL_VALUES_EQUAL (initial_result, trunc_result))
9573 return build_real (type, trunc_result);
9574 }
9575 }
9576 }
9577 }
9578
9579 return NULL_TREE;
9580}
9581
ebf8b4f5 9582/* Fold a call to builtin modf. */
9583
9584static tree
389dd41b 9585fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
ebf8b4f5 9586{
9587 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9588 return NULL_TREE;
9589
9590 STRIP_NOPS (arg0);
9591
9592 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9593 return NULL_TREE;
9594
389dd41b 9595 arg1 = build_fold_indirect_ref_loc (loc, arg1);
ebf8b4f5 9596
9597 /* Proceed if a valid pointer type was passed in. */
9598 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
9599 {
9600 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9601 REAL_VALUE_TYPE trunc, frac;
9602
9603 switch (value->cl)
9604 {
9605 case rvc_nan:
9606 case rvc_zero:
9607 /* For +-NaN or +-0, return (*arg1 = arg0, arg0). */
9608 trunc = frac = *value;
9609 break;
9610 case rvc_inf:
9611 /* For +-Inf, return (*arg1 = arg0, +-0). */
9612 frac = dconst0;
9613 frac.sign = value->sign;
9614 trunc = *value;
9615 break;
9616 case rvc_normal:
9617 /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)). */
9618 real_trunc (&trunc, VOIDmode, value);
9619 real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
9620 /* If the original number was negative and already
9621 integral, then the fractional part is -0.0. */
9622 if (value->sign && frac.cl == rvc_zero)
9623 frac.sign = value->sign;
9624 break;
9625 }
9626
9627 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
389dd41b 9628 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1,
ebf8b4f5 9629 build_real (rettype, trunc));
9630 TREE_SIDE_EFFECTS (arg1) = 1;
389dd41b 9631 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1,
ebf8b4f5 9632 build_real (rettype, frac));
9633 }
9634
9635 return NULL_TREE;
9636}
9637
a65c4d64 9638/* Given a location LOC, an interclass builtin function decl FNDECL
9639 and its single argument ARG, return an folded expression computing
9640 the same, or NULL_TREE if we either couldn't or didn't want to fold
9641 (the latter happen if there's an RTL instruction available). */
9642
9643static tree
9644fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
9645{
9646 enum machine_mode mode;
9647
9648 if (!validate_arg (arg, REAL_TYPE))
9649 return NULL_TREE;
9650
9651 if (interclass_mathfn_icode (arg, fndecl) != CODE_FOR_nothing)
9652 return NULL_TREE;
9653
9654 mode = TYPE_MODE (TREE_TYPE (arg));
9655
9656 /* If there is no optab, try generic code. */
9657 switch (DECL_FUNCTION_CODE (fndecl))
9658 {
9659 tree result;
9660
9661 CASE_FLT_FN (BUILT_IN_ISINF):
9662 {
9663 /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
9664 tree const isgr_fn = built_in_decls[BUILT_IN_ISGREATER];
9665 tree const type = TREE_TYPE (arg);
9666 REAL_VALUE_TYPE r;
9667 char buf[128];
9668
9669 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9670 real_from_string (&r, buf);
9671 result = build_call_expr (isgr_fn, 2,
9672 fold_build1_loc (loc, ABS_EXPR, type, arg),
9673 build_real (type, r));
9674 return result;
9675 }
9676 CASE_FLT_FN (BUILT_IN_FINITE):
9677 case BUILT_IN_ISFINITE:
9678 {
9679 /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
9680 tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
9681 tree const type = TREE_TYPE (arg);
9682 REAL_VALUE_TYPE r;
9683 char buf[128];
9684
9685 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9686 real_from_string (&r, buf);
9687 result = build_call_expr (isle_fn, 2,
9688 fold_build1_loc (loc, ABS_EXPR, type, arg),
9689 build_real (type, r));
9690 /*result = fold_build2_loc (loc, UNGT_EXPR,
9691 TREE_TYPE (TREE_TYPE (fndecl)),
9692 fold_build1_loc (loc, ABS_EXPR, type, arg),
9693 build_real (type, r));
9694 result = fold_build1_loc (loc, TRUTH_NOT_EXPR,
9695 TREE_TYPE (TREE_TYPE (fndecl)),
9696 result);*/
9697 return result;
9698 }
9699 case BUILT_IN_ISNORMAL:
9700 {
9701 /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
9702 islessequal(fabs(x),DBL_MAX). */
9703 tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
9704 tree const isge_fn = built_in_decls[BUILT_IN_ISGREATEREQUAL];
9705 tree const type = TREE_TYPE (arg);
9706 REAL_VALUE_TYPE rmax, rmin;
9707 char buf[128];
9708
9709 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9710 real_from_string (&rmax, buf);
9711 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
9712 real_from_string (&rmin, buf);
9713 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
9714 result = build_call_expr (isle_fn, 2, arg,
9715 build_real (type, rmax));
9716 result = fold_build2 (BIT_AND_EXPR, integer_type_node, result,
9717 build_call_expr (isge_fn, 2, arg,
9718 build_real (type, rmin)));
9719 return result;
9720 }
9721 default:
9722 break;
9723 }
9724
9725 return NULL_TREE;
9726}
9727
726069ba 9728/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
c2f47e15 9729 ARG is the argument for the call. */
726069ba 9730
9731static tree
389dd41b 9732fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
726069ba 9733{
726069ba 9734 tree type = TREE_TYPE (TREE_TYPE (fndecl));
726069ba 9735 REAL_VALUE_TYPE r;
9736
c2f47e15 9737 if (!validate_arg (arg, REAL_TYPE))
d43cee80 9738 return NULL_TREE;
726069ba 9739
726069ba 9740 switch (builtin_index)
9741 {
9742 case BUILT_IN_ISINF:
b70bfd00 9743 if (!HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 9744 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
726069ba 9745
9746 if (TREE_CODE (arg) == REAL_CST)
9747 {
9748 r = TREE_REAL_CST (arg);
9749 if (real_isinf (&r))
9750 return real_compare (GT_EXPR, &r, &dconst0)
9751 ? integer_one_node : integer_minus_one_node;
9752 else
9753 return integer_zero_node;
9754 }
9755
9756 return NULL_TREE;
9757
c319d56a 9758 case BUILT_IN_ISINF_SIGN:
9759 {
9760 /* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */
9761 /* In a boolean context, GCC will fold the inner COND_EXPR to
9762 1. So e.g. "if (isinf_sign(x))" would be folded to just
9763 "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
9764 tree signbit_fn = mathfn_built_in_1 (TREE_TYPE (arg), BUILT_IN_SIGNBIT, 0);
9765 tree isinf_fn = built_in_decls[BUILT_IN_ISINF];
9766 tree tmp = NULL_TREE;
9767
9768 arg = builtin_save_expr (arg);
9769
9770 if (signbit_fn && isinf_fn)
9771 {
389dd41b 9772 tree signbit_call = build_call_expr_loc (loc, signbit_fn, 1, arg);
9773 tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg);
c319d56a 9774
389dd41b 9775 signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
c319d56a 9776 signbit_call, integer_zero_node);
389dd41b 9777 isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
c319d56a 9778 isinf_call, integer_zero_node);
9779
389dd41b 9780 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call,
c319d56a 9781 integer_minus_one_node, integer_one_node);
389dd41b 9782 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
9783 isinf_call, tmp,
c319d56a 9784 integer_zero_node);
9785 }
9786
9787 return tmp;
9788 }
9789
cde061c1 9790 case BUILT_IN_ISFINITE:
b70bfd00 9791 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
9792 && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 9793 return omit_one_operand_loc (loc, type, integer_one_node, arg);
726069ba 9794
9795 if (TREE_CODE (arg) == REAL_CST)
9796 {
9797 r = TREE_REAL_CST (arg);
776a7bab 9798 return real_isfinite (&r) ? integer_one_node : integer_zero_node;
726069ba 9799 }
9800
9801 return NULL_TREE;
9802
9803 case BUILT_IN_ISNAN:
b70bfd00 9804 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 9805 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
726069ba 9806
9807 if (TREE_CODE (arg) == REAL_CST)
9808 {
9809 r = TREE_REAL_CST (arg);
9810 return real_isnan (&r) ? integer_one_node : integer_zero_node;
9811 }
9812
9813 arg = builtin_save_expr (arg);
389dd41b 9814 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
726069ba 9815
9816 default:
64db345d 9817 gcc_unreachable ();
726069ba 9818 }
9819}
9820
19fbe3a4 9821/* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...).
9822 This builtin will generate code to return the appropriate floating
9823 point classification depending on the value of the floating point
9824 number passed in. The possible return values must be supplied as
921b27c0 9825 int arguments to the call in the following order: FP_NAN, FP_INFINITE,
19fbe3a4 9826 FP_NORMAL, FP_SUBNORMAL and FP_ZERO. The ellipses is for exactly
9827 one floating point argument which is "type generic". */
9828
9829static tree
389dd41b 9830fold_builtin_fpclassify (location_t loc, tree exp)
19fbe3a4 9831{
921b27c0 9832 tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
9833 arg, type, res, tmp;
19fbe3a4 9834 enum machine_mode mode;
9835 REAL_VALUE_TYPE r;
9836 char buf[128];
9837
9838 /* Verify the required arguments in the original call. */
9839 if (!validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE,
9840 INTEGER_TYPE, INTEGER_TYPE,
9841 INTEGER_TYPE, REAL_TYPE, VOID_TYPE))
9842 return NULL_TREE;
9843
9844 fp_nan = CALL_EXPR_ARG (exp, 0);
921b27c0 9845 fp_infinite = CALL_EXPR_ARG (exp, 1);
19fbe3a4 9846 fp_normal = CALL_EXPR_ARG (exp, 2);
9847 fp_subnormal = CALL_EXPR_ARG (exp, 3);
9848 fp_zero = CALL_EXPR_ARG (exp, 4);
9849 arg = CALL_EXPR_ARG (exp, 5);
9850 type = TREE_TYPE (arg);
9851 mode = TYPE_MODE (type);
389dd41b 9852 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
19fbe3a4 9853
9854 /* fpclassify(x) ->
9855 isnan(x) ? FP_NAN :
921b27c0 9856 (fabs(x) == Inf ? FP_INFINITE :
19fbe3a4 9857 (fabs(x) >= DBL_MIN ? FP_NORMAL :
9858 (x == 0 ? FP_ZERO : FP_SUBNORMAL))). */
9859
389dd41b 9860 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
19fbe3a4 9861 build_real (type, dconst0));
389dd41b 9862 res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
9863 tmp, fp_zero, fp_subnormal);
19fbe3a4 9864
9865 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
9866 real_from_string (&r, buf);
389dd41b 9867 tmp = fold_build2_loc (loc, GE_EXPR, integer_type_node,
9868 arg, build_real (type, r));
9869 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, fp_normal, res);
19fbe3a4 9870
9871 if (HONOR_INFINITIES (mode))
9872 {
9873 real_inf (&r);
389dd41b 9874 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
19fbe3a4 9875 build_real (type, r));
389dd41b 9876 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
9877 fp_infinite, res);
19fbe3a4 9878 }
9879
9880 if (HONOR_NANS (mode))
9881 {
389dd41b 9882 tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
9883 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, res, fp_nan);
19fbe3a4 9884 }
9885
9886 return res;
9887}
9888
9bc9f15f 9889/* Fold a call to an unordered comparison function such as
d5019fe8 9890 __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function
c2f47e15 9891 being called and ARG0 and ARG1 are the arguments for the call.
726069ba 9892 UNORDERED_CODE and ORDERED_CODE are comparison codes that give
9893 the opposite of the desired result. UNORDERED_CODE is used
9894 for modes that can hold NaNs and ORDERED_CODE is used for
9895 the rest. */
9bc9f15f 9896
9897static tree
389dd41b 9898fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
9bc9f15f 9899 enum tree_code unordered_code,
9900 enum tree_code ordered_code)
9901{
859f903a 9902 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9bc9f15f 9903 enum tree_code code;
6978db0d 9904 tree type0, type1;
9905 enum tree_code code0, code1;
9906 tree cmp_type = NULL_TREE;
9bc9f15f 9907
6978db0d 9908 type0 = TREE_TYPE (arg0);
9909 type1 = TREE_TYPE (arg1);
a0c938f0 9910
6978db0d 9911 code0 = TREE_CODE (type0);
9912 code1 = TREE_CODE (type1);
a0c938f0 9913
6978db0d 9914 if (code0 == REAL_TYPE && code1 == REAL_TYPE)
9915 /* Choose the wider of two real types. */
9916 cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
9917 ? type0 : type1;
9918 else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
9919 cmp_type = type0;
9920 else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
9921 cmp_type = type1;
a0c938f0 9922
389dd41b 9923 arg0 = fold_convert_loc (loc, cmp_type, arg0);
9924 arg1 = fold_convert_loc (loc, cmp_type, arg1);
859f903a 9925
9926 if (unordered_code == UNORDERED_EXPR)
9927 {
b70bfd00 9928 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
389dd41b 9929 return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
9930 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
859f903a 9931 }
9bc9f15f 9932
b70bfd00 9933 code = HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
9934 : ordered_code;
389dd41b 9935 return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
9936 fold_build2_loc (loc, code, type, arg0, arg1));
9bc9f15f 9937}
9938
c2f47e15 9939/* Fold a call to built-in function FNDECL with 0 arguments.
9940 IGNORE is true if the result of the function call is ignored. This
9941 function returns NULL_TREE if no simplification was possible. */
650e4c94 9942
4ee9c684 9943static tree
389dd41b 9944fold_builtin_0 (location_t loc, tree fndecl, bool ignore ATTRIBUTE_UNUSED)
650e4c94 9945{
e9f80ff5 9946 tree type = TREE_TYPE (TREE_TYPE (fndecl));
c2f47e15 9947 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
189b3398 9948 switch (fcode)
650e4c94 9949 {
c2f47e15 9950 CASE_FLT_FN (BUILT_IN_INF):
9951 case BUILT_IN_INFD32:
9952 case BUILT_IN_INFD64:
9953 case BUILT_IN_INFD128:
389dd41b 9954 return fold_builtin_inf (loc, type, true);
7c2f0500 9955
c2f47e15 9956 CASE_FLT_FN (BUILT_IN_HUGE_VAL):
389dd41b 9957 return fold_builtin_inf (loc, type, false);
7c2f0500 9958
c2f47e15 9959 case BUILT_IN_CLASSIFY_TYPE:
9960 return fold_builtin_classify_type (NULL_TREE);
7c2f0500 9961
c2f47e15 9962 default:
9963 break;
9964 }
9965 return NULL_TREE;
9966}
7c2f0500 9967
c2f47e15 9968/* Fold a call to built-in function FNDECL with 1 argument, ARG0.
9969 IGNORE is true if the result of the function call is ignored. This
9970 function returns NULL_TREE if no simplification was possible. */
7c2f0500 9971
c2f47e15 9972static tree
389dd41b 9973fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
c2f47e15 9974{
9975 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9976 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9977 switch (fcode)
9978 {
7c2f0500 9979
650e4c94 9980 case BUILT_IN_CONSTANT_P:
7c2f0500 9981 {
c2f47e15 9982 tree val = fold_builtin_constant_p (arg0);
7c2f0500 9983
7c2f0500 9984 /* Gimplification will pull the CALL_EXPR for the builtin out of
9985 an if condition. When not optimizing, we'll not CSE it back.
9986 To avoid link error types of regressions, return false now. */
9987 if (!val && !optimize)
9988 val = integer_zero_node;
9989
9990 return val;
9991 }
650e4c94 9992
539a3a92 9993 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 9994 return fold_builtin_classify_type (arg0);
539a3a92 9995
650e4c94 9996 case BUILT_IN_STRLEN:
389dd41b 9997 return fold_builtin_strlen (loc, arg0);
650e4c94 9998
4f35b1fc 9999 CASE_FLT_FN (BUILT_IN_FABS):
389dd41b 10000 return fold_builtin_fabs (loc, arg0, type);
d1aade50 10001
10002 case BUILT_IN_ABS:
10003 case BUILT_IN_LABS:
10004 case BUILT_IN_LLABS:
10005 case BUILT_IN_IMAXABS:
389dd41b 10006 return fold_builtin_abs (loc, arg0, type);
c63f4ad3 10007
4f35b1fc 10008 CASE_FLT_FN (BUILT_IN_CONJ):
239d491a 10009 if (validate_arg (arg0, COMPLEX_TYPE)
10010 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10011 return fold_build1_loc (loc, CONJ_EXPR, type, arg0);
c2f47e15 10012 break;
36d3581d 10013
4f35b1fc 10014 CASE_FLT_FN (BUILT_IN_CREAL):
239d491a 10015 if (validate_arg (arg0, COMPLEX_TYPE)
10016 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10017 return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));;
c2f47e15 10018 break;
36d3581d 10019
4f35b1fc 10020 CASE_FLT_FN (BUILT_IN_CIMAG):
b0ce8887 10021 if (validate_arg (arg0, COMPLEX_TYPE)
10022 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10023 return non_lvalue_loc (loc, fold_build1_loc (loc, IMAGPART_EXPR, type, arg0));
c2f47e15 10024 break;
36d3581d 10025
503733d5 10026 CASE_FLT_FN (BUILT_IN_CCOS):
389dd41b 10027 return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ false);
239d491a 10028
503733d5 10029 CASE_FLT_FN (BUILT_IN_CCOSH):
389dd41b 10030 return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ true);
239d491a 10031
10032#ifdef HAVE_mpc
10033 CASE_FLT_FN (BUILT_IN_CSIN):
10034 if (validate_arg (arg0, COMPLEX_TYPE)
10035 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10036 return do_mpc_arg1 (arg0, type, mpc_sin);
c2f47e15 10037 break;
239d491a 10038
10039 CASE_FLT_FN (BUILT_IN_CSINH):
10040 if (validate_arg (arg0, COMPLEX_TYPE)
10041 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10042 return do_mpc_arg1 (arg0, type, mpc_sinh);
10043 break;
10044
10045 CASE_FLT_FN (BUILT_IN_CTAN):
10046 if (validate_arg (arg0, COMPLEX_TYPE)
10047 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10048 return do_mpc_arg1 (arg0, type, mpc_tan);
10049 break;
10050
10051 CASE_FLT_FN (BUILT_IN_CTANH):
10052 if (validate_arg (arg0, COMPLEX_TYPE)
10053 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10054 return do_mpc_arg1 (arg0, type, mpc_tanh);
10055 break;
10056
10057 CASE_FLT_FN (BUILT_IN_CLOG):
10058 if (validate_arg (arg0, COMPLEX_TYPE)
10059 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10060 return do_mpc_arg1 (arg0, type, mpc_log);
10061 break;
10062
10063 CASE_FLT_FN (BUILT_IN_CSQRT):
10064 if (validate_arg (arg0, COMPLEX_TYPE)
10065 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10066 return do_mpc_arg1 (arg0, type, mpc_sqrt);
10067 break;
0e7e6e7f 10068
10069#ifdef HAVE_mpc_arc
10070 CASE_FLT_FN (BUILT_IN_CASIN):
10071 if (validate_arg (arg0, COMPLEX_TYPE)
10072 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10073 return do_mpc_arg1 (arg0, type, mpc_asin);
10074 break;
10075
10076 CASE_FLT_FN (BUILT_IN_CACOS):
10077 if (validate_arg (arg0, COMPLEX_TYPE)
10078 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10079 return do_mpc_arg1 (arg0, type, mpc_acos);
10080 break;
10081
10082 CASE_FLT_FN (BUILT_IN_CATAN):
10083 if (validate_arg (arg0, COMPLEX_TYPE)
10084 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10085 return do_mpc_arg1 (arg0, type, mpc_atan);
10086 break;
10087
10088 CASE_FLT_FN (BUILT_IN_CASINH):
10089 if (validate_arg (arg0, COMPLEX_TYPE)
10090 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10091 return do_mpc_arg1 (arg0, type, mpc_asinh);
10092 break;
10093
10094 CASE_FLT_FN (BUILT_IN_CACOSH):
10095 if (validate_arg (arg0, COMPLEX_TYPE)
10096 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10097 return do_mpc_arg1 (arg0, type, mpc_acosh);
10098 break;
10099
10100 CASE_FLT_FN (BUILT_IN_CATANH):
10101 if (validate_arg (arg0, COMPLEX_TYPE)
10102 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
10103 return do_mpc_arg1 (arg0, type, mpc_atanh);
10104 break;
10105#endif /* HAVE_mpc_arc */
10106#endif /* HAVE_mpc */
239d491a 10107
4f35b1fc 10108 CASE_FLT_FN (BUILT_IN_CABS):
389dd41b 10109 return fold_builtin_cabs (loc, arg0, type, fndecl);
c63f4ad3 10110
abe4dcf6 10111 CASE_FLT_FN (BUILT_IN_CARG):
389dd41b 10112 return fold_builtin_carg (loc, arg0, type);
abe4dcf6 10113
4f35b1fc 10114 CASE_FLT_FN (BUILT_IN_SQRT):
389dd41b 10115 return fold_builtin_sqrt (loc, arg0, type);
805e22b2 10116
4f35b1fc 10117 CASE_FLT_FN (BUILT_IN_CBRT):
389dd41b 10118 return fold_builtin_cbrt (loc, arg0, type);
3bc5c41b 10119
728bac60 10120 CASE_FLT_FN (BUILT_IN_ASIN):
c2f47e15 10121 if (validate_arg (arg0, REAL_TYPE))
10122 return do_mpfr_arg1 (arg0, type, mpfr_asin,
728bac60 10123 &dconstm1, &dconst1, true);
10124 break;
10125
10126 CASE_FLT_FN (BUILT_IN_ACOS):
c2f47e15 10127 if (validate_arg (arg0, REAL_TYPE))
10128 return do_mpfr_arg1 (arg0, type, mpfr_acos,
728bac60 10129 &dconstm1, &dconst1, true);
10130 break;
10131
10132 CASE_FLT_FN (BUILT_IN_ATAN):
c2f47e15 10133 if (validate_arg (arg0, REAL_TYPE))
10134 return do_mpfr_arg1 (arg0, type, mpfr_atan, NULL, NULL, 0);
728bac60 10135 break;
10136
10137 CASE_FLT_FN (BUILT_IN_ASINH):
c2f47e15 10138 if (validate_arg (arg0, REAL_TYPE))
10139 return do_mpfr_arg1 (arg0, type, mpfr_asinh, NULL, NULL, 0);
728bac60 10140 break;
10141
10142 CASE_FLT_FN (BUILT_IN_ACOSH):
c2f47e15 10143 if (validate_arg (arg0, REAL_TYPE))
10144 return do_mpfr_arg1 (arg0, type, mpfr_acosh,
728bac60 10145 &dconst1, NULL, true);
10146 break;
10147
10148 CASE_FLT_FN (BUILT_IN_ATANH):
c2f47e15 10149 if (validate_arg (arg0, REAL_TYPE))
10150 return do_mpfr_arg1 (arg0, type, mpfr_atanh,
728bac60 10151 &dconstm1, &dconst1, false);
10152 break;
10153
4f35b1fc 10154 CASE_FLT_FN (BUILT_IN_SIN):
c2f47e15 10155 if (validate_arg (arg0, REAL_TYPE))
10156 return do_mpfr_arg1 (arg0, type, mpfr_sin, NULL, NULL, 0);
728bac60 10157 break;
77e89269 10158
4f35b1fc 10159 CASE_FLT_FN (BUILT_IN_COS):
389dd41b 10160 return fold_builtin_cos (loc, arg0, type, fndecl);
77e89269 10161
728bac60 10162 CASE_FLT_FN (BUILT_IN_TAN):
c2f47e15 10163 return fold_builtin_tan (arg0, type);
d735c391 10164
c5bb2c4b 10165 CASE_FLT_FN (BUILT_IN_CEXP):
389dd41b 10166 return fold_builtin_cexp (loc, arg0, type);
c5bb2c4b 10167
d735c391 10168 CASE_FLT_FN (BUILT_IN_CEXPI):
c2f47e15 10169 if (validate_arg (arg0, REAL_TYPE))
10170 return do_mpfr_sincos (arg0, NULL_TREE, NULL_TREE);
10171 break;
d92f994c 10172
728bac60 10173 CASE_FLT_FN (BUILT_IN_SINH):
c2f47e15 10174 if (validate_arg (arg0, REAL_TYPE))
10175 return do_mpfr_arg1 (arg0, type, mpfr_sinh, NULL, NULL, 0);
728bac60 10176 break;
10177
10178 CASE_FLT_FN (BUILT_IN_COSH):
389dd41b 10179 return fold_builtin_cosh (loc, arg0, type, fndecl);
728bac60 10180
10181 CASE_FLT_FN (BUILT_IN_TANH):
c2f47e15 10182 if (validate_arg (arg0, REAL_TYPE))
10183 return do_mpfr_arg1 (arg0, type, mpfr_tanh, NULL, NULL, 0);
728bac60 10184 break;
10185
29f4cd78 10186 CASE_FLT_FN (BUILT_IN_ERF):
c2f47e15 10187 if (validate_arg (arg0, REAL_TYPE))
10188 return do_mpfr_arg1 (arg0, type, mpfr_erf, NULL, NULL, 0);
29f4cd78 10189 break;
10190
10191 CASE_FLT_FN (BUILT_IN_ERFC):
c2f47e15 10192 if (validate_arg (arg0, REAL_TYPE))
10193 return do_mpfr_arg1 (arg0, type, mpfr_erfc, NULL, NULL, 0);
29f4cd78 10194 break;
10195
32dba52b 10196 CASE_FLT_FN (BUILT_IN_TGAMMA):
c2f47e15 10197 if (validate_arg (arg0, REAL_TYPE))
10198 return do_mpfr_arg1 (arg0, type, mpfr_gamma, NULL, NULL, 0);
32dba52b 10199 break;
10200
4f35b1fc 10201 CASE_FLT_FN (BUILT_IN_EXP):
389dd41b 10202 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp);
467214fd 10203
4f35b1fc 10204 CASE_FLT_FN (BUILT_IN_EXP2):
389dd41b 10205 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp2);
467214fd 10206
4f35b1fc 10207 CASE_FLT_FN (BUILT_IN_EXP10):
10208 CASE_FLT_FN (BUILT_IN_POW10):
389dd41b 10209 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp10);
467214fd 10210
29f4cd78 10211 CASE_FLT_FN (BUILT_IN_EXPM1):
c2f47e15 10212 if (validate_arg (arg0, REAL_TYPE))
10213 return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0);
29f4cd78 10214 break;
10215
4f35b1fc 10216 CASE_FLT_FN (BUILT_IN_LOG):
389dd41b 10217 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log);
467214fd 10218
4f35b1fc 10219 CASE_FLT_FN (BUILT_IN_LOG2):
389dd41b 10220 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log2);
467214fd 10221
4f35b1fc 10222 CASE_FLT_FN (BUILT_IN_LOG10):
389dd41b 10223 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log10);
29f4cd78 10224
10225 CASE_FLT_FN (BUILT_IN_LOG1P):
c2f47e15 10226 if (validate_arg (arg0, REAL_TYPE))
10227 return do_mpfr_arg1 (arg0, type, mpfr_log1p,
29f4cd78 10228 &dconstm1, NULL, false);
10229 break;
805e22b2 10230
65dd1378 10231 CASE_FLT_FN (BUILT_IN_J0):
10232 if (validate_arg (arg0, REAL_TYPE))
10233 return do_mpfr_arg1 (arg0, type, mpfr_j0,
10234 NULL, NULL, 0);
10235 break;
10236
10237 CASE_FLT_FN (BUILT_IN_J1):
10238 if (validate_arg (arg0, REAL_TYPE))
10239 return do_mpfr_arg1 (arg0, type, mpfr_j1,
10240 NULL, NULL, 0);
10241 break;
6ff9eeff 10242
10243 CASE_FLT_FN (BUILT_IN_Y0):
10244 if (validate_arg (arg0, REAL_TYPE))
10245 return do_mpfr_arg1 (arg0, type, mpfr_y0,
10246 &dconst0, NULL, false);
10247 break;
10248
10249 CASE_FLT_FN (BUILT_IN_Y1):
10250 if (validate_arg (arg0, REAL_TYPE))
10251 return do_mpfr_arg1 (arg0, type, mpfr_y1,
10252 &dconst0, NULL, false);
10253 break;
65dd1378 10254
4f35b1fc 10255 CASE_FLT_FN (BUILT_IN_NAN):
c4503c0a 10256 case BUILT_IN_NAND32:
10257 case BUILT_IN_NAND64:
10258 case BUILT_IN_NAND128:
c2f47e15 10259 return fold_builtin_nan (arg0, type, true);
b0db7939 10260
4f35b1fc 10261 CASE_FLT_FN (BUILT_IN_NANS):
c2f47e15 10262 return fold_builtin_nan (arg0, type, false);
b0db7939 10263
4f35b1fc 10264 CASE_FLT_FN (BUILT_IN_FLOOR):
389dd41b 10265 return fold_builtin_floor (loc, fndecl, arg0);
277f8dd2 10266
4f35b1fc 10267 CASE_FLT_FN (BUILT_IN_CEIL):
389dd41b 10268 return fold_builtin_ceil (loc, fndecl, arg0);
277f8dd2 10269
4f35b1fc 10270 CASE_FLT_FN (BUILT_IN_TRUNC):
389dd41b 10271 return fold_builtin_trunc (loc, fndecl, arg0);
277f8dd2 10272
4f35b1fc 10273 CASE_FLT_FN (BUILT_IN_ROUND):
389dd41b 10274 return fold_builtin_round (loc, fndecl, arg0);
89ab3887 10275
4f35b1fc 10276 CASE_FLT_FN (BUILT_IN_NEARBYINT):
10277 CASE_FLT_FN (BUILT_IN_RINT):
389dd41b 10278 return fold_trunc_transparent_mathfn (loc, fndecl, arg0);
6528f4f4 10279
4f35b1fc 10280 CASE_FLT_FN (BUILT_IN_LCEIL):
10281 CASE_FLT_FN (BUILT_IN_LLCEIL):
10282 CASE_FLT_FN (BUILT_IN_LFLOOR):
10283 CASE_FLT_FN (BUILT_IN_LLFLOOR):
a0c938f0 10284 CASE_FLT_FN (BUILT_IN_LROUND):
4f35b1fc 10285 CASE_FLT_FN (BUILT_IN_LLROUND):
389dd41b 10286 return fold_builtin_int_roundingfn (loc, fndecl, arg0);
34f17811 10287
4f35b1fc 10288 CASE_FLT_FN (BUILT_IN_LRINT):
10289 CASE_FLT_FN (BUILT_IN_LLRINT):
389dd41b 10290 return fold_fixed_mathfn (loc, fndecl, arg0);
9ed65c7f 10291
42791117 10292 case BUILT_IN_BSWAP32:
10293 case BUILT_IN_BSWAP64:
c2f47e15 10294 return fold_builtin_bswap (fndecl, arg0);
42791117 10295
4f35b1fc 10296 CASE_INT_FN (BUILT_IN_FFS):
10297 CASE_INT_FN (BUILT_IN_CLZ):
10298 CASE_INT_FN (BUILT_IN_CTZ):
10299 CASE_INT_FN (BUILT_IN_POPCOUNT):
10300 CASE_INT_FN (BUILT_IN_PARITY):
c2f47e15 10301 return fold_builtin_bitop (fndecl, arg0);
9c8a1629 10302
4f35b1fc 10303 CASE_FLT_FN (BUILT_IN_SIGNBIT):
389dd41b 10304 return fold_builtin_signbit (loc, arg0, type);
27f261ef 10305
cb2b9385 10306 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
389dd41b 10307 return fold_builtin_significand (loc, arg0, type);
cb2b9385 10308
10309 CASE_FLT_FN (BUILT_IN_ILOGB):
10310 CASE_FLT_FN (BUILT_IN_LOGB):
389dd41b 10311 return fold_builtin_logb (loc, arg0, type);
cb2b9385 10312
d49367d4 10313 case BUILT_IN_ISASCII:
389dd41b 10314 return fold_builtin_isascii (loc, arg0);
d49367d4 10315
10316 case BUILT_IN_TOASCII:
389dd41b 10317 return fold_builtin_toascii (loc, arg0);
d49367d4 10318
df1cf42e 10319 case BUILT_IN_ISDIGIT:
389dd41b 10320 return fold_builtin_isdigit (loc, arg0);
467214fd 10321
4f35b1fc 10322 CASE_FLT_FN (BUILT_IN_FINITE):
c4503c0a 10323 case BUILT_IN_FINITED32:
10324 case BUILT_IN_FINITED64:
10325 case BUILT_IN_FINITED128:
cde061c1 10326 case BUILT_IN_ISFINITE:
a65c4d64 10327 {
10328 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISFINITE);
10329 if (ret)
10330 return ret;
10331 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10332 }
726069ba 10333
4f35b1fc 10334 CASE_FLT_FN (BUILT_IN_ISINF):
c4503c0a 10335 case BUILT_IN_ISINFD32:
10336 case BUILT_IN_ISINFD64:
10337 case BUILT_IN_ISINFD128:
a65c4d64 10338 {
10339 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF);
10340 if (ret)
10341 return ret;
10342 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10343 }
10344
10345 case BUILT_IN_ISNORMAL:
10346 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
726069ba 10347
c319d56a 10348 case BUILT_IN_ISINF_SIGN:
389dd41b 10349 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF_SIGN);
c319d56a 10350
4f35b1fc 10351 CASE_FLT_FN (BUILT_IN_ISNAN):
c4503c0a 10352 case BUILT_IN_ISNAND32:
10353 case BUILT_IN_ISNAND64:
10354 case BUILT_IN_ISNAND128:
389dd41b 10355 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
c2f47e15 10356
10357 case BUILT_IN_PRINTF:
10358 case BUILT_IN_PRINTF_UNLOCKED:
10359 case BUILT_IN_VPRINTF:
389dd41b 10360 return fold_builtin_printf (loc, fndecl, arg0, NULL_TREE, ignore, fcode);
c2f47e15 10361
10362 default:
10363 break;
10364 }
10365
10366 return NULL_TREE;
10367
10368}
10369
10370/* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1.
10371 IGNORE is true if the result of the function call is ignored. This
10372 function returns NULL_TREE if no simplification was possible. */
10373
10374static tree
389dd41b 10375fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore)
c2f47e15 10376{
10377 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10378 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10379
10380 switch (fcode)
10381 {
65dd1378 10382 CASE_FLT_FN (BUILT_IN_JN):
10383 if (validate_arg (arg0, INTEGER_TYPE)
10384 && validate_arg (arg1, REAL_TYPE))
10385 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_jn, NULL, 0);
10386 break;
6ff9eeff 10387
10388 CASE_FLT_FN (BUILT_IN_YN):
10389 if (validate_arg (arg0, INTEGER_TYPE)
10390 && validate_arg (arg1, REAL_TYPE))
10391 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_yn,
10392 &dconst0, false);
10393 break;
e5407ca6 10394
10395 CASE_FLT_FN (BUILT_IN_DREM):
10396 CASE_FLT_FN (BUILT_IN_REMAINDER):
10397 if (validate_arg (arg0, REAL_TYPE)
10398 && validate_arg(arg1, REAL_TYPE))
10399 return do_mpfr_arg2 (arg0, arg1, type, mpfr_remainder);
10400 break;
e84da7c1 10401
10402 CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
10403 CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
10404 if (validate_arg (arg0, REAL_TYPE)
10405 && validate_arg(arg1, POINTER_TYPE))
10406 return do_mpfr_lgamma_r (arg0, arg1, type);
10407 break;
c2f47e15 10408
10409 CASE_FLT_FN (BUILT_IN_ATAN2):
10410 if (validate_arg (arg0, REAL_TYPE)
10411 && validate_arg(arg1, REAL_TYPE))
10412 return do_mpfr_arg2 (arg0, arg1, type, mpfr_atan2);
10413 break;
10414
10415 CASE_FLT_FN (BUILT_IN_FDIM):
10416 if (validate_arg (arg0, REAL_TYPE)
10417 && validate_arg(arg1, REAL_TYPE))
10418 return do_mpfr_arg2 (arg0, arg1, type, mpfr_dim);
10419 break;
10420
10421 CASE_FLT_FN (BUILT_IN_HYPOT):
389dd41b 10422 return fold_builtin_hypot (loc, fndecl, arg0, arg1, type);
c2f47e15 10423
c699fab8 10424#ifdef HAVE_mpc_pow
10425 CASE_FLT_FN (BUILT_IN_CPOW):
10426 if (validate_arg (arg0, COMPLEX_TYPE)
10427 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
10428 && validate_arg (arg1, COMPLEX_TYPE)
10429 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE)
652d9409 10430 return do_mpc_arg2 (arg0, arg1, type, /*do_nonfinite=*/ 0, mpc_pow);
c699fab8 10431 break;
10432#endif
10433
7587301b 10434 CASE_FLT_FN (BUILT_IN_LDEXP):
389dd41b 10435 return fold_builtin_load_exponent (loc, arg0, arg1, type, /*ldexp=*/true);
7587301b 10436 CASE_FLT_FN (BUILT_IN_SCALBN):
10437 CASE_FLT_FN (BUILT_IN_SCALBLN):
389dd41b 10438 return fold_builtin_load_exponent (loc, arg0, arg1,
10439 type, /*ldexp=*/false);
7587301b 10440
3838b9ae 10441 CASE_FLT_FN (BUILT_IN_FREXP):
389dd41b 10442 return fold_builtin_frexp (loc, arg0, arg1, type);
3838b9ae 10443
ebf8b4f5 10444 CASE_FLT_FN (BUILT_IN_MODF):
389dd41b 10445 return fold_builtin_modf (loc, arg0, arg1, type);
ebf8b4f5 10446
c2f47e15 10447 case BUILT_IN_BZERO:
389dd41b 10448 return fold_builtin_bzero (loc, arg0, arg1, ignore);
c2f47e15 10449
10450 case BUILT_IN_FPUTS:
389dd41b 10451 return fold_builtin_fputs (loc, arg0, arg1, ignore, false, NULL_TREE);
c2f47e15 10452
10453 case BUILT_IN_FPUTS_UNLOCKED:
389dd41b 10454 return fold_builtin_fputs (loc, arg0, arg1, ignore, true, NULL_TREE);
c2f47e15 10455
10456 case BUILT_IN_STRSTR:
389dd41b 10457 return fold_builtin_strstr (loc, arg0, arg1, type);
c2f47e15 10458
10459 case BUILT_IN_STRCAT:
389dd41b 10460 return fold_builtin_strcat (loc, arg0, arg1);
c2f47e15 10461
10462 case BUILT_IN_STRSPN:
389dd41b 10463 return fold_builtin_strspn (loc, arg0, arg1);
c2f47e15 10464
10465 case BUILT_IN_STRCSPN:
389dd41b 10466 return fold_builtin_strcspn (loc, arg0, arg1);
c2f47e15 10467
10468 case BUILT_IN_STRCHR:
10469 case BUILT_IN_INDEX:
389dd41b 10470 return fold_builtin_strchr (loc, arg0, arg1, type);
c2f47e15 10471
10472 case BUILT_IN_STRRCHR:
10473 case BUILT_IN_RINDEX:
389dd41b 10474 return fold_builtin_strrchr (loc, arg0, arg1, type);
c2f47e15 10475
10476 case BUILT_IN_STRCPY:
389dd41b 10477 return fold_builtin_strcpy (loc, fndecl, arg0, arg1, NULL_TREE);
c2f47e15 10478
c8b17b2e 10479 case BUILT_IN_STPCPY:
10480 if (ignore)
10481 {
10482 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
10483 if (!fn)
10484 break;
10485
389dd41b 10486 return build_call_expr_loc (loc, fn, 2, arg0, arg1);
c8b17b2e 10487 }
a65c4d64 10488 else
10489 return fold_builtin_stpcpy (loc, fndecl, arg0, arg1);
c8b17b2e 10490 break;
10491
c2f47e15 10492 case BUILT_IN_STRCMP:
389dd41b 10493 return fold_builtin_strcmp (loc, arg0, arg1);
c2f47e15 10494
10495 case BUILT_IN_STRPBRK:
389dd41b 10496 return fold_builtin_strpbrk (loc, arg0, arg1, type);
c2f47e15 10497
10498 case BUILT_IN_EXPECT:
389dd41b 10499 return fold_builtin_expect (loc, arg0, arg1);
c2f47e15 10500
10501 CASE_FLT_FN (BUILT_IN_POW):
389dd41b 10502 return fold_builtin_pow (loc, fndecl, arg0, arg1, type);
c2f47e15 10503
10504 CASE_FLT_FN (BUILT_IN_POWI):
389dd41b 10505 return fold_builtin_powi (loc, fndecl, arg0, arg1, type);
c2f47e15 10506
10507 CASE_FLT_FN (BUILT_IN_COPYSIGN):
389dd41b 10508 return fold_builtin_copysign (loc, fndecl, arg0, arg1, type);
c2f47e15 10509
10510 CASE_FLT_FN (BUILT_IN_FMIN):
389dd41b 10511 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/false);
c2f47e15 10512
10513 CASE_FLT_FN (BUILT_IN_FMAX):
389dd41b 10514 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/true);
726069ba 10515
9bc9f15f 10516 case BUILT_IN_ISGREATER:
389dd41b 10517 return fold_builtin_unordered_cmp (loc, fndecl,
10518 arg0, arg1, UNLE_EXPR, LE_EXPR);
9bc9f15f 10519 case BUILT_IN_ISGREATEREQUAL:
389dd41b 10520 return fold_builtin_unordered_cmp (loc, fndecl,
10521 arg0, arg1, UNLT_EXPR, LT_EXPR);
9bc9f15f 10522 case BUILT_IN_ISLESS:
389dd41b 10523 return fold_builtin_unordered_cmp (loc, fndecl,
10524 arg0, arg1, UNGE_EXPR, GE_EXPR);
9bc9f15f 10525 case BUILT_IN_ISLESSEQUAL:
389dd41b 10526 return fold_builtin_unordered_cmp (loc, fndecl,
10527 arg0, arg1, UNGT_EXPR, GT_EXPR);
9bc9f15f 10528 case BUILT_IN_ISLESSGREATER:
389dd41b 10529 return fold_builtin_unordered_cmp (loc, fndecl,
10530 arg0, arg1, UNEQ_EXPR, EQ_EXPR);
9bc9f15f 10531 case BUILT_IN_ISUNORDERED:
389dd41b 10532 return fold_builtin_unordered_cmp (loc, fndecl,
10533 arg0, arg1, UNORDERED_EXPR,
d5019fe8 10534 NOP_EXPR);
9bc9f15f 10535
7c2f0500 10536 /* We do the folding for va_start in the expander. */
10537 case BUILT_IN_VA_START:
10538 break;
f0613857 10539
c2f47e15 10540 case BUILT_IN_SPRINTF:
389dd41b 10541 return fold_builtin_sprintf (loc, arg0, arg1, NULL_TREE, ignore);
c2f47e15 10542
0a39fd54 10543 case BUILT_IN_OBJECT_SIZE:
c2f47e15 10544 return fold_builtin_object_size (arg0, arg1);
0a39fd54 10545
10546 case BUILT_IN_PRINTF:
10547 case BUILT_IN_PRINTF_UNLOCKED:
10548 case BUILT_IN_VPRINTF:
389dd41b 10549 return fold_builtin_printf (loc, fndecl, arg0, arg1, ignore, fcode);
c2f47e15 10550
0a39fd54 10551 case BUILT_IN_PRINTF_CHK:
10552 case BUILT_IN_VPRINTF_CHK:
c2f47e15 10553 if (!validate_arg (arg0, INTEGER_TYPE)
10554 || TREE_SIDE_EFFECTS (arg0))
10555 return NULL_TREE;
10556 else
389dd41b 10557 return fold_builtin_printf (loc, fndecl,
10558 arg1, NULL_TREE, ignore, fcode);
c2f47e15 10559 break;
0a39fd54 10560
10561 case BUILT_IN_FPRINTF:
10562 case BUILT_IN_FPRINTF_UNLOCKED:
10563 case BUILT_IN_VFPRINTF:
389dd41b 10564 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, NULL_TREE,
c2f47e15 10565 ignore, fcode);
10566
10567 default:
10568 break;
10569 }
10570 return NULL_TREE;
10571}
10572
10573/* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
10574 and ARG2. IGNORE is true if the result of the function call is ignored.
10575 This function returns NULL_TREE if no simplification was possible. */
10576
10577static tree
389dd41b 10578fold_builtin_3 (location_t loc, tree fndecl,
10579 tree arg0, tree arg1, tree arg2, bool ignore)
c2f47e15 10580{
10581 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10582 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10583 switch (fcode)
10584 {
10585
10586 CASE_FLT_FN (BUILT_IN_SINCOS):
389dd41b 10587 return fold_builtin_sincos (loc, arg0, arg1, arg2);
c2f47e15 10588
10589 CASE_FLT_FN (BUILT_IN_FMA):
10590 if (validate_arg (arg0, REAL_TYPE)
10591 && validate_arg(arg1, REAL_TYPE)
10592 && validate_arg(arg2, REAL_TYPE))
10593 return do_mpfr_arg3 (arg0, arg1, arg2, type, mpfr_fma);
10594 break;
10595
e5407ca6 10596 CASE_FLT_FN (BUILT_IN_REMQUO):
10597 if (validate_arg (arg0, REAL_TYPE)
10598 && validate_arg(arg1, REAL_TYPE)
10599 && validate_arg(arg2, POINTER_TYPE))
10600 return do_mpfr_remquo (arg0, arg1, arg2);
10601 break;
e5407ca6 10602
c2f47e15 10603 case BUILT_IN_MEMSET:
389dd41b 10604 return fold_builtin_memset (loc, arg0, arg1, arg2, type, ignore);
c2f47e15 10605
10606 case BUILT_IN_BCOPY:
389dd41b 10607 return fold_builtin_memory_op (loc, arg1, arg0, arg2,
10608 void_type_node, true, /*endp=*/3);
c2f47e15 10609
10610 case BUILT_IN_MEMCPY:
389dd41b 10611 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10612 type, ignore, /*endp=*/0);
c2f47e15 10613
10614 case BUILT_IN_MEMPCPY:
389dd41b 10615 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10616 type, ignore, /*endp=*/1);
c2f47e15 10617
10618 case BUILT_IN_MEMMOVE:
389dd41b 10619 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10620 type, ignore, /*endp=*/3);
c2f47e15 10621
10622 case BUILT_IN_STRNCAT:
389dd41b 10623 return fold_builtin_strncat (loc, arg0, arg1, arg2);
c2f47e15 10624
10625 case BUILT_IN_STRNCPY:
389dd41b 10626 return fold_builtin_strncpy (loc, fndecl, arg0, arg1, arg2, NULL_TREE);
c2f47e15 10627
10628 case BUILT_IN_STRNCMP:
389dd41b 10629 return fold_builtin_strncmp (loc, arg0, arg1, arg2);
c2f47e15 10630
7959b13b 10631 case BUILT_IN_MEMCHR:
389dd41b 10632 return fold_builtin_memchr (loc, arg0, arg1, arg2, type);
7959b13b 10633
c2f47e15 10634 case BUILT_IN_BCMP:
10635 case BUILT_IN_MEMCMP:
389dd41b 10636 return fold_builtin_memcmp (loc, arg0, arg1, arg2);;
c2f47e15 10637
10638 case BUILT_IN_SPRINTF:
389dd41b 10639 return fold_builtin_sprintf (loc, arg0, arg1, arg2, ignore);
c2f47e15 10640
10641 case BUILT_IN_STRCPY_CHK:
10642 case BUILT_IN_STPCPY_CHK:
389dd41b 10643 return fold_builtin_stxcpy_chk (loc, fndecl, arg0, arg1, arg2, NULL_TREE,
c2f47e15 10644 ignore, fcode);
10645
10646 case BUILT_IN_STRCAT_CHK:
389dd41b 10647 return fold_builtin_strcat_chk (loc, fndecl, arg0, arg1, arg2);
c2f47e15 10648
10649 case BUILT_IN_PRINTF_CHK:
10650 case BUILT_IN_VPRINTF_CHK:
10651 if (!validate_arg (arg0, INTEGER_TYPE)
10652 || TREE_SIDE_EFFECTS (arg0))
10653 return NULL_TREE;
10654 else
389dd41b 10655 return fold_builtin_printf (loc, fndecl, arg1, arg2, ignore, fcode);
c2f47e15 10656 break;
10657
10658 case BUILT_IN_FPRINTF:
10659 case BUILT_IN_FPRINTF_UNLOCKED:
10660 case BUILT_IN_VFPRINTF:
389dd41b 10661 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, arg2,
10662 ignore, fcode);
c2f47e15 10663
0a39fd54 10664 case BUILT_IN_FPRINTF_CHK:
10665 case BUILT_IN_VFPRINTF_CHK:
c2f47e15 10666 if (!validate_arg (arg1, INTEGER_TYPE)
10667 || TREE_SIDE_EFFECTS (arg1))
10668 return NULL_TREE;
10669 else
389dd41b 10670 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, NULL_TREE,
c2f47e15 10671 ignore, fcode);
0a39fd54 10672
650e4c94 10673 default:
10674 break;
10675 }
c2f47e15 10676 return NULL_TREE;
10677}
650e4c94 10678
c2f47e15 10679/* Fold a call to built-in function FNDECL with 4 arguments, ARG0, ARG1,
10680 ARG2, and ARG3. IGNORE is true if the result of the function call is
10681 ignored. This function returns NULL_TREE if no simplification was
10682 possible. */
10683
10684static tree
389dd41b 10685fold_builtin_4 (location_t loc, tree fndecl,
10686 tree arg0, tree arg1, tree arg2, tree arg3, bool ignore)
c2f47e15 10687{
10688 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10689
10690 switch (fcode)
10691 {
10692 case BUILT_IN_MEMCPY_CHK:
10693 case BUILT_IN_MEMPCPY_CHK:
10694 case BUILT_IN_MEMMOVE_CHK:
10695 case BUILT_IN_MEMSET_CHK:
389dd41b 10696 return fold_builtin_memory_chk (loc, fndecl, arg0, arg1, arg2, arg3,
c2f47e15 10697 NULL_TREE, ignore,
10698 DECL_FUNCTION_CODE (fndecl));
10699
10700 case BUILT_IN_STRNCPY_CHK:
389dd41b 10701 return fold_builtin_strncpy_chk (loc, arg0, arg1, arg2, arg3, NULL_TREE);
c2f47e15 10702
10703 case BUILT_IN_STRNCAT_CHK:
389dd41b 10704 return fold_builtin_strncat_chk (loc, fndecl, arg0, arg1, arg2, arg3);
c2f47e15 10705
10706 case BUILT_IN_FPRINTF_CHK:
10707 case BUILT_IN_VFPRINTF_CHK:
10708 if (!validate_arg (arg1, INTEGER_TYPE)
10709 || TREE_SIDE_EFFECTS (arg1))
10710 return NULL_TREE;
10711 else
389dd41b 10712 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, arg3,
c2f47e15 10713 ignore, fcode);
10714 break;
10715
10716 default:
10717 break;
10718 }
10719 return NULL_TREE;
10720}
10721
10722/* Fold a call to built-in function FNDECL. ARGS is an array of NARGS
10723 arguments, where NARGS <= 4. IGNORE is true if the result of the
10724 function call is ignored. This function returns NULL_TREE if no
10725 simplification was possible. Note that this only folds builtins with
10726 fixed argument patterns. Foldings that do varargs-to-varargs
10727 transformations, or that match calls with more than 4 arguments,
10728 need to be handled with fold_builtin_varargs instead. */
10729
10730#define MAX_ARGS_TO_FOLD_BUILTIN 4
10731
10732static tree
389dd41b 10733fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool ignore)
c2f47e15 10734{
10735 tree ret = NULL_TREE;
a7f5bb2d 10736
c2f47e15 10737 switch (nargs)
10738 {
10739 case 0:
389dd41b 10740 ret = fold_builtin_0 (loc, fndecl, ignore);
c2f47e15 10741 break;
10742 case 1:
389dd41b 10743 ret = fold_builtin_1 (loc, fndecl, args[0], ignore);
c2f47e15 10744 break;
10745 case 2:
389dd41b 10746 ret = fold_builtin_2 (loc, fndecl, args[0], args[1], ignore);
c2f47e15 10747 break;
10748 case 3:
389dd41b 10749 ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2], ignore);
c2f47e15 10750 break;
10751 case 4:
389dd41b 10752 ret = fold_builtin_4 (loc, fndecl, args[0], args[1], args[2], args[3],
c2f47e15 10753 ignore);
10754 break;
10755 default:
10756 break;
10757 }
10758 if (ret)
10759 {
75a70cf9 10760 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
389dd41b 10761 SET_EXPR_LOCATION (ret, loc);
c2f47e15 10762 TREE_NO_WARNING (ret) = 1;
10763 return ret;
10764 }
10765 return NULL_TREE;
10766}
10767
10768/* Builtins with folding operations that operate on "..." arguments
10769 need special handling; we need to store the arguments in a convenient
10770 data structure before attempting any folding. Fortunately there are
10771 only a few builtins that fall into this category. FNDECL is the
10772 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
10773 result of the function call is ignored. */
10774
10775static tree
389dd41b 10776fold_builtin_varargs (location_t loc, tree fndecl, tree exp,
10777 bool ignore ATTRIBUTE_UNUSED)
c2f47e15 10778{
10779 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10780 tree ret = NULL_TREE;
10781
10782 switch (fcode)
10783 {
10784 case BUILT_IN_SPRINTF_CHK:
10785 case BUILT_IN_VSPRINTF_CHK:
389dd41b 10786 ret = fold_builtin_sprintf_chk (loc, exp, fcode);
c2f47e15 10787 break;
10788
10789 case BUILT_IN_SNPRINTF_CHK:
10790 case BUILT_IN_VSNPRINTF_CHK:
389dd41b 10791 ret = fold_builtin_snprintf_chk (loc, exp, NULL_TREE, fcode);
19fbe3a4 10792 break;
10793
10794 case BUILT_IN_FPCLASSIFY:
389dd41b 10795 ret = fold_builtin_fpclassify (loc, exp);
19fbe3a4 10796 break;
c2f47e15 10797
10798 default:
10799 break;
10800 }
10801 if (ret)
10802 {
10803 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
389dd41b 10804 SET_EXPR_LOCATION (ret, loc);
c2f47e15 10805 TREE_NO_WARNING (ret) = 1;
10806 return ret;
10807 }
10808 return NULL_TREE;
650e4c94 10809}
7e15618b 10810
198622c0 10811/* Return true if FNDECL shouldn't be folded right now.
10812 If a built-in function has an inline attribute always_inline
10813 wrapper, defer folding it after always_inline functions have
10814 been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
10815 might not be performed. */
10816
10817static bool
10818avoid_folding_inline_builtin (tree fndecl)
10819{
10820 return (DECL_DECLARED_INLINE_P (fndecl)
10821 && DECL_DISREGARD_INLINE_LIMITS (fndecl)
10822 && cfun
10823 && !cfun->always_inline_functions_inlined
10824 && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)));
10825}
10826
4ee9c684 10827/* A wrapper function for builtin folding that prevents warnings for
491e04ef 10828 "statement without effect" and the like, caused by removing the
4ee9c684 10829 call node earlier than the warning is generated. */
10830
10831tree
389dd41b 10832fold_call_expr (location_t loc, tree exp, bool ignore)
4ee9c684 10833{
c2f47e15 10834 tree ret = NULL_TREE;
10835 tree fndecl = get_callee_fndecl (exp);
10836 if (fndecl
10837 && TREE_CODE (fndecl) == FUNCTION_DECL
48dc2227 10838 && DECL_BUILT_IN (fndecl)
10839 /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
10840 yet. Defer folding until we see all the arguments
10841 (after inlining). */
10842 && !CALL_EXPR_VA_ARG_PACK (exp))
10843 {
10844 int nargs = call_expr_nargs (exp);
10845
10846 /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
10847 instead last argument is __builtin_va_arg_pack (). Defer folding
10848 even in that case, until arguments are finalized. */
10849 if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
10850 {
10851 tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1));
10852 if (fndecl2
10853 && TREE_CODE (fndecl2) == FUNCTION_DECL
10854 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
10855 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
10856 return NULL_TREE;
10857 }
10858
198622c0 10859 if (avoid_folding_inline_builtin (fndecl))
10860 return NULL_TREE;
10861
c2f47e15 10862 /* FIXME: Don't use a list in this interface. */
10863 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
10864 return targetm.fold_builtin (fndecl, CALL_EXPR_ARGS (exp), ignore);
10865 else
10866 {
c2f47e15 10867 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
10868 {
10869 tree *args = CALL_EXPR_ARGP (exp);
389dd41b 10870 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
c2f47e15 10871 }
10872 if (!ret)
389dd41b 10873 ret = fold_builtin_varargs (loc, fndecl, exp, ignore);
c2f47e15 10874 if (ret)
389dd41b 10875 return ret;
c2f47e15 10876 }
4ee9c684 10877 }
c2f47e15 10878 return NULL_TREE;
10879}
10880
10881/* Conveniently construct a function call expression. FNDECL names the
10882 function to be called and ARGLIST is a TREE_LIST of arguments. */
10883
10884tree
389dd41b 10885build_function_call_expr (location_t loc, tree fndecl, tree arglist)
c2f47e15 10886{
10887 tree fntype = TREE_TYPE (fndecl);
10888 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
d01f58f9 10889 int n = list_length (arglist);
10890 tree *argarray = (tree *) alloca (n * sizeof (tree));
10891 int i;
389dd41b 10892
d01f58f9 10893 for (i = 0; i < n; i++, arglist = TREE_CHAIN (arglist))
10894 argarray[i] = TREE_VALUE (arglist);
389dd41b 10895 return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray);
c2f47e15 10896}
10897
10898/* Conveniently construct a function call expression. FNDECL names the
10899 function to be called, N is the number of arguments, and the "..."
10900 parameters are the argument expressions. */
10901
10902tree
389dd41b 10903build_call_expr_loc (location_t loc, tree fndecl, int n, ...)
c2f47e15 10904{
10905 va_list ap;
c2f47e15 10906 tree fntype = TREE_TYPE (fndecl);
10907 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
d01f58f9 10908 tree *argarray = (tree *) alloca (n * sizeof (tree));
10909 int i;
c2f47e15 10910
10911 va_start (ap, n);
d01f58f9 10912 for (i = 0; i < n; i++)
10913 argarray[i] = va_arg (ap, tree);
c2f47e15 10914 va_end (ap);
389dd41b 10915 return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray);
4ee9c684 10916}
10917
c2f47e15 10918/* Construct a CALL_EXPR with type TYPE with FN as the function expression.
d01f58f9 10919 N arguments are passed in the array ARGARRAY. */
805e22b2 10920
10921tree
389dd41b 10922fold_builtin_call_array (location_t loc, tree type,
d01f58f9 10923 tree fn,
10924 int n,
10925 tree *argarray)
7e15618b 10926{
c2f47e15 10927 tree ret = NULL_TREE;
10928 int i;
10929 tree exp;
10930
10931 if (TREE_CODE (fn) == ADDR_EXPR)
10932 {
10933 tree fndecl = TREE_OPERAND (fn, 0);
10934 if (TREE_CODE (fndecl) == FUNCTION_DECL
10935 && DECL_BUILT_IN (fndecl))
10936 {
48dc2227 10937 /* If last argument is __builtin_va_arg_pack (), arguments to this
10938 function are not finalized yet. Defer folding until they are. */
10939 if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
10940 {
10941 tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
10942 if (fndecl2
10943 && TREE_CODE (fndecl2) == FUNCTION_DECL
10944 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
10945 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
389dd41b 10946 return build_call_array_loc (loc, type, fn, n, argarray);
48dc2227 10947 }
198622c0 10948 if (avoid_folding_inline_builtin (fndecl))
389dd41b 10949 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 10950 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
10951 {
10952 tree arglist = NULL_TREE;
d01f58f9 10953 for (i = n - 1; i >= 0; i--)
10954 arglist = tree_cons (NULL_TREE, argarray[i], arglist);
c2f47e15 10955 ret = targetm.fold_builtin (fndecl, arglist, false);
10956 if (ret)
10957 return ret;
389dd41b 10958 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 10959 }
10960 else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
10961 {
10962 /* First try the transformations that don't require consing up
10963 an exp. */
389dd41b 10964 ret = fold_builtin_n (loc, fndecl, argarray, n, false);
c2f47e15 10965 if (ret)
10966 return ret;
10967 }
10968
10969 /* If we got this far, we need to build an exp. */
389dd41b 10970 exp = build_call_array_loc (loc, type, fn, n, argarray);
10971 ret = fold_builtin_varargs (loc, fndecl, exp, false);
c2f47e15 10972 return ret ? ret : exp;
10973 }
10974 }
10975
389dd41b 10976 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 10977}
10978
10979/* Construct a new CALL_EXPR using the tail of the argument list of EXP
10980 along with N new arguments specified as the "..." parameters. SKIP
10981 is the number of arguments in EXP to be omitted. This function is used
10982 to do varargs-to-varargs transformations. */
10983
10984static tree
389dd41b 10985rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...)
c2f47e15 10986{
10987 int oldnargs = call_expr_nargs (exp);
10988 int nargs = oldnargs - skip + n;
10989 tree fntype = TREE_TYPE (fndecl);
10990 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
10991 tree *buffer;
10992
10993 if (n > 0)
10994 {
10995 int i, j;
10996 va_list ap;
7e15618b 10997
364c0c59 10998 buffer = XALLOCAVEC (tree, nargs);
c2f47e15 10999 va_start (ap, n);
11000 for (i = 0; i < n; i++)
11001 buffer[i] = va_arg (ap, tree);
11002 va_end (ap);
11003 for (j = skip; j < oldnargs; j++, i++)
11004 buffer[i] = CALL_EXPR_ARG (exp, j);
11005 }
11006 else
11007 buffer = CALL_EXPR_ARGP (exp) + skip;
11008
389dd41b 11009 return fold (build_call_array_loc (loc, TREE_TYPE (exp), fn, nargs, buffer));
c2f47e15 11010}
11011
11012/* Validate a single argument ARG against a tree code CODE representing
11013 a type. */
11014
11015static bool
b7bf20db 11016validate_arg (const_tree arg, enum tree_code code)
c2f47e15 11017{
11018 if (!arg)
11019 return false;
11020 else if (code == POINTER_TYPE)
11021 return POINTER_TYPE_P (TREE_TYPE (arg));
c7f617c2 11022 else if (code == INTEGER_TYPE)
11023 return INTEGRAL_TYPE_P (TREE_TYPE (arg));
c2f47e15 11024 return code == TREE_CODE (TREE_TYPE (arg));
7e15618b 11025}
0eb671f7 11026
75a70cf9 11027/* This function validates the types of a function call argument list
11028 against a specified list of tree_codes. If the last specifier is a 0,
11029 that represents an ellipses, otherwise the last specifier must be a
11030 VOID_TYPE.
11031
11032 This is the GIMPLE version of validate_arglist. Eventually we want to
11033 completely convert builtins.c to work from GIMPLEs and the tree based
11034 validate_arglist will then be removed. */
11035
11036bool
11037validate_gimple_arglist (const_gimple call, ...)
11038{
11039 enum tree_code code;
11040 bool res = 0;
11041 va_list ap;
11042 const_tree arg;
11043 size_t i;
11044
11045 va_start (ap, call);
11046 i = 0;
11047
11048 do
11049 {
d62e827b 11050 code = (enum tree_code) va_arg (ap, int);
75a70cf9 11051 switch (code)
11052 {
11053 case 0:
11054 /* This signifies an ellipses, any further arguments are all ok. */
11055 res = true;
11056 goto end;
11057 case VOID_TYPE:
11058 /* This signifies an endlink, if no arguments remain, return
11059 true, otherwise return false. */
11060 res = (i == gimple_call_num_args (call));
11061 goto end;
11062 default:
11063 /* If no parameters remain or the parameter's code does not
11064 match the specified code, return false. Otherwise continue
11065 checking any remaining arguments. */
11066 arg = gimple_call_arg (call, i++);
11067 if (!validate_arg (arg, code))
11068 goto end;
11069 break;
11070 }
11071 }
11072 while (1);
11073
11074 /* We need gotos here since we can only have one VA_CLOSE in a
11075 function. */
11076 end: ;
11077 va_end (ap);
11078
11079 return res;
11080}
11081
0eb671f7 11082/* This function validates the types of a function call argument list
c2f47e15 11083 against a specified list of tree_codes. If the last specifier is a 0,
11084 that represents an ellipses, otherwise the last specifier must be a
11085 VOID_TYPE. */
27d0c333 11086
c2f47e15 11087bool
b7bf20db 11088validate_arglist (const_tree callexpr, ...)
0eb671f7 11089{
0eb671f7 11090 enum tree_code code;
c2f47e15 11091 bool res = 0;
ee582a61 11092 va_list ap;
b7bf20db 11093 const_call_expr_arg_iterator iter;
11094 const_tree arg;
aecda0d6 11095
c2f47e15 11096 va_start (ap, callexpr);
b7bf20db 11097 init_const_call_expr_arg_iterator (callexpr, &iter);
0eb671f7 11098
f0ce3b1f 11099 do
0eb671f7 11100 {
d62e827b 11101 code = (enum tree_code) va_arg (ap, int);
f0ce3b1f 11102 switch (code)
11103 {
11104 case 0:
11105 /* This signifies an ellipses, any further arguments are all ok. */
c2f47e15 11106 res = true;
f0ce3b1f 11107 goto end;
11108 case VOID_TYPE:
11109 /* This signifies an endlink, if no arguments remain, return
11110 true, otherwise return false. */
b7bf20db 11111 res = !more_const_call_expr_args_p (&iter);
f0ce3b1f 11112 goto end;
11113 default:
11114 /* If no parameters remain or the parameter's code does not
11115 match the specified code, return false. Otherwise continue
11116 checking any remaining arguments. */
b7bf20db 11117 arg = next_const_call_expr_arg (&iter);
c2f47e15 11118 if (!validate_arg (arg, code))
f0ce3b1f 11119 goto end;
11120 break;
11121 }
0eb671f7 11122 }
f0ce3b1f 11123 while (1);
0903457a 11124
11125 /* We need gotos here since we can only have one VA_CLOSE in a
11126 function. */
11127 end: ;
ee582a61 11128 va_end (ap);
0903457a 11129
11130 return res;
0eb671f7 11131}
fc2a2dcb 11132
fc2a2dcb 11133/* Default target-specific builtin expander that does nothing. */
11134
11135rtx
aecda0d6 11136default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
11137 rtx target ATTRIBUTE_UNUSED,
11138 rtx subtarget ATTRIBUTE_UNUSED,
11139 enum machine_mode mode ATTRIBUTE_UNUSED,
11140 int ignore ATTRIBUTE_UNUSED)
fc2a2dcb 11141{
11142 return NULL_RTX;
11143}
c7926a82 11144
01537105 11145/* Returns true is EXP represents data that would potentially reside
11146 in a readonly section. */
11147
11148static bool
11149readonly_data_expr (tree exp)
11150{
11151 STRIP_NOPS (exp);
11152
9ff0637e 11153 if (TREE_CODE (exp) != ADDR_EXPR)
11154 return false;
11155
11156 exp = get_base_address (TREE_OPERAND (exp, 0));
11157 if (!exp)
11158 return false;
11159
11160 /* Make sure we call decl_readonly_section only for trees it
11161 can handle (since it returns true for everything it doesn't
11162 understand). */
491e04ef 11163 if (TREE_CODE (exp) == STRING_CST
9ff0637e 11164 || TREE_CODE (exp) == CONSTRUCTOR
11165 || (TREE_CODE (exp) == VAR_DECL && TREE_STATIC (exp)))
11166 return decl_readonly_section (exp, 0);
01537105 11167 else
11168 return false;
11169}
4ee9c684 11170
c2f47e15 11171/* Simplify a call to the strstr builtin. S1 and S2 are the arguments
11172 to the call, and TYPE is its return type.
4ee9c684 11173
c2f47e15 11174 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11175 simplified form of the call as a tree.
11176
11177 The simplified form may be a constant or other expression which
11178 computes the same value, but in a more efficient manner (including
11179 calls to other builtin functions).
11180
11181 The call may contain arguments which need to be evaluated, but
11182 which are not useful to determine the result of the call. In
11183 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11184 COMPOUND_EXPR will be an argument which must be evaluated.
11185 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11186 COMPOUND_EXPR in the chain will contain the tree for the simplified
11187 form of the builtin function call. */
11188
11189static tree
389dd41b 11190fold_builtin_strstr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11191{
c2f47e15 11192 if (!validate_arg (s1, POINTER_TYPE)
11193 || !validate_arg (s2, POINTER_TYPE))
11194 return NULL_TREE;
4ee9c684 11195 else
11196 {
4ee9c684 11197 tree fn;
11198 const char *p1, *p2;
11199
11200 p2 = c_getstr (s2);
11201 if (p2 == NULL)
c2f47e15 11202 return NULL_TREE;
4ee9c684 11203
11204 p1 = c_getstr (s1);
11205 if (p1 != NULL)
11206 {
11207 const char *r = strstr (p1, p2);
daa1d5f5 11208 tree tem;
4ee9c684 11209
4ee9c684 11210 if (r == NULL)
779b4c41 11211 return build_int_cst (TREE_TYPE (s1), 0);
c0c67e38 11212
11213 /* Return an offset into the constant string argument. */
389dd41b 11214 tem = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (s1),
0de36bdb 11215 s1, size_int (r - p1));
389dd41b 11216 return fold_convert_loc (loc, type, tem);
4ee9c684 11217 }
11218
7efa231c 11219 /* The argument is const char *, and the result is char *, so we need
11220 a type conversion here to avoid a warning. */
4ee9c684 11221 if (p2[0] == '\0')
389dd41b 11222 return fold_convert_loc (loc, type, s1);
4ee9c684 11223
11224 if (p2[1] != '\0')
c2f47e15 11225 return NULL_TREE;
4ee9c684 11226
11227 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
11228 if (!fn)
c2f47e15 11229 return NULL_TREE;
4ee9c684 11230
11231 /* New argument list transforming strstr(s1, s2) to
11232 strchr(s1, s2[0]). */
389dd41b 11233 return build_call_expr_loc (loc, fn, 2, s1, build_int_cst (NULL_TREE, p2[0]));
4ee9c684 11234 }
11235}
11236
c2f47e15 11237/* Simplify a call to the strchr builtin. S1 and S2 are the arguments to
11238 the call, and TYPE is its return type.
4ee9c684 11239
c2f47e15 11240 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11241 simplified form of the call as a tree.
11242
11243 The simplified form may be a constant or other expression which
11244 computes the same value, but in a more efficient manner (including
11245 calls to other builtin functions).
11246
11247 The call may contain arguments which need to be evaluated, but
11248 which are not useful to determine the result of the call. In
11249 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11250 COMPOUND_EXPR will be an argument which must be evaluated.
11251 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11252 COMPOUND_EXPR in the chain will contain the tree for the simplified
11253 form of the builtin function call. */
11254
11255static tree
389dd41b 11256fold_builtin_strchr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11257{
c2f47e15 11258 if (!validate_arg (s1, POINTER_TYPE)
11259 || !validate_arg (s2, INTEGER_TYPE))
11260 return NULL_TREE;
4ee9c684 11261 else
11262 {
4ee9c684 11263 const char *p1;
11264
11265 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 11266 return NULL_TREE;
4ee9c684 11267
11268 p1 = c_getstr (s1);
11269 if (p1 != NULL)
11270 {
11271 char c;
11272 const char *r;
daa1d5f5 11273 tree tem;
4ee9c684 11274
11275 if (target_char_cast (s2, &c))
c2f47e15 11276 return NULL_TREE;
4ee9c684 11277
11278 r = strchr (p1, c);
11279
11280 if (r == NULL)
779b4c41 11281 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11282
11283 /* Return an offset into the constant string argument. */
389dd41b 11284 tem = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (s1),
0de36bdb 11285 s1, size_int (r - p1));
389dd41b 11286 return fold_convert_loc (loc, type, tem);
4ee9c684 11287 }
c2f47e15 11288 return NULL_TREE;
4ee9c684 11289 }
11290}
11291
c2f47e15 11292/* Simplify a call to the strrchr builtin. S1 and S2 are the arguments to
11293 the call, and TYPE is its return type.
4ee9c684 11294
c2f47e15 11295 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11296 simplified form of the call as a tree.
11297
11298 The simplified form may be a constant or other expression which
11299 computes the same value, but in a more efficient manner (including
11300 calls to other builtin functions).
11301
11302 The call may contain arguments which need to be evaluated, but
11303 which are not useful to determine the result of the call. In
11304 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11305 COMPOUND_EXPR will be an argument which must be evaluated.
11306 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11307 COMPOUND_EXPR in the chain will contain the tree for the simplified
11308 form of the builtin function call. */
11309
11310static tree
389dd41b 11311fold_builtin_strrchr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11312{
c2f47e15 11313 if (!validate_arg (s1, POINTER_TYPE)
11314 || !validate_arg (s2, INTEGER_TYPE))
11315 return NULL_TREE;
4ee9c684 11316 else
11317 {
4ee9c684 11318 tree fn;
11319 const char *p1;
11320
11321 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 11322 return NULL_TREE;
4ee9c684 11323
11324 p1 = c_getstr (s1);
11325 if (p1 != NULL)
11326 {
11327 char c;
11328 const char *r;
daa1d5f5 11329 tree tem;
4ee9c684 11330
11331 if (target_char_cast (s2, &c))
c2f47e15 11332 return NULL_TREE;
4ee9c684 11333
11334 r = strrchr (p1, c);
11335
11336 if (r == NULL)
779b4c41 11337 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11338
11339 /* Return an offset into the constant string argument. */
389dd41b 11340 tem = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (s1),
0de36bdb 11341 s1, size_int (r - p1));
389dd41b 11342 return fold_convert_loc (loc, type, tem);
4ee9c684 11343 }
11344
11345 if (! integer_zerop (s2))
c2f47e15 11346 return NULL_TREE;
4ee9c684 11347
11348 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
11349 if (!fn)
c2f47e15 11350 return NULL_TREE;
4ee9c684 11351
11352 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
389dd41b 11353 return build_call_expr_loc (loc, fn, 2, s1, s2);
4ee9c684 11354 }
11355}
11356
c2f47e15 11357/* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments
11358 to the call, and TYPE is its return type.
4ee9c684 11359
c2f47e15 11360 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11361 simplified form of the call as a tree.
11362
11363 The simplified form may be a constant or other expression which
11364 computes the same value, but in a more efficient manner (including
11365 calls to other builtin functions).
11366
11367 The call may contain arguments which need to be evaluated, but
11368 which are not useful to determine the result of the call. In
11369 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11370 COMPOUND_EXPR will be an argument which must be evaluated.
11371 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11372 COMPOUND_EXPR in the chain will contain the tree for the simplified
11373 form of the builtin function call. */
11374
11375static tree
389dd41b 11376fold_builtin_strpbrk (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11377{
c2f47e15 11378 if (!validate_arg (s1, POINTER_TYPE)
11379 || !validate_arg (s2, POINTER_TYPE))
11380 return NULL_TREE;
4ee9c684 11381 else
11382 {
4ee9c684 11383 tree fn;
11384 const char *p1, *p2;
11385
11386 p2 = c_getstr (s2);
11387 if (p2 == NULL)
c2f47e15 11388 return NULL_TREE;
4ee9c684 11389
11390 p1 = c_getstr (s1);
11391 if (p1 != NULL)
11392 {
11393 const char *r = strpbrk (p1, p2);
daa1d5f5 11394 tree tem;
4ee9c684 11395
11396 if (r == NULL)
779b4c41 11397 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11398
11399 /* Return an offset into the constant string argument. */
389dd41b 11400 tem = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (s1),
0de36bdb 11401 s1, size_int (r - p1));
389dd41b 11402 return fold_convert_loc (loc, type, tem);
4ee9c684 11403 }
11404
11405 if (p2[0] == '\0')
05abc81b 11406 /* strpbrk(x, "") == NULL.
11407 Evaluate and ignore s1 in case it had side-effects. */
389dd41b 11408 return omit_one_operand_loc (loc, TREE_TYPE (s1), integer_zero_node, s1);
4ee9c684 11409
11410 if (p2[1] != '\0')
c2f47e15 11411 return NULL_TREE; /* Really call strpbrk. */
4ee9c684 11412
11413 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
11414 if (!fn)
c2f47e15 11415 return NULL_TREE;
4ee9c684 11416
11417 /* New argument list transforming strpbrk(s1, s2) to
11418 strchr(s1, s2[0]). */
389dd41b 11419 return build_call_expr_loc (loc, fn, 2, s1, build_int_cst (NULL_TREE, p2[0]));
4ee9c684 11420 }
11421}
11422
c2f47e15 11423/* Simplify a call to the strcat builtin. DST and SRC are the arguments
11424 to the call.
4ee9c684 11425
c2f47e15 11426 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11427 simplified form of the call as a tree.
11428
11429 The simplified form may be a constant or other expression which
11430 computes the same value, but in a more efficient manner (including
11431 calls to other builtin functions).
11432
11433 The call may contain arguments which need to be evaluated, but
11434 which are not useful to determine the result of the call. In
11435 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11436 COMPOUND_EXPR will be an argument which must be evaluated.
11437 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11438 COMPOUND_EXPR in the chain will contain the tree for the simplified
11439 form of the builtin function call. */
11440
11441static tree
389dd41b 11442fold_builtin_strcat (location_t loc ATTRIBUTE_UNUSED, tree dst, tree src)
4ee9c684 11443{
c2f47e15 11444 if (!validate_arg (dst, POINTER_TYPE)
11445 || !validate_arg (src, POINTER_TYPE))
11446 return NULL_TREE;
4ee9c684 11447 else
11448 {
4ee9c684 11449 const char *p = c_getstr (src);
11450
11451 /* If the string length is zero, return the dst parameter. */
11452 if (p && *p == '\0')
11453 return dst;
11454
a65c4d64 11455 if (optimize_insn_for_speed_p ())
11456 {
11457 /* See if we can store by pieces into (dst + strlen(dst)). */
11458 tree newdst, call;
11459 tree strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
11460 tree strcpy_fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11461
11462 if (!strlen_fn || !strcpy_fn)
11463 return NULL_TREE;
11464
11465 /* If we don't have a movstr we don't want to emit an strcpy
11466 call. We have to do that if the length of the source string
11467 isn't computable (in that case we can use memcpy probably
11468 later expanding to a sequence of mov instructions). If we
11469 have movstr instructions we can emit strcpy calls. */
11470 if (!HAVE_movstr)
11471 {
11472 tree len = c_strlen (src, 1);
11473 if (! len || TREE_SIDE_EFFECTS (len))
11474 return NULL_TREE;
11475 }
11476
11477 /* Stabilize the argument list. */
11478 dst = builtin_save_expr (dst);
11479
11480 /* Create strlen (dst). */
11481 newdst = build_call_expr_loc (loc, strlen_fn, 1, dst);
11482 /* Create (dst p+ strlen (dst)). */
11483
11484 newdst = fold_build2_loc (loc, POINTER_PLUS_EXPR,
11485 TREE_TYPE (dst), dst, newdst);
11486 newdst = builtin_save_expr (newdst);
11487
11488 call = build_call_expr_loc (loc, strcpy_fn, 2, newdst, src);
11489 return build2 (COMPOUND_EXPR, TREE_TYPE (dst), call, dst);
11490 }
c2f47e15 11491 return NULL_TREE;
4ee9c684 11492 }
11493}
11494
c2f47e15 11495/* Simplify a call to the strncat builtin. DST, SRC, and LEN are the
11496 arguments to the call.
4ee9c684 11497
c2f47e15 11498 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11499 simplified form of the call as a tree.
11500
11501 The simplified form may be a constant or other expression which
11502 computes the same value, but in a more efficient manner (including
11503 calls to other builtin functions).
11504
11505 The call may contain arguments which need to be evaluated, but
11506 which are not useful to determine the result of the call. In
11507 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11508 COMPOUND_EXPR will be an argument which must be evaluated.
11509 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11510 COMPOUND_EXPR in the chain will contain the tree for the simplified
11511 form of the builtin function call. */
11512
11513static tree
389dd41b 11514fold_builtin_strncat (location_t loc, tree dst, tree src, tree len)
4ee9c684 11515{
c2f47e15 11516 if (!validate_arg (dst, POINTER_TYPE)
11517 || !validate_arg (src, POINTER_TYPE)
11518 || !validate_arg (len, INTEGER_TYPE))
11519 return NULL_TREE;
4ee9c684 11520 else
11521 {
4ee9c684 11522 const char *p = c_getstr (src);
11523
11524 /* If the requested length is zero, or the src parameter string
0a39fd54 11525 length is zero, return the dst parameter. */
4ee9c684 11526 if (integer_zerop (len) || (p && *p == '\0'))
389dd41b 11527 return omit_two_operands_loc (loc, TREE_TYPE (dst), dst, src, len);
4ee9c684 11528
11529 /* If the requested len is greater than or equal to the string
a0c938f0 11530 length, call strcat. */
4ee9c684 11531 if (TREE_CODE (len) == INTEGER_CST && p
11532 && compare_tree_int (len, strlen (p)) >= 0)
11533 {
4ee9c684 11534 tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
11535
11536 /* If the replacement _DECL isn't initialized, don't do the
11537 transformation. */
11538 if (!fn)
c2f47e15 11539 return NULL_TREE;
4ee9c684 11540
389dd41b 11541 return build_call_expr_loc (loc, fn, 2, dst, src);
4ee9c684 11542 }
c2f47e15 11543 return NULL_TREE;
4ee9c684 11544 }
11545}
11546
c2f47e15 11547/* Simplify a call to the strspn builtin. S1 and S2 are the arguments
11548 to the call.
4ee9c684 11549
c2f47e15 11550 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11551 simplified form of the call as a tree.
11552
11553 The simplified form may be a constant or other expression which
11554 computes the same value, but in a more efficient manner (including
11555 calls to other builtin functions).
11556
11557 The call may contain arguments which need to be evaluated, but
11558 which are not useful to determine the result of the call. In
11559 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11560 COMPOUND_EXPR will be an argument which must be evaluated.
11561 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11562 COMPOUND_EXPR in the chain will contain the tree for the simplified
11563 form of the builtin function call. */
11564
11565static tree
389dd41b 11566fold_builtin_strspn (location_t loc, tree s1, tree s2)
4ee9c684 11567{
c2f47e15 11568 if (!validate_arg (s1, POINTER_TYPE)
11569 || !validate_arg (s2, POINTER_TYPE))
11570 return NULL_TREE;
4ee9c684 11571 else
11572 {
4ee9c684 11573 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11574
11575 /* If both arguments are constants, evaluate at compile-time. */
11576 if (p1 && p2)
11577 {
11578 const size_t r = strspn (p1, p2);
11579 return size_int (r);
11580 }
11581
c2f47e15 11582 /* If either argument is "", return NULL_TREE. */
4ee9c684 11583 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9bc9f15f 11584 /* Evaluate and ignore both arguments in case either one has
11585 side-effects. */
389dd41b 11586 return omit_two_operands_loc (loc, size_type_node, size_zero_node,
9bc9f15f 11587 s1, s2);
c2f47e15 11588 return NULL_TREE;
4ee9c684 11589 }
11590}
11591
c2f47e15 11592/* Simplify a call to the strcspn builtin. S1 and S2 are the arguments
11593 to the call.
4ee9c684 11594
c2f47e15 11595 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11596 simplified form of the call as a tree.
11597
11598 The simplified form may be a constant or other expression which
11599 computes the same value, but in a more efficient manner (including
11600 calls to other builtin functions).
11601
11602 The call may contain arguments which need to be evaluated, but
11603 which are not useful to determine the result of the call. In
11604 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11605 COMPOUND_EXPR will be an argument which must be evaluated.
11606 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11607 COMPOUND_EXPR in the chain will contain the tree for the simplified
11608 form of the builtin function call. */
11609
11610static tree
389dd41b 11611fold_builtin_strcspn (location_t loc, tree s1, tree s2)
4ee9c684 11612{
c2f47e15 11613 if (!validate_arg (s1, POINTER_TYPE)
11614 || !validate_arg (s2, POINTER_TYPE))
11615 return NULL_TREE;
4ee9c684 11616 else
11617 {
4ee9c684 11618 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11619
11620 /* If both arguments are constants, evaluate at compile-time. */
11621 if (p1 && p2)
11622 {
11623 const size_t r = strcspn (p1, p2);
11624 return size_int (r);
11625 }
11626
c2f47e15 11627 /* If the first argument is "", return NULL_TREE. */
4ee9c684 11628 if (p1 && *p1 == '\0')
11629 {
11630 /* Evaluate and ignore argument s2 in case it has
11631 side-effects. */
389dd41b 11632 return omit_one_operand_loc (loc, size_type_node,
39761420 11633 size_zero_node, s2);
4ee9c684 11634 }
11635
11636 /* If the second argument is "", return __builtin_strlen(s1). */
11637 if (p2 && *p2 == '\0')
11638 {
c2f47e15 11639 tree fn = implicit_built_in_decls[BUILT_IN_STRLEN];
4ee9c684 11640
11641 /* If the replacement _DECL isn't initialized, don't do the
11642 transformation. */
11643 if (!fn)
c2f47e15 11644 return NULL_TREE;
4ee9c684 11645
389dd41b 11646 return build_call_expr_loc (loc, fn, 1, s1);
4ee9c684 11647 }
c2f47e15 11648 return NULL_TREE;
4ee9c684 11649 }
11650}
11651
c2f47e15 11652/* Fold a call to the fputs builtin. ARG0 and ARG1 are the arguments
11653 to the call. IGNORE is true if the value returned
f0613857 11654 by the builtin will be ignored. UNLOCKED is true is true if this
11655 actually a call to fputs_unlocked. If LEN in non-NULL, it represents
11656 the known length of the string. Return NULL_TREE if no simplification
11657 was possible. */
4ee9c684 11658
11659tree
389dd41b 11660fold_builtin_fputs (location_t loc, tree arg0, tree arg1,
11661 bool ignore, bool unlocked, tree len)
4ee9c684 11662{
6d77ed92 11663 /* If we're using an unlocked function, assume the other unlocked
11664 functions exist explicitly. */
11665 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
4ee9c684 11666 : implicit_built_in_decls[BUILT_IN_FPUTC];
6d77ed92 11667 tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
4ee9c684 11668 : implicit_built_in_decls[BUILT_IN_FWRITE];
11669
c403edd4 11670 /* If the return value is used, don't do the transformation. */
11671 if (!ignore)
c2f47e15 11672 return NULL_TREE;
4ee9c684 11673
11674 /* Verify the arguments in the original call. */
c2f47e15 11675 if (!validate_arg (arg0, POINTER_TYPE)
11676 || !validate_arg (arg1, POINTER_TYPE))
11677 return NULL_TREE;
4ee9c684 11678
f0613857 11679 if (! len)
c2f47e15 11680 len = c_strlen (arg0, 0);
4ee9c684 11681
11682 /* Get the length of the string passed to fputs. If the length
11683 can't be determined, punt. */
11684 if (!len
11685 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 11686 return NULL_TREE;
4ee9c684 11687
11688 switch (compare_tree_int (len, 1))
11689 {
11690 case -1: /* length is 0, delete the call entirely . */
389dd41b 11691 return omit_one_operand_loc (loc, integer_type_node,
11692 integer_zero_node, arg1);;
05abc81b 11693
4ee9c684 11694 case 0: /* length is 1, call fputc. */
11695 {
c2f47e15 11696 const char *p = c_getstr (arg0);
4ee9c684 11697
11698 if (p != NULL)
11699 {
c2f47e15 11700 if (fn_fputc)
389dd41b 11701 return build_call_expr_loc (loc, fn_fputc, 2,
c2f47e15 11702 build_int_cst (NULL_TREE, p[0]), arg1);
11703 else
11704 return NULL_TREE;
4ee9c684 11705 }
11706 }
11707 /* FALLTHROUGH */
11708 case 1: /* length is greater than 1, call fwrite. */
11709 {
0bed3869 11710 /* If optimizing for size keep fputs. */
0bfd8d5c 11711 if (optimize_function_for_size_p (cfun))
c2f47e15 11712 return NULL_TREE;
4ee9c684 11713 /* New argument list transforming fputs(string, stream) to
11714 fwrite(string, 1, len, stream). */
c2f47e15 11715 if (fn_fwrite)
389dd41b 11716 return build_call_expr_loc (loc, fn_fwrite, 4, arg0,
11717 size_one_node, len, arg1);
c2f47e15 11718 else
11719 return NULL_TREE;
4ee9c684 11720 }
11721 default:
64db345d 11722 gcc_unreachable ();
4ee9c684 11723 }
c2f47e15 11724 return NULL_TREE;
4ee9c684 11725}
11726
c2f47e15 11727/* Fold the next_arg or va_start call EXP. Returns true if there was an error
743b0c6a 11728 produced. False otherwise. This is done so that we don't output the error
11729 or warning twice or three times. */
75a70cf9 11730
743b0c6a 11731bool
c2f47e15 11732fold_builtin_next_arg (tree exp, bool va_start_p)
4ee9c684 11733{
11734 tree fntype = TREE_TYPE (current_function_decl);
c2f47e15 11735 int nargs = call_expr_nargs (exp);
11736 tree arg;
4ee9c684 11737
11738 if (TYPE_ARG_TYPES (fntype) == 0
11739 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
11740 == void_type_node))
743b0c6a 11741 {
11742 error ("%<va_start%> used in function with fixed args");
11743 return true;
11744 }
c2f47e15 11745
11746 if (va_start_p)
79012a9d 11747 {
c2f47e15 11748 if (va_start_p && (nargs != 2))
11749 {
11750 error ("wrong number of arguments to function %<va_start%>");
11751 return true;
11752 }
11753 arg = CALL_EXPR_ARG (exp, 1);
79012a9d 11754 }
11755 /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
11756 when we checked the arguments and if needed issued a warning. */
c2f47e15 11757 else
4ee9c684 11758 {
c2f47e15 11759 if (nargs == 0)
11760 {
11761 /* Evidently an out of date version of <stdarg.h>; can't validate
11762 va_start's second argument, but can still work as intended. */
11763 warning (0, "%<__builtin_next_arg%> called without an argument");
11764 return true;
11765 }
11766 else if (nargs > 1)
a0c938f0 11767 {
c2f47e15 11768 error ("wrong number of arguments to function %<__builtin_next_arg%>");
a0c938f0 11769 return true;
11770 }
c2f47e15 11771 arg = CALL_EXPR_ARG (exp, 0);
11772 }
11773
a8dd994c 11774 if (TREE_CODE (arg) == SSA_NAME)
11775 arg = SSA_NAME_VAR (arg);
11776
c2f47e15 11777 /* We destructively modify the call to be __builtin_va_start (ap, 0)
11778 or __builtin_next_arg (0) the first time we see it, after checking
11779 the arguments and if needed issuing a warning. */
11780 if (!integer_zerop (arg))
11781 {
11782 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
79012a9d 11783
4ee9c684 11784 /* Strip off all nops for the sake of the comparison. This
11785 is not quite the same as STRIP_NOPS. It does more.
11786 We must also strip off INDIRECT_EXPR for C++ reference
11787 parameters. */
72dd6141 11788 while (CONVERT_EXPR_P (arg)
4ee9c684 11789 || TREE_CODE (arg) == INDIRECT_REF)
11790 arg = TREE_OPERAND (arg, 0);
11791 if (arg != last_parm)
a0c938f0 11792 {
b08cf617 11793 /* FIXME: Sometimes with the tree optimizers we can get the
11794 not the last argument even though the user used the last
11795 argument. We just warn and set the arg to be the last
11796 argument so that we will get wrong-code because of
11797 it. */
c3ceba8e 11798 warning (0, "second parameter of %<va_start%> not last named argument");
743b0c6a 11799 }
24158ad7 11800
11801 /* Undefined by C99 7.15.1.4p4 (va_start):
11802 "If the parameter parmN is declared with the register storage
11803 class, with a function or array type, or with a type that is
11804 not compatible with the type that results after application of
11805 the default argument promotions, the behavior is undefined."
11806 */
11807 else if (DECL_REGISTER (arg))
11808 warning (0, "undefined behaviour when second parameter of "
11809 "%<va_start%> is declared with %<register%> storage");
11810
79012a9d 11811 /* We want to verify the second parameter just once before the tree
a0c938f0 11812 optimizers are run and then avoid keeping it in the tree,
11813 as otherwise we could warn even for correct code like:
11814 void foo (int i, ...)
11815 { va_list ap; i++; va_start (ap, i); va_end (ap); } */
c2f47e15 11816 if (va_start_p)
11817 CALL_EXPR_ARG (exp, 1) = integer_zero_node;
11818 else
11819 CALL_EXPR_ARG (exp, 0) = integer_zero_node;
743b0c6a 11820 }
11821 return false;
4ee9c684 11822}
11823
11824
c2f47e15 11825/* Simplify a call to the sprintf builtin with arguments DEST, FMT, and ORIG.
11826 ORIG may be null if this is a 2-argument call. We don't attempt to
11827 simplify calls with more than 3 arguments.
4ee9c684 11828
c2f47e15 11829 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11830 simplified form of the call as a tree. If IGNORED is true, it means that
11831 the caller does not use the returned value of the function. */
11832
11833static tree
389dd41b 11834fold_builtin_sprintf (location_t loc, tree dest, tree fmt,
11835 tree orig, int ignored)
4ee9c684 11836{
c2f47e15 11837 tree call, retval;
4ee9c684 11838 const char *fmt_str = NULL;
11839
11840 /* Verify the required arguments in the original call. We deal with two
11841 types of sprintf() calls: 'sprintf (str, fmt)' and
11842 'sprintf (dest, "%s", orig)'. */
c2f47e15 11843 if (!validate_arg (dest, POINTER_TYPE)
11844 || !validate_arg (fmt, POINTER_TYPE))
11845 return NULL_TREE;
11846 if (orig && !validate_arg (orig, POINTER_TYPE))
4ee9c684 11847 return NULL_TREE;
4ee9c684 11848
11849 /* Check whether the format is a literal string constant. */
11850 fmt_str = c_getstr (fmt);
11851 if (fmt_str == NULL)
11852 return NULL_TREE;
11853
11854 call = NULL_TREE;
11855 retval = NULL_TREE;
11856
d4473c84 11857 if (!init_target_chars ())
c2f47e15 11858 return NULL_TREE;
99eabcc1 11859
4ee9c684 11860 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 11861 if (strchr (fmt_str, target_percent) == NULL)
4ee9c684 11862 {
11863 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11864
11865 if (!fn)
11866 return NULL_TREE;
11867
72dfb3f2 11868 /* Don't optimize sprintf (buf, "abc", ptr++). */
c2f47e15 11869 if (orig)
72dfb3f2 11870 return NULL_TREE;
11871
4ee9c684 11872 /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
11873 'format' is known to contain no % formats. */
389dd41b 11874 call = build_call_expr_loc (loc, fn, 2, dest, fmt);
4ee9c684 11875 if (!ignored)
7016c612 11876 retval = build_int_cst (NULL_TREE, strlen (fmt_str));
4ee9c684 11877 }
11878
11879 /* If the format is "%s", use strcpy if the result isn't used. */
99eabcc1 11880 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
4ee9c684 11881 {
c2f47e15 11882 tree fn;
4ee9c684 11883 fn = implicit_built_in_decls[BUILT_IN_STRCPY];
11884
11885 if (!fn)
11886 return NULL_TREE;
11887
72dfb3f2 11888 /* Don't crash on sprintf (str1, "%s"). */
c2f47e15 11889 if (!orig)
72dfb3f2 11890 return NULL_TREE;
11891
4ee9c684 11892 /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2). */
4ee9c684 11893 if (!ignored)
11894 {
11895 retval = c_strlen (orig, 1);
11896 if (!retval || TREE_CODE (retval) != INTEGER_CST)
11897 return NULL_TREE;
11898 }
389dd41b 11899 call = build_call_expr_loc (loc, fn, 2, dest, orig);
4ee9c684 11900 }
11901
11902 if (call && retval)
11903 {
389dd41b 11904 retval = fold_convert_loc
11905 (loc, TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])),
4ee9c684 11906 retval);
05abc81b 11907 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
4ee9c684 11908 }
11909 else
11910 return call;
11911}
0a39fd54 11912
c2f47e15 11913/* Expand a call EXP to __builtin_object_size. */
0a39fd54 11914
11915rtx
11916expand_builtin_object_size (tree exp)
11917{
11918 tree ost;
11919 int object_size_type;
11920 tree fndecl = get_callee_fndecl (exp);
0a39fd54 11921
c2f47e15 11922 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
0a39fd54 11923 {
b8c23db3 11924 error ("%Kfirst argument of %D must be a pointer, second integer constant",
11925 exp, fndecl);
0a39fd54 11926 expand_builtin_trap ();
11927 return const0_rtx;
11928 }
11929
c2f47e15 11930 ost = CALL_EXPR_ARG (exp, 1);
0a39fd54 11931 STRIP_NOPS (ost);
11932
11933 if (TREE_CODE (ost) != INTEGER_CST
11934 || tree_int_cst_sgn (ost) < 0
11935 || compare_tree_int (ost, 3) > 0)
11936 {
b8c23db3 11937 error ("%Klast argument of %D is not integer constant between 0 and 3",
11938 exp, fndecl);
0a39fd54 11939 expand_builtin_trap ();
11940 return const0_rtx;
11941 }
11942
11943 object_size_type = tree_low_cst (ost, 0);
11944
11945 return object_size_type < 2 ? constm1_rtx : const0_rtx;
11946}
11947
11948/* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
11949 FCODE is the BUILT_IN_* to use.
c2f47e15 11950 Return NULL_RTX if we failed; the caller should emit a normal call,
0a39fd54 11951 otherwise try to get the result in TARGET, if convenient (and in
11952 mode MODE if that's convenient). */
11953
11954static rtx
11955expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
11956 enum built_in_function fcode)
11957{
0a39fd54 11958 tree dest, src, len, size;
11959
c2f47e15 11960 if (!validate_arglist (exp,
0a39fd54 11961 POINTER_TYPE,
11962 fcode == BUILT_IN_MEMSET_CHK
11963 ? INTEGER_TYPE : POINTER_TYPE,
11964 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
c2f47e15 11965 return NULL_RTX;
0a39fd54 11966
c2f47e15 11967 dest = CALL_EXPR_ARG (exp, 0);
11968 src = CALL_EXPR_ARG (exp, 1);
11969 len = CALL_EXPR_ARG (exp, 2);
11970 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 11971
11972 if (! host_integerp (size, 1))
c2f47e15 11973 return NULL_RTX;
0a39fd54 11974
11975 if (host_integerp (len, 1) || integer_all_onesp (size))
11976 {
11977 tree fn;
11978
11979 if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
11980 {
b430e8d9 11981 warning_at (tree_nonartificial_location (exp),
11982 0, "%Kcall to %D will always overflow destination buffer",
11983 exp, get_callee_fndecl (exp));
c2f47e15 11984 return NULL_RTX;
0a39fd54 11985 }
11986
0a39fd54 11987 fn = NULL_TREE;
11988 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
11989 mem{cpy,pcpy,move,set} is available. */
11990 switch (fcode)
11991 {
11992 case BUILT_IN_MEMCPY_CHK:
11993 fn = built_in_decls[BUILT_IN_MEMCPY];
11994 break;
11995 case BUILT_IN_MEMPCPY_CHK:
11996 fn = built_in_decls[BUILT_IN_MEMPCPY];
11997 break;
11998 case BUILT_IN_MEMMOVE_CHK:
11999 fn = built_in_decls[BUILT_IN_MEMMOVE];
12000 break;
12001 case BUILT_IN_MEMSET_CHK:
12002 fn = built_in_decls[BUILT_IN_MEMSET];
12003 break;
12004 default:
12005 break;
12006 }
12007
12008 if (! fn)
c2f47e15 12009 return NULL_RTX;
0a39fd54 12010
a65c4d64 12011 fn = build_call_nofold (fn, 3, dest, src, len);
12012 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
12013 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0a39fd54 12014 return expand_expr (fn, target, mode, EXPAND_NORMAL);
12015 }
12016 else if (fcode == BUILT_IN_MEMSET_CHK)
c2f47e15 12017 return NULL_RTX;
0a39fd54 12018 else
12019 {
12020 unsigned int dest_align
12021 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
12022
12023 /* If DEST is not a pointer type, call the normal function. */
12024 if (dest_align == 0)
c2f47e15 12025 return NULL_RTX;
0a39fd54 12026
12027 /* If SRC and DEST are the same (and not volatile), do nothing. */
12028 if (operand_equal_p (src, dest, 0))
12029 {
12030 tree expr;
12031
12032 if (fcode != BUILT_IN_MEMPCPY_CHK)
12033 {
12034 /* Evaluate and ignore LEN in case it has side-effects. */
12035 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
12036 return expand_expr (dest, target, mode, EXPAND_NORMAL);
12037 }
12038
0de36bdb 12039 expr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len);
0a39fd54 12040 return expand_expr (expr, target, mode, EXPAND_NORMAL);
12041 }
12042
12043 /* __memmove_chk special case. */
12044 if (fcode == BUILT_IN_MEMMOVE_CHK)
12045 {
12046 unsigned int src_align
12047 = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
12048
12049 if (src_align == 0)
c2f47e15 12050 return NULL_RTX;
0a39fd54 12051
12052 /* If src is categorized for a readonly section we can use
12053 normal __memcpy_chk. */
12054 if (readonly_data_expr (src))
12055 {
12056 tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
12057 if (!fn)
c2f47e15 12058 return NULL_RTX;
a65c4d64 12059 fn = build_call_nofold (fn, 4, dest, src, len, size);
12060 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
12061 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0a39fd54 12062 return expand_expr (fn, target, mode, EXPAND_NORMAL);
12063 }
12064 }
c2f47e15 12065 return NULL_RTX;
0a39fd54 12066 }
12067}
12068
12069/* Emit warning if a buffer overflow is detected at compile time. */
12070
12071static void
12072maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
12073{
c2f47e15 12074 int is_strlen = 0;
0a39fd54 12075 tree len, size;
b430e8d9 12076 location_t loc = tree_nonartificial_location (exp);
0a39fd54 12077
12078 switch (fcode)
12079 {
12080 case BUILT_IN_STRCPY_CHK:
12081 case BUILT_IN_STPCPY_CHK:
12082 /* For __strcat_chk the warning will be emitted only if overflowing
12083 by at least strlen (dest) + 1 bytes. */
12084 case BUILT_IN_STRCAT_CHK:
c2f47e15 12085 len = CALL_EXPR_ARG (exp, 1);
12086 size = CALL_EXPR_ARG (exp, 2);
0a39fd54 12087 is_strlen = 1;
12088 break;
b356dfef 12089 case BUILT_IN_STRNCAT_CHK:
0a39fd54 12090 case BUILT_IN_STRNCPY_CHK:
c2f47e15 12091 len = CALL_EXPR_ARG (exp, 2);
12092 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 12093 break;
12094 case BUILT_IN_SNPRINTF_CHK:
12095 case BUILT_IN_VSNPRINTF_CHK:
c2f47e15 12096 len = CALL_EXPR_ARG (exp, 1);
12097 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 12098 break;
12099 default:
12100 gcc_unreachable ();
12101 }
12102
0a39fd54 12103 if (!len || !size)
12104 return;
12105
0a39fd54 12106 if (! host_integerp (size, 1) || integer_all_onesp (size))
12107 return;
12108
12109 if (is_strlen)
12110 {
12111 len = c_strlen (len, 1);
12112 if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
12113 return;
12114 }
b356dfef 12115 else if (fcode == BUILT_IN_STRNCAT_CHK)
12116 {
c2f47e15 12117 tree src = CALL_EXPR_ARG (exp, 1);
b356dfef 12118 if (! src || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
12119 return;
12120 src = c_strlen (src, 1);
12121 if (! src || ! host_integerp (src, 1))
12122 {
b430e8d9 12123 warning_at (loc, 0, "%Kcall to %D might overflow destination buffer",
12124 exp, get_callee_fndecl (exp));
b356dfef 12125 return;
12126 }
12127 else if (tree_int_cst_lt (src, size))
12128 return;
12129 }
0a39fd54 12130 else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
12131 return;
12132
b430e8d9 12133 warning_at (loc, 0, "%Kcall to %D will always overflow destination buffer",
12134 exp, get_callee_fndecl (exp));
0a39fd54 12135}
12136
12137/* Emit warning if a buffer overflow is detected at compile time
12138 in __sprintf_chk/__vsprintf_chk calls. */
12139
12140static void
12141maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
12142{
0a39fd54 12143 tree dest, size, len, fmt, flag;
12144 const char *fmt_str;
c2f47e15 12145 int nargs = call_expr_nargs (exp);
0a39fd54 12146
12147 /* Verify the required arguments in the original call. */
c2f47e15 12148
12149 if (nargs < 4)
0a39fd54 12150 return;
c2f47e15 12151 dest = CALL_EXPR_ARG (exp, 0);
12152 flag = CALL_EXPR_ARG (exp, 1);
12153 size = CALL_EXPR_ARG (exp, 2);
12154 fmt = CALL_EXPR_ARG (exp, 3);
0a39fd54 12155
12156 if (! host_integerp (size, 1) || integer_all_onesp (size))
12157 return;
12158
12159 /* Check whether the format is a literal string constant. */
12160 fmt_str = c_getstr (fmt);
12161 if (fmt_str == NULL)
12162 return;
12163
d4473c84 12164 if (!init_target_chars ())
99eabcc1 12165 return;
12166
0a39fd54 12167 /* If the format doesn't contain % args or %%, we know its size. */
99eabcc1 12168 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 12169 len = build_int_cstu (size_type_node, strlen (fmt_str));
12170 /* If the format is "%s" and first ... argument is a string literal,
12171 we know it too. */
c2f47e15 12172 else if (fcode == BUILT_IN_SPRINTF_CHK
12173 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12174 {
12175 tree arg;
12176
c2f47e15 12177 if (nargs < 5)
0a39fd54 12178 return;
c2f47e15 12179 arg = CALL_EXPR_ARG (exp, 4);
0a39fd54 12180 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
12181 return;
12182
12183 len = c_strlen (arg, 1);
12184 if (!len || ! host_integerp (len, 1))
12185 return;
12186 }
12187 else
12188 return;
12189
12190 if (! tree_int_cst_lt (len, size))
b430e8d9 12191 warning_at (tree_nonartificial_location (exp),
12192 0, "%Kcall to %D will always overflow destination buffer",
12193 exp, get_callee_fndecl (exp));
0a39fd54 12194}
12195
2c281b15 12196/* Emit warning if a free is called with address of a variable. */
12197
12198static void
12199maybe_emit_free_warning (tree exp)
12200{
12201 tree arg = CALL_EXPR_ARG (exp, 0);
12202
12203 STRIP_NOPS (arg);
12204 if (TREE_CODE (arg) != ADDR_EXPR)
12205 return;
12206
12207 arg = get_base_address (TREE_OPERAND (arg, 0));
12208 if (arg == NULL || INDIRECT_REF_P (arg))
12209 return;
12210
12211 if (SSA_VAR_P (arg))
b430e8d9 12212 warning_at (tree_nonartificial_location (exp),
12213 0, "%Kattempt to free a non-heap object %qD", exp, arg);
2c281b15 12214 else
b430e8d9 12215 warning_at (tree_nonartificial_location (exp),
12216 0, "%Kattempt to free a non-heap object", exp);
2c281b15 12217}
12218
c2f47e15 12219/* Fold a call to __builtin_object_size with arguments PTR and OST,
12220 if possible. */
0a39fd54 12221
12222tree
c2f47e15 12223fold_builtin_object_size (tree ptr, tree ost)
0a39fd54 12224{
c2f47e15 12225 tree ret = NULL_TREE;
0a39fd54 12226 int object_size_type;
12227
c2f47e15 12228 if (!validate_arg (ptr, POINTER_TYPE)
12229 || !validate_arg (ost, INTEGER_TYPE))
12230 return NULL_TREE;
0a39fd54 12231
0a39fd54 12232 STRIP_NOPS (ost);
12233
12234 if (TREE_CODE (ost) != INTEGER_CST
12235 || tree_int_cst_sgn (ost) < 0
12236 || compare_tree_int (ost, 3) > 0)
c2f47e15 12237 return NULL_TREE;
0a39fd54 12238
12239 object_size_type = tree_low_cst (ost, 0);
12240
12241 /* __builtin_object_size doesn't evaluate side-effects in its arguments;
12242 if there are any side-effects, it returns (size_t) -1 for types 0 and 1
12243 and (size_t) 0 for types 2 and 3. */
12244 if (TREE_SIDE_EFFECTS (ptr))
697bbc3f 12245 return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
0a39fd54 12246
12247 if (TREE_CODE (ptr) == ADDR_EXPR)
12248 ret = build_int_cstu (size_type_node,
697bbc3f 12249 compute_builtin_object_size (ptr, object_size_type));
0a39fd54 12250
12251 else if (TREE_CODE (ptr) == SSA_NAME)
12252 {
12253 unsigned HOST_WIDE_INT bytes;
12254
12255 /* If object size is not known yet, delay folding until
12256 later. Maybe subsequent passes will help determining
12257 it. */
12258 bytes = compute_builtin_object_size (ptr, object_size_type);
12259 if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2
12260 ? -1 : 0))
12261 ret = build_int_cstu (size_type_node, bytes);
12262 }
12263
12264 if (ret)
12265 {
697bbc3f 12266 unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (ret);
12267 HOST_WIDE_INT high = TREE_INT_CST_HIGH (ret);
12268 if (fit_double_type (low, high, &low, &high, TREE_TYPE (ret)))
12269 ret = NULL_TREE;
0a39fd54 12270 }
12271
12272 return ret;
12273}
12274
12275/* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
c2f47e15 12276 DEST, SRC, LEN, and SIZE are the arguments to the call.
0a39fd54 12277 IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_*
12278 code of the builtin. If MAXLEN is not NULL, it is maximum length
12279 passed as third argument. */
12280
12281tree
389dd41b 12282fold_builtin_memory_chk (location_t loc, tree fndecl,
c2f47e15 12283 tree dest, tree src, tree len, tree size,
12284 tree maxlen, bool ignore,
0a39fd54 12285 enum built_in_function fcode)
12286{
c2f47e15 12287 tree fn;
0a39fd54 12288
c2f47e15 12289 if (!validate_arg (dest, POINTER_TYPE)
12290 || !validate_arg (src,
12291 (fcode == BUILT_IN_MEMSET_CHK
12292 ? INTEGER_TYPE : POINTER_TYPE))
12293 || !validate_arg (len, INTEGER_TYPE)
12294 || !validate_arg (size, INTEGER_TYPE))
12295 return NULL_TREE;
0a39fd54 12296
12297 /* If SRC and DEST are the same (and not volatile), return DEST
12298 (resp. DEST+LEN for __mempcpy_chk). */
12299 if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
12300 {
12301 if (fcode != BUILT_IN_MEMPCPY_CHK)
389dd41b 12302 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
12303 dest, len);
0a39fd54 12304 else
12305 {
389dd41b 12306 tree temp = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (dest),
12307 dest, len);
12308 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), temp);
0a39fd54 12309 }
12310 }
12311
12312 if (! host_integerp (size, 1))
c2f47e15 12313 return NULL_TREE;
0a39fd54 12314
12315 if (! integer_all_onesp (size))
12316 {
12317 if (! host_integerp (len, 1))
12318 {
12319 /* If LEN is not constant, try MAXLEN too.
12320 For MAXLEN only allow optimizing into non-_ocs function
12321 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12322 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
12323 {
12324 if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
12325 {
12326 /* (void) __mempcpy_chk () can be optimized into
12327 (void) __memcpy_chk (). */
12328 fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
12329 if (!fn)
c2f47e15 12330 return NULL_TREE;
0a39fd54 12331
389dd41b 12332 return build_call_expr_loc (loc, fn, 4, dest, src, len, size);
0a39fd54 12333 }
c2f47e15 12334 return NULL_TREE;
0a39fd54 12335 }
0a39fd54 12336 }
ad89623c 12337 else
12338 maxlen = len;
0a39fd54 12339
ad89623c 12340 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12341 return NULL_TREE;
0a39fd54 12342 }
12343
0a39fd54 12344 fn = NULL_TREE;
12345 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
12346 mem{cpy,pcpy,move,set} is available. */
12347 switch (fcode)
12348 {
12349 case BUILT_IN_MEMCPY_CHK:
12350 fn = built_in_decls[BUILT_IN_MEMCPY];
12351 break;
12352 case BUILT_IN_MEMPCPY_CHK:
12353 fn = built_in_decls[BUILT_IN_MEMPCPY];
12354 break;
12355 case BUILT_IN_MEMMOVE_CHK:
12356 fn = built_in_decls[BUILT_IN_MEMMOVE];
12357 break;
12358 case BUILT_IN_MEMSET_CHK:
12359 fn = built_in_decls[BUILT_IN_MEMSET];
12360 break;
12361 default:
12362 break;
12363 }
12364
12365 if (!fn)
c2f47e15 12366 return NULL_TREE;
0a39fd54 12367
389dd41b 12368 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12369}
12370
12371/* Fold a call to the __st[rp]cpy_chk builtin.
c2f47e15 12372 DEST, SRC, and SIZE are the arguments to the call.
12373 IGNORE is true if return value can be ignored. FCODE is the BUILT_IN_*
0a39fd54 12374 code of the builtin. If MAXLEN is not NULL, it is maximum length of
12375 strings passed as second argument. */
12376
12377tree
389dd41b 12378fold_builtin_stxcpy_chk (location_t loc, tree fndecl, tree dest,
12379 tree src, tree size,
c2f47e15 12380 tree maxlen, bool ignore,
0a39fd54 12381 enum built_in_function fcode)
12382{
c2f47e15 12383 tree len, fn;
0a39fd54 12384
c2f47e15 12385 if (!validate_arg (dest, POINTER_TYPE)
12386 || !validate_arg (src, POINTER_TYPE)
12387 || !validate_arg (size, INTEGER_TYPE))
12388 return NULL_TREE;
0a39fd54 12389
12390 /* If SRC and DEST are the same (and not volatile), return DEST. */
12391 if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
389dd41b 12392 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
a0c938f0 12393
0a39fd54 12394 if (! host_integerp (size, 1))
c2f47e15 12395 return NULL_TREE;
0a39fd54 12396
12397 if (! integer_all_onesp (size))
12398 {
12399 len = c_strlen (src, 1);
12400 if (! len || ! host_integerp (len, 1))
12401 {
12402 /* If LEN is not constant, try MAXLEN too.
12403 For MAXLEN only allow optimizing into non-_ocs function
12404 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12405 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
12406 {
12407 if (fcode == BUILT_IN_STPCPY_CHK)
12408 {
12409 if (! ignore)
c2f47e15 12410 return NULL_TREE;
0a39fd54 12411
12412 /* If return value of __stpcpy_chk is ignored,
12413 optimize into __strcpy_chk. */
12414 fn = built_in_decls[BUILT_IN_STRCPY_CHK];
12415 if (!fn)
c2f47e15 12416 return NULL_TREE;
0a39fd54 12417
389dd41b 12418 return build_call_expr_loc (loc, fn, 3, dest, src, size);
0a39fd54 12419 }
12420
12421 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 12422 return NULL_TREE;
0a39fd54 12423
12424 /* If c_strlen returned something, but not a constant,
12425 transform __strcpy_chk into __memcpy_chk. */
12426 fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
12427 if (!fn)
c2f47e15 12428 return NULL_TREE;
0a39fd54 12429
389dd41b 12430 len = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
12431 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
12432 build_call_expr_loc (loc, fn, 4,
12433 dest, src, len, size));
0a39fd54 12434 }
0a39fd54 12435 }
ad89623c 12436 else
12437 maxlen = len;
12438
12439 if (! tree_int_cst_lt (maxlen, size))
c2f47e15 12440 return NULL_TREE;
0a39fd54 12441 }
12442
0a39fd54 12443 /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available. */
12444 fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK
12445 ? BUILT_IN_STPCPY : BUILT_IN_STRCPY];
12446 if (!fn)
c2f47e15 12447 return NULL_TREE;
0a39fd54 12448
389dd41b 12449 return build_call_expr_loc (loc, fn, 2, dest, src);
0a39fd54 12450}
12451
c2f47e15 12452/* Fold a call to the __strncpy_chk builtin. DEST, SRC, LEN, and SIZE
12453 are the arguments to the call. If MAXLEN is not NULL, it is maximum
12454 length passed as third argument. */
0a39fd54 12455
12456tree
389dd41b 12457fold_builtin_strncpy_chk (location_t loc, tree dest, tree src,
12458 tree len, tree size, tree maxlen)
0a39fd54 12459{
c2f47e15 12460 tree fn;
0a39fd54 12461
c2f47e15 12462 if (!validate_arg (dest, POINTER_TYPE)
12463 || !validate_arg (src, POINTER_TYPE)
12464 || !validate_arg (len, INTEGER_TYPE)
12465 || !validate_arg (size, INTEGER_TYPE))
12466 return NULL_TREE;
0a39fd54 12467
12468 if (! host_integerp (size, 1))
c2f47e15 12469 return NULL_TREE;
0a39fd54 12470
12471 if (! integer_all_onesp (size))
12472 {
12473 if (! host_integerp (len, 1))
12474 {
12475 /* If LEN is not constant, try MAXLEN too.
12476 For MAXLEN only allow optimizing into non-_ocs function
12477 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12478 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 12479 return NULL_TREE;
0a39fd54 12480 }
ad89623c 12481 else
12482 maxlen = len;
0a39fd54 12483
ad89623c 12484 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12485 return NULL_TREE;
0a39fd54 12486 }
12487
0a39fd54 12488 /* If __builtin_strncpy_chk is used, assume strncpy is available. */
12489 fn = built_in_decls[BUILT_IN_STRNCPY];
12490 if (!fn)
c2f47e15 12491 return NULL_TREE;
0a39fd54 12492
389dd41b 12493 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12494}
12495
c2f47e15 12496/* Fold a call to the __strcat_chk builtin FNDECL. DEST, SRC, and SIZE
12497 are the arguments to the call. */
0a39fd54 12498
12499static tree
389dd41b 12500fold_builtin_strcat_chk (location_t loc, tree fndecl, tree dest,
12501 tree src, tree size)
0a39fd54 12502{
c2f47e15 12503 tree fn;
0a39fd54 12504 const char *p;
12505
c2f47e15 12506 if (!validate_arg (dest, POINTER_TYPE)
12507 || !validate_arg (src, POINTER_TYPE)
12508 || !validate_arg (size, INTEGER_TYPE))
12509 return NULL_TREE;
0a39fd54 12510
12511 p = c_getstr (src);
12512 /* If the SRC parameter is "", return DEST. */
12513 if (p && *p == '\0')
389dd41b 12514 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
0a39fd54 12515
12516 if (! host_integerp (size, 1) || ! integer_all_onesp (size))
c2f47e15 12517 return NULL_TREE;
0a39fd54 12518
12519 /* If __builtin_strcat_chk is used, assume strcat is available. */
12520 fn = built_in_decls[BUILT_IN_STRCAT];
12521 if (!fn)
c2f47e15 12522 return NULL_TREE;
0a39fd54 12523
389dd41b 12524 return build_call_expr_loc (loc, fn, 2, dest, src);
0a39fd54 12525}
12526
c2f47e15 12527/* Fold a call to the __strncat_chk builtin with arguments DEST, SRC,
12528 LEN, and SIZE. */
0a39fd54 12529
12530static tree
389dd41b 12531fold_builtin_strncat_chk (location_t loc, tree fndecl,
c2f47e15 12532 tree dest, tree src, tree len, tree size)
0a39fd54 12533{
c2f47e15 12534 tree fn;
0a39fd54 12535 const char *p;
12536
c2f47e15 12537 if (!validate_arg (dest, POINTER_TYPE)
12538 || !validate_arg (src, POINTER_TYPE)
12539 || !validate_arg (size, INTEGER_TYPE)
12540 || !validate_arg (size, INTEGER_TYPE))
12541 return NULL_TREE;
0a39fd54 12542
12543 p = c_getstr (src);
12544 /* If the SRC parameter is "" or if LEN is 0, return DEST. */
12545 if (p && *p == '\0')
389dd41b 12546 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
0a39fd54 12547 else if (integer_zerop (len))
389dd41b 12548 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
0a39fd54 12549
12550 if (! host_integerp (size, 1))
c2f47e15 12551 return NULL_TREE;
0a39fd54 12552
12553 if (! integer_all_onesp (size))
12554 {
12555 tree src_len = c_strlen (src, 1);
12556 if (src_len
12557 && host_integerp (src_len, 1)
12558 && host_integerp (len, 1)
12559 && ! tree_int_cst_lt (len, src_len))
12560 {
12561 /* If LEN >= strlen (SRC), optimize into __strcat_chk. */
12562 fn = built_in_decls[BUILT_IN_STRCAT_CHK];
12563 if (!fn)
c2f47e15 12564 return NULL_TREE;
0a39fd54 12565
389dd41b 12566 return build_call_expr_loc (loc, fn, 3, dest, src, size);
0a39fd54 12567 }
c2f47e15 12568 return NULL_TREE;
0a39fd54 12569 }
12570
0a39fd54 12571 /* If __builtin_strncat_chk is used, assume strncat is available. */
12572 fn = built_in_decls[BUILT_IN_STRNCAT];
12573 if (!fn)
c2f47e15 12574 return NULL_TREE;
0a39fd54 12575
389dd41b 12576 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12577}
12578
c2f47e15 12579/* Fold a call EXP to __{,v}sprintf_chk. Return NULL_TREE if
0a39fd54 12580 a normal call should be emitted rather than expanding the function
12581 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
12582
12583static tree
389dd41b 12584fold_builtin_sprintf_chk (location_t loc, tree exp,
12585 enum built_in_function fcode)
0a39fd54 12586{
12587 tree dest, size, len, fn, fmt, flag;
12588 const char *fmt_str;
c2f47e15 12589 int nargs = call_expr_nargs (exp);
0a39fd54 12590
12591 /* Verify the required arguments in the original call. */
c2f47e15 12592 if (nargs < 4)
12593 return NULL_TREE;
12594 dest = CALL_EXPR_ARG (exp, 0);
12595 if (!validate_arg (dest, POINTER_TYPE))
12596 return NULL_TREE;
12597 flag = CALL_EXPR_ARG (exp, 1);
12598 if (!validate_arg (flag, INTEGER_TYPE))
12599 return NULL_TREE;
12600 size = CALL_EXPR_ARG (exp, 2);
12601 if (!validate_arg (size, INTEGER_TYPE))
12602 return NULL_TREE;
12603 fmt = CALL_EXPR_ARG (exp, 3);
12604 if (!validate_arg (fmt, POINTER_TYPE))
12605 return NULL_TREE;
0a39fd54 12606
12607 if (! host_integerp (size, 1))
c2f47e15 12608 return NULL_TREE;
0a39fd54 12609
12610 len = NULL_TREE;
12611
d4473c84 12612 if (!init_target_chars ())
c2f47e15 12613 return NULL_TREE;
99eabcc1 12614
0a39fd54 12615 /* Check whether the format is a literal string constant. */
12616 fmt_str = c_getstr (fmt);
12617 if (fmt_str != NULL)
12618 {
12619 /* If the format doesn't contain % args or %%, we know the size. */
99eabcc1 12620 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 12621 {
c2f47e15 12622 if (fcode != BUILT_IN_SPRINTF_CHK || nargs == 4)
0a39fd54 12623 len = build_int_cstu (size_type_node, strlen (fmt_str));
12624 }
12625 /* If the format is "%s" and first ... argument is a string literal,
12626 we know the size too. */
c2f47e15 12627 else if (fcode == BUILT_IN_SPRINTF_CHK
12628 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12629 {
12630 tree arg;
12631
c2f47e15 12632 if (nargs == 5)
0a39fd54 12633 {
c2f47e15 12634 arg = CALL_EXPR_ARG (exp, 4);
12635 if (validate_arg (arg, POINTER_TYPE))
0a39fd54 12636 {
12637 len = c_strlen (arg, 1);
12638 if (! len || ! host_integerp (len, 1))
12639 len = NULL_TREE;
12640 }
12641 }
12642 }
12643 }
12644
12645 if (! integer_all_onesp (size))
12646 {
12647 if (! len || ! tree_int_cst_lt (len, size))
c2f47e15 12648 return NULL_TREE;
0a39fd54 12649 }
12650
12651 /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
12652 or if format doesn't contain % chars or is "%s". */
12653 if (! integer_zerop (flag))
12654 {
12655 if (fmt_str == NULL)
c2f47e15 12656 return NULL_TREE;
12657 if (strchr (fmt_str, target_percent) != NULL
12658 && strcmp (fmt_str, target_percent_s))
12659 return NULL_TREE;
0a39fd54 12660 }
12661
0a39fd54 12662 /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
12663 fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
12664 ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
12665 if (!fn)
c2f47e15 12666 return NULL_TREE;
0a39fd54 12667
389dd41b 12668 return rewrite_call_expr (loc, exp, 4, fn, 2, dest, fmt);
0a39fd54 12669}
12670
c2f47e15 12671/* Fold a call EXP to {,v}snprintf. Return NULL_TREE if
0a39fd54 12672 a normal call should be emitted rather than expanding the function
12673 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
12674 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
12675 passed as second argument. */
12676
12677tree
389dd41b 12678fold_builtin_snprintf_chk (location_t loc, tree exp, tree maxlen,
0a39fd54 12679 enum built_in_function fcode)
12680{
12681 tree dest, size, len, fn, fmt, flag;
12682 const char *fmt_str;
12683
12684 /* Verify the required arguments in the original call. */
c2f47e15 12685 if (call_expr_nargs (exp) < 5)
12686 return NULL_TREE;
12687 dest = CALL_EXPR_ARG (exp, 0);
12688 if (!validate_arg (dest, POINTER_TYPE))
12689 return NULL_TREE;
12690 len = CALL_EXPR_ARG (exp, 1);
12691 if (!validate_arg (len, INTEGER_TYPE))
12692 return NULL_TREE;
12693 flag = CALL_EXPR_ARG (exp, 2);
12694 if (!validate_arg (flag, INTEGER_TYPE))
12695 return NULL_TREE;
12696 size = CALL_EXPR_ARG (exp, 3);
12697 if (!validate_arg (size, INTEGER_TYPE))
12698 return NULL_TREE;
12699 fmt = CALL_EXPR_ARG (exp, 4);
12700 if (!validate_arg (fmt, POINTER_TYPE))
12701 return NULL_TREE;
0a39fd54 12702
12703 if (! host_integerp (size, 1))
c2f47e15 12704 return NULL_TREE;
0a39fd54 12705
12706 if (! integer_all_onesp (size))
12707 {
12708 if (! host_integerp (len, 1))
12709 {
12710 /* If LEN is not constant, try MAXLEN too.
12711 For MAXLEN only allow optimizing into non-_ocs function
12712 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12713 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 12714 return NULL_TREE;
0a39fd54 12715 }
ad89623c 12716 else
12717 maxlen = len;
0a39fd54 12718
ad89623c 12719 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12720 return NULL_TREE;
0a39fd54 12721 }
12722
d4473c84 12723 if (!init_target_chars ())
c2f47e15 12724 return NULL_TREE;
99eabcc1 12725
0a39fd54 12726 /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
12727 or if format doesn't contain % chars or is "%s". */
12728 if (! integer_zerop (flag))
12729 {
12730 fmt_str = c_getstr (fmt);
12731 if (fmt_str == NULL)
c2f47e15 12732 return NULL_TREE;
12733 if (strchr (fmt_str, target_percent) != NULL
12734 && strcmp (fmt_str, target_percent_s))
12735 return NULL_TREE;
0a39fd54 12736 }
12737
0a39fd54 12738 /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
12739 available. */
12740 fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
12741 ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
12742 if (!fn)
c2f47e15 12743 return NULL_TREE;
0a39fd54 12744
389dd41b 12745 return rewrite_call_expr (loc, exp, 5, fn, 3, dest, len, fmt);
0a39fd54 12746}
12747
12748/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 12749 FMT and ARG are the arguments to the call; we don't fold cases with
12750 more than 2 arguments, and ARG may be null if this is a 1-argument case.
0a39fd54 12751
c2f47e15 12752 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 12753 simplified form of the call as a tree. FCODE is the BUILT_IN_*
12754 code of the function to be simplified. */
12755
12756static tree
389dd41b 12757fold_builtin_printf (location_t loc, tree fndecl, tree fmt,
12758 tree arg, bool ignore,
0a39fd54 12759 enum built_in_function fcode)
12760{
c2f47e15 12761 tree fn_putchar, fn_puts, newarg, call = NULL_TREE;
0a39fd54 12762 const char *fmt_str = NULL;
12763
12764 /* If the return value is used, don't do the transformation. */
12765 if (! ignore)
c2f47e15 12766 return NULL_TREE;
0a39fd54 12767
12768 /* Verify the required arguments in the original call. */
c2f47e15 12769 if (!validate_arg (fmt, POINTER_TYPE))
12770 return NULL_TREE;
0a39fd54 12771
12772 /* Check whether the format is a literal string constant. */
12773 fmt_str = c_getstr (fmt);
12774 if (fmt_str == NULL)
12775 return NULL_TREE;
12776
12777 if (fcode == BUILT_IN_PRINTF_UNLOCKED)
12778 {
6d77ed92 12779 /* If we're using an unlocked function, assume the other
12780 unlocked functions exist explicitly. */
12781 fn_putchar = built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED];
12782 fn_puts = built_in_decls[BUILT_IN_PUTS_UNLOCKED];
0a39fd54 12783 }
12784 else
12785 {
12786 fn_putchar = implicit_built_in_decls[BUILT_IN_PUTCHAR];
12787 fn_puts = implicit_built_in_decls[BUILT_IN_PUTS];
12788 }
12789
d4473c84 12790 if (!init_target_chars ())
c2f47e15 12791 return NULL_TREE;
a0c938f0 12792
c2f47e15 12793 if (strcmp (fmt_str, target_percent_s) == 0
12794 || strchr (fmt_str, target_percent) == NULL)
0a39fd54 12795 {
12796 const char *str;
12797
99eabcc1 12798 if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12799 {
12800 if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 12801 return NULL_TREE;
0a39fd54 12802
c2f47e15 12803 if (!arg || !validate_arg (arg, POINTER_TYPE))
12804 return NULL_TREE;
0a39fd54 12805
c2f47e15 12806 str = c_getstr (arg);
0a39fd54 12807 if (str == NULL)
c2f47e15 12808 return NULL_TREE;
0a39fd54 12809 }
12810 else
12811 {
12812 /* The format specifier doesn't contain any '%' characters. */
12813 if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
c2f47e15 12814 && arg)
12815 return NULL_TREE;
0a39fd54 12816 str = fmt_str;
12817 }
12818
12819 /* If the string was "", printf does nothing. */
12820 if (str[0] == '\0')
12821 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
12822
12823 /* If the string has length of 1, call putchar. */
12824 if (str[1] == '\0')
12825 {
12826 /* Given printf("c"), (where c is any one character,)
12827 convert "c"[0] to an int and pass that to the replacement
12828 function. */
c2f47e15 12829 newarg = build_int_cst (NULL_TREE, str[0]);
12830 if (fn_putchar)
389dd41b 12831 call = build_call_expr_loc (loc, fn_putchar, 1, newarg);
0a39fd54 12832 }
12833 else
12834 {
12835 /* If the string was "string\n", call puts("string"). */
12836 size_t len = strlen (str);
99eabcc1 12837 if ((unsigned char)str[len - 1] == target_newline)
0a39fd54 12838 {
12839 /* Create a NUL-terminated string that's one char shorter
12840 than the original, stripping off the trailing '\n'. */
364c0c59 12841 char *newstr = XALLOCAVEC (char, len);
0a39fd54 12842 memcpy (newstr, str, len - 1);
12843 newstr[len - 1] = 0;
12844
c2f47e15 12845 newarg = build_string_literal (len, newstr);
12846 if (fn_puts)
389dd41b 12847 call = build_call_expr_loc (loc, fn_puts, 1, newarg);
0a39fd54 12848 }
12849 else
12850 /* We'd like to arrange to call fputs(string,stdout) here,
12851 but we need stdout and don't have a way to get it yet. */
c2f47e15 12852 return NULL_TREE;
0a39fd54 12853 }
12854 }
12855
12856 /* The other optimizations can be done only on the non-va_list variants. */
12857 else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 12858 return NULL_TREE;
0a39fd54 12859
12860 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
99eabcc1 12861 else if (strcmp (fmt_str, target_percent_s_newline) == 0)
0a39fd54 12862 {
c2f47e15 12863 if (!arg || !validate_arg (arg, POINTER_TYPE))
12864 return NULL_TREE;
12865 if (fn_puts)
389dd41b 12866 call = build_call_expr_loc (loc, fn_puts, 1, arg);
0a39fd54 12867 }
12868
12869 /* If the format specifier was "%c", call __builtin_putchar(arg). */
99eabcc1 12870 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 12871 {
c2f47e15 12872 if (!arg || !validate_arg (arg, INTEGER_TYPE))
12873 return NULL_TREE;
12874 if (fn_putchar)
389dd41b 12875 call = build_call_expr_loc (loc, fn_putchar, 1, arg);
0a39fd54 12876 }
12877
c2f47e15 12878 if (!call)
12879 return NULL_TREE;
0a39fd54 12880
389dd41b 12881 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
0a39fd54 12882}
12883
12884/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 12885 FP, FMT, and ARG are the arguments to the call. We don't fold calls with
12886 more than 3 arguments, and ARG may be null in the 2-argument case.
0a39fd54 12887
c2f47e15 12888 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 12889 simplified form of the call as a tree. FCODE is the BUILT_IN_*
12890 code of the function to be simplified. */
12891
12892static tree
389dd41b 12893fold_builtin_fprintf (location_t loc, tree fndecl, tree fp,
12894 tree fmt, tree arg, bool ignore,
0a39fd54 12895 enum built_in_function fcode)
12896{
c2f47e15 12897 tree fn_fputc, fn_fputs, call = NULL_TREE;
0a39fd54 12898 const char *fmt_str = NULL;
12899
12900 /* If the return value is used, don't do the transformation. */
12901 if (! ignore)
c2f47e15 12902 return NULL_TREE;
0a39fd54 12903
12904 /* Verify the required arguments in the original call. */
c2f47e15 12905 if (!validate_arg (fp, POINTER_TYPE))
12906 return NULL_TREE;
12907 if (!validate_arg (fmt, POINTER_TYPE))
12908 return NULL_TREE;
0a39fd54 12909
12910 /* Check whether the format is a literal string constant. */
12911 fmt_str = c_getstr (fmt);
12912 if (fmt_str == NULL)
12913 return NULL_TREE;
12914
12915 if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
12916 {
6d77ed92 12917 /* If we're using an unlocked function, assume the other
12918 unlocked functions exist explicitly. */
12919 fn_fputc = built_in_decls[BUILT_IN_FPUTC_UNLOCKED];
12920 fn_fputs = built_in_decls[BUILT_IN_FPUTS_UNLOCKED];
0a39fd54 12921 }
12922 else
12923 {
12924 fn_fputc = implicit_built_in_decls[BUILT_IN_FPUTC];
12925 fn_fputs = implicit_built_in_decls[BUILT_IN_FPUTS];
12926 }
12927
d4473c84 12928 if (!init_target_chars ())
c2f47e15 12929 return NULL_TREE;
a0c938f0 12930
0a39fd54 12931 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 12932 if (strchr (fmt_str, target_percent) == NULL)
0a39fd54 12933 {
12934 if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
c2f47e15 12935 && arg)
12936 return NULL_TREE;
0a39fd54 12937
12938 /* If the format specifier was "", fprintf does nothing. */
12939 if (fmt_str[0] == '\0')
12940 {
12941 /* If FP has side-effects, just wait until gimplification is
12942 done. */
12943 if (TREE_SIDE_EFFECTS (fp))
c2f47e15 12944 return NULL_TREE;
0a39fd54 12945
12946 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
12947 }
12948
12949 /* When "string" doesn't contain %, replace all cases of
12950 fprintf (fp, string) with fputs (string, fp). The fputs
12951 builtin will take care of special cases like length == 1. */
c2f47e15 12952 if (fn_fputs)
389dd41b 12953 call = build_call_expr_loc (loc, fn_fputs, 2, fmt, fp);
0a39fd54 12954 }
12955
12956 /* The other optimizations can be done only on the non-va_list variants. */
12957 else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
c2f47e15 12958 return NULL_TREE;
0a39fd54 12959
12960 /* If the format specifier was "%s", call __builtin_fputs (arg, fp). */
99eabcc1 12961 else if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12962 {
c2f47e15 12963 if (!arg || !validate_arg (arg, POINTER_TYPE))
12964 return NULL_TREE;
12965 if (fn_fputs)
389dd41b 12966 call = build_call_expr_loc (loc, fn_fputs, 2, arg, fp);
0a39fd54 12967 }
12968
12969 /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */
99eabcc1 12970 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 12971 {
c2f47e15 12972 if (!arg || !validate_arg (arg, INTEGER_TYPE))
12973 return NULL_TREE;
12974 if (fn_fputc)
389dd41b 12975 call = build_call_expr_loc (loc, fn_fputc, 2, arg, fp);
0a39fd54 12976 }
12977
c2f47e15 12978 if (!call)
12979 return NULL_TREE;
389dd41b 12980 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
0a39fd54 12981}
99eabcc1 12982
12983/* Initialize format string characters in the target charset. */
12984
12985static bool
12986init_target_chars (void)
12987{
12988 static bool init;
12989 if (!init)
12990 {
12991 target_newline = lang_hooks.to_target_charset ('\n');
12992 target_percent = lang_hooks.to_target_charset ('%');
12993 target_c = lang_hooks.to_target_charset ('c');
12994 target_s = lang_hooks.to_target_charset ('s');
12995 if (target_newline == 0 || target_percent == 0 || target_c == 0
12996 || target_s == 0)
12997 return false;
12998
12999 target_percent_c[0] = target_percent;
13000 target_percent_c[1] = target_c;
13001 target_percent_c[2] = '\0';
13002
13003 target_percent_s[0] = target_percent;
13004 target_percent_s[1] = target_s;
13005 target_percent_s[2] = '\0';
13006
13007 target_percent_s_newline[0] = target_percent;
13008 target_percent_s_newline[1] = target_s;
13009 target_percent_s_newline[2] = target_newline;
13010 target_percent_s_newline[3] = '\0';
a0c938f0 13011
99eabcc1 13012 init = true;
13013 }
13014 return true;
13015}
bffb7645 13016
f0c477f2 13017/* Helper function for do_mpfr_arg*(). Ensure M is a normal number
13018 and no overflow/underflow occurred. INEXACT is true if M was not
fa7637bd 13019 exactly calculated. TYPE is the tree type for the result. This
f0c477f2 13020 function assumes that you cleared the MPFR flags and then
13021 calculated M to see if anything subsequently set a flag prior to
13022 entering this function. Return NULL_TREE if any checks fail. */
13023
13024static tree
d4473c84 13025do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
f0c477f2 13026{
13027 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
13028 overflow/underflow occurred. If -frounding-math, proceed iff the
13029 result of calling FUNC was exact. */
d4473c84 13030 if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
f0c477f2 13031 && (!flag_rounding_math || !inexact))
13032 {
13033 REAL_VALUE_TYPE rr;
13034
66fa16e6 13035 real_from_mpfr (&rr, m, type, GMP_RNDN);
f0c477f2 13036 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
13037 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
13038 but the mpft_t is not, then we underflowed in the
13039 conversion. */
776a7bab 13040 if (real_isfinite (&rr)
f0c477f2 13041 && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
13042 {
13043 REAL_VALUE_TYPE rmode;
13044
13045 real_convert (&rmode, TYPE_MODE (type), &rr);
13046 /* Proceed iff the specified mode can hold the value. */
13047 if (real_identical (&rmode, &rr))
13048 return build_real (type, rmode);
13049 }
13050 }
13051 return NULL_TREE;
13052}
13053
239d491a 13054#ifdef HAVE_mpc
13055/* Helper function for do_mpc_arg*(). Ensure M is a normal complex
13056 number and no overflow/underflow occurred. INEXACT is true if M
13057 was not exactly calculated. TYPE is the tree type for the result.
13058 This function assumes that you cleared the MPFR flags and then
13059 calculated M to see if anything subsequently set a flag prior to
652d9409 13060 entering this function. Return NULL_TREE if any checks fail, if
13061 FORCE_CONVERT is true, then bypass the checks. */
239d491a 13062
13063static tree
652d9409 13064do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert)
239d491a 13065{
13066 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
13067 overflow/underflow occurred. If -frounding-math, proceed iff the
13068 result of calling FUNC was exact. */
652d9409 13069 if (force_convert
13070 || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m))
13071 && !mpfr_overflow_p () && !mpfr_underflow_p ()
13072 && (!flag_rounding_math || !inexact)))
239d491a 13073 {
13074 REAL_VALUE_TYPE re, im;
13075
c3cfad90 13076 real_from_mpfr (&re, mpc_realref (m), type, GMP_RNDN);
13077 real_from_mpfr (&im, mpc_imagref (m), type, GMP_RNDN);
239d491a 13078 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
13079 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
13080 but the mpft_t is not, then we underflowed in the
13081 conversion. */
652d9409 13082 if (force_convert
13083 || (real_isfinite (&re) && real_isfinite (&im)
13084 && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0)
13085 && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0)))
239d491a 13086 {
13087 REAL_VALUE_TYPE re_mode, im_mode;
13088
13089 real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re);
13090 real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im);
13091 /* Proceed iff the specified mode can hold the value. */
652d9409 13092 if (force_convert
13093 || (real_identical (&re_mode, &re)
13094 && real_identical (&im_mode, &im)))
239d491a 13095 return build_complex (type, build_real (TREE_TYPE (type), re_mode),
13096 build_real (TREE_TYPE (type), im_mode));
13097 }
13098 }
13099 return NULL_TREE;
13100}
13101#endif /* HAVE_mpc */
13102
bffb7645 13103/* If argument ARG is a REAL_CST, call the one-argument mpfr function
13104 FUNC on it and return the resulting value as a tree with type TYPE.
728bac60 13105 If MIN and/or MAX are not NULL, then the supplied ARG must be
13106 within those bounds. If INCLUSIVE is true, then MIN/MAX are
13107 acceptable values, otherwise they are not. The mpfr precision is
13108 set to the precision of TYPE. We assume that function FUNC returns
13109 zero if the result could be calculated exactly within the requested
13110 precision. */
bffb7645 13111
13112static tree
728bac60 13113do_mpfr_arg1 (tree arg, tree type, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
13114 const REAL_VALUE_TYPE *min, const REAL_VALUE_TYPE *max,
13115 bool inclusive)
bffb7645 13116{
13117 tree result = NULL_TREE;
13118
13119 STRIP_NOPS (arg);
13120
bd7d6fa4 13121 /* To proceed, MPFR must exactly represent the target floating point
13122 format, which only happens when the target base equals two. */
13123 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13124 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
bffb7645 13125 {
f0c477f2 13126 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
bffb7645 13127
776a7bab 13128 if (real_isfinite (ra)
f0c477f2 13129 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min))
13130 && (!max || real_compare (inclusive ? LE_EXPR: LT_EXPR , ra, max)))
bffb7645 13131 {
e2eb2b7f 13132 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13133 const int prec = fmt->p;
13134 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
debf9994 13135 int inexact;
bffb7645 13136 mpfr_t m;
13137
13138 mpfr_init2 (m, prec);
66fa16e6 13139 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 13140 mpfr_clear_flags ();
e2eb2b7f 13141 inexact = func (m, m, rnd);
f0c477f2 13142 result = do_mpfr_ckconv (m, type, inexact);
bffb7645 13143 mpfr_clear (m);
13144 }
13145 }
13146
13147 return result;
13148}
f0c477f2 13149
13150/* If argument ARG is a REAL_CST, call the two-argument mpfr function
13151 FUNC on it and return the resulting value as a tree with type TYPE.
13152 The mpfr precision is set to the precision of TYPE. We assume that
13153 function FUNC returns zero if the result could be calculated
13154 exactly within the requested precision. */
13155
13156static tree
13157do_mpfr_arg2 (tree arg1, tree arg2, tree type,
13158 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
13159{
13160 tree result = NULL_TREE;
13161
13162 STRIP_NOPS (arg1);
13163 STRIP_NOPS (arg2);
13164
bd7d6fa4 13165 /* To proceed, MPFR must exactly represent the target floating point
13166 format, which only happens when the target base equals two. */
13167 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13168 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
13169 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
f0c477f2 13170 {
13171 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
13172 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
13173
776a7bab 13174 if (real_isfinite (ra1) && real_isfinite (ra2))
f0c477f2 13175 {
e2eb2b7f 13176 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13177 const int prec = fmt->p;
13178 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
f0c477f2 13179 int inexact;
13180 mpfr_t m1, m2;
13181
13182 mpfr_inits2 (prec, m1, m2, NULL);
66fa16e6 13183 mpfr_from_real (m1, ra1, GMP_RNDN);
13184 mpfr_from_real (m2, ra2, GMP_RNDN);
d4473c84 13185 mpfr_clear_flags ();
e2eb2b7f 13186 inexact = func (m1, m1, m2, rnd);
f0c477f2 13187 result = do_mpfr_ckconv (m1, type, inexact);
13188 mpfr_clears (m1, m2, NULL);
13189 }
13190 }
13191
13192 return result;
13193}
d92f994c 13194
9917422b 13195/* If argument ARG is a REAL_CST, call the three-argument mpfr function
13196 FUNC on it and return the resulting value as a tree with type TYPE.
13197 The mpfr precision is set to the precision of TYPE. We assume that
13198 function FUNC returns zero if the result could be calculated
13199 exactly within the requested precision. */
13200
13201static tree
13202do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type,
13203 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
13204{
13205 tree result = NULL_TREE;
13206
13207 STRIP_NOPS (arg1);
13208 STRIP_NOPS (arg2);
13209 STRIP_NOPS (arg3);
13210
bd7d6fa4 13211 /* To proceed, MPFR must exactly represent the target floating point
13212 format, which only happens when the target base equals two. */
13213 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13214 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
13215 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2)
13216 && TREE_CODE (arg3) == REAL_CST && !TREE_OVERFLOW (arg3))
9917422b 13217 {
13218 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
13219 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
13220 const REAL_VALUE_TYPE *const ra3 = &TREE_REAL_CST (arg3);
13221
776a7bab 13222 if (real_isfinite (ra1) && real_isfinite (ra2) && real_isfinite (ra3))
9917422b 13223 {
e2eb2b7f 13224 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13225 const int prec = fmt->p;
13226 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
9917422b 13227 int inexact;
13228 mpfr_t m1, m2, m3;
13229
13230 mpfr_inits2 (prec, m1, m2, m3, NULL);
66fa16e6 13231 mpfr_from_real (m1, ra1, GMP_RNDN);
13232 mpfr_from_real (m2, ra2, GMP_RNDN);
13233 mpfr_from_real (m3, ra3, GMP_RNDN);
d4473c84 13234 mpfr_clear_flags ();
e2eb2b7f 13235 inexact = func (m1, m1, m2, m3, rnd);
9917422b 13236 result = do_mpfr_ckconv (m1, type, inexact);
13237 mpfr_clears (m1, m2, m3, NULL);
13238 }
13239 }
13240
13241 return result;
13242}
13243
d92f994c 13244/* If argument ARG is a REAL_CST, call mpfr_sin_cos() on it and set
13245 the pointers *(ARG_SINP) and *(ARG_COSP) to the resulting values.
d735c391 13246 If ARG_SINP and ARG_COSP are NULL then the result is returned
13247 as a complex value.
d92f994c 13248 The type is taken from the type of ARG and is used for setting the
13249 precision of the calculation and results. */
13250
13251static tree
13252do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp)
13253{
bd7d6fa4 13254 tree const type = TREE_TYPE (arg);
d92f994c 13255 tree result = NULL_TREE;
13256
13257 STRIP_NOPS (arg);
13258
bd7d6fa4 13259 /* To proceed, MPFR must exactly represent the target floating point
13260 format, which only happens when the target base equals two. */
13261 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13262 && TREE_CODE (arg) == REAL_CST
13263 && !TREE_OVERFLOW (arg))
d92f994c 13264 {
13265 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
13266
776a7bab 13267 if (real_isfinite (ra))
d92f994c 13268 {
e2eb2b7f 13269 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13270 const int prec = fmt->p;
13271 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
d92f994c 13272 tree result_s, result_c;
13273 int inexact;
13274 mpfr_t m, ms, mc;
13275
13276 mpfr_inits2 (prec, m, ms, mc, NULL);
66fa16e6 13277 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 13278 mpfr_clear_flags ();
e2eb2b7f 13279 inexact = mpfr_sin_cos (ms, mc, m, rnd);
d92f994c 13280 result_s = do_mpfr_ckconv (ms, type, inexact);
13281 result_c = do_mpfr_ckconv (mc, type, inexact);
13282 mpfr_clears (m, ms, mc, NULL);
13283 if (result_s && result_c)
13284 {
d735c391 13285 /* If we are to return in a complex value do so. */
13286 if (!arg_sinp && !arg_cosp)
13287 return build_complex (build_complex_type (type),
13288 result_c, result_s);
13289
d92f994c 13290 /* Dereference the sin/cos pointer arguments. */
13291 arg_sinp = build_fold_indirect_ref (arg_sinp);
13292 arg_cosp = build_fold_indirect_ref (arg_cosp);
13293 /* Proceed if valid pointer type were passed in. */
13294 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_sinp)) == TYPE_MAIN_VARIANT (type)
13295 && TYPE_MAIN_VARIANT (TREE_TYPE (arg_cosp)) == TYPE_MAIN_VARIANT (type))
13296 {
13297 /* Set the values. */
41076ef6 13298 result_s = fold_build2 (MODIFY_EXPR, type, arg_sinp,
35cc02b5 13299 result_s);
d92f994c 13300 TREE_SIDE_EFFECTS (result_s) = 1;
41076ef6 13301 result_c = fold_build2 (MODIFY_EXPR, type, arg_cosp,
35cc02b5 13302 result_c);
d92f994c 13303 TREE_SIDE_EFFECTS (result_c) = 1;
13304 /* Combine the assignments into a compound expr. */
13305 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13306 result_s, result_c));
13307 }
13308 }
13309 }
13310 }
13311 return result;
13312}
65dd1378 13313
65dd1378 13314/* If argument ARG1 is an INTEGER_CST and ARG2 is a REAL_CST, call the
13315 two-argument mpfr order N Bessel function FUNC on them and return
13316 the resulting value as a tree with type TYPE. The mpfr precision
13317 is set to the precision of TYPE. We assume that function FUNC
13318 returns zero if the result could be calculated exactly within the
13319 requested precision. */
13320static tree
13321do_mpfr_bessel_n (tree arg1, tree arg2, tree type,
13322 int (*func)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
13323 const REAL_VALUE_TYPE *min, bool inclusive)
13324{
13325 tree result = NULL_TREE;
13326
13327 STRIP_NOPS (arg1);
13328 STRIP_NOPS (arg2);
13329
13330 /* To proceed, MPFR must exactly represent the target floating point
13331 format, which only happens when the target base equals two. */
13332 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13333 && host_integerp (arg1, 0)
13334 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
13335 {
13336 const HOST_WIDE_INT n = tree_low_cst(arg1, 0);
13337 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg2);
13338
13339 if (n == (long)n
776a7bab 13340 && real_isfinite (ra)
65dd1378 13341 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min)))
13342 {
e2eb2b7f 13343 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13344 const int prec = fmt->p;
13345 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
65dd1378 13346 int inexact;
13347 mpfr_t m;
13348
13349 mpfr_init2 (m, prec);
13350 mpfr_from_real (m, ra, GMP_RNDN);
13351 mpfr_clear_flags ();
e2eb2b7f 13352 inexact = func (m, n, m, rnd);
65dd1378 13353 result = do_mpfr_ckconv (m, type, inexact);
13354 mpfr_clear (m);
13355 }
13356 }
13357
13358 return result;
13359}
e5407ca6 13360
13361/* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
13362 the pointer *(ARG_QUO) and return the result. The type is taken
13363 from the type of ARG0 and is used for setting the precision of the
13364 calculation and results. */
13365
13366static tree
13367do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
13368{
13369 tree const type = TREE_TYPE (arg0);
13370 tree result = NULL_TREE;
13371
13372 STRIP_NOPS (arg0);
13373 STRIP_NOPS (arg1);
13374
13375 /* To proceed, MPFR must exactly represent the target floating point
13376 format, which only happens when the target base equals two. */
13377 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13378 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
13379 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
13380 {
13381 const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
13382 const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
13383
776a7bab 13384 if (real_isfinite (ra0) && real_isfinite (ra1))
e5407ca6 13385 {
e2eb2b7f 13386 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13387 const int prec = fmt->p;
13388 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
e5407ca6 13389 tree result_rem;
13390 long integer_quo;
13391 mpfr_t m0, m1;
13392
13393 mpfr_inits2 (prec, m0, m1, NULL);
13394 mpfr_from_real (m0, ra0, GMP_RNDN);
13395 mpfr_from_real (m1, ra1, GMP_RNDN);
13396 mpfr_clear_flags ();
e2eb2b7f 13397 mpfr_remquo (m0, &integer_quo, m0, m1, rnd);
e5407ca6 13398 /* Remquo is independent of the rounding mode, so pass
13399 inexact=0 to do_mpfr_ckconv(). */
13400 result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
13401 mpfr_clears (m0, m1, NULL);
13402 if (result_rem)
13403 {
13404 /* MPFR calculates quo in the host's long so it may
13405 return more bits in quo than the target int can hold
13406 if sizeof(host long) > sizeof(target int). This can
13407 happen even for native compilers in LP64 mode. In
13408 these cases, modulo the quo value with the largest
13409 number that the target int can hold while leaving one
13410 bit for the sign. */
13411 if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
13412 integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
13413
13414 /* Dereference the quo pointer argument. */
13415 arg_quo = build_fold_indirect_ref (arg_quo);
13416 /* Proceed iff a valid pointer type was passed in. */
13417 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
13418 {
13419 /* Set the value. */
13420 tree result_quo = fold_build2 (MODIFY_EXPR,
13421 TREE_TYPE (arg_quo), arg_quo,
13422 build_int_cst (NULL, integer_quo));
13423 TREE_SIDE_EFFECTS (result_quo) = 1;
13424 /* Combine the quo assignment with the rem. */
13425 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13426 result_quo, result_rem));
13427 }
13428 }
13429 }
13430 }
13431 return result;
13432}
e84da7c1 13433
13434/* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
13435 resulting value as a tree with type TYPE. The mpfr precision is
13436 set to the precision of TYPE. We assume that this mpfr function
13437 returns zero if the result could be calculated exactly within the
13438 requested precision. In addition, the integer pointer represented
13439 by ARG_SG will be dereferenced and set to the appropriate signgam
13440 (-1,1) value. */
13441
13442static tree
13443do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
13444{
13445 tree result = NULL_TREE;
13446
13447 STRIP_NOPS (arg);
13448
13449 /* To proceed, MPFR must exactly represent the target floating point
13450 format, which only happens when the target base equals two. Also
13451 verify ARG is a constant and that ARG_SG is an int pointer. */
13452 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13453 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
13454 && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
13455 && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
13456 {
13457 const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
13458
13459 /* In addition to NaN and Inf, the argument cannot be zero or a
13460 negative integer. */
776a7bab 13461 if (real_isfinite (ra)
e84da7c1 13462 && ra->cl != rvc_zero
13463 && !(real_isneg(ra) && real_isinteger(ra, TYPE_MODE (type))))
13464 {
e2eb2b7f 13465 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13466 const int prec = fmt->p;
13467 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
e84da7c1 13468 int inexact, sg;
13469 mpfr_t m;
13470 tree result_lg;
13471
13472 mpfr_init2 (m, prec);
13473 mpfr_from_real (m, ra, GMP_RNDN);
13474 mpfr_clear_flags ();
e2eb2b7f 13475 inexact = mpfr_lgamma (m, &sg, m, rnd);
e84da7c1 13476 result_lg = do_mpfr_ckconv (m, type, inexact);
13477 mpfr_clear (m);
13478 if (result_lg)
13479 {
13480 tree result_sg;
13481
13482 /* Dereference the arg_sg pointer argument. */
13483 arg_sg = build_fold_indirect_ref (arg_sg);
13484 /* Assign the signgam value into *arg_sg. */
13485 result_sg = fold_build2 (MODIFY_EXPR,
13486 TREE_TYPE (arg_sg), arg_sg,
13487 build_int_cst (NULL, sg));
13488 TREE_SIDE_EFFECTS (result_sg) = 1;
13489 /* Combine the signgam assignment with the lgamma result. */
13490 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13491 result_sg, result_lg));
13492 }
13493 }
13494 }
13495
13496 return result;
13497}
75a70cf9 13498
239d491a 13499#ifdef HAVE_mpc
13500/* If argument ARG is a COMPLEX_CST, call the one-argument mpc
13501 function FUNC on it and return the resulting value as a tree with
13502 type TYPE. The mpfr precision is set to the precision of TYPE. We
13503 assume that function FUNC returns zero if the result could be
13504 calculated exactly within the requested precision. */
13505
13506static tree
13507do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t))
13508{
13509 tree result = NULL_TREE;
13510
13511 STRIP_NOPS (arg);
13512
13513 /* To proceed, MPFR must exactly represent the target floating point
13514 format, which only happens when the target base equals two. */
13515 if (TREE_CODE (arg) == COMPLEX_CST && !TREE_OVERFLOW (arg)
13516 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE
13517 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))))->b == 2)
13518 {
13519 const REAL_VALUE_TYPE *const re = TREE_REAL_CST_PTR (TREE_REALPART (arg));
13520 const REAL_VALUE_TYPE *const im = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
13521
13522 if (real_isfinite (re) && real_isfinite (im))
13523 {
13524 const struct real_format *const fmt =
13525 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
13526 const int prec = fmt->p;
13527 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
44d89feb 13528 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
239d491a 13529 int inexact;
13530 mpc_t m;
13531
13532 mpc_init2 (m, prec);
c3cfad90 13533 mpfr_from_real (mpc_realref(m), re, rnd);
13534 mpfr_from_real (mpc_imagref(m), im, rnd);
239d491a 13535 mpfr_clear_flags ();
44d89feb 13536 inexact = func (m, m, crnd);
652d9409 13537 result = do_mpc_ckconv (m, type, inexact, /*force_convert=*/ 0);
239d491a 13538 mpc_clear (m);
13539 }
13540 }
13541
13542 return result;
13543}
c699fab8 13544
13545/* If arguments ARG0 and ARG1 are a COMPLEX_CST, call the two-argument
13546 mpc function FUNC on it and return the resulting value as a tree
13547 with type TYPE. The mpfr precision is set to the precision of
13548 TYPE. We assume that function FUNC returns zero if the result
652d9409 13549 could be calculated exactly within the requested precision. If
13550 DO_NONFINITE is true, then fold expressions containing Inf or NaN
13551 in the arguments and/or results. */
c699fab8 13552
63e89698 13553#ifdef HAVE_mpc
13554tree
652d9409 13555do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
c699fab8 13556 int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
13557{
13558 tree result = NULL_TREE;
13559
13560 STRIP_NOPS (arg0);
13561 STRIP_NOPS (arg1);
13562
13563 /* To proceed, MPFR must exactly represent the target floating point
13564 format, which only happens when the target base equals two. */
13565 if (TREE_CODE (arg0) == COMPLEX_CST && !TREE_OVERFLOW (arg0)
13566 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
13567 && TREE_CODE (arg1) == COMPLEX_CST && !TREE_OVERFLOW (arg1)
13568 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE
13569 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))))->b == 2)
13570 {
13571 const REAL_VALUE_TYPE *const re0 = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
13572 const REAL_VALUE_TYPE *const im0 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
13573 const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1));
13574 const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1));
13575
652d9409 13576 if (do_nonfinite
13577 || (real_isfinite (re0) && real_isfinite (im0)
13578 && real_isfinite (re1) && real_isfinite (im1)))
c699fab8 13579 {
13580 const struct real_format *const fmt =
13581 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
13582 const int prec = fmt->p;
13583 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
13584 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
13585 int inexact;
13586 mpc_t m0, m1;
13587
13588 mpc_init2 (m0, prec);
13589 mpc_init2 (m1, prec);
13590 mpfr_from_real (mpc_realref(m0), re0, rnd);
13591 mpfr_from_real (mpc_imagref(m0), im0, rnd);
13592 mpfr_from_real (mpc_realref(m1), re1, rnd);
13593 mpfr_from_real (mpc_imagref(m1), im1, rnd);
13594 mpfr_clear_flags ();
13595 inexact = func (m0, m0, m1, crnd);
652d9409 13596 result = do_mpc_ckconv (m0, type, inexact, do_nonfinite);
c699fab8 13597 mpc_clear (m0);
13598 mpc_clear (m1);
13599 }
13600 }
13601
13602 return result;
13603}
13604# endif
239d491a 13605#endif /* HAVE_mpc */
13606
75a70cf9 13607/* FIXME tuples.
13608 The functions below provide an alternate interface for folding
13609 builtin function calls presented as GIMPLE_CALL statements rather
13610 than as CALL_EXPRs. The folded result is still expressed as a
13611 tree. There is too much code duplication in the handling of
13612 varargs functions, and a more intrusive re-factoring would permit
13613 better sharing of code between the tree and statement-based
13614 versions of these functions. */
13615
13616/* Construct a new CALL_EXPR using the tail of the argument list of STMT
13617 along with N new arguments specified as the "..." parameters. SKIP
13618 is the number of arguments in STMT to be omitted. This function is used
13619 to do varargs-to-varargs transformations. */
13620
13621static tree
13622gimple_rewrite_call_expr (gimple stmt, int skip, tree fndecl, int n, ...)
13623{
13624 int oldnargs = gimple_call_num_args (stmt);
13625 int nargs = oldnargs - skip + n;
13626 tree fntype = TREE_TYPE (fndecl);
13627 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
13628 tree *buffer;
13629 int i, j;
13630 va_list ap;
389dd41b 13631 location_t loc = gimple_location (stmt);
75a70cf9 13632
13633 buffer = XALLOCAVEC (tree, nargs);
13634 va_start (ap, n);
13635 for (i = 0; i < n; i++)
13636 buffer[i] = va_arg (ap, tree);
13637 va_end (ap);
13638 for (j = skip; j < oldnargs; j++, i++)
13639 buffer[i] = gimple_call_arg (stmt, j);
13640
389dd41b 13641 return fold (build_call_array_loc (loc, TREE_TYPE (fntype), fn, nargs, buffer));
75a70cf9 13642}
13643
13644/* Fold a call STMT to __{,v}sprintf_chk. Return NULL_TREE if
13645 a normal call should be emitted rather than expanding the function
13646 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
13647
13648static tree
13649gimple_fold_builtin_sprintf_chk (gimple stmt, enum built_in_function fcode)
13650{
13651 tree dest, size, len, fn, fmt, flag;
13652 const char *fmt_str;
13653 int nargs = gimple_call_num_args (stmt);
13654
13655 /* Verify the required arguments in the original call. */
13656 if (nargs < 4)
13657 return NULL_TREE;
13658 dest = gimple_call_arg (stmt, 0);
13659 if (!validate_arg (dest, POINTER_TYPE))
13660 return NULL_TREE;
13661 flag = gimple_call_arg (stmt, 1);
13662 if (!validate_arg (flag, INTEGER_TYPE))
13663 return NULL_TREE;
13664 size = gimple_call_arg (stmt, 2);
13665 if (!validate_arg (size, INTEGER_TYPE))
13666 return NULL_TREE;
13667 fmt = gimple_call_arg (stmt, 3);
13668 if (!validate_arg (fmt, POINTER_TYPE))
13669 return NULL_TREE;
13670
13671 if (! host_integerp (size, 1))
13672 return NULL_TREE;
13673
13674 len = NULL_TREE;
13675
13676 if (!init_target_chars ())
13677 return NULL_TREE;
13678
13679 /* Check whether the format is a literal string constant. */
13680 fmt_str = c_getstr (fmt);
13681 if (fmt_str != NULL)
13682 {
13683 /* If the format doesn't contain % args or %%, we know the size. */
13684 if (strchr (fmt_str, target_percent) == 0)
13685 {
13686 if (fcode != BUILT_IN_SPRINTF_CHK || nargs == 4)
13687 len = build_int_cstu (size_type_node, strlen (fmt_str));
13688 }
13689 /* If the format is "%s" and first ... argument is a string literal,
13690 we know the size too. */
13691 else if (fcode == BUILT_IN_SPRINTF_CHK
13692 && strcmp (fmt_str, target_percent_s) == 0)
13693 {
13694 tree arg;
13695
13696 if (nargs == 5)
13697 {
13698 arg = gimple_call_arg (stmt, 4);
13699 if (validate_arg (arg, POINTER_TYPE))
13700 {
13701 len = c_strlen (arg, 1);
13702 if (! len || ! host_integerp (len, 1))
13703 len = NULL_TREE;
13704 }
13705 }
13706 }
13707 }
13708
13709 if (! integer_all_onesp (size))
13710 {
13711 if (! len || ! tree_int_cst_lt (len, size))
13712 return NULL_TREE;
13713 }
13714
13715 /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
13716 or if format doesn't contain % chars or is "%s". */
13717 if (! integer_zerop (flag))
13718 {
13719 if (fmt_str == NULL)
13720 return NULL_TREE;
13721 if (strchr (fmt_str, target_percent) != NULL
13722 && strcmp (fmt_str, target_percent_s))
13723 return NULL_TREE;
13724 }
13725
13726 /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
13727 fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
13728 ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
13729 if (!fn)
13730 return NULL_TREE;
13731
13732 return gimple_rewrite_call_expr (stmt, 4, fn, 2, dest, fmt);
13733}
13734
13735/* Fold a call STMT to {,v}snprintf. Return NULL_TREE if
13736 a normal call should be emitted rather than expanding the function
13737 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
13738 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
13739 passed as second argument. */
13740
13741tree
13742gimple_fold_builtin_snprintf_chk (gimple stmt, tree maxlen,
13743 enum built_in_function fcode)
13744{
13745 tree dest, size, len, fn, fmt, flag;
13746 const char *fmt_str;
13747
13748 /* Verify the required arguments in the original call. */
13749 if (gimple_call_num_args (stmt) < 5)
13750 return NULL_TREE;
13751 dest = gimple_call_arg (stmt, 0);
13752 if (!validate_arg (dest, POINTER_TYPE))
13753 return NULL_TREE;
13754 len = gimple_call_arg (stmt, 1);
13755 if (!validate_arg (len, INTEGER_TYPE))
13756 return NULL_TREE;
13757 flag = gimple_call_arg (stmt, 2);
13758 if (!validate_arg (flag, INTEGER_TYPE))
13759 return NULL_TREE;
13760 size = gimple_call_arg (stmt, 3);
13761 if (!validate_arg (size, INTEGER_TYPE))
13762 return NULL_TREE;
13763 fmt = gimple_call_arg (stmt, 4);
13764 if (!validate_arg (fmt, POINTER_TYPE))
13765 return NULL_TREE;
13766
13767 if (! host_integerp (size, 1))
13768 return NULL_TREE;
13769
13770 if (! integer_all_onesp (size))
13771 {
13772 if (! host_integerp (len, 1))
13773 {
13774 /* If LEN is not constant, try MAXLEN too.
13775 For MAXLEN only allow optimizing into non-_ocs function
13776 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
13777 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
13778 return NULL_TREE;
13779 }
13780 else
13781 maxlen = len;
13782
13783 if (tree_int_cst_lt (size, maxlen))
13784 return NULL_TREE;
13785 }
13786
13787 if (!init_target_chars ())
13788 return NULL_TREE;
13789
13790 /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
13791 or if format doesn't contain % chars or is "%s". */
13792 if (! integer_zerop (flag))
13793 {
13794 fmt_str = c_getstr (fmt);
13795 if (fmt_str == NULL)
13796 return NULL_TREE;
13797 if (strchr (fmt_str, target_percent) != NULL
13798 && strcmp (fmt_str, target_percent_s))
13799 return NULL_TREE;
13800 }
13801
13802 /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
13803 available. */
13804 fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
13805 ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
13806 if (!fn)
13807 return NULL_TREE;
13808
13809 return gimple_rewrite_call_expr (stmt, 5, fn, 3, dest, len, fmt);
13810}
13811
13812/* Builtins with folding operations that operate on "..." arguments
13813 need special handling; we need to store the arguments in a convenient
13814 data structure before attempting any folding. Fortunately there are
13815 only a few builtins that fall into this category. FNDECL is the
13816 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
13817 result of the function call is ignored. */
13818
13819static tree
389dd41b 13820gimple_fold_builtin_varargs (tree fndecl, gimple stmt,
13821 bool ignore ATTRIBUTE_UNUSED)
75a70cf9 13822{
13823 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
13824 tree ret = NULL_TREE;
13825
13826 switch (fcode)
13827 {
13828 case BUILT_IN_SPRINTF_CHK:
13829 case BUILT_IN_VSPRINTF_CHK:
13830 ret = gimple_fold_builtin_sprintf_chk (stmt, fcode);
13831 break;
13832
13833 case BUILT_IN_SNPRINTF_CHK:
13834 case BUILT_IN_VSNPRINTF_CHK:
13835 ret = gimple_fold_builtin_snprintf_chk (stmt, NULL_TREE, fcode);
13836
13837 default:
13838 break;
13839 }
13840 if (ret)
13841 {
13842 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
13843 TREE_NO_WARNING (ret) = 1;
13844 return ret;
13845 }
13846 return NULL_TREE;
13847}
13848
13849/* A wrapper function for builtin folding that prevents warnings for
13850 "statement without effect" and the like, caused by removing the
13851 call node earlier than the warning is generated. */
13852
13853tree
13854fold_call_stmt (gimple stmt, bool ignore)
13855{
13856 tree ret = NULL_TREE;
13857 tree fndecl = gimple_call_fndecl (stmt);
389dd41b 13858 location_t loc = gimple_location (stmt);
75a70cf9 13859 if (fndecl
13860 && TREE_CODE (fndecl) == FUNCTION_DECL
13861 && DECL_BUILT_IN (fndecl)
13862 && !gimple_call_va_arg_pack_p (stmt))
13863 {
13864 int nargs = gimple_call_num_args (stmt);
13865
198622c0 13866 if (avoid_folding_inline_builtin (fndecl))
13867 return NULL_TREE;
75a70cf9 13868 /* FIXME: Don't use a list in this interface. */
13869 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
13870 {
13871 tree arglist = NULL_TREE;
13872 int i;
13873 for (i = nargs - 1; i >= 0; i--)
13874 arglist = tree_cons (NULL_TREE, gimple_call_arg (stmt, i), arglist);
13875 return targetm.fold_builtin (fndecl, arglist, ignore);
13876 }
13877 else
13878 {
13879 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
13880 {
13881 tree args[MAX_ARGS_TO_FOLD_BUILTIN];
13882 int i;
13883 for (i = 0; i < nargs; i++)
13884 args[i] = gimple_call_arg (stmt, i);
389dd41b 13885 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
75a70cf9 13886 }
13887 if (!ret)
13888 ret = gimple_fold_builtin_varargs (fndecl, stmt, ignore);
13889 if (ret)
13890 {
13891 /* Propagate location information from original call to
13892 expansion of builtin. Otherwise things like
13893 maybe_emit_chk_warning, that operate on the expansion
13894 of a builtin, will use the wrong location information. */
13895 if (gimple_has_location (stmt))
13896 {
13897 tree realret = ret;
13898 if (TREE_CODE (ret) == NOP_EXPR)
13899 realret = TREE_OPERAND (ret, 0);
13900 if (CAN_HAVE_LOCATION_P (realret)
13901 && !EXPR_HAS_LOCATION (realret))
389dd41b 13902 SET_EXPR_LOCATION (realret, loc);
75a70cf9 13903 return realret;
13904 }
13905 return ret;
13906 }
13907 }
13908 }
13909 return NULL_TREE;
13910}
7bfefa9d 13911
13912/* Look up the function in built_in_decls that corresponds to DECL
13913 and set ASMSPEC as its user assembler name. DECL must be a
13914 function decl that declares a builtin. */
13915
13916void
13917set_builtin_user_assembler_name (tree decl, const char *asmspec)
13918{
13919 tree builtin;
13920 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
13921 && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
13922 && asmspec != 0);
13923
13924 builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
13925 set_user_assembler_name (builtin, asmspec);
13926 switch (DECL_FUNCTION_CODE (decl))
13927 {
13928 case BUILT_IN_MEMCPY:
13929 init_block_move_fn (asmspec);
13930 memcpy_libfunc = set_user_assembler_libfunc ("memcpy", asmspec);
13931 break;
13932 case BUILT_IN_MEMSET:
13933 init_block_clear_fn (asmspec);
13934 memset_libfunc = set_user_assembler_libfunc ("memset", asmspec);
13935 break;
13936 case BUILT_IN_MEMMOVE:
13937 memmove_libfunc = set_user_assembler_libfunc ("memmove", asmspec);
13938 break;
13939 case BUILT_IN_MEMCMP:
13940 memcmp_libfunc = set_user_assembler_libfunc ("memcmp", asmspec);
13941 break;
13942 case BUILT_IN_ABORT:
13943 abort_libfunc = set_user_assembler_libfunc ("abort", asmspec);
13944 break;
13945 default:
13946 break;
13947 }
13948}