]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/builtins.c
Merge in trunk.
[thirdparty/gcc.git] / gcc / builtins.c
CommitLineData
53800dbe 1/* Expand builtin functions.
3aea1f79 2 Copyright (C) 1988-2014 Free Software Foundation, Inc.
53800dbe 3
f12b58b3 4This file is part of GCC.
53800dbe 5
f12b58b3 6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8c4c00c1 8Software Foundation; either version 3, or (at your option) any later
f12b58b3 9version.
53800dbe 10
f12b58b3 11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
53800dbe 15
16You should have received a copy of the GNU General Public License
8c4c00c1 17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
53800dbe 19
20#include "config.h"
21#include "system.h"
805e22b2 22#include "coretypes.h"
23#include "tm.h"
53800dbe 24#include "machmode.h"
25#include "rtl.h"
26#include "tree.h"
9ed99284 27#include "stringpool.h"
28#include "stor-layout.h"
29#include "calls.h"
30#include "varasm.h"
31#include "tree-object-size.h"
dae0b5cb 32#include "realmpfr.h"
bc61cadb 33#include "basic-block.h"
34#include "tree-ssa-alias.h"
35#include "internal-fn.h"
36#include "gimple-expr.h"
37#include "is-a.h"
75a70cf9 38#include "gimple.h"
53800dbe 39#include "flags.h"
40#include "regs.h"
41#include "hard-reg-set.h"
42#include "except.h"
43#include "function.h"
53800dbe 44#include "insn-config.h"
45#include "expr.h"
d8fc4d0b 46#include "optabs.h"
47#include "libfuncs.h"
53800dbe 48#include "recog.h"
49#include "output.h"
50#include "typeclass.h"
689df48e 51#include "predict.h"
1dd6c958 52#include "tm_p.h"
fc2a2dcb 53#include "target.h"
63c62881 54#include "langhooks.h"
073c1fd5 55#include "tree-ssanames.h"
56#include "tree-dfa.h"
162719b3 57#include "value-prof.h"
852f689e 58#include "diagnostic-core.h"
3b9c3a16 59#include "builtins.h"
9e46467d 60#include "ubsan.h"
d037099f 61#include "cilk.h"
53800dbe 62
5383fb56 63
239d491a 64static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_rnd_t));
726e2588 65
3b9c3a16 66struct target_builtins default_target_builtins;
67#if SWITCHABLE_TARGET
68struct target_builtins *this_target_builtins = &default_target_builtins;
69#endif
70
ab7943b9 71/* Define the names of the builtin function types and codes. */
96423453 72const char *const built_in_class_names[BUILT_IN_LAST]
ab7943b9 73 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
74
9cfddb70 75#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
0dfc45b5 76const char * built_in_names[(int) END_BUILTINS] =
4e9d90c7 77{
78#include "builtins.def"
79};
80#undef DEF_BUILTIN
ab7943b9 81
df94cd3b 82/* Setup an array of _DECL trees, make sure each element is
83 initialized to NULL_TREE. */
b9a16870 84builtin_info_type builtin_info;
df94cd3b 85
0b049e15 86/* Non-zero if __builtin_constant_p should be folded right away. */
87bool force_folding_builtin_constant_p;
88
aecda0d6 89static const char *c_getstr (tree);
90static rtx c_readstr (const char *, enum machine_mode);
91static int target_char_cast (tree, char *);
d8ae1baa 92static rtx get_memory_rtx (tree, tree);
aecda0d6 93static int apply_args_size (void);
94static int apply_result_size (void);
d8c9779c 95#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
aecda0d6 96static rtx result_vector (int, rtx);
d8c9779c 97#endif
843d08a9 98static void expand_builtin_update_setjmp_buf (rtx);
aecda0d6 99static void expand_builtin_prefetch (tree);
100static rtx expand_builtin_apply_args (void);
101static rtx expand_builtin_apply_args_1 (void);
102static rtx expand_builtin_apply (rtx, rtx, rtx);
103static void expand_builtin_return (rtx);
104static enum type_class type_to_class (tree);
105static rtx expand_builtin_classify_type (tree);
106static void expand_errno_check (tree, rtx);
107static rtx expand_builtin_mathfn (tree, rtx, rtx);
108static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
6b43bae4 109static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
7e0713b1 110static rtx expand_builtin_mathfn_ternary (tree, rtx, rtx);
f97eea22 111static rtx expand_builtin_interclass_mathfn (tree, rtx);
c3147c1a 112static rtx expand_builtin_sincos (tree);
f97eea22 113static rtx expand_builtin_cexpi (tree, rtx);
ff1b14e4 114static rtx expand_builtin_int_roundingfn (tree, rtx);
115static rtx expand_builtin_int_roundingfn_2 (tree, rtx);
79012a9d 116static rtx expand_builtin_next_arg (void);
aecda0d6 117static rtx expand_builtin_va_start (tree);
118static rtx expand_builtin_va_end (tree);
119static rtx expand_builtin_va_copy (tree);
c2f47e15 120static rtx expand_builtin_memcmp (tree, rtx, enum machine_mode);
a65c4d64 121static rtx expand_builtin_strcmp (tree, rtx);
aecda0d6 122static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
123static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
a65c4d64 124static rtx expand_builtin_memcpy (tree, rtx);
c2f47e15 125static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode);
48e1416a 126static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx,
c2f47e15 127 enum machine_mode, int);
a65c4d64 128static rtx expand_builtin_strcpy (tree, rtx);
129static rtx expand_builtin_strcpy_args (tree, tree, rtx);
aecda0d6 130static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
a65c4d64 131static rtx expand_builtin_strncpy (tree, rtx);
aecda0d6 132static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
c2f47e15 133static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
134static rtx expand_builtin_memset_args (tree, tree, tree, rtx, enum machine_mode, tree);
aecda0d6 135static rtx expand_builtin_bzero (tree);
136static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
5be42b39 137static rtx expand_builtin_alloca (tree, bool);
aecda0d6 138static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
139static rtx expand_builtin_frame_address (tree, tree);
389dd41b 140static tree stabilize_va_list_loc (location_t, tree, int);
aecda0d6 141static rtx expand_builtin_expect (tree, rtx);
142static tree fold_builtin_constant_p (tree);
389dd41b 143static tree fold_builtin_expect (location_t, tree, tree);
aecda0d6 144static tree fold_builtin_classify_type (tree);
c7cbde74 145static tree fold_builtin_strlen (location_t, tree, tree);
389dd41b 146static tree fold_builtin_inf (location_t, tree, int);
aecda0d6 147static tree fold_builtin_nan (tree, tree, int);
389dd41b 148static tree rewrite_call_expr (location_t, tree, int, tree, int, ...);
b7bf20db 149static bool validate_arg (const_tree, enum tree_code code);
277f8dd2 150static bool integer_valued_real_p (tree);
389dd41b 151static tree fold_trunc_transparent_mathfn (location_t, tree, tree);
aecda0d6 152static bool readonly_data_expr (tree);
153static rtx expand_builtin_fabs (tree, rtx, rtx);
27f261ef 154static rtx expand_builtin_signbit (tree, rtx);
389dd41b 155static tree fold_builtin_sqrt (location_t, tree, tree);
156static tree fold_builtin_cbrt (location_t, tree, tree);
157static tree fold_builtin_pow (location_t, tree, tree, tree, tree);
158static tree fold_builtin_powi (location_t, tree, tree, tree, tree);
159static tree fold_builtin_cos (location_t, tree, tree, tree);
160static tree fold_builtin_cosh (location_t, tree, tree, tree);
bffb7645 161static tree fold_builtin_tan (tree, tree);
389dd41b 162static tree fold_builtin_trunc (location_t, tree, tree);
163static tree fold_builtin_floor (location_t, tree, tree);
164static tree fold_builtin_ceil (location_t, tree, tree);
165static tree fold_builtin_round (location_t, tree, tree);
166static tree fold_builtin_int_roundingfn (location_t, tree, tree);
10b9666f 167static tree fold_builtin_bitop (tree, tree);
389dd41b 168static tree fold_builtin_memory_op (location_t, tree, tree, tree, tree, bool, int);
169static tree fold_builtin_strchr (location_t, tree, tree, tree);
170static tree fold_builtin_memchr (location_t, tree, tree, tree, tree);
171static tree fold_builtin_memcmp (location_t, tree, tree, tree);
172static tree fold_builtin_strcmp (location_t, tree, tree);
173static tree fold_builtin_strncmp (location_t, tree, tree, tree);
174static tree fold_builtin_signbit (location_t, tree, tree);
175static tree fold_builtin_copysign (location_t, tree, tree, tree, tree);
176static tree fold_builtin_isascii (location_t, tree);
177static tree fold_builtin_toascii (location_t, tree);
178static tree fold_builtin_isdigit (location_t, tree);
179static tree fold_builtin_fabs (location_t, tree, tree);
180static tree fold_builtin_abs (location_t, tree, tree);
181static tree fold_builtin_unordered_cmp (location_t, tree, tree, tree, enum tree_code,
d5019fe8 182 enum tree_code);
389dd41b 183static tree fold_builtin_n (location_t, tree, tree *, int, bool);
184static tree fold_builtin_0 (location_t, tree, bool);
185static tree fold_builtin_1 (location_t, tree, tree, bool);
186static tree fold_builtin_2 (location_t, tree, tree, tree, bool);
187static tree fold_builtin_3 (location_t, tree, tree, tree, tree, bool);
188static tree fold_builtin_4 (location_t, tree, tree, tree, tree, tree, bool);
189static tree fold_builtin_varargs (location_t, tree, tree, bool);
190
191static tree fold_builtin_strpbrk (location_t, tree, tree, tree);
192static tree fold_builtin_strstr (location_t, tree, tree, tree);
193static tree fold_builtin_strrchr (location_t, tree, tree, tree);
194static tree fold_builtin_strcat (location_t, tree, tree);
195static tree fold_builtin_strncat (location_t, tree, tree, tree);
196static tree fold_builtin_strspn (location_t, tree, tree);
197static tree fold_builtin_strcspn (location_t, tree, tree);
198static tree fold_builtin_sprintf (location_t, tree, tree, tree, int);
750d7b16 199static tree fold_builtin_snprintf (location_t, tree, tree, tree, tree, int);
4ee9c684 200
0a39fd54 201static rtx expand_builtin_object_size (tree);
202static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
203 enum built_in_function);
204static void maybe_emit_chk_warning (tree, enum built_in_function);
205static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
2c281b15 206static void maybe_emit_free_warning (tree);
c2f47e15 207static tree fold_builtin_object_size (tree, tree);
389dd41b 208static tree fold_builtin_strcat_chk (location_t, tree, tree, tree, tree);
209static tree fold_builtin_strncat_chk (location_t, tree, tree, tree, tree, tree);
210static tree fold_builtin_sprintf_chk (location_t, tree, enum built_in_function);
211static tree fold_builtin_printf (location_t, tree, tree, tree, bool, enum built_in_function);
212static tree fold_builtin_fprintf (location_t, tree, tree, tree, tree, bool,
c2f47e15 213 enum built_in_function);
99eabcc1 214static bool init_target_chars (void);
215
216static unsigned HOST_WIDE_INT target_newline;
217static unsigned HOST_WIDE_INT target_percent;
218static unsigned HOST_WIDE_INT target_c;
219static unsigned HOST_WIDE_INT target_s;
220static char target_percent_c[3];
221static char target_percent_s[3];
222static char target_percent_s_newline[4];
728bac60 223static tree do_mpfr_arg1 (tree, tree, int (*)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
224 const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, bool);
f0c477f2 225static tree do_mpfr_arg2 (tree, tree, tree,
226 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
9917422b 227static tree do_mpfr_arg3 (tree, tree, tree, tree,
228 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
d92f994c 229static tree do_mpfr_sincos (tree, tree, tree);
65dd1378 230static tree do_mpfr_bessel_n (tree, tree, tree,
231 int (*)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
232 const REAL_VALUE_TYPE *, bool);
e5407ca6 233static tree do_mpfr_remquo (tree, tree, tree);
e84da7c1 234static tree do_mpfr_lgamma_r (tree, tree, tree);
1cd6e20d 235static void expand_builtin_sync_synchronize (void);
0a39fd54 236
7bfefa9d 237/* Return true if NAME starts with __builtin_ or __sync_. */
238
b29139ad 239static bool
1c47b3e8 240is_builtin_name (const char *name)
b6a5fc45 241{
b6a5fc45 242 if (strncmp (name, "__builtin_", 10) == 0)
243 return true;
244 if (strncmp (name, "__sync_", 7) == 0)
245 return true;
1cd6e20d 246 if (strncmp (name, "__atomic_", 9) == 0)
247 return true;
d037099f 248 if (flag_enable_cilkplus
249 && (!strcmp (name, "__cilkrts_detach")
250 || !strcmp (name, "__cilkrts_pop_frame")))
251 return true;
b6a5fc45 252 return false;
253}
4ee9c684 254
7bfefa9d 255
256/* Return true if DECL is a function symbol representing a built-in. */
257
258bool
259is_builtin_fn (tree decl)
260{
261 return TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl);
262}
263
30f690e0 264/* By default we assume that c99 functions are present at the runtime,
265 but sincos is not. */
266bool
267default_libc_has_function (enum function_class fn_class)
268{
269 if (fn_class == function_c94
270 || fn_class == function_c99_misc
271 || fn_class == function_c99_math_complex)
272 return true;
273
274 return false;
275}
276
277bool
278gnu_libc_has_function (enum function_class fn_class ATTRIBUTE_UNUSED)
279{
280 return true;
281}
282
283bool
284no_c99_libc_has_function (enum function_class fn_class ATTRIBUTE_UNUSED)
285{
286 return false;
287}
7bfefa9d 288
1c47b3e8 289/* Return true if NODE should be considered for inline expansion regardless
290 of the optimization level. This means whenever a function is invoked with
291 its "internal" name, which normally contains the prefix "__builtin". */
292
293static bool
294called_as_built_in (tree node)
295{
296 /* Note that we must use DECL_NAME, not DECL_ASSEMBLER_NAME_SET_P since
297 we want the name used to call the function, not the name it
298 will have. */
299 const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
300 return is_builtin_name (name);
301}
302
ceea063b 303/* Compute values M and N such that M divides (address of EXP - N) and such
304 that N < M. If these numbers can be determined, store M in alignp and N in
305 *BITPOSP and return true. Otherwise return false and store BITS_PER_UNIT to
306 *alignp and any bit-offset to *bitposp.
0d8f7716 307
308 Note that the address (and thus the alignment) computed here is based
309 on the address to which a symbol resolves, whereas DECL_ALIGN is based
310 on the address at which an object is actually located. These two
311 addresses are not always the same. For example, on ARM targets,
312 the address &foo of a Thumb function foo() has the lowest bit set,
3482bf13 313 whereas foo() itself starts on an even address.
698537d1 314
3482bf13 315 If ADDR_P is true we are taking the address of the memory reference EXP
316 and thus cannot rely on the access taking place. */
317
318static bool
319get_object_alignment_2 (tree exp, unsigned int *alignp,
320 unsigned HOST_WIDE_INT *bitposp, bool addr_p)
698537d1 321{
98ab9e8f 322 HOST_WIDE_INT bitsize, bitpos;
323 tree offset;
324 enum machine_mode mode;
325 int unsignedp, volatilep;
c8a2b4ff 326 unsigned int align = BITS_PER_UNIT;
ceea063b 327 bool known_alignment = false;
698537d1 328
98ab9e8f 329 /* Get the innermost object and the constant (bitpos) and possibly
330 variable (offset) offset of the access. */
331 exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
332 &mode, &unsignedp, &volatilep, true);
333
334 /* Extract alignment information from the innermost object and
335 possibly adjust bitpos and offset. */
3482bf13 336 if (TREE_CODE (exp) == FUNCTION_DECL)
0d8f7716 337 {
3482bf13 338 /* Function addresses can encode extra information besides their
339 alignment. However, if TARGET_PTRMEMFUNC_VBIT_LOCATION
340 allows the low bit to be used as a virtual bit, we know
341 that the address itself must be at least 2-byte aligned. */
342 if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn)
343 align = 2 * BITS_PER_UNIT;
0d8f7716 344 }
3482bf13 345 else if (TREE_CODE (exp) == LABEL_DECL)
346 ;
347 else if (TREE_CODE (exp) == CONST_DECL)
98ab9e8f 348 {
3482bf13 349 /* The alignment of a CONST_DECL is determined by its initializer. */
350 exp = DECL_INITIAL (exp);
98ab9e8f 351 align = TYPE_ALIGN (TREE_TYPE (exp));
352#ifdef CONSTANT_ALIGNMENT
3482bf13 353 if (CONSTANT_CLASS_P (exp))
354 align = (unsigned) CONSTANT_ALIGNMENT (exp, align);
698537d1 355#endif
3482bf13 356 known_alignment = true;
98ab9e8f 357 }
3482bf13 358 else if (DECL_P (exp))
ceea063b 359 {
3482bf13 360 align = DECL_ALIGN (exp);
ceea063b 361 known_alignment = true;
ceea063b 362 }
3482bf13 363 else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR)
ceea063b 364 {
ceea063b 365 align = TYPE_ALIGN (TREE_TYPE (exp));
366 }
3482bf13 367 else if (TREE_CODE (exp) == INDIRECT_REF
368 || TREE_CODE (exp) == MEM_REF
369 || TREE_CODE (exp) == TARGET_MEM_REF)
98ab9e8f 370 {
371 tree addr = TREE_OPERAND (exp, 0);
ceea063b 372 unsigned ptr_align;
373 unsigned HOST_WIDE_INT ptr_bitpos;
374
98ab9e8f 375 if (TREE_CODE (addr) == BIT_AND_EXPR
376 && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
377 {
f9ae6f95 378 align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))
379 & -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)));
98ab9e8f 380 align *= BITS_PER_UNIT;
381 addr = TREE_OPERAND (addr, 0);
382 }
ceea063b 383
3482bf13 384 known_alignment
385 = get_pointer_alignment_1 (addr, &ptr_align, &ptr_bitpos);
3482bf13 386 align = MAX (ptr_align, align);
387
4083990a 388 /* The alignment of the pointer operand in a TARGET_MEM_REF
389 has to take the variable offset parts into account. */
3482bf13 390 if (TREE_CODE (exp) == TARGET_MEM_REF)
153c3b50 391 {
3482bf13 392 if (TMR_INDEX (exp))
393 {
394 unsigned HOST_WIDE_INT step = 1;
395 if (TMR_STEP (exp))
f9ae6f95 396 step = TREE_INT_CST_LOW (TMR_STEP (exp));
3482bf13 397 align = MIN (align, (step & -step) * BITS_PER_UNIT);
398 }
399 if (TMR_INDEX2 (exp))
400 align = BITS_PER_UNIT;
401 known_alignment = false;
153c3b50 402 }
ceea063b 403
3482bf13 404 /* When EXP is an actual memory reference then we can use
405 TYPE_ALIGN of a pointer indirection to derive alignment.
406 Do so only if get_pointer_alignment_1 did not reveal absolute
4083990a 407 alignment knowledge and if using that alignment would
408 improve the situation. */
409 if (!addr_p && !known_alignment
410 && TYPE_ALIGN (TREE_TYPE (exp)) > align)
411 align = TYPE_ALIGN (TREE_TYPE (exp));
412 else
413 {
414 /* Else adjust bitpos accordingly. */
415 bitpos += ptr_bitpos;
416 if (TREE_CODE (exp) == MEM_REF
417 || TREE_CODE (exp) == TARGET_MEM_REF)
e913b5cd 418 bitpos += mem_ref_offset (exp).to_short_addr () * BITS_PER_UNIT;
4083990a 419 }
98ab9e8f 420 }
3482bf13 421 else if (TREE_CODE (exp) == STRING_CST)
153c3b50 422 {
3482bf13 423 /* STRING_CST are the only constant objects we allow to be not
424 wrapped inside a CONST_DECL. */
425 align = TYPE_ALIGN (TREE_TYPE (exp));
426#ifdef CONSTANT_ALIGNMENT
427 if (CONSTANT_CLASS_P (exp))
428 align = (unsigned) CONSTANT_ALIGNMENT (exp, align);
429#endif
430 known_alignment = true;
98ab9e8f 431 }
98ab9e8f 432
433 /* If there is a non-constant offset part extract the maximum
434 alignment that can prevail. */
c8a2b4ff 435 if (offset)
98ab9e8f 436 {
ad464c56 437 unsigned int trailing_zeros = tree_ctz (offset);
c8a2b4ff 438 if (trailing_zeros < HOST_BITS_PER_INT)
98ab9e8f 439 {
c8a2b4ff 440 unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
441 if (inner)
442 align = MIN (align, inner);
98ab9e8f 443 }
98ab9e8f 444 }
445
3482bf13 446 *alignp = align;
447 *bitposp = bitpos & (*alignp - 1);
ceea063b 448 return known_alignment;
0c883ef3 449}
450
3482bf13 451/* For a memory reference expression EXP compute values M and N such that M
452 divides (&EXP - N) and such that N < M. If these numbers can be determined,
453 store M in alignp and N in *BITPOSP and return true. Otherwise return false
454 and store BITS_PER_UNIT to *alignp and any bit-offset to *bitposp. */
455
456bool
457get_object_alignment_1 (tree exp, unsigned int *alignp,
458 unsigned HOST_WIDE_INT *bitposp)
459{
460 return get_object_alignment_2 (exp, alignp, bitposp, false);
461}
462
957d0361 463/* Return the alignment in bits of EXP, an object. */
0c883ef3 464
465unsigned int
957d0361 466get_object_alignment (tree exp)
0c883ef3 467{
468 unsigned HOST_WIDE_INT bitpos = 0;
469 unsigned int align;
470
ceea063b 471 get_object_alignment_1 (exp, &align, &bitpos);
0c883ef3 472
98ab9e8f 473 /* align and bitpos now specify known low bits of the pointer.
474 ptr & (align - 1) == bitpos. */
475
476 if (bitpos != 0)
477 align = (bitpos & -bitpos);
957d0361 478 return align;
698537d1 479}
480
ceea063b 481/* For a pointer valued expression EXP compute values M and N such that M
482 divides (EXP - N) and such that N < M. If these numbers can be determined,
3482bf13 483 store M in alignp and N in *BITPOSP and return true. Return false if
484 the results are just a conservative approximation.
53800dbe 485
ceea063b 486 If EXP is not a pointer, false is returned too. */
53800dbe 487
ceea063b 488bool
489get_pointer_alignment_1 (tree exp, unsigned int *alignp,
490 unsigned HOST_WIDE_INT *bitposp)
53800dbe 491{
153c3b50 492 STRIP_NOPS (exp);
535e2026 493
153c3b50 494 if (TREE_CODE (exp) == ADDR_EXPR)
3482bf13 495 return get_object_alignment_2 (TREE_OPERAND (exp, 0),
496 alignp, bitposp, true);
153c3b50 497 else if (TREE_CODE (exp) == SSA_NAME
498 && POINTER_TYPE_P (TREE_TYPE (exp)))
53800dbe 499 {
ceea063b 500 unsigned int ptr_align, ptr_misalign;
153c3b50 501 struct ptr_info_def *pi = SSA_NAME_PTR_INFO (exp);
ceea063b 502
503 if (pi && get_ptr_info_alignment (pi, &ptr_align, &ptr_misalign))
504 {
505 *bitposp = ptr_misalign * BITS_PER_UNIT;
506 *alignp = ptr_align * BITS_PER_UNIT;
3482bf13 507 /* We cannot really tell whether this result is an approximation. */
ceea063b 508 return true;
509 }
510 else
69fbc3aa 511 {
512 *bitposp = 0;
ceea063b 513 *alignp = BITS_PER_UNIT;
514 return false;
69fbc3aa 515 }
53800dbe 516 }
0bb8b39a 517 else if (TREE_CODE (exp) == INTEGER_CST)
518 {
519 *alignp = BIGGEST_ALIGNMENT;
f9ae6f95 520 *bitposp = ((TREE_INT_CST_LOW (exp) * BITS_PER_UNIT)
0bb8b39a 521 & (BIGGEST_ALIGNMENT - 1));
522 return true;
523 }
153c3b50 524
69fbc3aa 525 *bitposp = 0;
ceea063b 526 *alignp = BITS_PER_UNIT;
527 return false;
53800dbe 528}
529
69fbc3aa 530/* Return the alignment in bits of EXP, a pointer valued expression.
531 The alignment returned is, by default, the alignment of the thing that
532 EXP points to. If it is not a POINTER_TYPE, 0 is returned.
533
534 Otherwise, look at the expression to see if we can do better, i.e., if the
535 expression is actually pointing at an object whose alignment is tighter. */
536
537unsigned int
538get_pointer_alignment (tree exp)
539{
540 unsigned HOST_WIDE_INT bitpos = 0;
541 unsigned int align;
ceea063b 542
543 get_pointer_alignment_1 (exp, &align, &bitpos);
69fbc3aa 544
545 /* align and bitpos now specify known low bits of the pointer.
546 ptr & (align - 1) == bitpos. */
547
548 if (bitpos != 0)
549 align = (bitpos & -bitpos);
550
551 return align;
552}
553
53800dbe 554/* Compute the length of a C string. TREE_STRING_LENGTH is not the right
555 way, because it could contain a zero byte in the middle.
556 TREE_STRING_LENGTH is the size of the character array, not the string.
557
4172d65e 558 ONLY_VALUE should be nonzero if the result is not going to be emitted
c09841f6 559 into the instruction stream and zero if it is going to be expanded.
4172d65e 560 E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
681fab1e 561 is returned, otherwise NULL, since
562 len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
563 evaluate the side-effects.
564
902de8ed 565 The value returned is of type `ssizetype'.
566
53800dbe 567 Unfortunately, string_constant can't access the values of const char
568 arrays with initializers, so neither can we do so here. */
569
4ee9c684 570tree
681fab1e 571c_strlen (tree src, int only_value)
53800dbe 572{
573 tree offset_node;
27d0c333 574 HOST_WIDE_INT offset;
575 int max;
44acf429 576 const char *ptr;
da136652 577 location_t loc;
53800dbe 578
681fab1e 579 STRIP_NOPS (src);
580 if (TREE_CODE (src) == COND_EXPR
581 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
582 {
583 tree len1, len2;
584
585 len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
586 len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
0862b7e9 587 if (tree_int_cst_equal (len1, len2))
681fab1e 588 return len1;
589 }
590
591 if (TREE_CODE (src) == COMPOUND_EXPR
592 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
593 return c_strlen (TREE_OPERAND (src, 1), only_value);
594
3df42822 595 loc = EXPR_LOC_OR_LOC (src, input_location);
da136652 596
53800dbe 597 src = string_constant (src, &offset_node);
598 if (src == 0)
c2f47e15 599 return NULL_TREE;
902de8ed 600
83d79705 601 max = TREE_STRING_LENGTH (src) - 1;
53800dbe 602 ptr = TREE_STRING_POINTER (src);
902de8ed 603
53800dbe 604 if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
605 {
606 /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
607 compute the offset to the following null if we don't know where to
608 start searching for it. */
609 int i;
902de8ed 610
53800dbe 611 for (i = 0; i < max; i++)
612 if (ptr[i] == 0)
c2f47e15 613 return NULL_TREE;
902de8ed 614
53800dbe 615 /* We don't know the starting offset, but we do know that the string
616 has no internal zero bytes. We can assume that the offset falls
617 within the bounds of the string; otherwise, the programmer deserves
618 what he gets. Subtract the offset from the length of the string,
902de8ed 619 and return that. This would perhaps not be valid if we were dealing
620 with named arrays in addition to literal string constants. */
621
da136652 622 return size_diffop_loc (loc, size_int (max), offset_node);
53800dbe 623 }
624
625 /* We have a known offset into the string. Start searching there for
27d0c333 626 a null character if we can represent it as a single HOST_WIDE_INT. */
dabc4084 627 if (offset_node == 0)
53800dbe 628 offset = 0;
35ec552a 629 else if (! tree_fits_shwi_p (offset_node))
dabc4084 630 offset = -1;
53800dbe 631 else
e913b5cd 632 offset = tree_to_shwi (offset_node);
902de8ed 633
1f63a7d6 634 /* If the offset is known to be out of bounds, warn, and call strlen at
635 runtime. */
53800dbe 636 if (offset < 0 || offset > max)
637 {
1f63a7d6 638 /* Suppress multiple warnings for propagated constant strings. */
639 if (! TREE_NO_WARNING (src))
640 {
da136652 641 warning_at (loc, 0, "offset outside bounds of constant string");
1f63a7d6 642 TREE_NO_WARNING (src) = 1;
643 }
c2f47e15 644 return NULL_TREE;
53800dbe 645 }
902de8ed 646
53800dbe 647 /* Use strlen to search for the first zero byte. Since any strings
648 constructed with build_string will have nulls appended, we win even
649 if we get handed something like (char[4])"abcd".
650
651 Since OFFSET is our starting index into the string, no further
652 calculation is needed. */
902de8ed 653 return ssize_int (strlen (ptr + offset));
53800dbe 654}
655
83d79705 656/* Return a char pointer for a C string if it is a string constant
657 or sum of string constant and integer constant. */
658
659static const char *
aecda0d6 660c_getstr (tree src)
83d79705 661{
662 tree offset_node;
83d79705 663
664 src = string_constant (src, &offset_node);
665 if (src == 0)
666 return 0;
667
8c85fcb7 668 if (offset_node == 0)
669 return TREE_STRING_POINTER (src);
e913b5cd 670 else if (!tree_fits_uhwi_p (offset_node)
8c85fcb7 671 || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
83d79705 672 return 0;
83d79705 673
e913b5cd 674 return TREE_STRING_POINTER (src) + tree_to_uhwi (offset_node);
83d79705 675}
676
e913b5cd 677/* Return a constant integer corresponding to target reading
8c85fcb7 678 GET_MODE_BITSIZE (MODE) bits from string constant STR. */
ecc318ff 679
6840589f 680static rtx
aecda0d6 681c_readstr (const char *str, enum machine_mode mode)
6840589f 682{
6840589f 683 HOST_WIDE_INT ch;
684 unsigned int i, j;
e913b5cd 685 HOST_WIDE_INT tmp[MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_WIDE_INT];
0407eaee 686
687 gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
688
e913b5cd 689 unsigned int len = (GET_MODE_PRECISION (mode) + HOST_BITS_PER_WIDE_INT - 1)
690 / HOST_BITS_PER_WIDE_INT;
691
692 for (i = 0; i < len; i++)
693 tmp[i] = 0;
6840589f 694
6840589f 695 ch = 1;
696 for (i = 0; i < GET_MODE_SIZE (mode); i++)
697 {
698 j = i;
699 if (WORDS_BIG_ENDIAN)
700 j = GET_MODE_SIZE (mode) - i - 1;
701 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
ad8f8e52 702 && GET_MODE_SIZE (mode) >= UNITS_PER_WORD)
6840589f 703 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
704 j *= BITS_PER_UNIT;
7d3f6cc7 705
6840589f 706 if (ch)
707 ch = (unsigned char) str[i];
e913b5cd 708 tmp[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
6840589f 709 }
ddb1be65 710
ab2c1de8 711 wide_int c = wide_int::from_array (tmp, len, GET_MODE_PRECISION (mode));
e913b5cd 712 return immed_wide_int_const (c, mode);
6840589f 713}
714
ecc318ff 715/* Cast a target constant CST to target CHAR and if that value fits into
5206b159 716 host char type, return zero and put that value into variable pointed to by
ecc318ff 717 P. */
718
719static int
aecda0d6 720target_char_cast (tree cst, char *p)
ecc318ff 721{
722 unsigned HOST_WIDE_INT val, hostval;
723
c19686c5 724 if (TREE_CODE (cst) != INTEGER_CST
ecc318ff 725 || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
726 return 1;
727
e913b5cd 728 /* Do not care if it fits or not right here. */
f9ae6f95 729 val = TREE_INT_CST_LOW (cst);
e913b5cd 730
ecc318ff 731 if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
732 val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
733
734 hostval = val;
735 if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
736 hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
737
738 if (val != hostval)
739 return 1;
740
741 *p = hostval;
742 return 0;
743}
744
4ee9c684 745/* Similar to save_expr, but assumes that arbitrary code is not executed
746 in between the multiple evaluations. In particular, we assume that a
747 non-addressable local variable will not be modified. */
748
749static tree
750builtin_save_expr (tree exp)
751{
f6c35aa4 752 if (TREE_CODE (exp) == SSA_NAME
753 || (TREE_ADDRESSABLE (exp) == 0
754 && (TREE_CODE (exp) == PARM_DECL
755 || (TREE_CODE (exp) == VAR_DECL && !TREE_STATIC (exp)))))
4ee9c684 756 return exp;
757
758 return save_expr (exp);
759}
760
53800dbe 761/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
762 times to get the address of either a higher stack frame, or a return
763 address located within it (depending on FNDECL_CODE). */
902de8ed 764
c626df3d 765static rtx
869d0ef0 766expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
53800dbe 767{
768 int i;
769
869d0ef0 770#ifdef INITIAL_FRAME_ADDRESS_RTX
771 rtx tem = INITIAL_FRAME_ADDRESS_RTX;
772#else
e3e15c50 773 rtx tem;
774
1b74fde7 775 /* For a zero count with __builtin_return_address, we don't care what
776 frame address we return, because target-specific definitions will
777 override us. Therefore frame pointer elimination is OK, and using
778 the soft frame pointer is OK.
779
fa7637bd 780 For a nonzero count, or a zero count with __builtin_frame_address,
1b74fde7 781 we require a stable offset from the current frame pointer to the
782 previous one, so we must use the hard frame pointer, and
e3e15c50 783 we must disable frame pointer elimination. */
1b74fde7 784 if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
e3e15c50 785 tem = frame_pointer_rtx;
a0c938f0 786 else
e3e15c50 787 {
788 tem = hard_frame_pointer_rtx;
789
790 /* Tell reload not to eliminate the frame pointer. */
18d50ae6 791 crtl->accesses_prior_frames = 1;
e3e15c50 792 }
869d0ef0 793#endif
794
53800dbe 795 /* Some machines need special handling before we can access
3a69c60c 796 arbitrary frames. For example, on the SPARC, we must first flush
53800dbe 797 all register windows to the stack. */
798#ifdef SETUP_FRAME_ADDRESSES
799 if (count > 0)
800 SETUP_FRAME_ADDRESSES ();
801#endif
802
3a69c60c 803 /* On the SPARC, the return address is not in the frame, it is in a
53800dbe 804 register. There is no way to access it off of the current frame
805 pointer, but it can be accessed off the previous frame pointer by
806 reading the value from the register window save area. */
807#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
808 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
809 count--;
810#endif
811
812 /* Scan back COUNT frames to the specified frame. */
813 for (i = 0; i < count; i++)
814 {
815 /* Assume the dynamic chain pointer is in the word that the
816 frame address points to, unless otherwise specified. */
817#ifdef DYNAMIC_CHAIN_ADDRESS
818 tem = DYNAMIC_CHAIN_ADDRESS (tem);
819#endif
820 tem = memory_address (Pmode, tem);
00060fc2 821 tem = gen_frame_mem (Pmode, tem);
83fc1478 822 tem = copy_to_reg (tem);
53800dbe 823 }
824
3a69c60c 825 /* For __builtin_frame_address, return what we've got. But, on
826 the SPARC for example, we may have to add a bias. */
53800dbe 827 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
3a69c60c 828#ifdef FRAME_ADDR_RTX
829 return FRAME_ADDR_RTX (tem);
830#else
53800dbe 831 return tem;
3a69c60c 832#endif
53800dbe 833
3a69c60c 834 /* For __builtin_return_address, get the return address from that frame. */
53800dbe 835#ifdef RETURN_ADDR_RTX
836 tem = RETURN_ADDR_RTX (count, tem);
837#else
838 tem = memory_address (Pmode,
29c05e22 839 plus_constant (Pmode, tem, GET_MODE_SIZE (Pmode)));
00060fc2 840 tem = gen_frame_mem (Pmode, tem);
53800dbe 841#endif
842 return tem;
843}
844
f7c44134 845/* Alias set used for setjmp buffer. */
32c2fdea 846static alias_set_type setjmp_alias_set = -1;
f7c44134 847
6b7f6858 848/* Construct the leading half of a __builtin_setjmp call. Control will
2c8a1497 849 return to RECEIVER_LABEL. This is also called directly by the SJLJ
850 exception handling code. */
53800dbe 851
6b7f6858 852void
aecda0d6 853expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
53800dbe 854{
53800dbe 855 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
53800dbe 856 rtx stack_save;
f7c44134 857 rtx mem;
53800dbe 858
f7c44134 859 if (setjmp_alias_set == -1)
860 setjmp_alias_set = new_alias_set ();
861
85d654dd 862 buf_addr = convert_memory_address (Pmode, buf_addr);
53800dbe 863
37ae8504 864 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
53800dbe 865
6b7f6858 866 /* We store the frame pointer and the address of receiver_label in
867 the buffer and use the rest of it for the stack save area, which
868 is machine-dependent. */
53800dbe 869
f7c44134 870 mem = gen_rtx_MEM (Pmode, buf_addr);
ab6ab77e 871 set_mem_alias_set (mem, setjmp_alias_set);
e3e026e8 872 emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
f7c44134 873
29c05e22 874 mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
875 GET_MODE_SIZE (Pmode))),
ab6ab77e 876 set_mem_alias_set (mem, setjmp_alias_set);
f7c44134 877
878 emit_move_insn (validize_mem (mem),
6b7f6858 879 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
53800dbe 880
881 stack_save = gen_rtx_MEM (sa_mode,
29c05e22 882 plus_constant (Pmode, buf_addr,
53800dbe 883 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 884 set_mem_alias_set (stack_save, setjmp_alias_set);
e9c97615 885 emit_stack_save (SAVE_NONLOCAL, &stack_save);
53800dbe 886
887 /* If there is further processing to do, do it. */
888#ifdef HAVE_builtin_setjmp_setup
889 if (HAVE_builtin_setjmp_setup)
890 emit_insn (gen_builtin_setjmp_setup (buf_addr));
891#endif
892
29f09705 893 /* We have a nonlocal label. */
18d50ae6 894 cfun->has_nonlocal_label = 1;
6b7f6858 895}
53800dbe 896
2c8a1497 897/* Construct the trailing part of a __builtin_setjmp call. This is
4598ade9 898 also called directly by the SJLJ exception handling code.
899 If RECEIVER_LABEL is NULL, instead contruct a nonlocal goto handler. */
6b7f6858 900
901void
aecda0d6 902expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
6b7f6858 903{
82c7907c 904 rtx chain;
905
4598ade9 906 /* Mark the FP as used when we get here, so we have to make sure it's
53800dbe 907 marked as used by this function. */
18b42941 908 emit_use (hard_frame_pointer_rtx);
53800dbe 909
910 /* Mark the static chain as clobbered here so life information
911 doesn't get messed up for it. */
82c7907c 912 chain = targetm.calls.static_chain (current_function_decl, true);
913 if (chain && REG_P (chain))
914 emit_clobber (chain);
53800dbe 915
916 /* Now put in the code to restore the frame pointer, and argument
491e04ef 917 pointer, if needed. */
53800dbe 918#ifdef HAVE_nonlocal_goto
919 if (! HAVE_nonlocal_goto)
920#endif
4598ade9 921 /* First adjust our frame pointer to its actual value. It was
922 previously set to the start of the virtual area corresponding to
923 the stacked variables when we branched here and now needs to be
924 adjusted to the actual hardware fp value.
925
926 Assignments to virtual registers are converted by
927 instantiate_virtual_regs into the corresponding assignment
928 to the underlying register (fp in this case) that makes
929 the original assignment true.
930 So the following insn will actually be decrementing fp by
931 STARTING_FRAME_OFFSET. */
932 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
53800dbe 933
5ae82d58 934#if !HARD_FRAME_POINTER_IS_ARG_POINTER
53800dbe 935 if (fixed_regs[ARG_POINTER_REGNUM])
936 {
937#ifdef ELIMINABLE_REGS
4598ade9 938 /* If the argument pointer can be eliminated in favor of the
939 frame pointer, we don't need to restore it. We assume here
940 that if such an elimination is present, it can always be used.
941 This is the case on all known machines; if we don't make this
942 assumption, we do unnecessary saving on many machines. */
53800dbe 943 size_t i;
e99c3a1d 944 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
53800dbe 945
3098b2d3 946 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
53800dbe 947 if (elim_regs[i].from == ARG_POINTER_REGNUM
948 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
949 break;
950
3098b2d3 951 if (i == ARRAY_SIZE (elim_regs))
53800dbe 952#endif
953 {
954 /* Now restore our arg pointer from the address at which it
05927e40 955 was saved in our stack frame. */
27a7a23a 956 emit_move_insn (crtl->args.internal_arg_pointer,
b079a207 957 copy_to_reg (get_arg_pointer_save_area ()));
53800dbe 958 }
959 }
960#endif
961
962#ifdef HAVE_builtin_setjmp_receiver
4598ade9 963 if (receiver_label != NULL && HAVE_builtin_setjmp_receiver)
6b7f6858 964 emit_insn (gen_builtin_setjmp_receiver (receiver_label));
53800dbe 965 else
966#endif
967#ifdef HAVE_nonlocal_goto_receiver
968 if (HAVE_nonlocal_goto_receiver)
969 emit_insn (gen_nonlocal_goto_receiver ());
970 else
971#endif
6b7f6858 972 { /* Nothing */ }
57f6bb94 973
3072d30e 974 /* We must not allow the code we just generated to be reordered by
975 scheduling. Specifically, the update of the frame pointer must
e12b44a3 976 happen immediately, not later. Similarly, we must block
977 (frame-related) register values to be used across this code. */
3072d30e 978 emit_insn (gen_blockage ());
6b7f6858 979}
53800dbe 980
53800dbe 981/* __builtin_longjmp is passed a pointer to an array of five words (not
982 all will be used on all machines). It operates similarly to the C
983 library function of the same name, but is more efficient. Much of
2c8a1497 984 the code below is copied from the handling of non-local gotos. */
53800dbe 985
c626df3d 986static void
aecda0d6 987expand_builtin_longjmp (rtx buf_addr, rtx value)
53800dbe 988{
4712c7d6 989 rtx fp, lab, stack, insn, last;
53800dbe 990 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
991
48e1416a 992 /* DRAP is needed for stack realign if longjmp is expanded to current
27a7a23a 993 function */
994 if (SUPPORTS_STACK_ALIGNMENT)
995 crtl->need_drap = true;
996
f7c44134 997 if (setjmp_alias_set == -1)
998 setjmp_alias_set = new_alias_set ();
999
85d654dd 1000 buf_addr = convert_memory_address (Pmode, buf_addr);
479e4d5e 1001
53800dbe 1002 buf_addr = force_reg (Pmode, buf_addr);
1003
82c7907c 1004 /* We require that the user must pass a second argument of 1, because
1005 that is what builtin_setjmp will return. */
64db345d 1006 gcc_assert (value == const1_rtx);
53800dbe 1007
4712c7d6 1008 last = get_last_insn ();
53800dbe 1009#ifdef HAVE_builtin_longjmp
1010 if (HAVE_builtin_longjmp)
1011 emit_insn (gen_builtin_longjmp (buf_addr));
1012 else
1013#endif
1014 {
1015 fp = gen_rtx_MEM (Pmode, buf_addr);
29c05e22 1016 lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
53800dbe 1017 GET_MODE_SIZE (Pmode)));
1018
29c05e22 1019 stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, buf_addr,
53800dbe 1020 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 1021 set_mem_alias_set (fp, setjmp_alias_set);
1022 set_mem_alias_set (lab, setjmp_alias_set);
1023 set_mem_alias_set (stack, setjmp_alias_set);
53800dbe 1024
1025 /* Pick up FP, label, and SP from the block and jump. This code is
1026 from expand_goto in stmt.c; see there for detailed comments. */
03fd9d2c 1027#ifdef HAVE_nonlocal_goto
53800dbe 1028 if (HAVE_nonlocal_goto)
1029 /* We have to pass a value to the nonlocal_goto pattern that will
1030 get copied into the static_chain pointer, but it does not matter
1031 what that value is, because builtin_setjmp does not use it. */
28d202a8 1032 emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
53800dbe 1033 else
1034#endif
1035 {
1036 lab = copy_to_reg (lab);
1037
18b42941 1038 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
1039 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
2a871ad1 1040
53800dbe 1041 emit_move_insn (hard_frame_pointer_rtx, fp);
e9c97615 1042 emit_stack_restore (SAVE_NONLOCAL, stack);
53800dbe 1043
18b42941 1044 emit_use (hard_frame_pointer_rtx);
1045 emit_use (stack_pointer_rtx);
53800dbe 1046 emit_indirect_jump (lab);
1047 }
1048 }
615166bb 1049
1050 /* Search backwards and mark the jump insn as a non-local goto.
1051 Note that this precludes the use of __builtin_longjmp to a
1052 __builtin_setjmp target in the same function. However, we've
1053 already cautioned the user that these functions are for
1054 internal exception handling use only. */
449c0509 1055 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
1056 {
64db345d 1057 gcc_assert (insn != last);
7d3f6cc7 1058
6d7dc5b9 1059 if (JUMP_P (insn))
449c0509 1060 {
a1ddb869 1061 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
449c0509 1062 break;
1063 }
6d7dc5b9 1064 else if (CALL_P (insn))
9342ee68 1065 break;
449c0509 1066 }
53800dbe 1067}
1068
0e80b01d 1069static inline bool
1070more_const_call_expr_args_p (const const_call_expr_arg_iterator *iter)
1071{
1072 return (iter->i < iter->n);
1073}
1074
1075/* This function validates the types of a function call argument list
1076 against a specified list of tree_codes. If the last specifier is a 0,
1077 that represents an ellipses, otherwise the last specifier must be a
1078 VOID_TYPE. */
1079
1080static bool
1081validate_arglist (const_tree callexpr, ...)
1082{
1083 enum tree_code code;
1084 bool res = 0;
1085 va_list ap;
1086 const_call_expr_arg_iterator iter;
1087 const_tree arg;
1088
1089 va_start (ap, callexpr);
1090 init_const_call_expr_arg_iterator (callexpr, &iter);
1091
1092 do
1093 {
1094 code = (enum tree_code) va_arg (ap, int);
1095 switch (code)
1096 {
1097 case 0:
1098 /* This signifies an ellipses, any further arguments are all ok. */
1099 res = true;
1100 goto end;
1101 case VOID_TYPE:
1102 /* This signifies an endlink, if no arguments remain, return
1103 true, otherwise return false. */
1104 res = !more_const_call_expr_args_p (&iter);
1105 goto end;
1106 default:
1107 /* If no parameters remain or the parameter's code does not
1108 match the specified code, return false. Otherwise continue
1109 checking any remaining arguments. */
1110 arg = next_const_call_expr_arg (&iter);
1111 if (!validate_arg (arg, code))
1112 goto end;
1113 break;
1114 }
1115 }
1116 while (1);
1117
1118 /* We need gotos here since we can only have one VA_CLOSE in a
1119 function. */
1120 end: ;
1121 va_end (ap);
1122
1123 return res;
1124}
1125
4ee9c684 1126/* Expand a call to __builtin_nonlocal_goto. We're passed the target label
1127 and the address of the save area. */
1128
1129static rtx
c2f47e15 1130expand_builtin_nonlocal_goto (tree exp)
4ee9c684 1131{
1132 tree t_label, t_save_area;
1133 rtx r_label, r_save_area, r_fp, r_sp, insn;
1134
c2f47e15 1135 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4ee9c684 1136 return NULL_RTX;
1137
c2f47e15 1138 t_label = CALL_EXPR_ARG (exp, 0);
1139 t_save_area = CALL_EXPR_ARG (exp, 1);
4ee9c684 1140
8ec3c5c2 1141 r_label = expand_normal (t_label);
3dce56cc 1142 r_label = convert_memory_address (Pmode, r_label);
8ec3c5c2 1143 r_save_area = expand_normal (t_save_area);
3dce56cc 1144 r_save_area = convert_memory_address (Pmode, r_save_area);
d1ff492e 1145 /* Copy the address of the save location to a register just in case it was
1146 based on the frame pointer. */
51adbc8a 1147 r_save_area = copy_to_reg (r_save_area);
4ee9c684 1148 r_fp = gen_rtx_MEM (Pmode, r_save_area);
1149 r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
29c05e22 1150 plus_constant (Pmode, r_save_area,
1151 GET_MODE_SIZE (Pmode)));
4ee9c684 1152
18d50ae6 1153 crtl->has_nonlocal_goto = 1;
4ee9c684 1154
03fd9d2c 1155#ifdef HAVE_nonlocal_goto
4ee9c684 1156 /* ??? We no longer need to pass the static chain value, afaik. */
1157 if (HAVE_nonlocal_goto)
1158 emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
1159 else
1160#endif
1161 {
1162 r_label = copy_to_reg (r_label);
1163
18b42941 1164 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
1165 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
491e04ef 1166
d1ff492e 1167 /* Restore frame pointer for containing function. */
4ee9c684 1168 emit_move_insn (hard_frame_pointer_rtx, r_fp);
e9c97615 1169 emit_stack_restore (SAVE_NONLOCAL, r_sp);
491e04ef 1170
4ee9c684 1171 /* USE of hard_frame_pointer_rtx added for consistency;
1172 not clear if really needed. */
18b42941 1173 emit_use (hard_frame_pointer_rtx);
1174 emit_use (stack_pointer_rtx);
ad0d0af8 1175
1176 /* If the architecture is using a GP register, we must
1177 conservatively assume that the target function makes use of it.
1178 The prologue of functions with nonlocal gotos must therefore
1179 initialize the GP register to the appropriate value, and we
1180 must then make sure that this value is live at the point
1181 of the jump. (Note that this doesn't necessarily apply
1182 to targets with a nonlocal_goto pattern; they are free
1183 to implement it in their own way. Note also that this is
1184 a no-op if the GP register is a global invariant.) */
1185 if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
1186 && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
18b42941 1187 emit_use (pic_offset_table_rtx);
ad0d0af8 1188
4ee9c684 1189 emit_indirect_jump (r_label);
1190 }
491e04ef 1191
4ee9c684 1192 /* Search backwards to the jump insn and mark it as a
1193 non-local goto. */
1194 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
1195 {
6d7dc5b9 1196 if (JUMP_P (insn))
4ee9c684 1197 {
a1ddb869 1198 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
4ee9c684 1199 break;
1200 }
6d7dc5b9 1201 else if (CALL_P (insn))
4ee9c684 1202 break;
1203 }
1204
1205 return const0_rtx;
1206}
1207
843d08a9 1208/* __builtin_update_setjmp_buf is passed a pointer to an array of five words
1209 (not all will be used on all machines) that was passed to __builtin_setjmp.
1210 It updates the stack pointer in that block to correspond to the current
1211 stack pointer. */
1212
1213static void
1214expand_builtin_update_setjmp_buf (rtx buf_addr)
1215{
d1ff492e 1216 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
1217 rtx stack_save
843d08a9 1218 = gen_rtx_MEM (sa_mode,
1219 memory_address
1220 (sa_mode,
29c05e22 1221 plus_constant (Pmode, buf_addr,
1222 2 * GET_MODE_SIZE (Pmode))));
843d08a9 1223
e9c97615 1224 emit_stack_save (SAVE_NONLOCAL, &stack_save);
843d08a9 1225}
1226
5e3608d8 1227/* Expand a call to __builtin_prefetch. For a target that does not support
1228 data prefetch, evaluate the memory address argument in case it has side
1229 effects. */
1230
1231static void
c2f47e15 1232expand_builtin_prefetch (tree exp)
5e3608d8 1233{
1234 tree arg0, arg1, arg2;
c2f47e15 1235 int nargs;
5e3608d8 1236 rtx op0, op1, op2;
1237
c2f47e15 1238 if (!validate_arglist (exp, POINTER_TYPE, 0))
26a5cadb 1239 return;
1240
c2f47e15 1241 arg0 = CALL_EXPR_ARG (exp, 0);
1242
26a5cadb 1243 /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
1244 zero (read) and argument 2 (locality) defaults to 3 (high degree of
1245 locality). */
c2f47e15 1246 nargs = call_expr_nargs (exp);
1247 if (nargs > 1)
1248 arg1 = CALL_EXPR_ARG (exp, 1);
26a5cadb 1249 else
c2f47e15 1250 arg1 = integer_zero_node;
1251 if (nargs > 2)
1252 arg2 = CALL_EXPR_ARG (exp, 2);
1253 else
2512209b 1254 arg2 = integer_three_node;
5e3608d8 1255
1256 /* Argument 0 is an address. */
1257 op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
1258
1259 /* Argument 1 (read/write flag) must be a compile-time constant int. */
1260 if (TREE_CODE (arg1) != INTEGER_CST)
1261 {
07e3a3d2 1262 error ("second argument to %<__builtin_prefetch%> must be a constant");
9342ee68 1263 arg1 = integer_zero_node;
5e3608d8 1264 }
8ec3c5c2 1265 op1 = expand_normal (arg1);
5e3608d8 1266 /* Argument 1 must be either zero or one. */
1267 if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
1268 {
c3ceba8e 1269 warning (0, "invalid second argument to %<__builtin_prefetch%>;"
07e3a3d2 1270 " using zero");
5e3608d8 1271 op1 = const0_rtx;
1272 }
1273
1274 /* Argument 2 (locality) must be a compile-time constant int. */
1275 if (TREE_CODE (arg2) != INTEGER_CST)
1276 {
07e3a3d2 1277 error ("third argument to %<__builtin_prefetch%> must be a constant");
5e3608d8 1278 arg2 = integer_zero_node;
1279 }
8ec3c5c2 1280 op2 = expand_normal (arg2);
5e3608d8 1281 /* Argument 2 must be 0, 1, 2, or 3. */
1282 if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
1283 {
c3ceba8e 1284 warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
5e3608d8 1285 op2 = const0_rtx;
1286 }
1287
1288#ifdef HAVE_prefetch
1289 if (HAVE_prefetch)
1290 {
8786db1e 1291 struct expand_operand ops[3];
1292
1293 create_address_operand (&ops[0], op0);
1294 create_integer_operand (&ops[1], INTVAL (op1));
1295 create_integer_operand (&ops[2], INTVAL (op2));
1296 if (maybe_expand_insn (CODE_FOR_prefetch, 3, ops))
1297 return;
5e3608d8 1298 }
5e3608d8 1299#endif
0a534ba7 1300
f0ce3b1f 1301 /* Don't do anything with direct references to volatile memory, but
1302 generate code to handle other side effects. */
e16ceb8e 1303 if (!MEM_P (op0) && side_effects_p (op0))
f0ce3b1f 1304 emit_insn (op0);
5e3608d8 1305}
1306
f7c44134 1307/* Get a MEM rtx for expression EXP which is the address of an operand
d8ae1baa 1308 to be used in a string instruction (cmpstrsi, movmemsi, ..). LEN is
1309 the maximum length of the block of memory that might be accessed or
1310 NULL if unknown. */
f7c44134 1311
53800dbe 1312static rtx
d8ae1baa 1313get_memory_rtx (tree exp, tree len)
53800dbe 1314{
ad0a178f 1315 tree orig_exp = exp;
1316 rtx addr, mem;
ad0a178f 1317
1318 /* When EXP is not resolved SAVE_EXPR, MEM_ATTRS can be still derived
1319 from its expression, for expr->a.b only <variable>.a.b is recorded. */
1320 if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp))
1321 exp = TREE_OPERAND (exp, 0);
1322
1323 addr = expand_expr (orig_exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
1324 mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
2a631e19 1325
f7c44134 1326 /* Get an expression we can use to find the attributes to assign to MEM.
5dd3f78f 1327 First remove any nops. */
72dd6141 1328 while (CONVERT_EXPR_P (exp)
f7c44134 1329 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
1330 exp = TREE_OPERAND (exp, 0);
1331
5dd3f78f 1332 /* Build a MEM_REF representing the whole accessed area as a byte blob,
1333 (as builtin stringops may alias with anything). */
1334 exp = fold_build2 (MEM_REF,
1335 build_array_type (char_type_node,
1336 build_range_type (sizetype,
1337 size_one_node, len)),
1338 exp, build_int_cst (ptr_type_node, 0));
1339
1340 /* If the MEM_REF has no acceptable address, try to get the base object
1341 from the original address we got, and build an all-aliasing
1342 unknown-sized access to that one. */
1343 if (is_gimple_mem_ref_addr (TREE_OPERAND (exp, 0)))
1344 set_mem_attributes (mem, exp, 0);
1345 else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
1346 && (exp = get_base_address (TREE_OPERAND (TREE_OPERAND (exp, 0),
1347 0))))
eec8e941 1348 {
5dd3f78f 1349 exp = build_fold_addr_expr (exp);
1350 exp = fold_build2 (MEM_REF,
1351 build_array_type (char_type_node,
1352 build_range_type (sizetype,
1353 size_zero_node,
1354 NULL)),
1355 exp, build_int_cst (ptr_type_node, 0));
a1a25d19 1356 set_mem_attributes (mem, exp, 0);
eec8e941 1357 }
5dd3f78f 1358 set_mem_alias_set (mem, 0);
53800dbe 1359 return mem;
1360}
1361\f
1362/* Built-in functions to perform an untyped call and return. */
1363
3b9c3a16 1364#define apply_args_mode \
1365 (this_target_builtins->x_apply_args_mode)
1366#define apply_result_mode \
1367 (this_target_builtins->x_apply_result_mode)
53800dbe 1368
53800dbe 1369/* Return the size required for the block returned by __builtin_apply_args,
1370 and initialize apply_args_mode. */
1371
1372static int
aecda0d6 1373apply_args_size (void)
53800dbe 1374{
1375 static int size = -1;
58e9ce8f 1376 int align;
1377 unsigned int regno;
53800dbe 1378 enum machine_mode mode;
1379
1380 /* The values computed by this function never change. */
1381 if (size < 0)
1382 {
1383 /* The first value is the incoming arg-pointer. */
1384 size = GET_MODE_SIZE (Pmode);
1385
1386 /* The second value is the structure value address unless this is
1387 passed as an "invisible" first argument. */
6812c89e 1388 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1389 size += GET_MODE_SIZE (Pmode);
1390
1391 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1392 if (FUNCTION_ARG_REGNO_P (regno))
1393 {
4bac51c9 1394 mode = targetm.calls.get_raw_arg_mode (regno);
0862b7e9 1395
64db345d 1396 gcc_assert (mode != VOIDmode);
53800dbe 1397
1398 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1399 if (size % align != 0)
1400 size = CEIL (size, align) * align;
53800dbe 1401 size += GET_MODE_SIZE (mode);
1402 apply_args_mode[regno] = mode;
1403 }
1404 else
1405 {
1406 apply_args_mode[regno] = VOIDmode;
53800dbe 1407 }
1408 }
1409 return size;
1410}
1411
1412/* Return the size required for the block returned by __builtin_apply,
1413 and initialize apply_result_mode. */
1414
1415static int
aecda0d6 1416apply_result_size (void)
53800dbe 1417{
1418 static int size = -1;
1419 int align, regno;
1420 enum machine_mode mode;
1421
1422 /* The values computed by this function never change. */
1423 if (size < 0)
1424 {
1425 size = 0;
1426
1427 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
e1ce1485 1428 if (targetm.calls.function_value_regno_p (regno))
53800dbe 1429 {
4bac51c9 1430 mode = targetm.calls.get_raw_result_mode (regno);
0862b7e9 1431
64db345d 1432 gcc_assert (mode != VOIDmode);
53800dbe 1433
1434 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1435 if (size % align != 0)
1436 size = CEIL (size, align) * align;
1437 size += GET_MODE_SIZE (mode);
1438 apply_result_mode[regno] = mode;
1439 }
1440 else
1441 apply_result_mode[regno] = VOIDmode;
1442
1443 /* Allow targets that use untyped_call and untyped_return to override
1444 the size so that machine-specific information can be stored here. */
1445#ifdef APPLY_RESULT_SIZE
1446 size = APPLY_RESULT_SIZE;
1447#endif
1448 }
1449 return size;
1450}
1451
1452#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1453/* Create a vector describing the result block RESULT. If SAVEP is true,
1454 the result block is used to save the values; otherwise it is used to
1455 restore the values. */
1456
1457static rtx
aecda0d6 1458result_vector (int savep, rtx result)
53800dbe 1459{
1460 int regno, size, align, nelts;
1461 enum machine_mode mode;
1462 rtx reg, mem;
364c0c59 1463 rtx *savevec = XALLOCAVEC (rtx, FIRST_PSEUDO_REGISTER);
bf8e3599 1464
53800dbe 1465 size = nelts = 0;
1466 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1467 if ((mode = apply_result_mode[regno]) != VOIDmode)
1468 {
1469 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1470 if (size % align != 0)
1471 size = CEIL (size, align) * align;
1472 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
e513d163 1473 mem = adjust_address (result, mode, size);
53800dbe 1474 savevec[nelts++] = (savep
1475 ? gen_rtx_SET (VOIDmode, mem, reg)
1476 : gen_rtx_SET (VOIDmode, reg, mem));
1477 size += GET_MODE_SIZE (mode);
1478 }
1479 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1480}
1481#endif /* HAVE_untyped_call or HAVE_untyped_return */
1482
1483/* Save the state required to perform an untyped call with the same
1484 arguments as were passed to the current function. */
1485
1486static rtx
aecda0d6 1487expand_builtin_apply_args_1 (void)
53800dbe 1488{
1c7e61a7 1489 rtx registers, tem;
53800dbe 1490 int size, align, regno;
1491 enum machine_mode mode;
6812c89e 1492 rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
53800dbe 1493
1494 /* Create a block where the arg-pointer, structure value address,
1495 and argument registers can be saved. */
1496 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1497
1498 /* Walk past the arg-pointer and structure value address. */
1499 size = GET_MODE_SIZE (Pmode);
6812c89e 1500 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1501 size += GET_MODE_SIZE (Pmode);
1502
1503 /* Save each register used in calling a function to the block. */
1504 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1505 if ((mode = apply_args_mode[regno]) != VOIDmode)
1506 {
53800dbe 1507 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1508 if (size % align != 0)
1509 size = CEIL (size, align) * align;
1510
1511 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1512
e513d163 1513 emit_move_insn (adjust_address (registers, mode, size), tem);
53800dbe 1514 size += GET_MODE_SIZE (mode);
1515 }
1516
1517 /* Save the arg pointer to the block. */
27a7a23a 1518 tem = copy_to_reg (crtl->args.internal_arg_pointer);
f083a92b 1519#ifdef STACK_GROWS_DOWNWARD
1c7e61a7 1520 /* We need the pointer as the caller actually passed them to us, not
9d4b544c 1521 as we might have pretended they were passed. Make sure it's a valid
1522 operand, as emit_move_insn isn't expected to handle a PLUS. */
1523 tem
29c05e22 1524 = force_operand (plus_constant (Pmode, tem, crtl->args.pretend_args_size),
9d4b544c 1525 NULL_RTX);
1c7e61a7 1526#endif
1527 emit_move_insn (adjust_address (registers, Pmode, 0), tem);
0862b7e9 1528
53800dbe 1529 size = GET_MODE_SIZE (Pmode);
1530
1531 /* Save the structure value address unless this is passed as an
1532 "invisible" first argument. */
45550790 1533 if (struct_incoming_value)
53800dbe 1534 {
e513d163 1535 emit_move_insn (adjust_address (registers, Pmode, size),
45550790 1536 copy_to_reg (struct_incoming_value));
53800dbe 1537 size += GET_MODE_SIZE (Pmode);
1538 }
1539
1540 /* Return the address of the block. */
1541 return copy_addr_to_reg (XEXP (registers, 0));
1542}
1543
1544/* __builtin_apply_args returns block of memory allocated on
1545 the stack into which is stored the arg pointer, structure
1546 value address, static chain, and all the registers that might
1547 possibly be used in performing a function call. The code is
1548 moved to the start of the function so the incoming values are
1549 saved. */
27d0c333 1550
53800dbe 1551static rtx
aecda0d6 1552expand_builtin_apply_args (void)
53800dbe 1553{
1554 /* Don't do __builtin_apply_args more than once in a function.
1555 Save the result of the first call and reuse it. */
1556 if (apply_args_value != 0)
1557 return apply_args_value;
1558 {
1559 /* When this function is called, it means that registers must be
1560 saved on entry to this function. So we migrate the
1561 call to the first insn of this function. */
1562 rtx temp;
1563 rtx seq;
1564
1565 start_sequence ();
1566 temp = expand_builtin_apply_args_1 ();
1567 seq = get_insns ();
1568 end_sequence ();
1569
1570 apply_args_value = temp;
1571
31d3e01c 1572 /* Put the insns after the NOTE that starts the function.
1573 If this is inside a start_sequence, make the outer-level insn
53800dbe 1574 chain current, so the code is placed at the start of the
0ef1a651 1575 function. If internal_arg_pointer is a non-virtual pseudo,
1576 it needs to be placed after the function that initializes
1577 that pseudo. */
53800dbe 1578 push_topmost_sequence ();
0ef1a651 1579 if (REG_P (crtl->args.internal_arg_pointer)
1580 && REGNO (crtl->args.internal_arg_pointer) > LAST_VIRTUAL_REGISTER)
1581 emit_insn_before (seq, parm_birth_insn);
1582 else
1583 emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
53800dbe 1584 pop_topmost_sequence ();
1585 return temp;
1586 }
1587}
1588
1589/* Perform an untyped call and save the state required to perform an
1590 untyped return of whatever value was returned by the given function. */
1591
1592static rtx
aecda0d6 1593expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
53800dbe 1594{
1595 int size, align, regno;
1596 enum machine_mode mode;
2a631e19 1597 rtx incoming_args, result, reg, dest, src, call_insn;
53800dbe 1598 rtx old_stack_level = 0;
1599 rtx call_fusage = 0;
6812c89e 1600 rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
53800dbe 1601
85d654dd 1602 arguments = convert_memory_address (Pmode, arguments);
726ec87c 1603
53800dbe 1604 /* Create a block where the return registers can be saved. */
1605 result = assign_stack_local (BLKmode, apply_result_size (), -1);
1606
53800dbe 1607 /* Fetch the arg pointer from the ARGUMENTS block. */
1608 incoming_args = gen_reg_rtx (Pmode);
726ec87c 1609 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
53800dbe 1610#ifndef STACK_GROWS_DOWNWARD
ad99e708 1611 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1612 incoming_args, 0, OPTAB_LIB_WIDEN);
53800dbe 1613#endif
1614
04a46d40 1615 /* Push a new argument block and copy the arguments. Do not allow
1616 the (potential) memcpy call below to interfere with our stack
1617 manipulations. */
53800dbe 1618 do_pending_stack_adjust ();
04a46d40 1619 NO_DEFER_POP;
53800dbe 1620
2358393e 1621 /* Save the stack with nonlocal if available. */
53800dbe 1622#ifdef HAVE_save_stack_nonlocal
1623 if (HAVE_save_stack_nonlocal)
e9c97615 1624 emit_stack_save (SAVE_NONLOCAL, &old_stack_level);
53800dbe 1625 else
1626#endif
e9c97615 1627 emit_stack_save (SAVE_BLOCK, &old_stack_level);
53800dbe 1628
59647703 1629 /* Allocate a block of memory onto the stack and copy the memory
990495a7 1630 arguments to the outgoing arguments address. We can pass TRUE
1631 as the 4th argument because we just saved the stack pointer
1632 and will restore it right after the call. */
5be42b39 1633 allocate_dynamic_stack_space (argsize, 0, BIGGEST_ALIGNMENT, true);
27a7a23a 1634
1635 /* Set DRAP flag to true, even though allocate_dynamic_stack_space
1636 may have already set current_function_calls_alloca to true.
1637 current_function_calls_alloca won't be set if argsize is zero,
1638 so we have to guarantee need_drap is true here. */
1639 if (SUPPORTS_STACK_ALIGNMENT)
1640 crtl->need_drap = true;
1641
59647703 1642 dest = virtual_outgoing_args_rtx;
1643#ifndef STACK_GROWS_DOWNWARD
971ba038 1644 if (CONST_INT_P (argsize))
29c05e22 1645 dest = plus_constant (Pmode, dest, -INTVAL (argsize));
59647703 1646 else
1647 dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1648#endif
2a631e19 1649 dest = gen_rtx_MEM (BLKmode, dest);
1650 set_mem_align (dest, PARM_BOUNDARY);
1651 src = gen_rtx_MEM (BLKmode, incoming_args);
1652 set_mem_align (src, PARM_BOUNDARY);
0378dbdc 1653 emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
53800dbe 1654
1655 /* Refer to the argument block. */
1656 apply_args_size ();
1657 arguments = gen_rtx_MEM (BLKmode, arguments);
2a631e19 1658 set_mem_align (arguments, PARM_BOUNDARY);
53800dbe 1659
1660 /* Walk past the arg-pointer and structure value address. */
1661 size = GET_MODE_SIZE (Pmode);
45550790 1662 if (struct_value)
53800dbe 1663 size += GET_MODE_SIZE (Pmode);
1664
1665 /* Restore each of the registers previously saved. Make USE insns
1666 for each of these registers for use in making the call. */
1667 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1668 if ((mode = apply_args_mode[regno]) != VOIDmode)
1669 {
1670 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1671 if (size % align != 0)
1672 size = CEIL (size, align) * align;
1673 reg = gen_rtx_REG (mode, regno);
e513d163 1674 emit_move_insn (reg, adjust_address (arguments, mode, size));
53800dbe 1675 use_reg (&call_fusage, reg);
1676 size += GET_MODE_SIZE (mode);
1677 }
1678
1679 /* Restore the structure value address unless this is passed as an
1680 "invisible" first argument. */
1681 size = GET_MODE_SIZE (Pmode);
45550790 1682 if (struct_value)
53800dbe 1683 {
1684 rtx value = gen_reg_rtx (Pmode);
e513d163 1685 emit_move_insn (value, adjust_address (arguments, Pmode, size));
45550790 1686 emit_move_insn (struct_value, value);
8ad4c111 1687 if (REG_P (struct_value))
45550790 1688 use_reg (&call_fusage, struct_value);
53800dbe 1689 size += GET_MODE_SIZE (Pmode);
1690 }
1691
1692 /* All arguments and registers used for the call are set up by now! */
82c7907c 1693 function = prepare_call_address (NULL, function, NULL, &call_fusage, 0, 0);
53800dbe 1694
1695 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1696 and we don't want to load it into a register as an optimization,
1697 because prepare_call_address already did it if it should be done. */
1698 if (GET_CODE (function) != SYMBOL_REF)
1699 function = memory_address (FUNCTION_MODE, function);
1700
1701 /* Generate the actual call instruction and save the return value. */
1702#ifdef HAVE_untyped_call
1703 if (HAVE_untyped_call)
1704 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1705 result, result_vector (1, result)));
1706 else
1707#endif
1708#ifdef HAVE_call_value
1709 if (HAVE_call_value)
1710 {
1711 rtx valreg = 0;
1712
1713 /* Locate the unique return register. It is not possible to
1714 express a call that sets more than one return register using
1715 call_value; use untyped_call for that. In fact, untyped_call
1716 only needs to save the return registers in the given block. */
1717 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1718 if ((mode = apply_result_mode[regno]) != VOIDmode)
1719 {
64db345d 1720 gcc_assert (!valreg); /* HAVE_untyped_call required. */
7d3f6cc7 1721
53800dbe 1722 valreg = gen_rtx_REG (mode, regno);
1723 }
1724
2ed6c343 1725 emit_call_insn (GEN_CALL_VALUE (valreg,
53800dbe 1726 gen_rtx_MEM (FUNCTION_MODE, function),
1727 const0_rtx, NULL_RTX, const0_rtx));
1728
e513d163 1729 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
53800dbe 1730 }
1731 else
1732#endif
64db345d 1733 gcc_unreachable ();
53800dbe 1734
d5f9786f 1735 /* Find the CALL insn we just emitted, and attach the register usage
1736 information. */
1737 call_insn = last_call_insn ();
1738 add_function_usage_to (call_insn, call_fusage);
53800dbe 1739
1740 /* Restore the stack. */
1741#ifdef HAVE_save_stack_nonlocal
1742 if (HAVE_save_stack_nonlocal)
e9c97615 1743 emit_stack_restore (SAVE_NONLOCAL, old_stack_level);
53800dbe 1744 else
1745#endif
e9c97615 1746 emit_stack_restore (SAVE_BLOCK, old_stack_level);
9af5ce0c 1747 fixup_args_size_notes (call_insn, get_last_insn (), 0);
53800dbe 1748
04a46d40 1749 OK_DEFER_POP;
1750
53800dbe 1751 /* Return the address of the result block. */
85d654dd 1752 result = copy_addr_to_reg (XEXP (result, 0));
1753 return convert_memory_address (ptr_mode, result);
53800dbe 1754}
1755
1756/* Perform an untyped return. */
1757
1758static void
aecda0d6 1759expand_builtin_return (rtx result)
53800dbe 1760{
1761 int size, align, regno;
1762 enum machine_mode mode;
1763 rtx reg;
1764 rtx call_fusage = 0;
1765
85d654dd 1766 result = convert_memory_address (Pmode, result);
726ec87c 1767
53800dbe 1768 apply_result_size ();
1769 result = gen_rtx_MEM (BLKmode, result);
1770
1771#ifdef HAVE_untyped_return
1772 if (HAVE_untyped_return)
1773 {
1774 emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1775 emit_barrier ();
1776 return;
1777 }
1778#endif
1779
1780 /* Restore the return value and note that each value is used. */
1781 size = 0;
1782 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1783 if ((mode = apply_result_mode[regno]) != VOIDmode)
1784 {
1785 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1786 if (size % align != 0)
1787 size = CEIL (size, align) * align;
1788 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
e513d163 1789 emit_move_insn (reg, adjust_address (result, mode, size));
53800dbe 1790
1791 push_to_sequence (call_fusage);
18b42941 1792 emit_use (reg);
53800dbe 1793 call_fusage = get_insns ();
1794 end_sequence ();
1795 size += GET_MODE_SIZE (mode);
1796 }
1797
1798 /* Put the USE insns before the return. */
31d3e01c 1799 emit_insn (call_fusage);
53800dbe 1800
1801 /* Return whatever values was restored by jumping directly to the end
1802 of the function. */
62380d2d 1803 expand_naked_return ();
53800dbe 1804}
1805
539a3a92 1806/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
27d0c333 1807
539a3a92 1808static enum type_class
aecda0d6 1809type_to_class (tree type)
539a3a92 1810{
1811 switch (TREE_CODE (type))
1812 {
1813 case VOID_TYPE: return void_type_class;
1814 case INTEGER_TYPE: return integer_type_class;
539a3a92 1815 case ENUMERAL_TYPE: return enumeral_type_class;
1816 case BOOLEAN_TYPE: return boolean_type_class;
1817 case POINTER_TYPE: return pointer_type_class;
1818 case REFERENCE_TYPE: return reference_type_class;
1819 case OFFSET_TYPE: return offset_type_class;
1820 case REAL_TYPE: return real_type_class;
1821 case COMPLEX_TYPE: return complex_type_class;
1822 case FUNCTION_TYPE: return function_type_class;
1823 case METHOD_TYPE: return method_type_class;
1824 case RECORD_TYPE: return record_type_class;
1825 case UNION_TYPE:
1826 case QUAL_UNION_TYPE: return union_type_class;
1827 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1828 ? string_type_class : array_type_class);
539a3a92 1829 case LANG_TYPE: return lang_type_class;
1830 default: return no_type_class;
1831 }
1832}
bf8e3599 1833
c2f47e15 1834/* Expand a call EXP to __builtin_classify_type. */
27d0c333 1835
53800dbe 1836static rtx
c2f47e15 1837expand_builtin_classify_type (tree exp)
53800dbe 1838{
c2f47e15 1839 if (call_expr_nargs (exp))
1840 return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0))));
53800dbe 1841 return GEN_INT (no_type_class);
1842}
1843
07976da7 1844/* This helper macro, meant to be used in mathfn_built_in below,
1845 determines which among a set of three builtin math functions is
1846 appropriate for a given type mode. The `F' and `L' cases are
1847 automatically generated from the `double' case. */
1848#define CASE_MATHFN(BUILT_IN_MATHFN) \
1849 case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1850 fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1851 fcodel = BUILT_IN_MATHFN##L ; break;
cd2656b0 1852/* Similar to above, but appends _R after any F/L suffix. */
1853#define CASE_MATHFN_REENT(BUILT_IN_MATHFN) \
1854 case BUILT_IN_MATHFN##_R: case BUILT_IN_MATHFN##F_R: case BUILT_IN_MATHFN##L_R: \
1855 fcode = BUILT_IN_MATHFN##_R; fcodef = BUILT_IN_MATHFN##F_R ; \
1856 fcodel = BUILT_IN_MATHFN##L_R ; break;
07976da7 1857
b9a16870 1858/* Return mathematic function equivalent to FN but operating directly on TYPE,
1859 if available. If IMPLICIT is true use the implicit builtin declaration,
1860 otherwise use the explicit declaration. If we can't do the conversion,
1861 return zero. */
c319d56a 1862
1863static tree
b9a16870 1864mathfn_built_in_1 (tree type, enum built_in_function fn, bool implicit_p)
0a68165a 1865{
b9a16870 1866 enum built_in_function fcode, fcodef, fcodel, fcode2;
07976da7 1867
1868 switch (fn)
1869 {
746114e8 1870 CASE_MATHFN (BUILT_IN_ACOS)
1871 CASE_MATHFN (BUILT_IN_ACOSH)
1872 CASE_MATHFN (BUILT_IN_ASIN)
1873 CASE_MATHFN (BUILT_IN_ASINH)
07976da7 1874 CASE_MATHFN (BUILT_IN_ATAN)
746114e8 1875 CASE_MATHFN (BUILT_IN_ATAN2)
1876 CASE_MATHFN (BUILT_IN_ATANH)
1877 CASE_MATHFN (BUILT_IN_CBRT)
07976da7 1878 CASE_MATHFN (BUILT_IN_CEIL)
d735c391 1879 CASE_MATHFN (BUILT_IN_CEXPI)
746114e8 1880 CASE_MATHFN (BUILT_IN_COPYSIGN)
07976da7 1881 CASE_MATHFN (BUILT_IN_COS)
746114e8 1882 CASE_MATHFN (BUILT_IN_COSH)
1883 CASE_MATHFN (BUILT_IN_DREM)
1884 CASE_MATHFN (BUILT_IN_ERF)
1885 CASE_MATHFN (BUILT_IN_ERFC)
07976da7 1886 CASE_MATHFN (BUILT_IN_EXP)
746114e8 1887 CASE_MATHFN (BUILT_IN_EXP10)
1888 CASE_MATHFN (BUILT_IN_EXP2)
1889 CASE_MATHFN (BUILT_IN_EXPM1)
1890 CASE_MATHFN (BUILT_IN_FABS)
1891 CASE_MATHFN (BUILT_IN_FDIM)
07976da7 1892 CASE_MATHFN (BUILT_IN_FLOOR)
746114e8 1893 CASE_MATHFN (BUILT_IN_FMA)
1894 CASE_MATHFN (BUILT_IN_FMAX)
1895 CASE_MATHFN (BUILT_IN_FMIN)
1896 CASE_MATHFN (BUILT_IN_FMOD)
1897 CASE_MATHFN (BUILT_IN_FREXP)
1898 CASE_MATHFN (BUILT_IN_GAMMA)
cd2656b0 1899 CASE_MATHFN_REENT (BUILT_IN_GAMMA) /* GAMMA_R */
746114e8 1900 CASE_MATHFN (BUILT_IN_HUGE_VAL)
1901 CASE_MATHFN (BUILT_IN_HYPOT)
1902 CASE_MATHFN (BUILT_IN_ILOGB)
80ff6494 1903 CASE_MATHFN (BUILT_IN_ICEIL)
1904 CASE_MATHFN (BUILT_IN_IFLOOR)
746114e8 1905 CASE_MATHFN (BUILT_IN_INF)
80ff6494 1906 CASE_MATHFN (BUILT_IN_IRINT)
1907 CASE_MATHFN (BUILT_IN_IROUND)
69b779ea 1908 CASE_MATHFN (BUILT_IN_ISINF)
746114e8 1909 CASE_MATHFN (BUILT_IN_J0)
1910 CASE_MATHFN (BUILT_IN_J1)
1911 CASE_MATHFN (BUILT_IN_JN)
ac148751 1912 CASE_MATHFN (BUILT_IN_LCEIL)
746114e8 1913 CASE_MATHFN (BUILT_IN_LDEXP)
ad52b9b7 1914 CASE_MATHFN (BUILT_IN_LFLOOR)
746114e8 1915 CASE_MATHFN (BUILT_IN_LGAMMA)
cd2656b0 1916 CASE_MATHFN_REENT (BUILT_IN_LGAMMA) /* LGAMMA_R */
ac148751 1917 CASE_MATHFN (BUILT_IN_LLCEIL)
ad52b9b7 1918 CASE_MATHFN (BUILT_IN_LLFLOOR)
746114e8 1919 CASE_MATHFN (BUILT_IN_LLRINT)
1920 CASE_MATHFN (BUILT_IN_LLROUND)
07976da7 1921 CASE_MATHFN (BUILT_IN_LOG)
746114e8 1922 CASE_MATHFN (BUILT_IN_LOG10)
1923 CASE_MATHFN (BUILT_IN_LOG1P)
1924 CASE_MATHFN (BUILT_IN_LOG2)
1925 CASE_MATHFN (BUILT_IN_LOGB)
1926 CASE_MATHFN (BUILT_IN_LRINT)
1927 CASE_MATHFN (BUILT_IN_LROUND)
1928 CASE_MATHFN (BUILT_IN_MODF)
1929 CASE_MATHFN (BUILT_IN_NAN)
1930 CASE_MATHFN (BUILT_IN_NANS)
07976da7 1931 CASE_MATHFN (BUILT_IN_NEARBYINT)
746114e8 1932 CASE_MATHFN (BUILT_IN_NEXTAFTER)
1933 CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1934 CASE_MATHFN (BUILT_IN_POW)
757c219d 1935 CASE_MATHFN (BUILT_IN_POWI)
746114e8 1936 CASE_MATHFN (BUILT_IN_POW10)
1937 CASE_MATHFN (BUILT_IN_REMAINDER)
1938 CASE_MATHFN (BUILT_IN_REMQUO)
1939 CASE_MATHFN (BUILT_IN_RINT)
07976da7 1940 CASE_MATHFN (BUILT_IN_ROUND)
746114e8 1941 CASE_MATHFN (BUILT_IN_SCALB)
1942 CASE_MATHFN (BUILT_IN_SCALBLN)
1943 CASE_MATHFN (BUILT_IN_SCALBN)
c319d56a 1944 CASE_MATHFN (BUILT_IN_SIGNBIT)
746114e8 1945 CASE_MATHFN (BUILT_IN_SIGNIFICAND)
07976da7 1946 CASE_MATHFN (BUILT_IN_SIN)
746114e8 1947 CASE_MATHFN (BUILT_IN_SINCOS)
1948 CASE_MATHFN (BUILT_IN_SINH)
07976da7 1949 CASE_MATHFN (BUILT_IN_SQRT)
1950 CASE_MATHFN (BUILT_IN_TAN)
746114e8 1951 CASE_MATHFN (BUILT_IN_TANH)
1952 CASE_MATHFN (BUILT_IN_TGAMMA)
07976da7 1953 CASE_MATHFN (BUILT_IN_TRUNC)
746114e8 1954 CASE_MATHFN (BUILT_IN_Y0)
1955 CASE_MATHFN (BUILT_IN_Y1)
1956 CASE_MATHFN (BUILT_IN_YN)
07976da7 1957
0a68165a 1958 default:
c2f47e15 1959 return NULL_TREE;
0a68165a 1960 }
07976da7 1961
96b9f485 1962 if (TYPE_MAIN_VARIANT (type) == double_type_node)
b9a16870 1963 fcode2 = fcode;
96b9f485 1964 else if (TYPE_MAIN_VARIANT (type) == float_type_node)
b9a16870 1965 fcode2 = fcodef;
96b9f485 1966 else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
b9a16870 1967 fcode2 = fcodel;
07976da7 1968 else
c2f47e15 1969 return NULL_TREE;
b9a16870 1970
1971 if (implicit_p && !builtin_decl_implicit_p (fcode2))
1972 return NULL_TREE;
1973
1974 return builtin_decl_explicit (fcode2);
0a68165a 1975}
1976
c319d56a 1977/* Like mathfn_built_in_1(), but always use the implicit array. */
1978
1979tree
1980mathfn_built_in (tree type, enum built_in_function fn)
1981{
1982 return mathfn_built_in_1 (type, fn, /*implicit=*/ 1);
1983}
1984
0fd605a5 1985/* If errno must be maintained, expand the RTL to check if the result,
1986 TARGET, of a built-in function call, EXP, is NaN, and if so set
1987 errno to EDOM. */
1988
1989static void
aecda0d6 1990expand_errno_check (tree exp, rtx target)
0fd605a5 1991{
7f05340e 1992 rtx lab = gen_label_rtx ();
0fd605a5 1993
7f05340e 1994 /* Test the result; if it is NaN, set errno=EDOM because
1995 the argument was not in the domain. */
3fcf767f 1996 do_compare_rtx_and_jump (target, target, EQ, 0, GET_MODE (target),
79ab74cc 1997 NULL_RTX, NULL_RTX, lab,
1998 /* The jump is very likely. */
1999 REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1));
0fd605a5 2000
2001#ifdef TARGET_EDOM
7f05340e 2002 /* If this built-in doesn't throw an exception, set errno directly. */
c2f47e15 2003 if (TREE_NOTHROW (TREE_OPERAND (CALL_EXPR_FN (exp), 0)))
7f05340e 2004 {
0fd605a5 2005#ifdef GEN_ERRNO_RTX
7f05340e 2006 rtx errno_rtx = GEN_ERRNO_RTX;
0fd605a5 2007#else
7f05340e 2008 rtx errno_rtx
0fd605a5 2009 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
2010#endif
d11aedc7 2011 emit_move_insn (errno_rtx,
2012 gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
0fd605a5 2013 emit_label (lab);
7f05340e 2014 return;
0fd605a5 2015 }
7f05340e 2016#endif
2017
08491912 2018 /* Make sure the library call isn't expanded as a tail call. */
2019 CALL_EXPR_TAILCALL (exp) = 0;
2020
7f05340e 2021 /* We can't set errno=EDOM directly; let the library call do it.
2022 Pop the arguments right away in case the call gets deleted. */
2023 NO_DEFER_POP;
2024 expand_call (exp, target, 0);
2025 OK_DEFER_POP;
2026 emit_label (lab);
0fd605a5 2027}
2028
6b43bae4 2029/* Expand a call to one of the builtin math functions (sqrt, exp, or log).
c2f47e15 2030 Return NULL_RTX if a normal call should be emitted rather than expanding
2031 the function in-line. EXP is the expression that is a call to the builtin
53800dbe 2032 function; if convenient, the result should be placed in TARGET.
2033 SUBTARGET may be used as the target for computing one of EXP's operands. */
27d0c333 2034
53800dbe 2035static rtx
aecda0d6 2036expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
53800dbe 2037{
bf8e3599 2038 optab builtin_optab;
1e4adcfc 2039 rtx op0, insns;
c6e6ecb1 2040 tree fndecl = get_callee_fndecl (exp);
7f05340e 2041 enum machine_mode mode;
528ee710 2042 bool errno_set = false;
d6a0a4b0 2043 bool try_widening = false;
abfea505 2044 tree arg;
53800dbe 2045
c2f47e15 2046 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2047 return NULL_RTX;
53800dbe 2048
c2f47e15 2049 arg = CALL_EXPR_ARG (exp, 0);
53800dbe 2050
2051 switch (DECL_FUNCTION_CODE (fndecl))
2052 {
4f35b1fc 2053 CASE_FLT_FN (BUILT_IN_SQRT):
7f05340e 2054 errno_set = ! tree_expr_nonnegative_p (arg);
d6a0a4b0 2055 try_widening = true;
7f05340e 2056 builtin_optab = sqrt_optab;
2057 break;
4f35b1fc 2058 CASE_FLT_FN (BUILT_IN_EXP):
528ee710 2059 errno_set = true; builtin_optab = exp_optab; break;
4f35b1fc 2060 CASE_FLT_FN (BUILT_IN_EXP10):
2061 CASE_FLT_FN (BUILT_IN_POW10):
750ef9f5 2062 errno_set = true; builtin_optab = exp10_optab; break;
4f35b1fc 2063 CASE_FLT_FN (BUILT_IN_EXP2):
750ef9f5 2064 errno_set = true; builtin_optab = exp2_optab; break;
4f35b1fc 2065 CASE_FLT_FN (BUILT_IN_EXPM1):
a6b4eed2 2066 errno_set = true; builtin_optab = expm1_optab; break;
4f35b1fc 2067 CASE_FLT_FN (BUILT_IN_LOGB):
4efbc641 2068 errno_set = true; builtin_optab = logb_optab; break;
4f35b1fc 2069 CASE_FLT_FN (BUILT_IN_LOG):
528ee710 2070 errno_set = true; builtin_optab = log_optab; break;
4f35b1fc 2071 CASE_FLT_FN (BUILT_IN_LOG10):
d3cd9bde 2072 errno_set = true; builtin_optab = log10_optab; break;
4f35b1fc 2073 CASE_FLT_FN (BUILT_IN_LOG2):
d3cd9bde 2074 errno_set = true; builtin_optab = log2_optab; break;
4f35b1fc 2075 CASE_FLT_FN (BUILT_IN_LOG1P):
f474cd93 2076 errno_set = true; builtin_optab = log1p_optab; break;
4f35b1fc 2077 CASE_FLT_FN (BUILT_IN_ASIN):
8de2f465 2078 builtin_optab = asin_optab; break;
4f35b1fc 2079 CASE_FLT_FN (BUILT_IN_ACOS):
8de2f465 2080 builtin_optab = acos_optab; break;
4f35b1fc 2081 CASE_FLT_FN (BUILT_IN_TAN):
528ee710 2082 builtin_optab = tan_optab; break;
4f35b1fc 2083 CASE_FLT_FN (BUILT_IN_ATAN):
528ee710 2084 builtin_optab = atan_optab; break;
4f35b1fc 2085 CASE_FLT_FN (BUILT_IN_FLOOR):
528ee710 2086 builtin_optab = floor_optab; break;
4f35b1fc 2087 CASE_FLT_FN (BUILT_IN_CEIL):
528ee710 2088 builtin_optab = ceil_optab; break;
4f35b1fc 2089 CASE_FLT_FN (BUILT_IN_TRUNC):
a7cc195f 2090 builtin_optab = btrunc_optab; break;
4f35b1fc 2091 CASE_FLT_FN (BUILT_IN_ROUND):
528ee710 2092 builtin_optab = round_optab; break;
4f35b1fc 2093 CASE_FLT_FN (BUILT_IN_NEARBYINT):
0ddf4ad9 2094 builtin_optab = nearbyint_optab;
2095 if (flag_trapping_math)
2096 break;
2097 /* Else fallthrough and expand as rint. */
4f35b1fc 2098 CASE_FLT_FN (BUILT_IN_RINT):
aef94a0f 2099 builtin_optab = rint_optab; break;
b3154a1f 2100 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
2101 builtin_optab = significand_optab; break;
42721db0 2102 default:
64db345d 2103 gcc_unreachable ();
53800dbe 2104 }
2105
7f05340e 2106 /* Make a suitable register to place result in. */
2107 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2108
7f05340e 2109 if (! flag_errno_math || ! HONOR_NANS (mode))
2110 errno_set = false;
2111
d6a0a4b0 2112 /* Before working hard, check whether the instruction is available, but try
2113 to widen the mode for specific operations. */
2114 if ((optab_handler (builtin_optab, mode) != CODE_FOR_nothing
2115 || (try_widening && !excess_precision_type (TREE_TYPE (exp))))
f2aca212 2116 && (!errno_set || !optimize_insn_for_size_p ()))
68e6cb9d 2117 {
de2e453e 2118 rtx result = gen_reg_rtx (mode);
7f05340e 2119
bd421108 2120 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2121 need to expand the argument again. This way, we will not perform
2122 side-effects more the once. */
abfea505 2123 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7f05340e 2124
1db6d067 2125 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
7f05340e 2126
bd421108 2127 start_sequence ();
53800dbe 2128
de2e453e 2129 /* Compute into RESULT.
2130 Set RESULT to wherever the result comes back. */
2131 result = expand_unop (mode, builtin_optab, op0, result, 0);
bd421108 2132
de2e453e 2133 if (result != 0)
bd421108 2134 {
2135 if (errno_set)
de2e453e 2136 expand_errno_check (exp, result);
bd421108 2137
2138 /* Output the entire sequence. */
2139 insns = get_insns ();
2140 end_sequence ();
2141 emit_insn (insns);
de2e453e 2142 return result;
bd421108 2143 }
2144
2145 /* If we were unable to expand via the builtin, stop the sequence
2146 (without outputting the insns) and call to the library function
2147 with the stabilized argument list. */
53800dbe 2148 end_sequence ();
53800dbe 2149 }
2150
1e5b92fa 2151 return expand_call (exp, target, target == const0_rtx);
0fd605a5 2152}
2153
2154/* Expand a call to the builtin binary math functions (pow and atan2).
c2f47e15 2155 Return NULL_RTX if a normal call should be emitted rather than expanding the
0fd605a5 2156 function in-line. EXP is the expression that is a call to the builtin
2157 function; if convenient, the result should be placed in TARGET.
2158 SUBTARGET may be used as the target for computing one of EXP's
2159 operands. */
2160
2161static rtx
aecda0d6 2162expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
0fd605a5 2163{
2164 optab builtin_optab;
de2e453e 2165 rtx op0, op1, insns, result;
4737caf2 2166 int op1_type = REAL_TYPE;
c6e6ecb1 2167 tree fndecl = get_callee_fndecl (exp);
abfea505 2168 tree arg0, arg1;
7f05340e 2169 enum machine_mode mode;
0fd605a5 2170 bool errno_set = true;
0fd605a5 2171
73a954a1 2172 switch (DECL_FUNCTION_CODE (fndecl))
2173 {
2174 CASE_FLT_FN (BUILT_IN_SCALBN):
2175 CASE_FLT_FN (BUILT_IN_SCALBLN):
2176 CASE_FLT_FN (BUILT_IN_LDEXP):
2177 op1_type = INTEGER_TYPE;
2178 default:
2179 break;
2180 }
4737caf2 2181
c2f47e15 2182 if (!validate_arglist (exp, REAL_TYPE, op1_type, VOID_TYPE))
2183 return NULL_RTX;
0fd605a5 2184
c2f47e15 2185 arg0 = CALL_EXPR_ARG (exp, 0);
2186 arg1 = CALL_EXPR_ARG (exp, 1);
0fd605a5 2187
0fd605a5 2188 switch (DECL_FUNCTION_CODE (fndecl))
2189 {
4f35b1fc 2190 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 2191 builtin_optab = pow_optab; break;
4f35b1fc 2192 CASE_FLT_FN (BUILT_IN_ATAN2):
0fd605a5 2193 builtin_optab = atan2_optab; break;
73a954a1 2194 CASE_FLT_FN (BUILT_IN_SCALB):
2195 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2196 return 0;
2197 builtin_optab = scalb_optab; break;
2198 CASE_FLT_FN (BUILT_IN_SCALBN):
2199 CASE_FLT_FN (BUILT_IN_SCALBLN):
2200 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2201 return 0;
2202 /* Fall through... */
4f35b1fc 2203 CASE_FLT_FN (BUILT_IN_LDEXP):
4737caf2 2204 builtin_optab = ldexp_optab; break;
4f35b1fc 2205 CASE_FLT_FN (BUILT_IN_FMOD):
80ed5c06 2206 builtin_optab = fmod_optab; break;
ef722005 2207 CASE_FLT_FN (BUILT_IN_REMAINDER):
4f35b1fc 2208 CASE_FLT_FN (BUILT_IN_DREM):
ef722005 2209 builtin_optab = remainder_optab; break;
0fd605a5 2210 default:
64db345d 2211 gcc_unreachable ();
0fd605a5 2212 }
2213
7f05340e 2214 /* Make a suitable register to place result in. */
2215 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2216
2217 /* Before working hard, check whether the instruction is available. */
d6bf3b14 2218 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
c2f47e15 2219 return NULL_RTX;
fc4eef90 2220
de2e453e 2221 result = gen_reg_rtx (mode);
7f05340e 2222
2223 if (! flag_errno_math || ! HONOR_NANS (mode))
2224 errno_set = false;
2225
f2aca212 2226 if (errno_set && optimize_insn_for_size_p ())
2227 return 0;
2228
4ee9c684 2229 /* Always stabilize the argument list. */
abfea505 2230 CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
2231 CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
7f05340e 2232
8ec3c5c2 2233 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2234 op1 = expand_normal (arg1);
7f05340e 2235
7f05340e 2236 start_sequence ();
2237
de2e453e 2238 /* Compute into RESULT.
2239 Set RESULT to wherever the result comes back. */
2240 result = expand_binop (mode, builtin_optab, op0, op1,
2241 result, 0, OPTAB_DIRECT);
53800dbe 2242
68e6cb9d 2243 /* If we were unable to expand via the builtin, stop the sequence
2244 (without outputting the insns) and call to the library function
2245 with the stabilized argument list. */
de2e453e 2246 if (result == 0)
0fd605a5 2247 {
2248 end_sequence ();
68e6cb9d 2249 return expand_call (exp, target, target == const0_rtx);
53800dbe 2250 }
2251
a4356fb9 2252 if (errno_set)
de2e453e 2253 expand_errno_check (exp, result);
0fd605a5 2254
53800dbe 2255 /* Output the entire sequence. */
2256 insns = get_insns ();
2257 end_sequence ();
31d3e01c 2258 emit_insn (insns);
bf8e3599 2259
de2e453e 2260 return result;
53800dbe 2261}
2262
7e0713b1 2263/* Expand a call to the builtin trinary math functions (fma).
2264 Return NULL_RTX if a normal call should be emitted rather than expanding the
2265 function in-line. EXP is the expression that is a call to the builtin
2266 function; if convenient, the result should be placed in TARGET.
2267 SUBTARGET may be used as the target for computing one of EXP's
2268 operands. */
2269
2270static rtx
2271expand_builtin_mathfn_ternary (tree exp, rtx target, rtx subtarget)
2272{
2273 optab builtin_optab;
de2e453e 2274 rtx op0, op1, op2, insns, result;
7e0713b1 2275 tree fndecl = get_callee_fndecl (exp);
2276 tree arg0, arg1, arg2;
2277 enum machine_mode mode;
2278
2279 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2280 return NULL_RTX;
2281
2282 arg0 = CALL_EXPR_ARG (exp, 0);
2283 arg1 = CALL_EXPR_ARG (exp, 1);
2284 arg2 = CALL_EXPR_ARG (exp, 2);
2285
2286 switch (DECL_FUNCTION_CODE (fndecl))
2287 {
2288 CASE_FLT_FN (BUILT_IN_FMA):
2289 builtin_optab = fma_optab; break;
2290 default:
2291 gcc_unreachable ();
2292 }
2293
2294 /* Make a suitable register to place result in. */
2295 mode = TYPE_MODE (TREE_TYPE (exp));
2296
2297 /* Before working hard, check whether the instruction is available. */
2298 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
2299 return NULL_RTX;
2300
de2e453e 2301 result = gen_reg_rtx (mode);
7e0713b1 2302
2303 /* Always stabilize the argument list. */
2304 CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
2305 CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
2306 CALL_EXPR_ARG (exp, 2) = arg2 = builtin_save_expr (arg2);
2307
2308 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2309 op1 = expand_normal (arg1);
2310 op2 = expand_normal (arg2);
2311
2312 start_sequence ();
2313
de2e453e 2314 /* Compute into RESULT.
2315 Set RESULT to wherever the result comes back. */
2316 result = expand_ternary_op (mode, builtin_optab, op0, op1, op2,
2317 result, 0);
7e0713b1 2318
2319 /* If we were unable to expand via the builtin, stop the sequence
2320 (without outputting the insns) and call to the library function
2321 with the stabilized argument list. */
de2e453e 2322 if (result == 0)
7e0713b1 2323 {
2324 end_sequence ();
2325 return expand_call (exp, target, target == const0_rtx);
2326 }
2327
2328 /* Output the entire sequence. */
2329 insns = get_insns ();
2330 end_sequence ();
2331 emit_insn (insns);
2332
de2e453e 2333 return result;
7e0713b1 2334}
2335
6b43bae4 2336/* Expand a call to the builtin sin and cos math functions.
c2f47e15 2337 Return NULL_RTX if a normal call should be emitted rather than expanding the
6b43bae4 2338 function in-line. EXP is the expression that is a call to the builtin
2339 function; if convenient, the result should be placed in TARGET.
2340 SUBTARGET may be used as the target for computing one of EXP's
2341 operands. */
2342
2343static rtx
2344expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
2345{
2346 optab builtin_optab;
7511b819 2347 rtx op0, insns;
6b43bae4 2348 tree fndecl = get_callee_fndecl (exp);
6b43bae4 2349 enum machine_mode mode;
abfea505 2350 tree arg;
6b43bae4 2351
c2f47e15 2352 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2353 return NULL_RTX;
6b43bae4 2354
c2f47e15 2355 arg = CALL_EXPR_ARG (exp, 0);
6b43bae4 2356
2357 switch (DECL_FUNCTION_CODE (fndecl))
2358 {
4f35b1fc 2359 CASE_FLT_FN (BUILT_IN_SIN):
2360 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2361 builtin_optab = sincos_optab; break;
2362 default:
64db345d 2363 gcc_unreachable ();
6b43bae4 2364 }
2365
2366 /* Make a suitable register to place result in. */
2367 mode = TYPE_MODE (TREE_TYPE (exp));
2368
6b43bae4 2369 /* Check if sincos insn is available, otherwise fallback
0bed3869 2370 to sin or cos insn. */
d6bf3b14 2371 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
6b43bae4 2372 switch (DECL_FUNCTION_CODE (fndecl))
2373 {
4f35b1fc 2374 CASE_FLT_FN (BUILT_IN_SIN):
6b43bae4 2375 builtin_optab = sin_optab; break;
4f35b1fc 2376 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2377 builtin_optab = cos_optab; break;
2378 default:
64db345d 2379 gcc_unreachable ();
6b43bae4 2380 }
6b43bae4 2381
2382 /* Before working hard, check whether the instruction is available. */
d6bf3b14 2383 if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing)
6b43bae4 2384 {
de2e453e 2385 rtx result = gen_reg_rtx (mode);
6b43bae4 2386
2387 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2388 need to expand the argument again. This way, we will not perform
2389 side-effects more the once. */
abfea505 2390 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
6b43bae4 2391
1db6d067 2392 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
6b43bae4 2393
6b43bae4 2394 start_sequence ();
2395
de2e453e 2396 /* Compute into RESULT.
2397 Set RESULT to wherever the result comes back. */
6b43bae4 2398 if (builtin_optab == sincos_optab)
2399 {
de2e453e 2400 int ok;
7d3f6cc7 2401
6b43bae4 2402 switch (DECL_FUNCTION_CODE (fndecl))
2403 {
4f35b1fc 2404 CASE_FLT_FN (BUILT_IN_SIN):
de2e453e 2405 ok = expand_twoval_unop (builtin_optab, op0, 0, result, 0);
6b43bae4 2406 break;
4f35b1fc 2407 CASE_FLT_FN (BUILT_IN_COS):
de2e453e 2408 ok = expand_twoval_unop (builtin_optab, op0, result, 0, 0);
6b43bae4 2409 break;
2410 default:
64db345d 2411 gcc_unreachable ();
6b43bae4 2412 }
de2e453e 2413 gcc_assert (ok);
6b43bae4 2414 }
2415 else
de2e453e 2416 result = expand_unop (mode, builtin_optab, op0, result, 0);
6b43bae4 2417
de2e453e 2418 if (result != 0)
6b43bae4 2419 {
6b43bae4 2420 /* Output the entire sequence. */
2421 insns = get_insns ();
2422 end_sequence ();
2423 emit_insn (insns);
de2e453e 2424 return result;
6b43bae4 2425 }
2426
2427 /* If we were unable to expand via the builtin, stop the sequence
2428 (without outputting the insns) and call to the library function
2429 with the stabilized argument list. */
2430 end_sequence ();
2431 }
2432
de2e453e 2433 return expand_call (exp, target, target == const0_rtx);
6b43bae4 2434}
2435
a65c4d64 2436/* Given an interclass math builtin decl FNDECL and it's argument ARG
2437 return an RTL instruction code that implements the functionality.
2438 If that isn't possible or available return CODE_FOR_nothing. */
a67a90e5 2439
a65c4d64 2440static enum insn_code
2441interclass_mathfn_icode (tree arg, tree fndecl)
a67a90e5 2442{
a65c4d64 2443 bool errno_set = false;
6cdd383a 2444 optab builtin_optab = unknown_optab;
a67a90e5 2445 enum machine_mode mode;
a67a90e5 2446
2447 switch (DECL_FUNCTION_CODE (fndecl))
2448 {
2449 CASE_FLT_FN (BUILT_IN_ILOGB):
2450 errno_set = true; builtin_optab = ilogb_optab; break;
69b779ea 2451 CASE_FLT_FN (BUILT_IN_ISINF):
2452 builtin_optab = isinf_optab; break;
8a1a9cb7 2453 case BUILT_IN_ISNORMAL:
cde061c1 2454 case BUILT_IN_ISFINITE:
2455 CASE_FLT_FN (BUILT_IN_FINITE):
a65c4d64 2456 case BUILT_IN_FINITED32:
2457 case BUILT_IN_FINITED64:
2458 case BUILT_IN_FINITED128:
2459 case BUILT_IN_ISINFD32:
2460 case BUILT_IN_ISINFD64:
2461 case BUILT_IN_ISINFD128:
cde061c1 2462 /* These builtins have no optabs (yet). */
2463 break;
a67a90e5 2464 default:
2465 gcc_unreachable ();
2466 }
2467
2468 /* There's no easy way to detect the case we need to set EDOM. */
2469 if (flag_errno_math && errno_set)
a65c4d64 2470 return CODE_FOR_nothing;
a67a90e5 2471
2472 /* Optab mode depends on the mode of the input argument. */
2473 mode = TYPE_MODE (TREE_TYPE (arg));
2474
cde061c1 2475 if (builtin_optab)
d6bf3b14 2476 return optab_handler (builtin_optab, mode);
a65c4d64 2477 return CODE_FOR_nothing;
2478}
2479
2480/* Expand a call to one of the builtin math functions that operate on
2481 floating point argument and output an integer result (ilogb, isinf,
2482 isnan, etc).
2483 Return 0 if a normal call should be emitted rather than expanding the
2484 function in-line. EXP is the expression that is a call to the builtin
f97eea22 2485 function; if convenient, the result should be placed in TARGET. */
a65c4d64 2486
2487static rtx
f97eea22 2488expand_builtin_interclass_mathfn (tree exp, rtx target)
a65c4d64 2489{
2490 enum insn_code icode = CODE_FOR_nothing;
2491 rtx op0;
2492 tree fndecl = get_callee_fndecl (exp);
2493 enum machine_mode mode;
2494 tree arg;
2495
2496 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2497 return NULL_RTX;
2498
2499 arg = CALL_EXPR_ARG (exp, 0);
2500 icode = interclass_mathfn_icode (arg, fndecl);
2501 mode = TYPE_MODE (TREE_TYPE (arg));
2502
a67a90e5 2503 if (icode != CODE_FOR_nothing)
2504 {
8786db1e 2505 struct expand_operand ops[1];
4e2a2fb4 2506 rtx last = get_last_insn ();
2507 tree orig_arg = arg;
a67a90e5 2508
2509 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2510 need to expand the argument again. This way, we will not perform
2511 side-effects more the once. */
abfea505 2512 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
a67a90e5 2513
f97eea22 2514 op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
a67a90e5 2515
2516 if (mode != GET_MODE (op0))
2517 op0 = convert_to_mode (mode, op0, 0);
2518
8786db1e 2519 create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
2520 if (maybe_legitimize_operands (icode, 0, 1, ops)
2521 && maybe_emit_unop_insn (icode, ops[0].value, op0, UNKNOWN))
2522 return ops[0].value;
2523
4e2a2fb4 2524 delete_insns_since (last);
2525 CALL_EXPR_ARG (exp, 0) = orig_arg;
a67a90e5 2526 }
2527
a65c4d64 2528 return NULL_RTX;
a67a90e5 2529}
2530
c3147c1a 2531/* Expand a call to the builtin sincos math function.
c2f47e15 2532 Return NULL_RTX if a normal call should be emitted rather than expanding the
c3147c1a 2533 function in-line. EXP is the expression that is a call to the builtin
2534 function. */
2535
2536static rtx
2537expand_builtin_sincos (tree exp)
2538{
2539 rtx op0, op1, op2, target1, target2;
c3147c1a 2540 enum machine_mode mode;
2541 tree arg, sinp, cosp;
2542 int result;
389dd41b 2543 location_t loc = EXPR_LOCATION (exp);
be5575b2 2544 tree alias_type, alias_off;
c3147c1a 2545
c2f47e15 2546 if (!validate_arglist (exp, REAL_TYPE,
2547 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2548 return NULL_RTX;
c3147c1a 2549
c2f47e15 2550 arg = CALL_EXPR_ARG (exp, 0);
2551 sinp = CALL_EXPR_ARG (exp, 1);
2552 cosp = CALL_EXPR_ARG (exp, 2);
c3147c1a 2553
2554 /* Make a suitable register to place result in. */
2555 mode = TYPE_MODE (TREE_TYPE (arg));
2556
2557 /* Check if sincos insn is available, otherwise emit the call. */
d6bf3b14 2558 if (optab_handler (sincos_optab, mode) == CODE_FOR_nothing)
c3147c1a 2559 return NULL_RTX;
2560
2561 target1 = gen_reg_rtx (mode);
2562 target2 = gen_reg_rtx (mode);
2563
8ec3c5c2 2564 op0 = expand_normal (arg);
be5575b2 2565 alias_type = build_pointer_type_for_mode (TREE_TYPE (arg), ptr_mode, true);
2566 alias_off = build_int_cst (alias_type, 0);
2567 op1 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
2568 sinp, alias_off));
2569 op2 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
2570 cosp, alias_off));
c3147c1a 2571
2572 /* Compute into target1 and target2.
2573 Set TARGET to wherever the result comes back. */
2574 result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
2575 gcc_assert (result);
2576
2577 /* Move target1 and target2 to the memory locations indicated
2578 by op1 and op2. */
2579 emit_move_insn (op1, target1);
2580 emit_move_insn (op2, target2);
2581
2582 return const0_rtx;
2583}
2584
d735c391 2585/* Expand a call to the internal cexpi builtin to the sincos math function.
2586 EXP is the expression that is a call to the builtin function; if convenient,
f97eea22 2587 the result should be placed in TARGET. */
d735c391 2588
2589static rtx
f97eea22 2590expand_builtin_cexpi (tree exp, rtx target)
d735c391 2591{
2592 tree fndecl = get_callee_fndecl (exp);
d735c391 2593 tree arg, type;
c2f47e15 2594 enum machine_mode mode;
d735c391 2595 rtx op0, op1, op2;
389dd41b 2596 location_t loc = EXPR_LOCATION (exp);
d735c391 2597
c2f47e15 2598 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2599 return NULL_RTX;
d735c391 2600
c2f47e15 2601 arg = CALL_EXPR_ARG (exp, 0);
d735c391 2602 type = TREE_TYPE (arg);
2603 mode = TYPE_MODE (TREE_TYPE (arg));
2604
2605 /* Try expanding via a sincos optab, fall back to emitting a libcall
18b8d8ae 2606 to sincos or cexp. We are sure we have sincos or cexp because cexpi
2607 is only generated from sincos, cexp or if we have either of them. */
d6bf3b14 2608 if (optab_handler (sincos_optab, mode) != CODE_FOR_nothing)
d735c391 2609 {
2610 op1 = gen_reg_rtx (mode);
2611 op2 = gen_reg_rtx (mode);
2612
f97eea22 2613 op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
d735c391 2614
2615 /* Compute into op1 and op2. */
2616 expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
2617 }
30f690e0 2618 else if (targetm.libc_has_function (function_sincos))
d735c391 2619 {
c2f47e15 2620 tree call, fn = NULL_TREE;
d735c391 2621 tree top1, top2;
2622 rtx op1a, op2a;
2623
2624 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
b9a16870 2625 fn = builtin_decl_explicit (BUILT_IN_SINCOSF);
d735c391 2626 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
b9a16870 2627 fn = builtin_decl_explicit (BUILT_IN_SINCOS);
d735c391 2628 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
b9a16870 2629 fn = builtin_decl_explicit (BUILT_IN_SINCOSL);
c2f47e15 2630 else
2631 gcc_unreachable ();
48e1416a 2632
0ab48139 2633 op1 = assign_temp (TREE_TYPE (arg), 1, 1);
2634 op2 = assign_temp (TREE_TYPE (arg), 1, 1);
99182918 2635 op1a = copy_addr_to_reg (XEXP (op1, 0));
2636 op2a = copy_addr_to_reg (XEXP (op2, 0));
d735c391 2637 top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
2638 top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
2639
d735c391 2640 /* Make sure not to fold the sincos call again. */
2641 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
c2f47e15 2642 expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
2643 call, 3, arg, top1, top2));
d735c391 2644 }
18b8d8ae 2645 else
2646 {
0ecbc158 2647 tree call, fn = NULL_TREE, narg;
18b8d8ae 2648 tree ctype = build_complex_type (type);
2649
0ecbc158 2650 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
b9a16870 2651 fn = builtin_decl_explicit (BUILT_IN_CEXPF);
0ecbc158 2652 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
b9a16870 2653 fn = builtin_decl_explicit (BUILT_IN_CEXP);
0ecbc158 2654 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
b9a16870 2655 fn = builtin_decl_explicit (BUILT_IN_CEXPL);
c2f47e15 2656 else
2657 gcc_unreachable ();
fc0dfa6e 2658
2659 /* If we don't have a decl for cexp create one. This is the
2660 friendliest fallback if the user calls __builtin_cexpi
2661 without full target C99 function support. */
2662 if (fn == NULL_TREE)
2663 {
2664 tree fntype;
2665 const char *name = NULL;
2666
2667 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2668 name = "cexpf";
2669 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2670 name = "cexp";
2671 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2672 name = "cexpl";
2673
2674 fntype = build_function_type_list (ctype, ctype, NULL_TREE);
2675 fn = build_fn_decl (name, fntype);
2676 }
2677
389dd41b 2678 narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype,
18b8d8ae 2679 build_real (type, dconst0), arg);
2680
2681 /* Make sure not to fold the cexp call again. */
2682 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
48e1416a 2683 return expand_expr (build_call_nary (ctype, call, 1, narg),
1db6d067 2684 target, VOIDmode, EXPAND_NORMAL);
18b8d8ae 2685 }
d735c391 2686
2687 /* Now build the proper return type. */
2688 return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
2689 make_tree (TREE_TYPE (arg), op2),
2690 make_tree (TREE_TYPE (arg), op1)),
1db6d067 2691 target, VOIDmode, EXPAND_NORMAL);
d735c391 2692}
2693
a65c4d64 2694/* Conveniently construct a function call expression. FNDECL names the
2695 function to be called, N is the number of arguments, and the "..."
2696 parameters are the argument expressions. Unlike build_call_exr
2697 this doesn't fold the call, hence it will always return a CALL_EXPR. */
2698
2699static tree
2700build_call_nofold_loc (location_t loc, tree fndecl, int n, ...)
2701{
2702 va_list ap;
2703 tree fntype = TREE_TYPE (fndecl);
2704 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
2705
2706 va_start (ap, n);
2707 fn = build_call_valist (TREE_TYPE (fntype), fn, n, ap);
2708 va_end (ap);
2709 SET_EXPR_LOCATION (fn, loc);
2710 return fn;
2711}
a65c4d64 2712
7d3afc77 2713/* Expand a call to one of the builtin rounding functions gcc defines
2714 as an extension (lfloor and lceil). As these are gcc extensions we
2715 do not need to worry about setting errno to EDOM.
ad52b9b7 2716 If expanding via optab fails, lower expression to (int)(floor(x)).
2717 EXP is the expression that is a call to the builtin function;
ff1b14e4 2718 if convenient, the result should be placed in TARGET. */
ad52b9b7 2719
2720static rtx
ff1b14e4 2721expand_builtin_int_roundingfn (tree exp, rtx target)
ad52b9b7 2722{
9c42dd28 2723 convert_optab builtin_optab;
ad52b9b7 2724 rtx op0, insns, tmp;
2725 tree fndecl = get_callee_fndecl (exp);
ad52b9b7 2726 enum built_in_function fallback_fn;
2727 tree fallback_fndecl;
2728 enum machine_mode mode;
4de0924f 2729 tree arg;
ad52b9b7 2730
c2f47e15 2731 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
ad52b9b7 2732 gcc_unreachable ();
2733
c2f47e15 2734 arg = CALL_EXPR_ARG (exp, 0);
ad52b9b7 2735
2736 switch (DECL_FUNCTION_CODE (fndecl))
2737 {
80ff6494 2738 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 2739 CASE_FLT_FN (BUILT_IN_LCEIL):
2740 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 2741 builtin_optab = lceil_optab;
2742 fallback_fn = BUILT_IN_CEIL;
2743 break;
2744
80ff6494 2745 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 2746 CASE_FLT_FN (BUILT_IN_LFLOOR):
2747 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 2748 builtin_optab = lfloor_optab;
2749 fallback_fn = BUILT_IN_FLOOR;
2750 break;
2751
2752 default:
2753 gcc_unreachable ();
2754 }
2755
2756 /* Make a suitable register to place result in. */
2757 mode = TYPE_MODE (TREE_TYPE (exp));
2758
9c42dd28 2759 target = gen_reg_rtx (mode);
ad52b9b7 2760
9c42dd28 2761 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2762 need to expand the argument again. This way, we will not perform
2763 side-effects more the once. */
abfea505 2764 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
ad52b9b7 2765
ff1b14e4 2766 op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
ad52b9b7 2767
9c42dd28 2768 start_sequence ();
ad52b9b7 2769
9c42dd28 2770 /* Compute into TARGET. */
2771 if (expand_sfix_optab (target, op0, builtin_optab))
2772 {
2773 /* Output the entire sequence. */
2774 insns = get_insns ();
ad52b9b7 2775 end_sequence ();
9c42dd28 2776 emit_insn (insns);
2777 return target;
ad52b9b7 2778 }
2779
9c42dd28 2780 /* If we were unable to expand via the builtin, stop the sequence
2781 (without outputting the insns). */
2782 end_sequence ();
2783
ad52b9b7 2784 /* Fall back to floating point rounding optab. */
2785 fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
fc0dfa6e 2786
2787 /* For non-C99 targets we may end up without a fallback fndecl here
2788 if the user called __builtin_lfloor directly. In this case emit
2789 a call to the floor/ceil variants nevertheless. This should result
2790 in the best user experience for not full C99 targets. */
2791 if (fallback_fndecl == NULL_TREE)
2792 {
2793 tree fntype;
2794 const char *name = NULL;
2795
2796 switch (DECL_FUNCTION_CODE (fndecl))
2797 {
80ff6494 2798 case BUILT_IN_ICEIL:
fc0dfa6e 2799 case BUILT_IN_LCEIL:
2800 case BUILT_IN_LLCEIL:
2801 name = "ceil";
2802 break;
80ff6494 2803 case BUILT_IN_ICEILF:
fc0dfa6e 2804 case BUILT_IN_LCEILF:
2805 case BUILT_IN_LLCEILF:
2806 name = "ceilf";
2807 break;
80ff6494 2808 case BUILT_IN_ICEILL:
fc0dfa6e 2809 case BUILT_IN_LCEILL:
2810 case BUILT_IN_LLCEILL:
2811 name = "ceill";
2812 break;
80ff6494 2813 case BUILT_IN_IFLOOR:
fc0dfa6e 2814 case BUILT_IN_LFLOOR:
2815 case BUILT_IN_LLFLOOR:
2816 name = "floor";
2817 break;
80ff6494 2818 case BUILT_IN_IFLOORF:
fc0dfa6e 2819 case BUILT_IN_LFLOORF:
2820 case BUILT_IN_LLFLOORF:
2821 name = "floorf";
2822 break;
80ff6494 2823 case BUILT_IN_IFLOORL:
fc0dfa6e 2824 case BUILT_IN_LFLOORL:
2825 case BUILT_IN_LLFLOORL:
2826 name = "floorl";
2827 break;
2828 default:
2829 gcc_unreachable ();
2830 }
2831
2832 fntype = build_function_type_list (TREE_TYPE (arg),
2833 TREE_TYPE (arg), NULL_TREE);
2834 fallback_fndecl = build_fn_decl (name, fntype);
2835 }
2836
0568e9c1 2837 exp = build_call_nofold_loc (EXPR_LOCATION (exp), fallback_fndecl, 1, arg);
ad52b9b7 2838
d4c690af 2839 tmp = expand_normal (exp);
933eb13a 2840 tmp = maybe_emit_group_store (tmp, TREE_TYPE (exp));
ad52b9b7 2841
2842 /* Truncate the result of floating point optab to integer
2843 via expand_fix (). */
2844 target = gen_reg_rtx (mode);
2845 expand_fix (target, tmp, 0);
2846
2847 return target;
2848}
2849
7d3afc77 2850/* Expand a call to one of the builtin math functions doing integer
2851 conversion (lrint).
2852 Return 0 if a normal call should be emitted rather than expanding the
2853 function in-line. EXP is the expression that is a call to the builtin
ff1b14e4 2854 function; if convenient, the result should be placed in TARGET. */
7d3afc77 2855
2856static rtx
ff1b14e4 2857expand_builtin_int_roundingfn_2 (tree exp, rtx target)
7d3afc77 2858{
5f51ee59 2859 convert_optab builtin_optab;
7d3afc77 2860 rtx op0, insns;
2861 tree fndecl = get_callee_fndecl (exp);
4de0924f 2862 tree arg;
c2f47e15 2863 enum machine_mode mode;
e951f9a4 2864 enum built_in_function fallback_fn = BUILT_IN_NONE;
7d3afc77 2865
c2f47e15 2866 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2867 gcc_unreachable ();
48e1416a 2868
c2f47e15 2869 arg = CALL_EXPR_ARG (exp, 0);
7d3afc77 2870
2871 switch (DECL_FUNCTION_CODE (fndecl))
2872 {
80ff6494 2873 CASE_FLT_FN (BUILT_IN_IRINT):
e951f9a4 2874 fallback_fn = BUILT_IN_LRINT;
2875 /* FALLTHRU */
7d3afc77 2876 CASE_FLT_FN (BUILT_IN_LRINT):
2877 CASE_FLT_FN (BUILT_IN_LLRINT):
e951f9a4 2878 builtin_optab = lrint_optab;
2879 break;
80ff6494 2880
2881 CASE_FLT_FN (BUILT_IN_IROUND):
e951f9a4 2882 fallback_fn = BUILT_IN_LROUND;
2883 /* FALLTHRU */
ef2f1a10 2884 CASE_FLT_FN (BUILT_IN_LROUND):
2885 CASE_FLT_FN (BUILT_IN_LLROUND):
e951f9a4 2886 builtin_optab = lround_optab;
2887 break;
80ff6494 2888
7d3afc77 2889 default:
2890 gcc_unreachable ();
2891 }
2892
e951f9a4 2893 /* There's no easy way to detect the case we need to set EDOM. */
2894 if (flag_errno_math && fallback_fn == BUILT_IN_NONE)
2895 return NULL_RTX;
2896
7d3afc77 2897 /* Make a suitable register to place result in. */
2898 mode = TYPE_MODE (TREE_TYPE (exp));
2899
e951f9a4 2900 /* There's no easy way to detect the case we need to set EDOM. */
2901 if (!flag_errno_math)
2902 {
de2e453e 2903 rtx result = gen_reg_rtx (mode);
7d3afc77 2904
e951f9a4 2905 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2906 need to expand the argument again. This way, we will not perform
2907 side-effects more the once. */
2908 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7d3afc77 2909
e951f9a4 2910 op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
7d3afc77 2911
e951f9a4 2912 start_sequence ();
7d3afc77 2913
de2e453e 2914 if (expand_sfix_optab (result, op0, builtin_optab))
e951f9a4 2915 {
2916 /* Output the entire sequence. */
2917 insns = get_insns ();
2918 end_sequence ();
2919 emit_insn (insns);
de2e453e 2920 return result;
e951f9a4 2921 }
2922
2923 /* If we were unable to expand via the builtin, stop the sequence
2924 (without outputting the insns) and call to the library function
2925 with the stabilized argument list. */
7d3afc77 2926 end_sequence ();
2927 }
2928
e951f9a4 2929 if (fallback_fn != BUILT_IN_NONE)
2930 {
2931 /* Fall back to rounding to long int. Use implicit_p 0 - for non-C99
2932 targets, (int) round (x) should never be transformed into
2933 BUILT_IN_IROUND and if __builtin_iround is called directly, emit
2934 a call to lround in the hope that the target provides at least some
2935 C99 functions. This should result in the best user experience for
2936 not full C99 targets. */
2937 tree fallback_fndecl = mathfn_built_in_1 (TREE_TYPE (arg),
2938 fallback_fn, 0);
2939
2940 exp = build_call_nofold_loc (EXPR_LOCATION (exp),
2941 fallback_fndecl, 1, arg);
2942
2943 target = expand_call (exp, NULL_RTX, target == const0_rtx);
933eb13a 2944 target = maybe_emit_group_store (target, TREE_TYPE (exp));
e951f9a4 2945 return convert_to_mode (mode, target, 0);
2946 }
5f51ee59 2947
de2e453e 2948 return expand_call (exp, target, target == const0_rtx);
7d3afc77 2949}
2950
c2f47e15 2951/* Expand a call to the powi built-in mathematical function. Return NULL_RTX if
757c219d 2952 a normal call should be emitted rather than expanding the function
2953 in-line. EXP is the expression that is a call to the builtin
2954 function; if convenient, the result should be placed in TARGET. */
2955
2956static rtx
f97eea22 2957expand_builtin_powi (tree exp, rtx target)
757c219d 2958{
757c219d 2959 tree arg0, arg1;
2960 rtx op0, op1;
2961 enum machine_mode mode;
d0405f40 2962 enum machine_mode mode2;
757c219d 2963
c2f47e15 2964 if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
2965 return NULL_RTX;
757c219d 2966
c2f47e15 2967 arg0 = CALL_EXPR_ARG (exp, 0);
2968 arg1 = CALL_EXPR_ARG (exp, 1);
757c219d 2969 mode = TYPE_MODE (TREE_TYPE (exp));
2970
757c219d 2971 /* Emit a libcall to libgcc. */
2972
c2f47e15 2973 /* Mode of the 2nd argument must match that of an int. */
d0405f40 2974 mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
2975
757c219d 2976 if (target == NULL_RTX)
2977 target = gen_reg_rtx (mode);
2978
f97eea22 2979 op0 = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
757c219d 2980 if (GET_MODE (op0) != mode)
2981 op0 = convert_to_mode (mode, op0, 0);
1db6d067 2982 op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
d0405f40 2983 if (GET_MODE (op1) != mode2)
2984 op1 = convert_to_mode (mode2, op1, 0);
757c219d 2985
f36b9f69 2986 target = emit_library_call_value (optab_libfunc (powi_optab, mode),
2dd6f9ed 2987 target, LCT_CONST, mode, 2,
d0405f40 2988 op0, mode, op1, mode2);
757c219d 2989
2990 return target;
2991}
2992
48e1416a 2993/* Expand expression EXP which is a call to the strlen builtin. Return
c2f47e15 2994 NULL_RTX if we failed the caller should emit a normal call, otherwise
aed0bd19 2995 try to get the result in TARGET, if convenient. */
f7c44134 2996
53800dbe 2997static rtx
c2f47e15 2998expand_builtin_strlen (tree exp, rtx target,
aecda0d6 2999 enum machine_mode target_mode)
53800dbe 3000{
c2f47e15 3001 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
3002 return NULL_RTX;
53800dbe 3003 else
3004 {
8786db1e 3005 struct expand_operand ops[4];
911c0150 3006 rtx pat;
c2f47e15 3007 tree len;
3008 tree src = CALL_EXPR_ARG (exp, 0);
8786db1e 3009 rtx src_reg, before_strlen;
3010 enum machine_mode insn_mode = target_mode;
ef2c4a29 3011 enum insn_code icode = CODE_FOR_nothing;
153c3b50 3012 unsigned int align;
6248e345 3013
3014 /* If the length can be computed at compile-time, return it. */
681fab1e 3015 len = c_strlen (src, 0);
6248e345 3016 if (len)
80cd7a5e 3017 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
6248e345 3018
681fab1e 3019 /* If the length can be computed at compile-time and is constant
3020 integer, but there are side-effects in src, evaluate
3021 src for side-effects, then return len.
3022 E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
3023 can be optimized into: i++; x = 3; */
3024 len = c_strlen (src, 1);
3025 if (len && TREE_CODE (len) == INTEGER_CST)
3026 {
3027 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
3028 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
3029 }
3030
957d0361 3031 align = get_pointer_alignment (src) / BITS_PER_UNIT;
53800dbe 3032
53800dbe 3033 /* If SRC is not a pointer type, don't do this operation inline. */
3034 if (align == 0)
c2f47e15 3035 return NULL_RTX;
53800dbe 3036
911c0150 3037 /* Bail out if we can't compute strlen in the right mode. */
53800dbe 3038 while (insn_mode != VOIDmode)
3039 {
d6bf3b14 3040 icode = optab_handler (strlen_optab, insn_mode);
53800dbe 3041 if (icode != CODE_FOR_nothing)
c28ae87f 3042 break;
53800dbe 3043
3044 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
3045 }
3046 if (insn_mode == VOIDmode)
c2f47e15 3047 return NULL_RTX;
53800dbe 3048
911c0150 3049 /* Make a place to hold the source address. We will not expand
3050 the actual source until we are sure that the expansion will
3051 not fail -- there are trees that cannot be expanded twice. */
3052 src_reg = gen_reg_rtx (Pmode);
53800dbe 3053
911c0150 3054 /* Mark the beginning of the strlen sequence so we can emit the
3055 source operand later. */
f0ce3b1f 3056 before_strlen = get_last_insn ();
53800dbe 3057
8786db1e 3058 create_output_operand (&ops[0], target, insn_mode);
3059 create_fixed_operand (&ops[1], gen_rtx_MEM (BLKmode, src_reg));
3060 create_integer_operand (&ops[2], 0);
3061 create_integer_operand (&ops[3], align);
3062 if (!maybe_expand_insn (icode, 4, ops))
c2f47e15 3063 return NULL_RTX;
911c0150 3064
3065 /* Now that we are assured of success, expand the source. */
3066 start_sequence ();
499eee58 3067 pat = expand_expr (src, src_reg, Pmode, EXPAND_NORMAL);
911c0150 3068 if (pat != src_reg)
499eee58 3069 {
3070#ifdef POINTERS_EXTEND_UNSIGNED
3071 if (GET_MODE (pat) != Pmode)
3072 pat = convert_to_mode (Pmode, pat,
3073 POINTERS_EXTEND_UNSIGNED);
3074#endif
3075 emit_move_insn (src_reg, pat);
3076 }
31d3e01c 3077 pat = get_insns ();
911c0150 3078 end_sequence ();
bceb0d1f 3079
3080 if (before_strlen)
3081 emit_insn_after (pat, before_strlen);
3082 else
3083 emit_insn_before (pat, get_insns ());
53800dbe 3084
3085 /* Return the value in the proper mode for this function. */
8786db1e 3086 if (GET_MODE (ops[0].value) == target_mode)
3087 target = ops[0].value;
53800dbe 3088 else if (target != 0)
8786db1e 3089 convert_move (target, ops[0].value, 0);
53800dbe 3090 else
8786db1e 3091 target = convert_to_mode (target_mode, ops[0].value, 0);
911c0150 3092
3093 return target;
53800dbe 3094 }
3095}
3096
6840589f 3097/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3098 bytes from constant string DATA + OFFSET and return it as target
3099 constant. */
3100
3101static rtx
aecda0d6 3102builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
3103 enum machine_mode mode)
6840589f 3104{
3105 const char *str = (const char *) data;
3106
64db345d 3107 gcc_assert (offset >= 0
3108 && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
3109 <= strlen (str) + 1));
6840589f 3110
3111 return c_readstr (str + offset, mode);
3112}
3113
36d63243 3114/* LEN specify length of the block of memcpy/memset operation.
9db0f34d 3115 Figure out its range and put it into MIN_SIZE/MAX_SIZE.
3116 In some cases we can make very likely guess on max size, then we
3117 set it into PROBABLE_MAX_SIZE. */
36d63243 3118
3119static void
3120determine_block_size (tree len, rtx len_rtx,
3121 unsigned HOST_WIDE_INT *min_size,
9db0f34d 3122 unsigned HOST_WIDE_INT *max_size,
3123 unsigned HOST_WIDE_INT *probable_max_size)
36d63243 3124{
3125 if (CONST_INT_P (len_rtx))
3126 {
3127 *min_size = *max_size = UINTVAL (len_rtx);
3128 return;
3129 }
3130 else
3131 {
9c1be15e 3132 wide_int min, max;
9db0f34d 3133 enum value_range_type range_type = VR_UNDEFINED;
3134
3135 /* Determine bounds from the type. */
3136 if (tree_fits_uhwi_p (TYPE_MIN_VALUE (TREE_TYPE (len))))
3137 *min_size = tree_to_uhwi (TYPE_MIN_VALUE (TREE_TYPE (len)));
3138 else
3139 *min_size = 0;
3140 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (TREE_TYPE (len))))
3141 *probable_max_size = *max_size = tree_to_uhwi (TYPE_MAX_VALUE (TREE_TYPE (len)));
3142 else
3143 *probable_max_size = *max_size = GET_MODE_MASK (GET_MODE (len_rtx));
3144
3145 if (TREE_CODE (len) == SSA_NAME)
3146 range_type = get_range_info (len, &min, &max);
3147 if (range_type == VR_RANGE)
36d63243 3148 {
fe5ad926 3149 if (wi::fits_uhwi_p (min) && *min_size < min.to_uhwi ())
36d63243 3150 *min_size = min.to_uhwi ();
fe5ad926 3151 if (wi::fits_uhwi_p (max) && *max_size > max.to_uhwi ())
9db0f34d 3152 *probable_max_size = *max_size = max.to_uhwi ();
36d63243 3153 }
9db0f34d 3154 else if (range_type == VR_ANTI_RANGE)
36d63243 3155 {
4a474a5a 3156 /* Anti range 0...N lets us to determine minimal size to N+1. */
fe5ad926 3157 if (min == 0)
9db0f34d 3158 {
9c1be15e 3159 if (wi::fits_uhwi_p (max) && max.to_uhwi () + 1 != 0)
3160 *min_size = max.to_uhwi () + 1;
9db0f34d 3161 }
3162 /* Code like
3163
3164 int n;
3165 if (n < 100)
4a474a5a 3166 memcpy (a, b, n)
9db0f34d 3167
3168 Produce anti range allowing negative values of N. We still
3169 can use the information and make a guess that N is not negative.
3170 */
fe5ad926 3171 else if (!wi::leu_p (max, 1 << 30) && wi::fits_uhwi_p (min))
3172 *probable_max_size = min.to_uhwi () - 1;
36d63243 3173 }
3174 }
3175 gcc_checking_assert (*max_size <=
3176 (unsigned HOST_WIDE_INT)
3177 GET_MODE_MASK (GET_MODE (len_rtx)));
3178}
3179
c2f47e15 3180/* Expand a call EXP to the memcpy builtin.
3181 Return NULL_RTX if we failed, the caller should emit a normal call,
3b824fa6 3182 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3183 mode MODE if that's convenient). */
c2f47e15 3184
53800dbe 3185static rtx
a65c4d64 3186expand_builtin_memcpy (tree exp, rtx target)
53800dbe 3187{
c2f47e15 3188 if (!validate_arglist (exp,
3189 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3190 return NULL_RTX;
53800dbe 3191 else
3192 {
c2f47e15 3193 tree dest = CALL_EXPR_ARG (exp, 0);
3194 tree src = CALL_EXPR_ARG (exp, 1);
3195 tree len = CALL_EXPR_ARG (exp, 2);
6840589f 3196 const char *src_str;
957d0361 3197 unsigned int src_align = get_pointer_alignment (src);
3198 unsigned int dest_align = get_pointer_alignment (dest);
53800dbe 3199 rtx dest_mem, src_mem, dest_addr, len_rtx;
162719b3 3200 HOST_WIDE_INT expected_size = -1;
3201 unsigned int expected_align = 0;
36d63243 3202 unsigned HOST_WIDE_INT min_size;
3203 unsigned HOST_WIDE_INT max_size;
9db0f34d 3204 unsigned HOST_WIDE_INT probable_max_size;
5a0de151 3205
6f428e8b 3206 /* If DEST is not a pointer type, call the normal function. */
3207 if (dest_align == 0)
c2f47e15 3208 return NULL_RTX;
6f428e8b 3209
6f428e8b 3210 /* If either SRC is not a pointer type, don't do this
a0c938f0 3211 operation in-line. */
6f428e8b 3212 if (src_align == 0)
c2f47e15 3213 return NULL_RTX;
48e1416a 3214
8cee8dc0 3215 if (currently_expanding_gimple_stmt)
3216 stringop_block_profile (currently_expanding_gimple_stmt,
3217 &expected_align, &expected_size);
75a70cf9 3218
162719b3 3219 if (expected_align < dest_align)
3220 expected_align = dest_align;
d8ae1baa 3221 dest_mem = get_memory_rtx (dest, len);
2a631e19 3222 set_mem_align (dest_mem, dest_align);
8ec3c5c2 3223 len_rtx = expand_normal (len);
9db0f34d 3224 determine_block_size (len, len_rtx, &min_size, &max_size,
3225 &probable_max_size);
6840589f 3226 src_str = c_getstr (src);
3227
3228 /* If SRC is a string constant and block move would be done
3229 by pieces, we can avoid loading the string from memory
3230 and only stored the computed constants. */
3231 if (src_str
971ba038 3232 && CONST_INT_P (len_rtx)
6840589f 3233 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3234 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3235 CONST_CAST (char *, src_str),
3236 dest_align, false))
6840589f 3237 {
9fe0e1b8 3238 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3239 builtin_memcpy_read_str,
364c0c59 3240 CONST_CAST (char *, src_str),
3241 dest_align, false, 0);
a65c4d64 3242 dest_mem = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3243 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3244 return dest_mem;
6840589f 3245 }
3246
d8ae1baa 3247 src_mem = get_memory_rtx (src, len);
2a631e19 3248 set_mem_align (src_mem, src_align);
53800dbe 3249
53800dbe 3250 /* Copy word part most expediently. */
162719b3 3251 dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
3252 CALL_EXPR_TAILCALL (exp)
3253 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
36d63243 3254 expected_align, expected_size,
9db0f34d 3255 min_size, max_size, probable_max_size);
53800dbe 3256
3257 if (dest_addr == 0)
e5716f7e 3258 {
a65c4d64 3259 dest_addr = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3260 dest_addr = convert_memory_address (ptr_mode, dest_addr);
e5716f7e 3261 }
9fe0e1b8 3262 return dest_addr;
53800dbe 3263 }
3264}
3265
c2f47e15 3266/* Expand a call EXP to the mempcpy builtin.
3267 Return NULL_RTX if we failed; the caller should emit a normal call,
647661c6 3268 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3269 mode MODE if that's convenient). If ENDP is 0 return the
3270 destination pointer, if ENDP is 1 return the end pointer ala
3271 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3272 stpcpy. */
647661c6 3273
3274static rtx
c8b17b2e 3275expand_builtin_mempcpy (tree exp, rtx target, enum machine_mode mode)
647661c6 3276{
c2f47e15 3277 if (!validate_arglist (exp,
3278 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3279 return NULL_RTX;
3280 else
3281 {
3282 tree dest = CALL_EXPR_ARG (exp, 0);
3283 tree src = CALL_EXPR_ARG (exp, 1);
3284 tree len = CALL_EXPR_ARG (exp, 2);
3285 return expand_builtin_mempcpy_args (dest, src, len,
c2f47e15 3286 target, mode, /*endp=*/ 1);
3287 }
3288}
3289
3290/* Helper function to do the actual work for expand_builtin_mempcpy. The
3291 arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out
3292 so that this can also be called without constructing an actual CALL_EXPR.
a65c4d64 3293 The other arguments and return value are the same as for
3294 expand_builtin_mempcpy. */
c2f47e15 3295
3296static rtx
a65c4d64 3297expand_builtin_mempcpy_args (tree dest, tree src, tree len,
c2f47e15 3298 rtx target, enum machine_mode mode, int endp)
3299{
3300 /* If return value is ignored, transform mempcpy into memcpy. */
b9a16870 3301 if (target == const0_rtx && builtin_decl_implicit_p (BUILT_IN_MEMCPY))
9fe0e1b8 3302 {
b9a16870 3303 tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
0568e9c1 3304 tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3,
3305 dest, src, len);
c8b17b2e 3306 return expand_expr (result, target, mode, EXPAND_NORMAL);
9fe0e1b8 3307 }
647661c6 3308 else
3309 {
9fe0e1b8 3310 const char *src_str;
957d0361 3311 unsigned int src_align = get_pointer_alignment (src);
3312 unsigned int dest_align = get_pointer_alignment (dest);
9fe0e1b8 3313 rtx dest_mem, src_mem, len_rtx;
a0c938f0 3314
7da1412b 3315 /* If either SRC or DEST is not a pointer type, don't do this
a0c938f0 3316 operation in-line. */
7da1412b 3317 if (dest_align == 0 || src_align == 0)
c2f47e15 3318 return NULL_RTX;
9fe0e1b8 3319
6217c238 3320 /* If LEN is not constant, call the normal function. */
e913b5cd 3321 if (! tree_fits_uhwi_p (len))
c2f47e15 3322 return NULL_RTX;
0862b7e9 3323
8ec3c5c2 3324 len_rtx = expand_normal (len);
9fe0e1b8 3325 src_str = c_getstr (src);
647661c6 3326
9fe0e1b8 3327 /* If SRC is a string constant and block move would be done
3328 by pieces, we can avoid loading the string from memory
3329 and only stored the computed constants. */
3330 if (src_str
971ba038 3331 && CONST_INT_P (len_rtx)
9fe0e1b8 3332 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3333 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3334 CONST_CAST (char *, src_str),
3335 dest_align, false))
9fe0e1b8 3336 {
d8ae1baa 3337 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3338 set_mem_align (dest_mem, dest_align);
3339 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3340 builtin_memcpy_read_str,
364c0c59 3341 CONST_CAST (char *, src_str),
3342 dest_align, false, endp);
9fe0e1b8 3343 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3344 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3345 return dest_mem;
647661c6 3346 }
3347
971ba038 3348 if (CONST_INT_P (len_rtx)
9fe0e1b8 3349 && can_move_by_pieces (INTVAL (len_rtx),
3350 MIN (dest_align, src_align)))
3351 {
d8ae1baa 3352 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3353 set_mem_align (dest_mem, dest_align);
d8ae1baa 3354 src_mem = get_memory_rtx (src, len);
9fe0e1b8 3355 set_mem_align (src_mem, src_align);
3356 dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
3357 MIN (dest_align, src_align), endp);
3358 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3359 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3360 return dest_mem;
3361 }
3362
c2f47e15 3363 return NULL_RTX;
647661c6 3364 }
3365}
3366
727c62dd 3367#ifndef HAVE_movstr
3368# define HAVE_movstr 0
3369# define CODE_FOR_movstr CODE_FOR_nothing
3370#endif
3371
c2f47e15 3372/* Expand into a movstr instruction, if one is available. Return NULL_RTX if
727c62dd 3373 we failed, the caller should emit a normal call, otherwise try to
3374 get the result in TARGET, if convenient. If ENDP is 0 return the
3375 destination pointer, if ENDP is 1 return the end pointer ala
3376 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3377 stpcpy. */
3378
3379static rtx
3380expand_movstr (tree dest, tree src, rtx target, int endp)
3381{
8786db1e 3382 struct expand_operand ops[3];
727c62dd 3383 rtx dest_mem;
3384 rtx src_mem;
727c62dd 3385
3386 if (!HAVE_movstr)
c2f47e15 3387 return NULL_RTX;
727c62dd 3388
d8ae1baa 3389 dest_mem = get_memory_rtx (dest, NULL);
3390 src_mem = get_memory_rtx (src, NULL);
727c62dd 3391 if (!endp)
3392 {
3393 target = force_reg (Pmode, XEXP (dest_mem, 0));
3394 dest_mem = replace_equiv_address (dest_mem, target);
727c62dd 3395 }
3396
8786db1e 3397 create_output_operand (&ops[0], endp ? target : NULL_RTX, Pmode);
3398 create_fixed_operand (&ops[1], dest_mem);
3399 create_fixed_operand (&ops[2], src_mem);
3400 expand_insn (CODE_FOR_movstr, 3, ops);
727c62dd 3401
8786db1e 3402 if (endp && target != const0_rtx)
c5aba89c 3403 {
8786db1e 3404 target = ops[0].value;
3405 /* movstr is supposed to set end to the address of the NUL
3406 terminator. If the caller requested a mempcpy-like return value,
3407 adjust it. */
3408 if (endp == 1)
3409 {
29c05e22 3410 rtx tem = plus_constant (GET_MODE (target),
3411 gen_lowpart (GET_MODE (target), target), 1);
8786db1e 3412 emit_move_insn (target, force_operand (tem, NULL_RTX));
3413 }
c5aba89c 3414 }
727c62dd 3415 return target;
3416}
3417
48e1416a 3418/* Expand expression EXP, which is a call to the strcpy builtin. Return
3419 NULL_RTX if we failed the caller should emit a normal call, otherwise
c2f47e15 3420 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3421 convenient). */
902de8ed 3422
53800dbe 3423static rtx
a65c4d64 3424expand_builtin_strcpy (tree exp, rtx target)
53800dbe 3425{
c2f47e15 3426 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3427 {
3428 tree dest = CALL_EXPR_ARG (exp, 0);
3429 tree src = CALL_EXPR_ARG (exp, 1);
a65c4d64 3430 return expand_builtin_strcpy_args (dest, src, target);
c2f47e15 3431 }
3432 return NULL_RTX;
3433}
3434
3435/* Helper function to do the actual work for expand_builtin_strcpy. The
3436 arguments to the builtin_strcpy call DEST and SRC are broken out
3437 so that this can also be called without constructing an actual CALL_EXPR.
3438 The other arguments and return value are the same as for
3439 expand_builtin_strcpy. */
3440
3441static rtx
a65c4d64 3442expand_builtin_strcpy_args (tree dest, tree src, rtx target)
c2f47e15 3443{
c2f47e15 3444 return expand_movstr (dest, src, target, /*endp=*/0);
53800dbe 3445}
3446
c2f47e15 3447/* Expand a call EXP to the stpcpy builtin.
3448 Return NULL_RTX if we failed the caller should emit a normal call,
3b824fa6 3449 otherwise try to get the result in TARGET, if convenient (and in
3450 mode MODE if that's convenient). */
3451
3452static rtx
dc369150 3453expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
3b824fa6 3454{
c2f47e15 3455 tree dst, src;
389dd41b 3456 location_t loc = EXPR_LOCATION (exp);
c2f47e15 3457
3458 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3459 return NULL_RTX;
3460
3461 dst = CALL_EXPR_ARG (exp, 0);
3462 src = CALL_EXPR_ARG (exp, 1);
3463
727c62dd 3464 /* If return value is ignored, transform stpcpy into strcpy. */
b9a16870 3465 if (target == const0_rtx && builtin_decl_implicit (BUILT_IN_STRCPY))
978836e5 3466 {
b9a16870 3467 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
0568e9c1 3468 tree result = build_call_nofold_loc (loc, fn, 2, dst, src);
c8b17b2e 3469 return expand_expr (result, target, mode, EXPAND_NORMAL);
978836e5 3470 }
3b824fa6 3471 else
3472 {
c2f47e15 3473 tree len, lenp1;
727c62dd 3474 rtx ret;
647661c6 3475
9fe0e1b8 3476 /* Ensure we get an actual string whose length can be evaluated at
a0c938f0 3477 compile-time, not an expression containing a string. This is
3478 because the latter will potentially produce pessimized code
3479 when used to produce the return value. */
681fab1e 3480 if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
c2f47e15 3481 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3482
389dd41b 3483 lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
a65c4d64 3484 ret = expand_builtin_mempcpy_args (dst, src, lenp1,
c2f47e15 3485 target, mode, /*endp=*/2);
727c62dd 3486
3487 if (ret)
3488 return ret;
3489
3490 if (TREE_CODE (len) == INTEGER_CST)
3491 {
8ec3c5c2 3492 rtx len_rtx = expand_normal (len);
727c62dd 3493
971ba038 3494 if (CONST_INT_P (len_rtx))
727c62dd 3495 {
a65c4d64 3496 ret = expand_builtin_strcpy_args (dst, src, target);
727c62dd 3497
3498 if (ret)
3499 {
3500 if (! target)
7ac87324 3501 {
3502 if (mode != VOIDmode)
3503 target = gen_reg_rtx (mode);
3504 else
3505 target = gen_reg_rtx (GET_MODE (ret));
3506 }
727c62dd 3507 if (GET_MODE (target) != GET_MODE (ret))
3508 ret = gen_lowpart (GET_MODE (target), ret);
3509
29c05e22 3510 ret = plus_constant (GET_MODE (ret), ret, INTVAL (len_rtx));
c5aba89c 3511 ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
64db345d 3512 gcc_assert (ret);
727c62dd 3513
3514 return target;
3515 }
3516 }
3517 }
3518
c2f47e15 3519 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3520 }
3521}
3522
6840589f 3523/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3524 bytes from constant string DATA + OFFSET and return it as target
3525 constant. */
3526
09879952 3527rtx
aecda0d6 3528builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
3529 enum machine_mode mode)
6840589f 3530{
3531 const char *str = (const char *) data;
3532
3533 if ((unsigned HOST_WIDE_INT) offset > strlen (str))
3534 return const0_rtx;
3535
3536 return c_readstr (str + offset, mode);
3537}
3538
48e1416a 3539/* Expand expression EXP, which is a call to the strncpy builtin. Return
c2f47e15 3540 NULL_RTX if we failed the caller should emit a normal call. */
ed09096d 3541
3542static rtx
a65c4d64 3543expand_builtin_strncpy (tree exp, rtx target)
ed09096d 3544{
389dd41b 3545 location_t loc = EXPR_LOCATION (exp);
c2f47e15 3546
3547 if (validate_arglist (exp,
3548 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
ed09096d 3549 {
c2f47e15 3550 tree dest = CALL_EXPR_ARG (exp, 0);
3551 tree src = CALL_EXPR_ARG (exp, 1);
3552 tree len = CALL_EXPR_ARG (exp, 2);
3553 tree slen = c_strlen (src, 1);
6840589f 3554
8ff6a5cd 3555 /* We must be passed a constant len and src parameter. */
e913b5cd 3556 if (!tree_fits_uhwi_p (len) || !slen || !tree_fits_uhwi_p (slen))
c2f47e15 3557 return NULL_RTX;
ed09096d 3558
389dd41b 3559 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
ed09096d 3560
3561 /* We're required to pad with trailing zeros if the requested
a0c938f0 3562 len is greater than strlen(s2)+1. In that case try to
6840589f 3563 use store_by_pieces, if it fails, punt. */
ed09096d 3564 if (tree_int_cst_lt (slen, len))
6840589f 3565 {
957d0361 3566 unsigned int dest_align = get_pointer_alignment (dest);
c2f47e15 3567 const char *p = c_getstr (src);
6840589f 3568 rtx dest_mem;
3569
e913b5cd 3570 if (!p || dest_align == 0 || !tree_fits_uhwi_p (len)
3571 || !can_store_by_pieces (tree_to_uhwi (len),
6840589f 3572 builtin_strncpy_read_str,
364c0c59 3573 CONST_CAST (char *, p),
3574 dest_align, false))
c2f47e15 3575 return NULL_RTX;
6840589f 3576
d8ae1baa 3577 dest_mem = get_memory_rtx (dest, len);
e913b5cd 3578 store_by_pieces (dest_mem, tree_to_uhwi (len),
6840589f 3579 builtin_strncpy_read_str,
364c0c59 3580 CONST_CAST (char *, p), dest_align, false, 0);
a65c4d64 3581 dest_mem = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3582 dest_mem = convert_memory_address (ptr_mode, dest_mem);
e5716f7e 3583 return dest_mem;
6840589f 3584 }
ed09096d 3585 }
c2f47e15 3586 return NULL_RTX;
ed09096d 3587}
3588
ecc318ff 3589/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3590 bytes from constant string DATA + OFFSET and return it as target
3591 constant. */
3592
f656b751 3593rtx
aecda0d6 3594builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3595 enum machine_mode mode)
ecc318ff 3596{
3597 const char *c = (const char *) data;
364c0c59 3598 char *p = XALLOCAVEC (char, GET_MODE_SIZE (mode));
ecc318ff 3599
3600 memset (p, *c, GET_MODE_SIZE (mode));
3601
3602 return c_readstr (p, mode);
3603}
3604
a7ec6974 3605/* Callback routine for store_by_pieces. Return the RTL of a register
3606 containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
3607 char value given in the RTL register data. For example, if mode is
3608 4 bytes wide, return the RTL for 0x01010101*data. */
3609
3610static rtx
aecda0d6 3611builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3612 enum machine_mode mode)
a7ec6974 3613{
3614 rtx target, coeff;
3615 size_t size;
3616 char *p;
3617
3618 size = GET_MODE_SIZE (mode);
f0ce3b1f 3619 if (size == 1)
3620 return (rtx) data;
a7ec6974 3621
364c0c59 3622 p = XALLOCAVEC (char, size);
a7ec6974 3623 memset (p, 1, size);
3624 coeff = c_readstr (p, mode);
3625
f0ce3b1f 3626 target = convert_to_mode (mode, (rtx) data, 1);
a7ec6974 3627 target = expand_mult (mode, target, coeff, NULL_RTX, 1);
3628 return force_reg (mode, target);
3629}
3630
48e1416a 3631/* Expand expression EXP, which is a call to the memset builtin. Return
3632 NULL_RTX if we failed the caller should emit a normal call, otherwise
c2f47e15 3633 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3634 convenient). */
902de8ed 3635
53800dbe 3636static rtx
c2f47e15 3637expand_builtin_memset (tree exp, rtx target, enum machine_mode mode)
53800dbe 3638{
c2f47e15 3639 if (!validate_arglist (exp,
3640 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
3641 return NULL_RTX;
53800dbe 3642 else
3643 {
c2f47e15 3644 tree dest = CALL_EXPR_ARG (exp, 0);
3645 tree val = CALL_EXPR_ARG (exp, 1);
3646 tree len = CALL_EXPR_ARG (exp, 2);
3647 return expand_builtin_memset_args (dest, val, len, target, mode, exp);
3648 }
3649}
53800dbe 3650
c2f47e15 3651/* Helper function to do the actual work for expand_builtin_memset. The
3652 arguments to the builtin_memset call DEST, VAL, and LEN are broken out
3653 so that this can also be called without constructing an actual CALL_EXPR.
3654 The other arguments and return value are the same as for
3655 expand_builtin_memset. */
6b961939 3656
c2f47e15 3657static rtx
3658expand_builtin_memset_args (tree dest, tree val, tree len,
3659 rtx target, enum machine_mode mode, tree orig_exp)
3660{
3661 tree fndecl, fn;
3662 enum built_in_function fcode;
03a5dda9 3663 enum machine_mode val_mode;
c2f47e15 3664 char c;
3665 unsigned int dest_align;
3666 rtx dest_mem, dest_addr, len_rtx;
3667 HOST_WIDE_INT expected_size = -1;
3668 unsigned int expected_align = 0;
36d63243 3669 unsigned HOST_WIDE_INT min_size;
3670 unsigned HOST_WIDE_INT max_size;
9db0f34d 3671 unsigned HOST_WIDE_INT probable_max_size;
53800dbe 3672
957d0361 3673 dest_align = get_pointer_alignment (dest);
162719b3 3674
c2f47e15 3675 /* If DEST is not a pointer type, don't do this operation in-line. */
3676 if (dest_align == 0)
3677 return NULL_RTX;
6f428e8b 3678
8cee8dc0 3679 if (currently_expanding_gimple_stmt)
3680 stringop_block_profile (currently_expanding_gimple_stmt,
3681 &expected_align, &expected_size);
75a70cf9 3682
c2f47e15 3683 if (expected_align < dest_align)
3684 expected_align = dest_align;
6b961939 3685
c2f47e15 3686 /* If the LEN parameter is zero, return DEST. */
3687 if (integer_zerop (len))
3688 {
3689 /* Evaluate and ignore VAL in case it has side-effects. */
3690 expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
3691 return expand_expr (dest, target, mode, EXPAND_NORMAL);
3692 }
7a3e5564 3693
c2f47e15 3694 /* Stabilize the arguments in case we fail. */
3695 dest = builtin_save_expr (dest);
3696 val = builtin_save_expr (val);
3697 len = builtin_save_expr (len);
a7ec6974 3698
c2f47e15 3699 len_rtx = expand_normal (len);
9db0f34d 3700 determine_block_size (len, len_rtx, &min_size, &max_size,
3701 &probable_max_size);
c2f47e15 3702 dest_mem = get_memory_rtx (dest, len);
03a5dda9 3703 val_mode = TYPE_MODE (unsigned_char_type_node);
a7ec6974 3704
c2f47e15 3705 if (TREE_CODE (val) != INTEGER_CST)
3706 {
3707 rtx val_rtx;
a7ec6974 3708
c2f47e15 3709 val_rtx = expand_normal (val);
03a5dda9 3710 val_rtx = convert_to_mode (val_mode, val_rtx, 0);
53800dbe 3711
c2f47e15 3712 /* Assume that we can memset by pieces if we can store
3713 * the coefficients by pieces (in the required modes).
3714 * We can't pass builtin_memset_gen_str as that emits RTL. */
3715 c = 1;
e913b5cd 3716 if (tree_fits_uhwi_p (len)
3717 && can_store_by_pieces (tree_to_uhwi (len),
4b297e2e 3718 builtin_memset_read_str, &c, dest_align,
3719 true))
c2f47e15 3720 {
03a5dda9 3721 val_rtx = force_reg (val_mode, val_rtx);
e913b5cd 3722 store_by_pieces (dest_mem, tree_to_uhwi (len),
4b297e2e 3723 builtin_memset_gen_str, val_rtx, dest_align,
3724 true, 0);
c2f47e15 3725 }
3726 else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
3727 dest_align, expected_align,
9db0f34d 3728 expected_size, min_size, max_size,
3729 probable_max_size))
6b961939 3730 goto do_libcall;
48e1416a 3731
c2f47e15 3732 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3733 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3734 return dest_mem;
3735 }
53800dbe 3736
c2f47e15 3737 if (target_char_cast (val, &c))
3738 goto do_libcall;
ecc318ff 3739
c2f47e15 3740 if (c)
3741 {
e913b5cd 3742 if (tree_fits_uhwi_p (len)
3743 && can_store_by_pieces (tree_to_uhwi (len),
4b297e2e 3744 builtin_memset_read_str, &c, dest_align,
3745 true))
e913b5cd 3746 store_by_pieces (dest_mem, tree_to_uhwi (len),
4b297e2e 3747 builtin_memset_read_str, &c, dest_align, true, 0);
03a5dda9 3748 else if (!set_storage_via_setmem (dest_mem, len_rtx,
3749 gen_int_mode (c, val_mode),
c2f47e15 3750 dest_align, expected_align,
9db0f34d 3751 expected_size, min_size, max_size,
3752 probable_max_size))
c2f47e15 3753 goto do_libcall;
48e1416a 3754
c2f47e15 3755 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3756 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3757 return dest_mem;
3758 }
ecc318ff 3759
c2f47e15 3760 set_mem_align (dest_mem, dest_align);
3761 dest_addr = clear_storage_hints (dest_mem, len_rtx,
3762 CALL_EXPR_TAILCALL (orig_exp)
3763 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
36d63243 3764 expected_align, expected_size,
9db0f34d 3765 min_size, max_size,
3766 probable_max_size);
53800dbe 3767
c2f47e15 3768 if (dest_addr == 0)
3769 {
3770 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3771 dest_addr = convert_memory_address (ptr_mode, dest_addr);
3772 }
53800dbe 3773
c2f47e15 3774 return dest_addr;
6b961939 3775
c2f47e15 3776 do_libcall:
3777 fndecl = get_callee_fndecl (orig_exp);
3778 fcode = DECL_FUNCTION_CODE (fndecl);
3779 if (fcode == BUILT_IN_MEMSET)
0568e9c1 3780 fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 3,
3781 dest, val, len);
c2f47e15 3782 else if (fcode == BUILT_IN_BZERO)
0568e9c1 3783 fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 2,
3784 dest, len);
c2f47e15 3785 else
3786 gcc_unreachable ();
a65c4d64 3787 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
3788 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
c2f47e15 3789 return expand_call (fn, target, target == const0_rtx);
53800dbe 3790}
3791
48e1416a 3792/* Expand expression EXP, which is a call to the bzero builtin. Return
c2f47e15 3793 NULL_RTX if we failed the caller should emit a normal call. */
27d0c333 3794
ffc83088 3795static rtx
0b25db21 3796expand_builtin_bzero (tree exp)
ffc83088 3797{
c2f47e15 3798 tree dest, size;
389dd41b 3799 location_t loc = EXPR_LOCATION (exp);
ffc83088 3800
c2f47e15 3801 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
7369e7ba 3802 return NULL_RTX;
ffc83088 3803
c2f47e15 3804 dest = CALL_EXPR_ARG (exp, 0);
3805 size = CALL_EXPR_ARG (exp, 1);
bf8e3599 3806
7369e7ba 3807 /* New argument list transforming bzero(ptr x, int y) to
6f428e8b 3808 memset(ptr x, int 0, size_t y). This is done this way
3809 so that if it isn't expanded inline, we fallback to
3810 calling bzero instead of memset. */
bf8e3599 3811
c2f47e15 3812 return expand_builtin_memset_args (dest, integer_zero_node,
a0553bff 3813 fold_convert_loc (loc,
3814 size_type_node, size),
c2f47e15 3815 const0_rtx, VOIDmode, exp);
ffc83088 3816}
3817
7a3f89b5 3818/* Expand expression EXP, which is a call to the memcmp built-in function.
bd021c1c 3819 Return NULL_RTX if we failed and the caller should emit a normal call,
3820 otherwise try to get the result in TARGET, if convenient (and in mode
3821 MODE, if that's convenient). */
27d0c333 3822
53800dbe 3823static rtx
a65c4d64 3824expand_builtin_memcmp (tree exp, ATTRIBUTE_UNUSED rtx target,
3825 ATTRIBUTE_UNUSED enum machine_mode mode)
53800dbe 3826{
a65c4d64 3827 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
389dd41b 3828
c2f47e15 3829 if (!validate_arglist (exp,
3830 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3831 return NULL_RTX;
6f428e8b 3832
bd021c1c 3833 /* Note: The cmpstrnsi pattern, if it exists, is not suitable for
3834 implementing memcmp because it will stop if it encounters two
3835 zero bytes. */
3836#if defined HAVE_cmpmemsi
53800dbe 3837 {
0cd832f0 3838 rtx arg1_rtx, arg2_rtx, arg3_rtx;
53800dbe 3839 rtx result;
0cd832f0 3840 rtx insn;
c2f47e15 3841 tree arg1 = CALL_EXPR_ARG (exp, 0);
3842 tree arg2 = CALL_EXPR_ARG (exp, 1);
3843 tree len = CALL_EXPR_ARG (exp, 2);
53800dbe 3844
957d0361 3845 unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
3846 unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
b428c0a5 3847 enum machine_mode insn_mode;
3848
b428c0a5 3849 if (HAVE_cmpmemsi)
3850 insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
3851 else
c2f47e15 3852 return NULL_RTX;
53800dbe 3853
3854 /* If we don't have POINTER_TYPE, call the function. */
3855 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 3856 return NULL_RTX;
53800dbe 3857
3858 /* Make a place to write the result of the instruction. */
3859 result = target;
3860 if (! (result != 0
8ad4c111 3861 && REG_P (result) && GET_MODE (result) == insn_mode
53800dbe 3862 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3863 result = gen_reg_rtx (insn_mode);
3864
d8ae1baa 3865 arg1_rtx = get_memory_rtx (arg1, len);
3866 arg2_rtx = get_memory_rtx (arg2, len);
389dd41b 3867 arg3_rtx = expand_normal (fold_convert_loc (loc, sizetype, len));
83f88f8e 3868
3869 /* Set MEM_SIZE as appropriate. */
971ba038 3870 if (CONST_INT_P (arg3_rtx))
83f88f8e 3871 {
5b2a69fa 3872 set_mem_size (arg1_rtx, INTVAL (arg3_rtx));
3873 set_mem_size (arg2_rtx, INTVAL (arg3_rtx));
83f88f8e 3874 }
3875
b428c0a5 3876 if (HAVE_cmpmemsi)
3877 insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3878 GEN_INT (MIN (arg1_align, arg2_align)));
0cd832f0 3879 else
64db345d 3880 gcc_unreachable ();
0cd832f0 3881
3882 if (insn)
3883 emit_insn (insn);
3884 else
2dd6f9ed 3885 emit_library_call_value (memcmp_libfunc, result, LCT_PURE,
0cd832f0 3886 TYPE_MODE (integer_type_node), 3,
3887 XEXP (arg1_rtx, 0), Pmode,
3888 XEXP (arg2_rtx, 0), Pmode,
3889 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
78a8ed03 3890 TYPE_UNSIGNED (sizetype)),
0cd832f0 3891 TYPE_MODE (sizetype));
53800dbe 3892
3893 /* Return the value in the proper mode for this function. */
3894 mode = TYPE_MODE (TREE_TYPE (exp));
3895 if (GET_MODE (result) == mode)
3896 return result;
3897 else if (target != 0)
3898 {
3899 convert_move (target, result, 0);
3900 return target;
3901 }
3902 else
3903 return convert_to_mode (mode, result, 0);
3904 }
bd021c1c 3905#endif /* HAVE_cmpmemsi. */
53800dbe 3906
c2f47e15 3907 return NULL_RTX;
6f428e8b 3908}
3909
c2f47e15 3910/* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX
53800dbe 3911 if we failed the caller should emit a normal call, otherwise try to get
3912 the result in TARGET, if convenient. */
902de8ed 3913
53800dbe 3914static rtx
a65c4d64 3915expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
53800dbe 3916{
c2f47e15 3917 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3918 return NULL_RTX;
bf8e3599 3919
6ac5504b 3920#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
6b531606 3921 if (direct_optab_handler (cmpstr_optab, SImode) != CODE_FOR_nothing
3922 || direct_optab_handler (cmpstrn_optab, SImode) != CODE_FOR_nothing)
6ac5504b 3923 {
3924 rtx arg1_rtx, arg2_rtx;
3925 rtx result, insn = NULL_RTX;
3926 tree fndecl, fn;
c2f47e15 3927 tree arg1 = CALL_EXPR_ARG (exp, 0);
3928 tree arg2 = CALL_EXPR_ARG (exp, 1);
a0c938f0 3929
957d0361 3930 unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
3931 unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
6ac5504b 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;
7a3f89b5 3936
6ac5504b 3937 /* Stabilize the arguments in case gen_cmpstr(n)si fail. */
3938 arg1 = builtin_save_expr (arg1);
3939 arg2 = builtin_save_expr (arg2);
7a3f89b5 3940
d8ae1baa 3941 arg1_rtx = get_memory_rtx (arg1, NULL);
3942 arg2_rtx = get_memory_rtx (arg2, NULL);
53800dbe 3943
6ac5504b 3944#ifdef HAVE_cmpstrsi
3945 /* Try to call cmpstrsi. */
3946 if (HAVE_cmpstrsi)
3947 {
a0c938f0 3948 enum machine_mode insn_mode
6ac5504b 3949 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3950
3951 /* Make a place to write the result of the instruction. */
3952 result = target;
3953 if (! (result != 0
3954 && REG_P (result) && GET_MODE (result) == insn_mode
3955 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3956 result = gen_reg_rtx (insn_mode);
3957
3958 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
3959 GEN_INT (MIN (arg1_align, arg2_align)));
3960 }
3961#endif
03fd9d2c 3962#ifdef HAVE_cmpstrnsi
6ac5504b 3963 /* Try to determine at least one length and call cmpstrnsi. */
a0c938f0 3964 if (!insn && HAVE_cmpstrnsi)
6ac5504b 3965 {
3966 tree len;
3967 rtx arg3_rtx;
3968
a0c938f0 3969 enum machine_mode insn_mode
6ac5504b 3970 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
3971 tree len1 = c_strlen (arg1, 1);
3972 tree len2 = c_strlen (arg2, 1);
3973
3974 if (len1)
3975 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3976 if (len2)
3977 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3978
3979 /* If we don't have a constant length for the first, use the length
3980 of the second, if we know it. We don't require a constant for
3981 this case; some cost analysis could be done if both are available
3982 but neither is constant. For now, assume they're equally cheap,
3983 unless one has side effects. If both strings have constant lengths,
3984 use the smaller. */
3985
3986 if (!len1)
3987 len = len2;
3988 else if (!len2)
3989 len = len1;
3990 else if (TREE_SIDE_EFFECTS (len1))
3991 len = len2;
3992 else if (TREE_SIDE_EFFECTS (len2))
3993 len = len1;
3994 else if (TREE_CODE (len1) != INTEGER_CST)
3995 len = len2;
3996 else if (TREE_CODE (len2) != INTEGER_CST)
3997 len = len1;
3998 else if (tree_int_cst_lt (len1, len2))
3999 len = len1;
4000 else
4001 len = len2;
4002
4003 /* If both arguments have side effects, we cannot optimize. */
4004 if (!len || TREE_SIDE_EFFECTS (len))
6b961939 4005 goto do_libcall;
53800dbe 4006
8ec3c5c2 4007 arg3_rtx = expand_normal (len);
902de8ed 4008
6ac5504b 4009 /* Make a place to write the result of the instruction. */
4010 result = target;
4011 if (! (result != 0
4012 && REG_P (result) && GET_MODE (result) == insn_mode
4013 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4014 result = gen_reg_rtx (insn_mode);
53800dbe 4015
6ac5504b 4016 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4017 GEN_INT (MIN (arg1_align, arg2_align)));
4018 }
4019#endif
3f8aefe2 4020
6ac5504b 4021 if (insn)
4022 {
a65c4d64 4023 enum machine_mode mode;
6ac5504b 4024 emit_insn (insn);
3f8aefe2 4025
6ac5504b 4026 /* Return the value in the proper mode for this function. */
4027 mode = TYPE_MODE (TREE_TYPE (exp));
4028 if (GET_MODE (result) == mode)
4029 return result;
4030 if (target == 0)
4031 return convert_to_mode (mode, result, 0);
4032 convert_move (target, result, 0);
4033 return target;
4034 }
902de8ed 4035
6ac5504b 4036 /* Expand the library call ourselves using a stabilized argument
4037 list to avoid re-evaluating the function's arguments twice. */
2694880e 4038#ifdef HAVE_cmpstrnsi
6b961939 4039 do_libcall:
2694880e 4040#endif
6ac5504b 4041 fndecl = get_callee_fndecl (exp);
0568e9c1 4042 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2);
a65c4d64 4043 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
4044 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
6ac5504b 4045 return expand_call (fn, target, target == const0_rtx);
4046 }
7a3f89b5 4047#endif
c2f47e15 4048 return NULL_RTX;
83d79705 4049}
53800dbe 4050
48e1416a 4051/* Expand expression EXP, which is a call to the strncmp builtin. Return
c2f47e15 4052 NULL_RTX if we failed the caller should emit a normal call, otherwise try to get
ed09096d 4053 the result in TARGET, if convenient. */
27d0c333 4054
ed09096d 4055static rtx
a65c4d64 4056expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
4057 ATTRIBUTE_UNUSED enum machine_mode mode)
ed09096d 4058{
a65c4d64 4059 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
389dd41b 4060
c2f47e15 4061 if (!validate_arglist (exp,
4062 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4063 return NULL_RTX;
ed09096d 4064
6e34e617 4065 /* If c_strlen can determine an expression for one of the string
6ac5504b 4066 lengths, and it doesn't have side effects, then emit cmpstrnsi
7a3f89b5 4067 using length MIN(strlen(string)+1, arg3). */
6ac5504b 4068#ifdef HAVE_cmpstrnsi
4069 if (HAVE_cmpstrnsi)
7a3f89b5 4070 {
4071 tree len, len1, len2;
4072 rtx arg1_rtx, arg2_rtx, arg3_rtx;
4073 rtx result, insn;
0b25db21 4074 tree fndecl, fn;
c2f47e15 4075 tree arg1 = CALL_EXPR_ARG (exp, 0);
4076 tree arg2 = CALL_EXPR_ARG (exp, 1);
4077 tree arg3 = CALL_EXPR_ARG (exp, 2);
6f428e8b 4078
957d0361 4079 unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
4080 unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
7a3f89b5 4081 enum machine_mode insn_mode
6ac5504b 4082 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
bf8e3599 4083
681fab1e 4084 len1 = c_strlen (arg1, 1);
4085 len2 = c_strlen (arg2, 1);
7a3f89b5 4086
4087 if (len1)
389dd41b 4088 len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1);
7a3f89b5 4089 if (len2)
389dd41b 4090 len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2);
7a3f89b5 4091
4092 /* If we don't have a constant length for the first, use the length
4093 of the second, if we know it. We don't require a constant for
4094 this case; some cost analysis could be done if both are available
4095 but neither is constant. For now, assume they're equally cheap,
4096 unless one has side effects. If both strings have constant lengths,
4097 use the smaller. */
4098
4099 if (!len1)
4100 len = len2;
4101 else if (!len2)
4102 len = len1;
4103 else if (TREE_SIDE_EFFECTS (len1))
4104 len = len2;
4105 else if (TREE_SIDE_EFFECTS (len2))
4106 len = len1;
4107 else if (TREE_CODE (len1) != INTEGER_CST)
4108 len = len2;
4109 else if (TREE_CODE (len2) != INTEGER_CST)
4110 len = len1;
4111 else if (tree_int_cst_lt (len1, len2))
4112 len = len1;
4113 else
4114 len = len2;
6e34e617 4115
7a3f89b5 4116 /* If both arguments have side effects, we cannot optimize. */
4117 if (!len || TREE_SIDE_EFFECTS (len))
c2f47e15 4118 return NULL_RTX;
bf8e3599 4119
7a3f89b5 4120 /* The actual new length parameter is MIN(len,arg3). */
389dd41b 4121 len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len,
4122 fold_convert_loc (loc, TREE_TYPE (len), arg3));
7a3f89b5 4123
4124 /* If we don't have POINTER_TYPE, call the function. */
4125 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4126 return NULL_RTX;
7a3f89b5 4127
4128 /* Make a place to write the result of the instruction. */
4129 result = target;
4130 if (! (result != 0
8ad4c111 4131 && REG_P (result) && GET_MODE (result) == insn_mode
7a3f89b5 4132 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4133 result = gen_reg_rtx (insn_mode);
4134
a65c4d64 4135 /* Stabilize the arguments in case gen_cmpstrnsi fails. */
4136 arg1 = builtin_save_expr (arg1);
4137 arg2 = builtin_save_expr (arg2);
4138 len = builtin_save_expr (len);
27d0c333 4139
a65c4d64 4140 arg1_rtx = get_memory_rtx (arg1, len);
4141 arg2_rtx = get_memory_rtx (arg2, len);
4142 arg3_rtx = expand_normal (len);
4143 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4144 GEN_INT (MIN (arg1_align, arg2_align)));
4145 if (insn)
4146 {
4147 emit_insn (insn);
49f0327b 4148
a65c4d64 4149 /* Return the value in the proper mode for this function. */
4150 mode = TYPE_MODE (TREE_TYPE (exp));
4151 if (GET_MODE (result) == mode)
4152 return result;
4153 if (target == 0)
4154 return convert_to_mode (mode, result, 0);
4155 convert_move (target, result, 0);
4156 return target;
4157 }
27d0c333 4158
a65c4d64 4159 /* Expand the library call ourselves using a stabilized argument
4160 list to avoid re-evaluating the function's arguments twice. */
4161 fndecl = get_callee_fndecl (exp);
0568e9c1 4162 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 3,
4163 arg1, arg2, len);
a65c4d64 4164 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
4165 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4166 return expand_call (fn, target, target == const0_rtx);
4167 }
4168#endif
c2f47e15 4169 return NULL_RTX;
49f0327b 4170}
4171
a66c9326 4172/* Expand a call to __builtin_saveregs, generating the result in TARGET,
4173 if that's convenient. */
902de8ed 4174
a66c9326 4175rtx
aecda0d6 4176expand_builtin_saveregs (void)
53800dbe 4177{
a66c9326 4178 rtx val, seq;
53800dbe 4179
4180 /* Don't do __builtin_saveregs more than once in a function.
4181 Save the result of the first call and reuse it. */
4182 if (saveregs_value != 0)
4183 return saveregs_value;
53800dbe 4184
a66c9326 4185 /* When this function is called, it means that registers must be
4186 saved on entry to this function. So we migrate the call to the
4187 first insn of this function. */
4188
4189 start_sequence ();
53800dbe 4190
a66c9326 4191 /* Do whatever the machine needs done in this case. */
45550790 4192 val = targetm.calls.expand_builtin_saveregs ();
53800dbe 4193
a66c9326 4194 seq = get_insns ();
4195 end_sequence ();
53800dbe 4196
a66c9326 4197 saveregs_value = val;
53800dbe 4198
31d3e01c 4199 /* Put the insns after the NOTE that starts the function. If this
4200 is inside a start_sequence, make the outer-level insn chain current, so
a66c9326 4201 the code is placed at the start of the function. */
4202 push_topmost_sequence ();
0ec80471 4203 emit_insn_after (seq, entry_of_function ());
a66c9326 4204 pop_topmost_sequence ();
4205
4206 return val;
53800dbe 4207}
4208
79012a9d 4209/* Expand a call to __builtin_next_arg. */
27d0c333 4210
53800dbe 4211static rtx
79012a9d 4212expand_builtin_next_arg (void)
53800dbe 4213{
79012a9d 4214 /* Checking arguments is already done in fold_builtin_next_arg
4215 that must be called before this function. */
940ddc5c 4216 return expand_binop (ptr_mode, add_optab,
abe32cce 4217 crtl->args.internal_arg_pointer,
4218 crtl->args.arg_offset_rtx,
53800dbe 4219 NULL_RTX, 0, OPTAB_LIB_WIDEN);
4220}
4221
a66c9326 4222/* Make it easier for the backends by protecting the valist argument
4223 from multiple evaluations. */
4224
4225static tree
389dd41b 4226stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
a66c9326 4227{
5f57a8b1 4228 tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
4229
182cf5a9 4230 /* The current way of determining the type of valist is completely
4231 bogus. We should have the information on the va builtin instead. */
4232 if (!vatype)
4233 vatype = targetm.fn_abi_va_list (cfun->decl);
5f57a8b1 4234
4235 if (TREE_CODE (vatype) == ARRAY_TYPE)
a66c9326 4236 {
2d47cc32 4237 if (TREE_SIDE_EFFECTS (valist))
4238 valist = save_expr (valist);
11a61dea 4239
2d47cc32 4240 /* For this case, the backends will be expecting a pointer to
5f57a8b1 4241 vatype, but it's possible we've actually been given an array
4242 (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)).
2d47cc32 4243 So fix it. */
4244 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
8a15c04a 4245 {
5f57a8b1 4246 tree p1 = build_pointer_type (TREE_TYPE (vatype));
389dd41b 4247 valist = build_fold_addr_expr_with_type_loc (loc, valist, p1);
8a15c04a 4248 }
a66c9326 4249 }
11a61dea 4250 else
a66c9326 4251 {
182cf5a9 4252 tree pt = build_pointer_type (vatype);
11a61dea 4253
2d47cc32 4254 if (! needs_lvalue)
4255 {
11a61dea 4256 if (! TREE_SIDE_EFFECTS (valist))
4257 return valist;
bf8e3599 4258
389dd41b 4259 valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist);
a66c9326 4260 TREE_SIDE_EFFECTS (valist) = 1;
a66c9326 4261 }
2d47cc32 4262
11a61dea 4263 if (TREE_SIDE_EFFECTS (valist))
2d47cc32 4264 valist = save_expr (valist);
182cf5a9 4265 valist = fold_build2_loc (loc, MEM_REF,
4266 vatype, valist, build_int_cst (pt, 0));
a66c9326 4267 }
4268
4269 return valist;
4270}
4271
2e15d750 4272/* The "standard" definition of va_list is void*. */
4273
4274tree
4275std_build_builtin_va_list (void)
4276{
4277 return ptr_type_node;
4278}
4279
5f57a8b1 4280/* The "standard" abi va_list is va_list_type_node. */
4281
4282tree
4283std_fn_abi_va_list (tree fndecl ATTRIBUTE_UNUSED)
4284{
4285 return va_list_type_node;
4286}
4287
4288/* The "standard" type of va_list is va_list_type_node. */
4289
4290tree
4291std_canonical_va_list_type (tree type)
4292{
4293 tree wtype, htype;
4294
4295 if (INDIRECT_REF_P (type))
4296 type = TREE_TYPE (type);
9af5ce0c 4297 else if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE (type)))
5f57a8b1 4298 type = TREE_TYPE (type);
5f57a8b1 4299 wtype = va_list_type_node;
4300 htype = type;
7b36f9ab 4301 /* Treat structure va_list types. */
4302 if (TREE_CODE (wtype) == RECORD_TYPE && POINTER_TYPE_P (htype))
4303 htype = TREE_TYPE (htype);
4304 else if (TREE_CODE (wtype) == ARRAY_TYPE)
5f57a8b1 4305 {
4306 /* If va_list is an array type, the argument may have decayed
4307 to a pointer type, e.g. by being passed to another function.
4308 In that case, unwrap both types so that we can compare the
4309 underlying records. */
4310 if (TREE_CODE (htype) == ARRAY_TYPE
4311 || POINTER_TYPE_P (htype))
4312 {
4313 wtype = TREE_TYPE (wtype);
4314 htype = TREE_TYPE (htype);
4315 }
4316 }
4317 if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype))
4318 return va_list_type_node;
4319
4320 return NULL_TREE;
4321}
4322
a66c9326 4323/* The "standard" implementation of va_start: just assign `nextarg' to
4324 the variable. */
27d0c333 4325
a66c9326 4326void
aecda0d6 4327std_expand_builtin_va_start (tree valist, rtx nextarg)
a66c9326 4328{
f03c17bc 4329 rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
4330 convert_move (va_r, nextarg, 0);
a66c9326 4331}
4332
c2f47e15 4333/* Expand EXP, a call to __builtin_va_start. */
27d0c333 4334
a66c9326 4335static rtx
c2f47e15 4336expand_builtin_va_start (tree exp)
a66c9326 4337{
4338 rtx nextarg;
c2f47e15 4339 tree valist;
389dd41b 4340 location_t loc = EXPR_LOCATION (exp);
a66c9326 4341
c2f47e15 4342 if (call_expr_nargs (exp) < 2)
cb166087 4343 {
389dd41b 4344 error_at (loc, "too few arguments to function %<va_start%>");
cb166087 4345 return const0_rtx;
4346 }
a66c9326 4347
c2f47e15 4348 if (fold_builtin_next_arg (exp, true))
79012a9d 4349 return const0_rtx;
7c2f0500 4350
79012a9d 4351 nextarg = expand_builtin_next_arg ();
389dd41b 4352 valist = stabilize_va_list_loc (loc, CALL_EXPR_ARG (exp, 0), 1);
a66c9326 4353
8a58ed0a 4354 if (targetm.expand_builtin_va_start)
4355 targetm.expand_builtin_va_start (valist, nextarg);
4356 else
4357 std_expand_builtin_va_start (valist, nextarg);
a66c9326 4358
4359 return const0_rtx;
4360}
4361
c2f47e15 4362/* Expand EXP, a call to __builtin_va_end. */
f7c44134 4363
a66c9326 4364static rtx
c2f47e15 4365expand_builtin_va_end (tree exp)
a66c9326 4366{
c2f47e15 4367 tree valist = CALL_EXPR_ARG (exp, 0);
8a15c04a 4368
8a15c04a 4369 /* Evaluate for side effects, if needed. I hate macros that don't
4370 do that. */
4371 if (TREE_SIDE_EFFECTS (valist))
4372 expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
a66c9326 4373
4374 return const0_rtx;
4375}
4376
c2f47e15 4377/* Expand EXP, a call to __builtin_va_copy. We do this as a
a66c9326 4378 builtin rather than just as an assignment in stdarg.h because of the
4379 nastiness of array-type va_list types. */
f7c44134 4380
a66c9326 4381static rtx
c2f47e15 4382expand_builtin_va_copy (tree exp)
a66c9326 4383{
4384 tree dst, src, t;
389dd41b 4385 location_t loc = EXPR_LOCATION (exp);
a66c9326 4386
c2f47e15 4387 dst = CALL_EXPR_ARG (exp, 0);
4388 src = CALL_EXPR_ARG (exp, 1);
a66c9326 4389
389dd41b 4390 dst = stabilize_va_list_loc (loc, dst, 1);
4391 src = stabilize_va_list_loc (loc, src, 0);
a66c9326 4392
5f57a8b1 4393 gcc_assert (cfun != NULL && cfun->decl != NULL_TREE);
4394
4395 if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE)
a66c9326 4396 {
5f57a8b1 4397 t = build2 (MODIFY_EXPR, targetm.fn_abi_va_list (cfun->decl), dst, src);
a66c9326 4398 TREE_SIDE_EFFECTS (t) = 1;
4399 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4400 }
4401 else
4402 {
11a61dea 4403 rtx dstb, srcb, size;
4404
4405 /* Evaluate to pointers. */
4406 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
4407 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
5f57a8b1 4408 size = expand_expr (TYPE_SIZE_UNIT (targetm.fn_abi_va_list (cfun->decl)),
4409 NULL_RTX, VOIDmode, EXPAND_NORMAL);
11a61dea 4410
85d654dd 4411 dstb = convert_memory_address (Pmode, dstb);
4412 srcb = convert_memory_address (Pmode, srcb);
726ec87c 4413
11a61dea 4414 /* "Dereference" to BLKmode memories. */
4415 dstb = gen_rtx_MEM (BLKmode, dstb);
ab6ab77e 4416 set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
5f57a8b1 4417 set_mem_align (dstb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 4418 srcb = gen_rtx_MEM (BLKmode, srcb);
ab6ab77e 4419 set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
5f57a8b1 4420 set_mem_align (srcb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 4421
4422 /* Copy. */
0378dbdc 4423 emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
a66c9326 4424 }
4425
4426 return const0_rtx;
4427}
4428
53800dbe 4429/* Expand a call to one of the builtin functions __builtin_frame_address or
4430 __builtin_return_address. */
27d0c333 4431
53800dbe 4432static rtx
c2f47e15 4433expand_builtin_frame_address (tree fndecl, tree exp)
53800dbe 4434{
53800dbe 4435 /* The argument must be a nonnegative integer constant.
4436 It counts the number of frames to scan up the stack.
4437 The value is the return address saved in that frame. */
c2f47e15 4438 if (call_expr_nargs (exp) == 0)
53800dbe 4439 /* Warning about missing arg was already issued. */
4440 return const0_rtx;
e913b5cd 4441 else if (! tree_fits_uhwi_p (CALL_EXPR_ARG (exp, 0)))
53800dbe 4442 {
4443 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
07e3a3d2 4444 error ("invalid argument to %<__builtin_frame_address%>");
53800dbe 4445 else
07e3a3d2 4446 error ("invalid argument to %<__builtin_return_address%>");
53800dbe 4447 return const0_rtx;
4448 }
4449 else
4450 {
27d0c333 4451 rtx tem
4452 = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
e913b5cd 4453 tree_to_uhwi (CALL_EXPR_ARG (exp, 0)));
53800dbe 4454
4455 /* Some ports cannot access arbitrary stack frames. */
4456 if (tem == NULL)
4457 {
4458 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
c3ceba8e 4459 warning (0, "unsupported argument to %<__builtin_frame_address%>");
53800dbe 4460 else
c3ceba8e 4461 warning (0, "unsupported argument to %<__builtin_return_address%>");
53800dbe 4462 return const0_rtx;
4463 }
4464
4465 /* For __builtin_frame_address, return what we've got. */
4466 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4467 return tem;
4468
8ad4c111 4469 if (!REG_P (tem)
53800dbe 4470 && ! CONSTANT_P (tem))
99182918 4471 tem = copy_addr_to_reg (tem);
53800dbe 4472 return tem;
4473 }
4474}
4475
990495a7 4476/* Expand EXP, a call to the alloca builtin. Return NULL_RTX if we
5be42b39 4477 failed and the caller should emit a normal call. CANNOT_ACCUMULATE
4478 is the same as for allocate_dynamic_stack_space. */
15c6cf6b 4479
53800dbe 4480static rtx
5be42b39 4481expand_builtin_alloca (tree exp, bool cannot_accumulate)
53800dbe 4482{
4483 rtx op0;
15c6cf6b 4484 rtx result;
581bf1c2 4485 bool valid_arglist;
4486 unsigned int align;
4487 bool alloca_with_align = (DECL_FUNCTION_CODE (get_callee_fndecl (exp))
4488 == BUILT_IN_ALLOCA_WITH_ALIGN);
53800dbe 4489
581bf1c2 4490 valid_arglist
4491 = (alloca_with_align
4492 ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
4493 : validate_arglist (exp, INTEGER_TYPE, VOID_TYPE));
4494
4495 if (!valid_arglist)
c2f47e15 4496 return NULL_RTX;
53800dbe 4497
4498 /* Compute the argument. */
c2f47e15 4499 op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
53800dbe 4500
581bf1c2 4501 /* Compute the alignment. */
4502 align = (alloca_with_align
f9ae6f95 4503 ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1))
581bf1c2 4504 : BIGGEST_ALIGNMENT);
4505
53800dbe 4506 /* Allocate the desired space. */
581bf1c2 4507 result = allocate_dynamic_stack_space (op0, 0, align, cannot_accumulate);
85d654dd 4508 result = convert_memory_address (ptr_mode, result);
15c6cf6b 4509
4510 return result;
53800dbe 4511}
4512
74bdbe96 4513/* Expand a call to bswap builtin in EXP.
4514 Return NULL_RTX if a normal call should be emitted rather than expanding the
4515 function in-line. If convenient, the result should be placed in TARGET.
4516 SUBTARGET may be used as the target for computing one of EXP's operands. */
42791117 4517
4518static rtx
74bdbe96 4519expand_builtin_bswap (enum machine_mode target_mode, tree exp, rtx target,
4520 rtx subtarget)
42791117 4521{
42791117 4522 tree arg;
4523 rtx op0;
4524
c2f47e15 4525 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4526 return NULL_RTX;
42791117 4527
c2f47e15 4528 arg = CALL_EXPR_ARG (exp, 0);
74bdbe96 4529 op0 = expand_expr (arg,
4530 subtarget && GET_MODE (subtarget) == target_mode
4531 ? subtarget : NULL_RTX,
4532 target_mode, EXPAND_NORMAL);
4533 if (GET_MODE (op0) != target_mode)
4534 op0 = convert_to_mode (target_mode, op0, 1);
42791117 4535
74bdbe96 4536 target = expand_unop (target_mode, bswap_optab, op0, target, 1);
42791117 4537
4538 gcc_assert (target);
4539
74bdbe96 4540 return convert_to_mode (target_mode, target, 1);
42791117 4541}
4542
c2f47e15 4543/* Expand a call to a unary builtin in EXP.
4544 Return NULL_RTX if a normal call should be emitted rather than expanding the
53800dbe 4545 function in-line. If convenient, the result should be placed in TARGET.
4546 SUBTARGET may be used as the target for computing one of EXP's operands. */
15c6cf6b 4547
53800dbe 4548static rtx
c2f47e15 4549expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target,
aecda0d6 4550 rtx subtarget, optab op_optab)
53800dbe 4551{
4552 rtx op0;
c2f47e15 4553
4554 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4555 return NULL_RTX;
53800dbe 4556
4557 /* Compute the argument. */
f97eea22 4558 op0 = expand_expr (CALL_EXPR_ARG (exp, 0),
4559 (subtarget
4560 && (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0)))
4561 == GET_MODE (subtarget))) ? subtarget : NULL_RTX,
1db6d067 4562 VOIDmode, EXPAND_NORMAL);
6a08d0ab 4563 /* Compute op, into TARGET if possible.
53800dbe 4564 Set TARGET to wherever the result comes back. */
c2f47e15 4565 target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
6aaa1f9e 4566 op_optab, op0, target, op_optab != clrsb_optab);
64db345d 4567 gcc_assert (target);
7d3f6cc7 4568
efb070c8 4569 return convert_to_mode (target_mode, target, 0);
53800dbe 4570}
89cfe6e5 4571
48e1416a 4572/* Expand a call to __builtin_expect. We just return our argument
5a74f77e 4573 as the builtin_expect semantic should've been already executed by
4574 tree branch prediction pass. */
89cfe6e5 4575
4576static rtx
c2f47e15 4577expand_builtin_expect (tree exp, rtx target)
89cfe6e5 4578{
1e4adcfc 4579 tree arg;
89cfe6e5 4580
c2f47e15 4581 if (call_expr_nargs (exp) < 2)
89cfe6e5 4582 return const0_rtx;
c2f47e15 4583 arg = CALL_EXPR_ARG (exp, 0);
89cfe6e5 4584
c2f47e15 4585 target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5a74f77e 4586 /* When guessing was done, the hints should be already stripped away. */
07311427 4587 gcc_assert (!flag_guess_branch_prob
852f689e 4588 || optimize == 0 || seen_error ());
89cfe6e5 4589 return target;
4590}
689df48e 4591
fca0886c 4592/* Expand a call to __builtin_assume_aligned. We just return our first
4593 argument as the builtin_assume_aligned semantic should've been already
4594 executed by CCP. */
4595
4596static rtx
4597expand_builtin_assume_aligned (tree exp, rtx target)
4598{
4599 if (call_expr_nargs (exp) < 2)
4600 return const0_rtx;
4601 target = expand_expr (CALL_EXPR_ARG (exp, 0), target, VOIDmode,
4602 EXPAND_NORMAL);
4603 gcc_assert (!TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 1))
4604 && (call_expr_nargs (exp) < 3
4605 || !TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 2))));
4606 return target;
4607}
4608
c22de3f0 4609void
aecda0d6 4610expand_builtin_trap (void)
a0ef1725 4611{
4612#ifdef HAVE_trap
4613 if (HAVE_trap)
f73960eb 4614 {
4615 rtx insn = emit_insn (gen_trap ());
4616 /* For trap insns when not accumulating outgoing args force
4617 REG_ARGS_SIZE note to prevent crossjumping of calls with
4618 different args sizes. */
4619 if (!ACCUMULATE_OUTGOING_ARGS)
4620 add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (stack_pointer_delta));
4621 }
a0ef1725 4622 else
4623#endif
4624 emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
4625 emit_barrier ();
4626}
78a74442 4627
d2b48f0c 4628/* Expand a call to __builtin_unreachable. We do nothing except emit
4629 a barrier saying that control flow will not pass here.
4630
4631 It is the responsibility of the program being compiled to ensure
4632 that control flow does never reach __builtin_unreachable. */
4633static void
4634expand_builtin_unreachable (void)
4635{
4636 emit_barrier ();
4637}
4638
c2f47e15 4639/* Expand EXP, a call to fabs, fabsf or fabsl.
4640 Return NULL_RTX if a normal call should be emitted rather than expanding
78a74442 4641 the function inline. If convenient, the result should be placed
4642 in TARGET. SUBTARGET may be used as the target for computing
4643 the operand. */
4644
4645static rtx
c2f47e15 4646expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
78a74442 4647{
4648 enum machine_mode mode;
4649 tree arg;
4650 rtx op0;
4651
c2f47e15 4652 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
4653 return NULL_RTX;
78a74442 4654
c2f47e15 4655 arg = CALL_EXPR_ARG (exp, 0);
c7f617c2 4656 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
78a74442 4657 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 4658 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
78a74442 4659 return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
4660}
4661
c2f47e15 4662/* Expand EXP, a call to copysign, copysignf, or copysignl.
270436f3 4663 Return NULL is a normal call should be emitted rather than expanding the
4664 function inline. If convenient, the result should be placed in TARGET.
4665 SUBTARGET may be used as the target for computing the operand. */
4666
4667static rtx
c2f47e15 4668expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
270436f3 4669{
4670 rtx op0, op1;
4671 tree arg;
4672
c2f47e15 4673 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
4674 return NULL_RTX;
270436f3 4675
c2f47e15 4676 arg = CALL_EXPR_ARG (exp, 0);
8ec3c5c2 4677 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
270436f3 4678
c2f47e15 4679 arg = CALL_EXPR_ARG (exp, 1);
8ec3c5c2 4680 op1 = expand_normal (arg);
270436f3 4681
4682 return expand_copysign (op0, op1, target);
4683}
4684
19bf118a 4685/* Create a new constant string literal and return a char* pointer to it.
4686 The STRING_CST value is the LEN characters at STR. */
1e8e9920 4687tree
19bf118a 4688build_string_literal (int len, const char *str)
4689{
4690 tree t, elem, index, type;
4691
4692 t = build_string (len, str);
4693 elem = build_type_variant (char_type_node, 1, 0);
40238f64 4694 index = build_index_type (size_int (len - 1));
19bf118a 4695 type = build_array_type (elem, index);
4696 TREE_TYPE (t) = type;
4697 TREE_CONSTANT (t) = 1;
4698 TREE_READONLY (t) = 1;
4699 TREE_STATIC (t) = 1;
4700
19bf118a 4701 type = build_pointer_type (elem);
40238f64 4702 t = build1 (ADDR_EXPR, type,
4703 build4 (ARRAY_REF, elem,
4704 t, integer_zero_node, NULL_TREE, NULL_TREE));
19bf118a 4705 return t;
4706}
4707
ac8fb6db 4708/* Expand a call to __builtin___clear_cache. */
4709
4710static rtx
4711expand_builtin___clear_cache (tree exp ATTRIBUTE_UNUSED)
4712{
4713#ifndef HAVE_clear_cache
4714#ifdef CLEAR_INSN_CACHE
4715 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
4716 does something. Just do the default expansion to a call to
4717 __clear_cache(). */
4718 return NULL_RTX;
4719#else
4720 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
4721 does nothing. There is no need to call it. Do nothing. */
4722 return const0_rtx;
4723#endif /* CLEAR_INSN_CACHE */
4724#else
4725 /* We have a "clear_cache" insn, and it will handle everything. */
4726 tree begin, end;
4727 rtx begin_rtx, end_rtx;
ac8fb6db 4728
4729 /* We must not expand to a library call. If we did, any
4730 fallback library function in libgcc that might contain a call to
4731 __builtin___clear_cache() would recurse infinitely. */
4732 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4733 {
4734 error ("both arguments to %<__builtin___clear_cache%> must be pointers");
4735 return const0_rtx;
4736 }
4737
4738 if (HAVE_clear_cache)
4739 {
8786db1e 4740 struct expand_operand ops[2];
ac8fb6db 4741
4742 begin = CALL_EXPR_ARG (exp, 0);
4743 begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
ac8fb6db 4744
4745 end = CALL_EXPR_ARG (exp, 1);
4746 end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
ac8fb6db 4747
8786db1e 4748 create_address_operand (&ops[0], begin_rtx);
4749 create_address_operand (&ops[1], end_rtx);
4750 if (maybe_expand_insn (CODE_FOR_clear_cache, 2, ops))
4751 return const0_rtx;
ac8fb6db 4752 }
4753 return const0_rtx;
4754#endif /* HAVE_clear_cache */
4755}
4756
4ee9c684 4757/* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
4758
4759static rtx
4760round_trampoline_addr (rtx tramp)
4761{
4762 rtx temp, addend, mask;
4763
4764 /* If we don't need too much alignment, we'll have been guaranteed
4765 proper alignment by get_trampoline_type. */
4766 if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
4767 return tramp;
4768
4769 /* Round address up to desired boundary. */
4770 temp = gen_reg_rtx (Pmode);
0359f9f5 4771 addend = gen_int_mode (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1, Pmode);
4772 mask = gen_int_mode (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT, Pmode);
4ee9c684 4773
4774 temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
4775 temp, 0, OPTAB_LIB_WIDEN);
4776 tramp = expand_simple_binop (Pmode, AND, temp, mask,
4777 temp, 0, OPTAB_LIB_WIDEN);
4778
4779 return tramp;
4780}
4781
4782static rtx
c307f106 4783expand_builtin_init_trampoline (tree exp, bool onstack)
4ee9c684 4784{
4785 tree t_tramp, t_func, t_chain;
82c7907c 4786 rtx m_tramp, r_tramp, r_chain, tmp;
4ee9c684 4787
c2f47e15 4788 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
4ee9c684 4789 POINTER_TYPE, VOID_TYPE))
4790 return NULL_RTX;
4791
c2f47e15 4792 t_tramp = CALL_EXPR_ARG (exp, 0);
4793 t_func = CALL_EXPR_ARG (exp, 1);
4794 t_chain = CALL_EXPR_ARG (exp, 2);
4ee9c684 4795
8ec3c5c2 4796 r_tramp = expand_normal (t_tramp);
82c7907c 4797 m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
4798 MEM_NOTRAP_P (m_tramp) = 1;
4799
c307f106 4800 /* If ONSTACK, the TRAMP argument should be the address of a field
4801 within the local function's FRAME decl. Either way, let's see if
4802 we can fill in the MEM_ATTRs for this memory. */
82c7907c 4803 if (TREE_CODE (t_tramp) == ADDR_EXPR)
f4146cb8 4804 set_mem_attributes (m_tramp, TREE_OPERAND (t_tramp, 0), true);
82c7907c 4805
c307f106 4806 /* Creator of a heap trampoline is responsible for making sure the
4807 address is aligned to at least STACK_BOUNDARY. Normally malloc
4808 will ensure this anyhow. */
82c7907c 4809 tmp = round_trampoline_addr (r_tramp);
4810 if (tmp != r_tramp)
4811 {
4812 m_tramp = change_address (m_tramp, BLKmode, tmp);
4813 set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
5b2a69fa 4814 set_mem_size (m_tramp, TRAMPOLINE_SIZE);
82c7907c 4815 }
4816
4817 /* The FUNC argument should be the address of the nested function.
4818 Extract the actual function decl to pass to the hook. */
4819 gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
4820 t_func = TREE_OPERAND (t_func, 0);
4821 gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
4822
8ec3c5c2 4823 r_chain = expand_normal (t_chain);
4ee9c684 4824
4825 /* Generate insns to initialize the trampoline. */
82c7907c 4826 targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
4ee9c684 4827
c307f106 4828 if (onstack)
4829 {
4830 trampolines_created = 1;
8bc8a8f4 4831
c307f106 4832 warning_at (DECL_SOURCE_LOCATION (t_func), OPT_Wtrampolines,
4833 "trampoline generated for nested function %qD", t_func);
4834 }
8bc8a8f4 4835
4ee9c684 4836 return const0_rtx;
4837}
4838
4839static rtx
c2f47e15 4840expand_builtin_adjust_trampoline (tree exp)
4ee9c684 4841{
4842 rtx tramp;
4843
c2f47e15 4844 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
4ee9c684 4845 return NULL_RTX;
4846
c2f47e15 4847 tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
4ee9c684 4848 tramp = round_trampoline_addr (tramp);
82c7907c 4849 if (targetm.calls.trampoline_adjust_address)
4850 tramp = targetm.calls.trampoline_adjust_address (tramp);
4ee9c684 4851
4852 return tramp;
4853}
4854
93f564d6 4855/* Expand the call EXP to the built-in signbit, signbitf or signbitl
4856 function. The function first checks whether the back end provides
4857 an insn to implement signbit for the respective mode. If not, it
4858 checks whether the floating point format of the value is such that
4859 the sign bit can be extracted. If that is not the case, the
4860 function returns NULL_RTX to indicate that a normal call should be
4861 emitted rather than expanding the function in-line. EXP is the
4862 expression that is a call to the builtin function; if convenient,
4863 the result should be placed in TARGET. */
27f261ef 4864static rtx
4865expand_builtin_signbit (tree exp, rtx target)
4866{
4867 const struct real_format *fmt;
4868 enum machine_mode fmode, imode, rmode;
c2f47e15 4869 tree arg;
ca4f1f5b 4870 int word, bitpos;
27eda240 4871 enum insn_code icode;
27f261ef 4872 rtx temp;
389dd41b 4873 location_t loc = EXPR_LOCATION (exp);
27f261ef 4874
c2f47e15 4875 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
4876 return NULL_RTX;
27f261ef 4877
c2f47e15 4878 arg = CALL_EXPR_ARG (exp, 0);
27f261ef 4879 fmode = TYPE_MODE (TREE_TYPE (arg));
4880 rmode = TYPE_MODE (TREE_TYPE (exp));
4881 fmt = REAL_MODE_FORMAT (fmode);
4882
93f564d6 4883 arg = builtin_save_expr (arg);
4884
4885 /* Expand the argument yielding a RTX expression. */
4886 temp = expand_normal (arg);
4887
4888 /* Check if the back end provides an insn that handles signbit for the
4889 argument's mode. */
d6bf3b14 4890 icode = optab_handler (signbit_optab, fmode);
27eda240 4891 if (icode != CODE_FOR_nothing)
93f564d6 4892 {
4e2a2fb4 4893 rtx last = get_last_insn ();
93f564d6 4894 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
4e2a2fb4 4895 if (maybe_emit_unop_insn (icode, target, temp, UNKNOWN))
4896 return target;
4897 delete_insns_since (last);
93f564d6 4898 }
4899
27f261ef 4900 /* For floating point formats without a sign bit, implement signbit
4901 as "ARG < 0.0". */
8d564692 4902 bitpos = fmt->signbit_ro;
ca4f1f5b 4903 if (bitpos < 0)
27f261ef 4904 {
4905 /* But we can't do this if the format supports signed zero. */
4906 if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
c2f47e15 4907 return NULL_RTX;
27f261ef 4908
389dd41b 4909 arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
49d00087 4910 build_real (TREE_TYPE (arg), dconst0));
27f261ef 4911 return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
4912 }
4913
ca4f1f5b 4914 if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
27f261ef 4915 {
ca4f1f5b 4916 imode = int_mode_for_mode (fmode);
4917 if (imode == BLKmode)
c2f47e15 4918 return NULL_RTX;
ca4f1f5b 4919 temp = gen_lowpart (imode, temp);
24fd4260 4920 }
4921 else
4922 {
ca4f1f5b 4923 imode = word_mode;
4924 /* Handle targets with different FP word orders. */
4925 if (FLOAT_WORDS_BIG_ENDIAN)
a0c938f0 4926 word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
ca4f1f5b 4927 else
a0c938f0 4928 word = bitpos / BITS_PER_WORD;
ca4f1f5b 4929 temp = operand_subword_force (temp, word, fmode);
4930 bitpos = bitpos % BITS_PER_WORD;
4931 }
4932
44b0f1d0 4933 /* Force the intermediate word_mode (or narrower) result into a
4934 register. This avoids attempting to create paradoxical SUBREGs
4935 of floating point modes below. */
4936 temp = force_reg (imode, temp);
4937
ca4f1f5b 4938 /* If the bitpos is within the "result mode" lowpart, the operation
4939 can be implement with a single bitwise AND. Otherwise, we need
4940 a right shift and an AND. */
4941
4942 if (bitpos < GET_MODE_BITSIZE (rmode))
4943 {
796b6678 4944 wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (rmode));
27f261ef 4945
4a46f016 4946 if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
ca4f1f5b 4947 temp = gen_lowpart (rmode, temp);
24fd4260 4948 temp = expand_binop (rmode, and_optab, temp,
e913b5cd 4949 immed_wide_int_const (mask, rmode),
ca4f1f5b 4950 NULL_RTX, 1, OPTAB_LIB_WIDEN);
27f261ef 4951 }
ca4f1f5b 4952 else
4953 {
4954 /* Perform a logical right shift to place the signbit in the least
a0c938f0 4955 significant bit, then truncate the result to the desired mode
ca4f1f5b 4956 and mask just this bit. */
f5ff0b21 4957 temp = expand_shift (RSHIFT_EXPR, imode, temp, bitpos, NULL_RTX, 1);
ca4f1f5b 4958 temp = gen_lowpart (rmode, temp);
4959 temp = expand_binop (rmode, and_optab, temp, const1_rtx,
4960 NULL_RTX, 1, OPTAB_LIB_WIDEN);
4961 }
4962
27f261ef 4963 return temp;
4964}
73673831 4965
4966/* Expand fork or exec calls. TARGET is the desired target of the
c2f47e15 4967 call. EXP is the call. FN is the
73673831 4968 identificator of the actual function. IGNORE is nonzero if the
4969 value is to be ignored. */
4970
4971static rtx
c2f47e15 4972expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
73673831 4973{
4974 tree id, decl;
4975 tree call;
4976
4977 /* If we are not profiling, just call the function. */
4978 if (!profile_arc_flag)
4979 return NULL_RTX;
4980
4981 /* Otherwise call the wrapper. This should be equivalent for the rest of
4982 compiler, so the code does not diverge, and the wrapper may run the
9c9bad97 4983 code necessary for keeping the profiling sane. */
73673831 4984
4985 switch (DECL_FUNCTION_CODE (fn))
4986 {
4987 case BUILT_IN_FORK:
4988 id = get_identifier ("__gcov_fork");
4989 break;
4990
4991 case BUILT_IN_EXECL:
4992 id = get_identifier ("__gcov_execl");
4993 break;
4994
4995 case BUILT_IN_EXECV:
4996 id = get_identifier ("__gcov_execv");
4997 break;
4998
4999 case BUILT_IN_EXECLP:
5000 id = get_identifier ("__gcov_execlp");
5001 break;
5002
5003 case BUILT_IN_EXECLE:
5004 id = get_identifier ("__gcov_execle");
5005 break;
5006
5007 case BUILT_IN_EXECVP:
5008 id = get_identifier ("__gcov_execvp");
5009 break;
5010
5011 case BUILT_IN_EXECVE:
5012 id = get_identifier ("__gcov_execve");
5013 break;
5014
5015 default:
64db345d 5016 gcc_unreachable ();
73673831 5017 }
5018
e60a6f7b 5019 decl = build_decl (DECL_SOURCE_LOCATION (fn),
5020 FUNCTION_DECL, id, TREE_TYPE (fn));
73673831 5021 DECL_EXTERNAL (decl) = 1;
5022 TREE_PUBLIC (decl) = 1;
5023 DECL_ARTIFICIAL (decl) = 1;
5024 TREE_NOTHROW (decl) = 1;
e82d310b 5025 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
5026 DECL_VISIBILITY_SPECIFIED (decl) = 1;
389dd41b 5027 call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0);
73673831 5028 return expand_call (call, target, ignore);
c2f47e15 5029 }
48e1416a 5030
b6a5fc45 5031
5032\f
3e272de8 5033/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
5034 the pointer in these functions is void*, the tree optimizers may remove
5035 casts. The mode computed in expand_builtin isn't reliable either, due
5036 to __sync_bool_compare_and_swap.
5037
5038 FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
5039 group of builtins. This gives us log2 of the mode size. */
5040
5041static inline enum machine_mode
5042get_builtin_sync_mode (int fcode_diff)
5043{
ad3a13b5 5044 /* The size is not negotiable, so ask not to get BLKmode in return
5045 if the target indicates that a smaller size would be better. */
5046 return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
3e272de8 5047}
5048
041e0215 5049/* Expand the memory expression LOC and return the appropriate memory operand
5050 for the builtin_sync operations. */
5051
5052static rtx
5053get_builtin_sync_mem (tree loc, enum machine_mode mode)
5054{
5055 rtx addr, mem;
5056
7f4d56ad 5057 addr = expand_expr (loc, NULL_RTX, ptr_mode, EXPAND_SUM);
5058 addr = convert_memory_address (Pmode, addr);
041e0215 5059
5060 /* Note that we explicitly do not want any alias information for this
5061 memory, so that we kill all other live memories. Otherwise we don't
5062 satisfy the full barrier semantics of the intrinsic. */
5063 mem = validize_mem (gen_rtx_MEM (mode, addr));
5064
153c3b50 5065 /* The alignment needs to be at least according to that of the mode. */
5066 set_mem_align (mem, MAX (GET_MODE_ALIGNMENT (mode),
957d0361 5067 get_pointer_alignment (loc)));
c94cfd1c 5068 set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
041e0215 5069 MEM_VOLATILE_P (mem) = 1;
5070
5071 return mem;
5072}
5073
1cd6e20d 5074/* Make sure an argument is in the right mode.
5075 EXP is the tree argument.
5076 MODE is the mode it should be in. */
5077
5078static rtx
5079expand_expr_force_mode (tree exp, enum machine_mode mode)
5080{
5081 rtx val;
5082 enum machine_mode old_mode;
5083
5084 val = expand_expr (exp, NULL_RTX, mode, EXPAND_NORMAL);
5085 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5086 of CONST_INTs, where we know the old_mode only from the call argument. */
5087
5088 old_mode = GET_MODE (val);
5089 if (old_mode == VOIDmode)
5090 old_mode = TYPE_MODE (TREE_TYPE (exp));
5091 val = convert_modes (mode, old_mode, val, 1);
5092 return val;
5093}
5094
5095
b6a5fc45 5096/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
c2f47e15 5097 EXP is the CALL_EXPR. CODE is the rtx code
b6a5fc45 5098 that corresponds to the arithmetic or logical operation from the name;
5099 an exception here is that NOT actually means NAND. TARGET is an optional
5100 place for us to store the results; AFTER is true if this is the
1cd6e20d 5101 fetch_and_xxx form. */
b6a5fc45 5102
5103static rtx
c2f47e15 5104expand_builtin_sync_operation (enum machine_mode mode, tree exp,
3e272de8 5105 enum rtx_code code, bool after,
1cd6e20d 5106 rtx target)
b6a5fc45 5107{
041e0215 5108 rtx val, mem;
e60a6f7b 5109 location_t loc = EXPR_LOCATION (exp);
b6a5fc45 5110
cf73e559 5111 if (code == NOT && warn_sync_nand)
5112 {
5113 tree fndecl = get_callee_fndecl (exp);
5114 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
5115
5116 static bool warned_f_a_n, warned_n_a_f;
5117
5118 switch (fcode)
5119 {
2797f13a 5120 case BUILT_IN_SYNC_FETCH_AND_NAND_1:
5121 case BUILT_IN_SYNC_FETCH_AND_NAND_2:
5122 case BUILT_IN_SYNC_FETCH_AND_NAND_4:
5123 case BUILT_IN_SYNC_FETCH_AND_NAND_8:
5124 case BUILT_IN_SYNC_FETCH_AND_NAND_16:
cf73e559 5125 if (warned_f_a_n)
5126 break;
5127
b9a16870 5128 fndecl = builtin_decl_implicit (BUILT_IN_SYNC_FETCH_AND_NAND_N);
e60a6f7b 5129 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
cf73e559 5130 warned_f_a_n = true;
5131 break;
5132
2797f13a 5133 case BUILT_IN_SYNC_NAND_AND_FETCH_1:
5134 case BUILT_IN_SYNC_NAND_AND_FETCH_2:
5135 case BUILT_IN_SYNC_NAND_AND_FETCH_4:
5136 case BUILT_IN_SYNC_NAND_AND_FETCH_8:
5137 case BUILT_IN_SYNC_NAND_AND_FETCH_16:
cf73e559 5138 if (warned_n_a_f)
5139 break;
5140
b9a16870 5141 fndecl = builtin_decl_implicit (BUILT_IN_SYNC_NAND_AND_FETCH_N);
e60a6f7b 5142 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
cf73e559 5143 warned_n_a_f = true;
5144 break;
5145
5146 default:
5147 gcc_unreachable ();
5148 }
5149 }
5150
b6a5fc45 5151 /* Expand the operands. */
c2f47e15 5152 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1cd6e20d 5153 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
b6a5fc45 5154
1cd6e20d 5155 return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SEQ_CST,
5156 after);
b6a5fc45 5157}
5158
5159/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
c2f47e15 5160 intrinsics. EXP is the CALL_EXPR. IS_BOOL is
b6a5fc45 5161 true if this is the boolean form. TARGET is a place for us to store the
5162 results; this is NOT optional if IS_BOOL is true. */
5163
5164static rtx
c2f47e15 5165expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
3e272de8 5166 bool is_bool, rtx target)
b6a5fc45 5167{
041e0215 5168 rtx old_val, new_val, mem;
ba885f6a 5169 rtx *pbool, *poval;
b6a5fc45 5170
5171 /* Expand the operands. */
c2f47e15 5172 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1cd6e20d 5173 old_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5174 new_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
b6a5fc45 5175
ba885f6a 5176 pbool = poval = NULL;
5177 if (target != const0_rtx)
5178 {
5179 if (is_bool)
5180 pbool = &target;
5181 else
5182 poval = &target;
5183 }
5184 if (!expand_atomic_compare_and_swap (pbool, poval, mem, old_val, new_val,
5185 false, MEMMODEL_SEQ_CST,
5186 MEMMODEL_SEQ_CST))
1cd6e20d 5187 return NULL_RTX;
c2f47e15 5188
1cd6e20d 5189 return target;
b6a5fc45 5190}
5191
5192/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
5193 general form is actually an atomic exchange, and some targets only
5194 support a reduced form with the second argument being a constant 1.
48e1416a 5195 EXP is the CALL_EXPR; TARGET is an optional place for us to store
c2f47e15 5196 the results. */
b6a5fc45 5197
5198static rtx
2797f13a 5199expand_builtin_sync_lock_test_and_set (enum machine_mode mode, tree exp,
1cd6e20d 5200 rtx target)
b6a5fc45 5201{
041e0215 5202 rtx val, mem;
b6a5fc45 5203
5204 /* Expand the operands. */
c2f47e15 5205 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1cd6e20d 5206 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5207
7821cde1 5208 return expand_sync_lock_test_and_set (target, mem, val);
1cd6e20d 5209}
5210
5211/* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */
5212
5213static void
5214expand_builtin_sync_lock_release (enum machine_mode mode, tree exp)
5215{
5216 rtx mem;
5217
5218 /* Expand the operands. */
5219 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5220
8808bf16 5221 expand_atomic_store (mem, const0_rtx, MEMMODEL_RELEASE, true);
1cd6e20d 5222}
5223
5224/* Given an integer representing an ``enum memmodel'', verify its
5225 correctness and return the memory model enum. */
5226
5227static enum memmodel
5228get_memmodel (tree exp)
5229{
5230 rtx op;
7f738025 5231 unsigned HOST_WIDE_INT val;
1cd6e20d 5232
5233 /* If the parameter is not a constant, it's a run time value so we'll just
5234 convert it to MEMMODEL_SEQ_CST to avoid annoying runtime checking. */
5235 if (TREE_CODE (exp) != INTEGER_CST)
5236 return MEMMODEL_SEQ_CST;
5237
5238 op = expand_normal (exp);
7f738025 5239
5240 val = INTVAL (op);
5241 if (targetm.memmodel_check)
5242 val = targetm.memmodel_check (val);
5243 else if (val & ~MEMMODEL_MASK)
5244 {
5245 warning (OPT_Winvalid_memory_model,
5246 "Unknown architecture specifier in memory model to builtin.");
5247 return MEMMODEL_SEQ_CST;
5248 }
5249
9af5ce0c 5250 if ((INTVAL (op) & MEMMODEL_MASK) >= MEMMODEL_LAST)
1cd6e20d 5251 {
5252 warning (OPT_Winvalid_memory_model,
5253 "invalid memory model argument to builtin");
5254 return MEMMODEL_SEQ_CST;
5255 }
7f738025 5256
5257 return (enum memmodel) val;
1cd6e20d 5258}
5259
5260/* Expand the __atomic_exchange intrinsic:
5261 TYPE __atomic_exchange (TYPE *object, TYPE desired, enum memmodel)
5262 EXP is the CALL_EXPR.
5263 TARGET is an optional place for us to store the results. */
5264
5265static rtx
5266expand_builtin_atomic_exchange (enum machine_mode mode, tree exp, rtx target)
5267{
5268 rtx val, mem;
5269 enum memmodel model;
5270
5271 model = get_memmodel (CALL_EXPR_ARG (exp, 2));
7f738025 5272 if ((model & MEMMODEL_MASK) == MEMMODEL_CONSUME)
1cd6e20d 5273 {
5274 error ("invalid memory model for %<__atomic_exchange%>");
5275 return NULL_RTX;
5276 }
5277
5278 if (!flag_inline_atomics)
5279 return NULL_RTX;
5280
5281 /* Expand the operands. */
5282 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5283 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5284
7821cde1 5285 return expand_atomic_exchange (target, mem, val, model);
1cd6e20d 5286}
5287
5288/* Expand the __atomic_compare_exchange intrinsic:
5289 bool __atomic_compare_exchange (TYPE *object, TYPE *expect,
5290 TYPE desired, BOOL weak,
5291 enum memmodel success,
5292 enum memmodel failure)
5293 EXP is the CALL_EXPR.
5294 TARGET is an optional place for us to store the results. */
5295
5296static rtx
5297expand_builtin_atomic_compare_exchange (enum machine_mode mode, tree exp,
5298 rtx target)
5299{
5300 rtx expect, desired, mem, oldval;
5301 enum memmodel success, failure;
5302 tree weak;
5303 bool is_weak;
5304
5305 success = get_memmodel (CALL_EXPR_ARG (exp, 4));
5306 failure = get_memmodel (CALL_EXPR_ARG (exp, 5));
5307
7f738025 5308 if ((failure & MEMMODEL_MASK) == MEMMODEL_RELEASE
5309 || (failure & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
1cd6e20d 5310 {
5311 error ("invalid failure memory model for %<__atomic_compare_exchange%>");
5312 return NULL_RTX;
5313 }
5314
5315 if (failure > success)
5316 {
5317 error ("failure memory model cannot be stronger than success "
5318 "memory model for %<__atomic_compare_exchange%>");
5319 return NULL_RTX;
5320 }
5321
5322 if (!flag_inline_atomics)
5323 return NULL_RTX;
5324
5325 /* Expand the operands. */
5326 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5327
5328 expect = expand_normal (CALL_EXPR_ARG (exp, 1));
5329 expect = convert_memory_address (Pmode, expect);
c401b131 5330 expect = gen_rtx_MEM (mode, expect);
1cd6e20d 5331 desired = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
5332
5333 weak = CALL_EXPR_ARG (exp, 3);
5334 is_weak = false;
e913b5cd 5335 if (tree_fits_shwi_p (weak) && tree_to_shwi (weak) != 0)
1cd6e20d 5336 is_weak = true;
5337
c401b131 5338 oldval = expect;
ba885f6a 5339 if (!expand_atomic_compare_and_swap ((target == const0_rtx ? NULL : &target),
5340 &oldval, mem, oldval, desired,
5341 is_weak, success, failure))
1cd6e20d 5342 return NULL_RTX;
5343
c401b131 5344 if (oldval != expect)
5345 emit_move_insn (expect, oldval);
5346
1cd6e20d 5347 return target;
5348}
5349
5350/* Expand the __atomic_load intrinsic:
5351 TYPE __atomic_load (TYPE *object, enum memmodel)
5352 EXP is the CALL_EXPR.
5353 TARGET is an optional place for us to store the results. */
5354
5355static rtx
5356expand_builtin_atomic_load (enum machine_mode mode, tree exp, rtx target)
5357{
5358 rtx mem;
5359 enum memmodel model;
5360
5361 model = get_memmodel (CALL_EXPR_ARG (exp, 1));
7f738025 5362 if ((model & MEMMODEL_MASK) == MEMMODEL_RELEASE
5363 || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
1cd6e20d 5364 {
5365 error ("invalid memory model for %<__atomic_load%>");
5366 return NULL_RTX;
5367 }
5368
5369 if (!flag_inline_atomics)
5370 return NULL_RTX;
5371
5372 /* Expand the operand. */
5373 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5374
5375 return expand_atomic_load (target, mem, model);
5376}
5377
5378
5379/* Expand the __atomic_store intrinsic:
5380 void __atomic_store (TYPE *object, TYPE desired, enum memmodel)
5381 EXP is the CALL_EXPR.
5382 TARGET is an optional place for us to store the results. */
5383
5384static rtx
5385expand_builtin_atomic_store (enum machine_mode mode, tree exp)
5386{
5387 rtx mem, val;
5388 enum memmodel model;
5389
5390 model = get_memmodel (CALL_EXPR_ARG (exp, 2));
7f738025 5391 if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED
5392 && (model & MEMMODEL_MASK) != MEMMODEL_SEQ_CST
5393 && (model & MEMMODEL_MASK) != MEMMODEL_RELEASE)
1cd6e20d 5394 {
5395 error ("invalid memory model for %<__atomic_store%>");
5396 return NULL_RTX;
5397 }
5398
5399 if (!flag_inline_atomics)
5400 return NULL_RTX;
5401
5402 /* Expand the operands. */
5403 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5404 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5405
8808bf16 5406 return expand_atomic_store (mem, val, model, false);
1cd6e20d 5407}
5408
5409/* Expand the __atomic_fetch_XXX intrinsic:
5410 TYPE __atomic_fetch_XXX (TYPE *object, TYPE val, enum memmodel)
5411 EXP is the CALL_EXPR.
5412 TARGET is an optional place for us to store the results.
5413 CODE is the operation, PLUS, MINUS, ADD, XOR, or IOR.
5414 FETCH_AFTER is true if returning the result of the operation.
5415 FETCH_AFTER is false if returning the value before the operation.
5416 IGNORE is true if the result is not used.
5417 EXT_CALL is the correct builtin for an external call if this cannot be
5418 resolved to an instruction sequence. */
5419
5420static rtx
5421expand_builtin_atomic_fetch_op (enum machine_mode mode, tree exp, rtx target,
5422 enum rtx_code code, bool fetch_after,
5423 bool ignore, enum built_in_function ext_call)
5424{
5425 rtx val, mem, ret;
5426 enum memmodel model;
5427 tree fndecl;
5428 tree addr;
5429
5430 model = get_memmodel (CALL_EXPR_ARG (exp, 2));
5431
5432 /* Expand the operands. */
5433 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5434 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5435
5436 /* Only try generating instructions if inlining is turned on. */
5437 if (flag_inline_atomics)
5438 {
5439 ret = expand_atomic_fetch_op (target, mem, val, code, model, fetch_after);
5440 if (ret)
5441 return ret;
5442 }
5443
5444 /* Return if a different routine isn't needed for the library call. */
5445 if (ext_call == BUILT_IN_NONE)
5446 return NULL_RTX;
5447
5448 /* Change the call to the specified function. */
5449 fndecl = get_callee_fndecl (exp);
5450 addr = CALL_EXPR_FN (exp);
5451 STRIP_NOPS (addr);
5452
5453 gcc_assert (TREE_OPERAND (addr, 0) == fndecl);
9af5ce0c 5454 TREE_OPERAND (addr, 0) = builtin_decl_explicit (ext_call);
1cd6e20d 5455
5456 /* Expand the call here so we can emit trailing code. */
5457 ret = expand_call (exp, target, ignore);
5458
5459 /* Replace the original function just in case it matters. */
5460 TREE_OPERAND (addr, 0) = fndecl;
5461
5462 /* Then issue the arithmetic correction to return the right result. */
5463 if (!ignore)
c449f851 5464 {
5465 if (code == NOT)
5466 {
5467 ret = expand_simple_binop (mode, AND, ret, val, NULL_RTX, true,
5468 OPTAB_LIB_WIDEN);
5469 ret = expand_simple_unop (mode, NOT, ret, target, true);
5470 }
5471 else
5472 ret = expand_simple_binop (mode, code, ret, val, target, true,
5473 OPTAB_LIB_WIDEN);
5474 }
1cd6e20d 5475 return ret;
5476}
5477
10b744a3 5478
7821cde1 5479#ifndef HAVE_atomic_clear
5480# define HAVE_atomic_clear 0
5481# define gen_atomic_clear(x,y) (gcc_unreachable (), NULL_RTX)
5482#endif
5483
10b744a3 5484/* Expand an atomic clear operation.
5485 void _atomic_clear (BOOL *obj, enum memmodel)
5486 EXP is the call expression. */
5487
5488static rtx
5489expand_builtin_atomic_clear (tree exp)
5490{
5491 enum machine_mode mode;
5492 rtx mem, ret;
5493 enum memmodel model;
5494
5495 mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0);
5496 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5497 model = get_memmodel (CALL_EXPR_ARG (exp, 1));
5498
7f738025 5499 if ((model & MEMMODEL_MASK) == MEMMODEL_ACQUIRE
5500 || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
10b744a3 5501 {
5502 error ("invalid memory model for %<__atomic_store%>");
5503 return const0_rtx;
5504 }
5505
7821cde1 5506 if (HAVE_atomic_clear)
5507 {
5508 emit_insn (gen_atomic_clear (mem, model));
5509 return const0_rtx;
5510 }
5511
10b744a3 5512 /* Try issuing an __atomic_store, and allow fallback to __sync_lock_release.
5513 Failing that, a store is issued by __atomic_store. The only way this can
5514 fail is if the bool type is larger than a word size. Unlikely, but
5515 handle it anyway for completeness. Assume a single threaded model since
5516 there is no atomic support in this case, and no barriers are required. */
5517 ret = expand_atomic_store (mem, const0_rtx, model, true);
5518 if (!ret)
5519 emit_move_insn (mem, const0_rtx);
5520 return const0_rtx;
5521}
5522
5523/* Expand an atomic test_and_set operation.
5524 bool _atomic_test_and_set (BOOL *obj, enum memmodel)
5525 EXP is the call expression. */
5526
5527static rtx
7821cde1 5528expand_builtin_atomic_test_and_set (tree exp, rtx target)
10b744a3 5529{
7821cde1 5530 rtx mem;
10b744a3 5531 enum memmodel model;
5532 enum machine_mode mode;
5533
5534 mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0);
5535 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5536 model = get_memmodel (CALL_EXPR_ARG (exp, 1));
5537
7821cde1 5538 return expand_atomic_test_and_set (target, mem, model);
10b744a3 5539}
5540
5541
1cd6e20d 5542/* Return true if (optional) argument ARG1 of size ARG0 is always lock free on
5543 this architecture. If ARG1 is NULL, use typical alignment for size ARG0. */
5544
5545static tree
5546fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
5547{
5548 int size;
5549 enum machine_mode mode;
5550 unsigned int mode_align, type_align;
5551
5552 if (TREE_CODE (arg0) != INTEGER_CST)
5553 return NULL_TREE;
b6a5fc45 5554
1cd6e20d 5555 size = INTVAL (expand_normal (arg0)) * BITS_PER_UNIT;
5556 mode = mode_for_size (size, MODE_INT, 0);
5557 mode_align = GET_MODE_ALIGNMENT (mode);
5558
5559 if (TREE_CODE (arg1) == INTEGER_CST && INTVAL (expand_normal (arg1)) == 0)
5560 type_align = mode_align;
5561 else
5562 {
5563 tree ttype = TREE_TYPE (arg1);
5564
5565 /* This function is usually invoked and folded immediately by the front
5566 end before anything else has a chance to look at it. The pointer
5567 parameter at this point is usually cast to a void *, so check for that
5568 and look past the cast. */
5569 if (TREE_CODE (arg1) == NOP_EXPR && POINTER_TYPE_P (ttype)
5570 && VOID_TYPE_P (TREE_TYPE (ttype)))
5571 arg1 = TREE_OPERAND (arg1, 0);
5572
5573 ttype = TREE_TYPE (arg1);
5574 gcc_assert (POINTER_TYPE_P (ttype));
5575
5576 /* Get the underlying type of the object. */
5577 ttype = TREE_TYPE (ttype);
5578 type_align = TYPE_ALIGN (ttype);
5579 }
5580
5581 /* If the object has smaller alignment, the the lock free routines cannot
5582 be used. */
5583 if (type_align < mode_align)
06308d2a 5584 return boolean_false_node;
1cd6e20d 5585
5586 /* Check if a compare_and_swap pattern exists for the mode which represents
5587 the required size. The pattern is not allowed to fail, so the existence
5588 of the pattern indicates support is present. */
29139cdc 5589 if (can_compare_and_swap_p (mode, true))
06308d2a 5590 return boolean_true_node;
1cd6e20d 5591 else
06308d2a 5592 return boolean_false_node;
1cd6e20d 5593}
5594
5595/* Return true if the parameters to call EXP represent an object which will
5596 always generate lock free instructions. The first argument represents the
5597 size of the object, and the second parameter is a pointer to the object
5598 itself. If NULL is passed for the object, then the result is based on
5599 typical alignment for an object of the specified size. Otherwise return
5600 false. */
5601
5602static rtx
5603expand_builtin_atomic_always_lock_free (tree exp)
5604{
5605 tree size;
5606 tree arg0 = CALL_EXPR_ARG (exp, 0);
5607 tree arg1 = CALL_EXPR_ARG (exp, 1);
5608
5609 if (TREE_CODE (arg0) != INTEGER_CST)
5610 {
5611 error ("non-constant argument 1 to __atomic_always_lock_free");
5612 return const0_rtx;
5613 }
5614
5615 size = fold_builtin_atomic_always_lock_free (arg0, arg1);
06308d2a 5616 if (size == boolean_true_node)
1cd6e20d 5617 return const1_rtx;
5618 return const0_rtx;
5619}
5620
5621/* Return a one or zero if it can be determined that object ARG1 of size ARG
5622 is lock free on this architecture. */
5623
5624static tree
5625fold_builtin_atomic_is_lock_free (tree arg0, tree arg1)
5626{
5627 if (!flag_inline_atomics)
5628 return NULL_TREE;
5629
5630 /* If it isn't always lock free, don't generate a result. */
06308d2a 5631 if (fold_builtin_atomic_always_lock_free (arg0, arg1) == boolean_true_node)
5632 return boolean_true_node;
1cd6e20d 5633
5634 return NULL_TREE;
5635}
5636
5637/* Return true if the parameters to call EXP represent an object which will
5638 always generate lock free instructions. The first argument represents the
5639 size of the object, and the second parameter is a pointer to the object
5640 itself. If NULL is passed for the object, then the result is based on
5641 typical alignment for an object of the specified size. Otherwise return
5642 NULL*/
5643
5644static rtx
5645expand_builtin_atomic_is_lock_free (tree exp)
5646{
5647 tree size;
5648 tree arg0 = CALL_EXPR_ARG (exp, 0);
5649 tree arg1 = CALL_EXPR_ARG (exp, 1);
5650
5651 if (!INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
5652 {
5653 error ("non-integer argument 1 to __atomic_is_lock_free");
5654 return NULL_RTX;
5655 }
5656
5657 if (!flag_inline_atomics)
5658 return NULL_RTX;
5659
5660 /* If the value is known at compile time, return the RTX for it. */
5661 size = fold_builtin_atomic_is_lock_free (arg0, arg1);
06308d2a 5662 if (size == boolean_true_node)
1cd6e20d 5663 return const1_rtx;
5664
5665 return NULL_RTX;
5666}
5667
1cd6e20d 5668/* Expand the __atomic_thread_fence intrinsic:
5669 void __atomic_thread_fence (enum memmodel)
5670 EXP is the CALL_EXPR. */
5671
5672static void
5673expand_builtin_atomic_thread_fence (tree exp)
5674{
fe54c06b 5675 enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
5676 expand_mem_thread_fence (model);
1cd6e20d 5677}
5678
5679/* Expand the __atomic_signal_fence intrinsic:
5680 void __atomic_signal_fence (enum memmodel)
5681 EXP is the CALL_EXPR. */
5682
5683static void
5684expand_builtin_atomic_signal_fence (tree exp)
5685{
fe54c06b 5686 enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
5687 expand_mem_signal_fence (model);
b6a5fc45 5688}
5689
5690/* Expand the __sync_synchronize intrinsic. */
5691
5692static void
2797f13a 5693expand_builtin_sync_synchronize (void)
b6a5fc45 5694{
fe54c06b 5695 expand_mem_thread_fence (MEMMODEL_SEQ_CST);
b6a5fc45 5696}
5697
badaa04c 5698static rtx
5699expand_builtin_thread_pointer (tree exp, rtx target)
5700{
5701 enum insn_code icode;
5702 if (!validate_arglist (exp, VOID_TYPE))
5703 return const0_rtx;
5704 icode = direct_optab_handler (get_thread_pointer_optab, Pmode);
5705 if (icode != CODE_FOR_nothing)
5706 {
5707 struct expand_operand op;
5708 if (!REG_P (target) || GET_MODE (target) != Pmode)
5709 target = gen_reg_rtx (Pmode);
5710 create_output_operand (&op, target, Pmode);
5711 expand_insn (icode, 1, &op);
5712 return target;
5713 }
5714 error ("__builtin_thread_pointer is not supported on this target");
5715 return const0_rtx;
5716}
5717
5718static void
5719expand_builtin_set_thread_pointer (tree exp)
5720{
5721 enum insn_code icode;
5722 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
5723 return;
5724 icode = direct_optab_handler (set_thread_pointer_optab, Pmode);
5725 if (icode != CODE_FOR_nothing)
5726 {
5727 struct expand_operand op;
5728 rtx val = expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX,
5729 Pmode, EXPAND_NORMAL);
6f343c10 5730 create_input_operand (&op, val, Pmode);
badaa04c 5731 expand_insn (icode, 1, &op);
5732 return;
5733 }
5734 error ("__builtin_set_thread_pointer is not supported on this target");
5735}
5736
53800dbe 5737\f
0e80b01d 5738/* Emit code to restore the current value of stack. */
5739
5740static void
5741expand_stack_restore (tree var)
5742{
5743 rtx prev, sa = expand_normal (var);
5744
5745 sa = convert_memory_address (Pmode, sa);
5746
5747 prev = get_last_insn ();
5748 emit_stack_restore (SAVE_BLOCK, sa);
5749 fixup_args_size_notes (prev, get_last_insn (), 0);
5750}
5751
5752
5753/* Emit code to save the current value of stack. */
5754
5755static rtx
5756expand_stack_save (void)
5757{
5758 rtx ret = NULL_RTX;
5759
5760 do_pending_stack_adjust ();
5761 emit_stack_save (SAVE_BLOCK, &ret);
5762 return ret;
5763}
5764
53800dbe 5765/* Expand an expression EXP that calls a built-in function,
5766 with result going to TARGET if that's convenient
5767 (and in mode MODE if that's convenient).
5768 SUBTARGET may be used as the target for computing one of EXP's operands.
5769 IGNORE is nonzero if the value is to be ignored. */
5770
5771rtx
aecda0d6 5772expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
5773 int ignore)
53800dbe 5774{
c6e6ecb1 5775 tree fndecl = get_callee_fndecl (exp);
53800dbe 5776 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
efb070c8 5777 enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
67fa4078 5778 int flags;
53800dbe 5779
8305149e 5780 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
883b2e73 5781 return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
bf8e3599 5782
53800dbe 5783 /* When not optimizing, generate calls to library functions for a certain
5784 set of builtins. */
cd9ff771 5785 if (!optimize
b6a5fc45 5786 && !called_as_built_in (fndecl)
73037a1e 5787 && fcode != BUILT_IN_FORK
5788 && fcode != BUILT_IN_EXECL
5789 && fcode != BUILT_IN_EXECV
5790 && fcode != BUILT_IN_EXECLP
5791 && fcode != BUILT_IN_EXECLE
5792 && fcode != BUILT_IN_EXECVP
5793 && fcode != BUILT_IN_EXECVE
2c281b15 5794 && fcode != BUILT_IN_ALLOCA
581bf1c2 5795 && fcode != BUILT_IN_ALLOCA_WITH_ALIGN
bbc26dcc 5796 && fcode != BUILT_IN_FREE)
cd9ff771 5797 return expand_call (exp, target, ignore);
53800dbe 5798
8d6d7930 5799 /* The built-in function expanders test for target == const0_rtx
5800 to determine whether the function's result will be ignored. */
5801 if (ignore)
5802 target = const0_rtx;
5803
5804 /* If the result of a pure or const built-in function is ignored, and
5805 none of its arguments are volatile, we can avoid expanding the
5806 built-in call and just evaluate the arguments for side-effects. */
5807 if (target == const0_rtx
67fa4078 5808 && ((flags = flags_from_decl_or_type (fndecl)) & (ECF_CONST | ECF_PURE))
5809 && !(flags & ECF_LOOPING_CONST_OR_PURE))
8d6d7930 5810 {
5811 bool volatilep = false;
5812 tree arg;
c2f47e15 5813 call_expr_arg_iterator iter;
8d6d7930 5814
c2f47e15 5815 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5816 if (TREE_THIS_VOLATILE (arg))
8d6d7930 5817 {
5818 volatilep = true;
5819 break;
5820 }
5821
5822 if (! volatilep)
5823 {
c2f47e15 5824 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5825 expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
8d6d7930 5826 return const0_rtx;
5827 }
5828 }
5829
53800dbe 5830 switch (fcode)
5831 {
4f35b1fc 5832 CASE_FLT_FN (BUILT_IN_FABS):
8aa32773 5833 case BUILT_IN_FABSD32:
5834 case BUILT_IN_FABSD64:
5835 case BUILT_IN_FABSD128:
c2f47e15 5836 target = expand_builtin_fabs (exp, target, subtarget);
78a74442 5837 if (target)
a0c938f0 5838 return target;
78a74442 5839 break;
5840
4f35b1fc 5841 CASE_FLT_FN (BUILT_IN_COPYSIGN):
c2f47e15 5842 target = expand_builtin_copysign (exp, target, subtarget);
270436f3 5843 if (target)
5844 return target;
5845 break;
5846
7d3f6cc7 5847 /* Just do a normal library call if we were unable to fold
5848 the values. */
4f35b1fc 5849 CASE_FLT_FN (BUILT_IN_CABS):
78a74442 5850 break;
53800dbe 5851
4f35b1fc 5852 CASE_FLT_FN (BUILT_IN_EXP):
5853 CASE_FLT_FN (BUILT_IN_EXP10):
5854 CASE_FLT_FN (BUILT_IN_POW10):
5855 CASE_FLT_FN (BUILT_IN_EXP2):
5856 CASE_FLT_FN (BUILT_IN_EXPM1):
5857 CASE_FLT_FN (BUILT_IN_LOGB):
4f35b1fc 5858 CASE_FLT_FN (BUILT_IN_LOG):
5859 CASE_FLT_FN (BUILT_IN_LOG10):
5860 CASE_FLT_FN (BUILT_IN_LOG2):
5861 CASE_FLT_FN (BUILT_IN_LOG1P):
5862 CASE_FLT_FN (BUILT_IN_TAN):
5863 CASE_FLT_FN (BUILT_IN_ASIN):
5864 CASE_FLT_FN (BUILT_IN_ACOS):
5865 CASE_FLT_FN (BUILT_IN_ATAN):
b3154a1f 5866 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
7f3be425 5867 /* Treat these like sqrt only if unsafe math optimizations are allowed,
5868 because of possible accuracy problems. */
5869 if (! flag_unsafe_math_optimizations)
53800dbe 5870 break;
4f35b1fc 5871 CASE_FLT_FN (BUILT_IN_SQRT):
5872 CASE_FLT_FN (BUILT_IN_FLOOR):
5873 CASE_FLT_FN (BUILT_IN_CEIL):
5874 CASE_FLT_FN (BUILT_IN_TRUNC):
5875 CASE_FLT_FN (BUILT_IN_ROUND):
5876 CASE_FLT_FN (BUILT_IN_NEARBYINT):
5877 CASE_FLT_FN (BUILT_IN_RINT):
53800dbe 5878 target = expand_builtin_mathfn (exp, target, subtarget);
5879 if (target)
5880 return target;
5881 break;
5882
7e0713b1 5883 CASE_FLT_FN (BUILT_IN_FMA):
5884 target = expand_builtin_mathfn_ternary (exp, target, subtarget);
5885 if (target)
5886 return target;
5887 break;
5888
a67a90e5 5889 CASE_FLT_FN (BUILT_IN_ILOGB):
5890 if (! flag_unsafe_math_optimizations)
5891 break;
69b779ea 5892 CASE_FLT_FN (BUILT_IN_ISINF):
cde061c1 5893 CASE_FLT_FN (BUILT_IN_FINITE):
5894 case BUILT_IN_ISFINITE:
8a1a9cb7 5895 case BUILT_IN_ISNORMAL:
f97eea22 5896 target = expand_builtin_interclass_mathfn (exp, target);
a67a90e5 5897 if (target)
5898 return target;
5899 break;
5900
80ff6494 5901 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 5902 CASE_FLT_FN (BUILT_IN_LCEIL):
5903 CASE_FLT_FN (BUILT_IN_LLCEIL):
5904 CASE_FLT_FN (BUILT_IN_LFLOOR):
80ff6494 5905 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 5906 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ff1b14e4 5907 target = expand_builtin_int_roundingfn (exp, target);
ad52b9b7 5908 if (target)
5909 return target;
5910 break;
5911
80ff6494 5912 CASE_FLT_FN (BUILT_IN_IRINT):
7d3afc77 5913 CASE_FLT_FN (BUILT_IN_LRINT):
5914 CASE_FLT_FN (BUILT_IN_LLRINT):
80ff6494 5915 CASE_FLT_FN (BUILT_IN_IROUND):
ef2f1a10 5916 CASE_FLT_FN (BUILT_IN_LROUND):
5917 CASE_FLT_FN (BUILT_IN_LLROUND):
ff1b14e4 5918 target = expand_builtin_int_roundingfn_2 (exp, target);
7d3afc77 5919 if (target)
5920 return target;
5921 break;
5922
4f35b1fc 5923 CASE_FLT_FN (BUILT_IN_POWI):
f97eea22 5924 target = expand_builtin_powi (exp, target);
757c219d 5925 if (target)
5926 return target;
5927 break;
5928
4f35b1fc 5929 CASE_FLT_FN (BUILT_IN_ATAN2):
5930 CASE_FLT_FN (BUILT_IN_LDEXP):
73a954a1 5931 CASE_FLT_FN (BUILT_IN_SCALB):
5932 CASE_FLT_FN (BUILT_IN_SCALBN):
5933 CASE_FLT_FN (BUILT_IN_SCALBLN):
0fd605a5 5934 if (! flag_unsafe_math_optimizations)
5935 break;
ef722005 5936
5937 CASE_FLT_FN (BUILT_IN_FMOD):
5938 CASE_FLT_FN (BUILT_IN_REMAINDER):
5939 CASE_FLT_FN (BUILT_IN_DREM):
0810ff17 5940 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 5941 target = expand_builtin_mathfn_2 (exp, target, subtarget);
5942 if (target)
5943 return target;
5944 break;
5945
d735c391 5946 CASE_FLT_FN (BUILT_IN_CEXPI):
f97eea22 5947 target = expand_builtin_cexpi (exp, target);
d735c391 5948 gcc_assert (target);
5949 return target;
5950
4f35b1fc 5951 CASE_FLT_FN (BUILT_IN_SIN):
5952 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 5953 if (! flag_unsafe_math_optimizations)
5954 break;
5955 target = expand_builtin_mathfn_3 (exp, target, subtarget);
5956 if (target)
5957 return target;
5958 break;
5959
c3147c1a 5960 CASE_FLT_FN (BUILT_IN_SINCOS):
5961 if (! flag_unsafe_math_optimizations)
5962 break;
5963 target = expand_builtin_sincos (exp);
5964 if (target)
5965 return target;
5966 break;
5967
53800dbe 5968 case BUILT_IN_APPLY_ARGS:
5969 return expand_builtin_apply_args ();
5970
5971 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
5972 FUNCTION with a copy of the parameters described by
5973 ARGUMENTS, and ARGSIZE. It returns a block of memory
5974 allocated on the stack into which is stored all the registers
5975 that might possibly be used for returning the result of a
5976 function. ARGUMENTS is the value returned by
5977 __builtin_apply_args. ARGSIZE is the number of bytes of
5978 arguments that must be copied. ??? How should this value be
5979 computed? We'll also need a safe worst case value for varargs
5980 functions. */
5981 case BUILT_IN_APPLY:
c2f47e15 5982 if (!validate_arglist (exp, POINTER_TYPE,
0eb671f7 5983 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
c2f47e15 5984 && !validate_arglist (exp, REFERENCE_TYPE,
0eb671f7 5985 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 5986 return const0_rtx;
5987 else
5988 {
53800dbe 5989 rtx ops[3];
5990
c2f47e15 5991 ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
5992 ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
5993 ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
53800dbe 5994
5995 return expand_builtin_apply (ops[0], ops[1], ops[2]);
5996 }
5997
5998 /* __builtin_return (RESULT) causes the function to return the
5999 value described by RESULT. RESULT is address of the block of
6000 memory returned by __builtin_apply. */
6001 case BUILT_IN_RETURN:
c2f47e15 6002 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
6003 expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
53800dbe 6004 return const0_rtx;
6005
6006 case BUILT_IN_SAVEREGS:
a66c9326 6007 return expand_builtin_saveregs ();
53800dbe 6008
48dc2227 6009 case BUILT_IN_VA_ARG_PACK:
6010 /* All valid uses of __builtin_va_arg_pack () are removed during
6011 inlining. */
b8c23db3 6012 error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
48dc2227 6013 return const0_rtx;
6014
4e1d7ea4 6015 case BUILT_IN_VA_ARG_PACK_LEN:
6016 /* All valid uses of __builtin_va_arg_pack_len () are removed during
6017 inlining. */
b8c23db3 6018 error ("%Kinvalid use of %<__builtin_va_arg_pack_len ()%>", exp);
4e1d7ea4 6019 return const0_rtx;
6020
53800dbe 6021 /* Return the address of the first anonymous stack arg. */
6022 case BUILT_IN_NEXT_ARG:
c2f47e15 6023 if (fold_builtin_next_arg (exp, false))
a0c938f0 6024 return const0_rtx;
79012a9d 6025 return expand_builtin_next_arg ();
53800dbe 6026
ac8fb6db 6027 case BUILT_IN_CLEAR_CACHE:
6028 target = expand_builtin___clear_cache (exp);
6029 if (target)
6030 return target;
6031 break;
6032
53800dbe 6033 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 6034 return expand_builtin_classify_type (exp);
53800dbe 6035
6036 case BUILT_IN_CONSTANT_P:
4ee9c684 6037 return const0_rtx;
53800dbe 6038
6039 case BUILT_IN_FRAME_ADDRESS:
6040 case BUILT_IN_RETURN_ADDRESS:
c2f47e15 6041 return expand_builtin_frame_address (fndecl, exp);
53800dbe 6042
6043 /* Returns the address of the area where the structure is returned.
6044 0 otherwise. */
6045 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
c2f47e15 6046 if (call_expr_nargs (exp) != 0
9342ee68 6047 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
e16ceb8e 6048 || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
9342ee68 6049 return const0_rtx;
53800dbe 6050 else
9342ee68 6051 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
53800dbe 6052
6053 case BUILT_IN_ALLOCA:
581bf1c2 6054 case BUILT_IN_ALLOCA_WITH_ALIGN:
990495a7 6055 /* If the allocation stems from the declaration of a variable-sized
6056 object, it cannot accumulate. */
a882d754 6057 target = expand_builtin_alloca (exp, CALL_ALLOCA_FOR_VAR_P (exp));
53800dbe 6058 if (target)
6059 return target;
6060 break;
6061
4ee9c684 6062 case BUILT_IN_STACK_SAVE:
6063 return expand_stack_save ();
6064
6065 case BUILT_IN_STACK_RESTORE:
c2f47e15 6066 expand_stack_restore (CALL_EXPR_ARG (exp, 0));
4ee9c684 6067 return const0_rtx;
6068
74bdbe96 6069 case BUILT_IN_BSWAP16:
42791117 6070 case BUILT_IN_BSWAP32:
6071 case BUILT_IN_BSWAP64:
74bdbe96 6072 target = expand_builtin_bswap (target_mode, exp, target, subtarget);
42791117 6073 if (target)
6074 return target;
6075 break;
6076
4f35b1fc 6077 CASE_INT_FN (BUILT_IN_FFS):
c2f47e15 6078 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6079 subtarget, ffs_optab);
6a08d0ab 6080 if (target)
6081 return target;
6082 break;
6083
4f35b1fc 6084 CASE_INT_FN (BUILT_IN_CLZ):
c2f47e15 6085 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6086 subtarget, clz_optab);
6a08d0ab 6087 if (target)
6088 return target;
6089 break;
6090
4f35b1fc 6091 CASE_INT_FN (BUILT_IN_CTZ):
c2f47e15 6092 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6093 subtarget, ctz_optab);
6a08d0ab 6094 if (target)
6095 return target;
6096 break;
6097
d8492bd3 6098 CASE_INT_FN (BUILT_IN_CLRSB):
d8492bd3 6099 target = expand_builtin_unop (target_mode, exp, target,
6100 subtarget, clrsb_optab);
6101 if (target)
6102 return target;
6103 break;
6104
4f35b1fc 6105 CASE_INT_FN (BUILT_IN_POPCOUNT):
c2f47e15 6106 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6107 subtarget, popcount_optab);
6a08d0ab 6108 if (target)
6109 return target;
6110 break;
6111
4f35b1fc 6112 CASE_INT_FN (BUILT_IN_PARITY):
c2f47e15 6113 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6114 subtarget, parity_optab);
53800dbe 6115 if (target)
6116 return target;
6117 break;
6118
6119 case BUILT_IN_STRLEN:
c2f47e15 6120 target = expand_builtin_strlen (exp, target, target_mode);
53800dbe 6121 if (target)
6122 return target;
6123 break;
6124
6125 case BUILT_IN_STRCPY:
a65c4d64 6126 target = expand_builtin_strcpy (exp, target);
53800dbe 6127 if (target)
6128 return target;
6129 break;
bf8e3599 6130
ed09096d 6131 case BUILT_IN_STRNCPY:
a65c4d64 6132 target = expand_builtin_strncpy (exp, target);
ed09096d 6133 if (target)
6134 return target;
6135 break;
bf8e3599 6136
3b824fa6 6137 case BUILT_IN_STPCPY:
dc369150 6138 target = expand_builtin_stpcpy (exp, target, mode);
3b824fa6 6139 if (target)
6140 return target;
6141 break;
6142
53800dbe 6143 case BUILT_IN_MEMCPY:
a65c4d64 6144 target = expand_builtin_memcpy (exp, target);
3b824fa6 6145 if (target)
6146 return target;
6147 break;
6148
6149 case BUILT_IN_MEMPCPY:
c2f47e15 6150 target = expand_builtin_mempcpy (exp, target, mode);
53800dbe 6151 if (target)
6152 return target;
6153 break;
6154
6155 case BUILT_IN_MEMSET:
c2f47e15 6156 target = expand_builtin_memset (exp, target, mode);
53800dbe 6157 if (target)
6158 return target;
6159 break;
6160
ffc83088 6161 case BUILT_IN_BZERO:
0b25db21 6162 target = expand_builtin_bzero (exp);
ffc83088 6163 if (target)
6164 return target;
6165 break;
6166
53800dbe 6167 case BUILT_IN_STRCMP:
a65c4d64 6168 target = expand_builtin_strcmp (exp, target);
53800dbe 6169 if (target)
6170 return target;
6171 break;
6172
ed09096d 6173 case BUILT_IN_STRNCMP:
6174 target = expand_builtin_strncmp (exp, target, mode);
6175 if (target)
6176 return target;
6177 break;
6178
071f1696 6179 case BUILT_IN_BCMP:
53800dbe 6180 case BUILT_IN_MEMCMP:
c2f47e15 6181 target = expand_builtin_memcmp (exp, target, mode);
53800dbe 6182 if (target)
6183 return target;
6184 break;
53800dbe 6185
6186 case BUILT_IN_SETJMP:
2c8a1497 6187 /* This should have been lowered to the builtins below. */
6188 gcc_unreachable ();
6189
6190 case BUILT_IN_SETJMP_SETUP:
6191 /* __builtin_setjmp_setup is passed a pointer to an array of five words
6192 and the receiver label. */
c2f47e15 6193 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2c8a1497 6194 {
c2f47e15 6195 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
2c8a1497 6196 VOIDmode, EXPAND_NORMAL);
c2f47e15 6197 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
2c8a1497 6198 rtx label_r = label_rtx (label);
6199
6200 /* This is copied from the handling of non-local gotos. */
6201 expand_builtin_setjmp_setup (buf_addr, label_r);
6202 nonlocal_goto_handler_labels
6203 = gen_rtx_EXPR_LIST (VOIDmode, label_r,
6204 nonlocal_goto_handler_labels);
6205 /* ??? Do not let expand_label treat us as such since we would
6206 not want to be both on the list of non-local labels and on
6207 the list of forced labels. */
6208 FORCED_LABEL (label) = 0;
6209 return const0_rtx;
6210 }
6211 break;
6212
6213 case BUILT_IN_SETJMP_DISPATCHER:
6214 /* __builtin_setjmp_dispatcher is passed the dispatcher label. */
c2f47e15 6215 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6216 {
c2f47e15 6217 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6218 rtx label_r = label_rtx (label);
6219
6220 /* Remove the dispatcher label from the list of non-local labels
6221 since the receiver labels have been added to it above. */
6222 remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels);
6223 return const0_rtx;
6224 }
6225 break;
6226
6227 case BUILT_IN_SETJMP_RECEIVER:
6228 /* __builtin_setjmp_receiver is passed the receiver label. */
c2f47e15 6229 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6230 {
c2f47e15 6231 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6232 rtx label_r = label_rtx (label);
6233
6234 expand_builtin_setjmp_receiver (label_r);
6235 return const0_rtx;
6236 }
6b7f6858 6237 break;
53800dbe 6238
6239 /* __builtin_longjmp is passed a pointer to an array of five words.
6240 It's similar to the C library longjmp function but works with
6241 __builtin_setjmp above. */
6242 case BUILT_IN_LONGJMP:
c2f47e15 6243 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 6244 {
c2f47e15 6245 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
8ec3c5c2 6246 VOIDmode, EXPAND_NORMAL);
c2f47e15 6247 rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
53800dbe 6248
6249 if (value != const1_rtx)
6250 {
1e5fcbe2 6251 error ("%<__builtin_longjmp%> second argument must be 1");
53800dbe 6252 return const0_rtx;
6253 }
6254
6255 expand_builtin_longjmp (buf_addr, value);
6256 return const0_rtx;
6257 }
2c8a1497 6258 break;
53800dbe 6259
4ee9c684 6260 case BUILT_IN_NONLOCAL_GOTO:
c2f47e15 6261 target = expand_builtin_nonlocal_goto (exp);
4ee9c684 6262 if (target)
6263 return target;
6264 break;
6265
843d08a9 6266 /* This updates the setjmp buffer that is its argument with the value
6267 of the current stack pointer. */
6268 case BUILT_IN_UPDATE_SETJMP_BUF:
c2f47e15 6269 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
843d08a9 6270 {
6271 rtx buf_addr
c2f47e15 6272 = expand_normal (CALL_EXPR_ARG (exp, 0));
843d08a9 6273
6274 expand_builtin_update_setjmp_buf (buf_addr);
6275 return const0_rtx;
6276 }
6277 break;
6278
53800dbe 6279 case BUILT_IN_TRAP:
a0ef1725 6280 expand_builtin_trap ();
53800dbe 6281 return const0_rtx;
6282
d2b48f0c 6283 case BUILT_IN_UNREACHABLE:
6284 expand_builtin_unreachable ();
6285 return const0_rtx;
6286
4f35b1fc 6287 CASE_FLT_FN (BUILT_IN_SIGNBIT):
004e23c4 6288 case BUILT_IN_SIGNBITD32:
6289 case BUILT_IN_SIGNBITD64:
6290 case BUILT_IN_SIGNBITD128:
27f261ef 6291 target = expand_builtin_signbit (exp, target);
6292 if (target)
6293 return target;
6294 break;
6295
53800dbe 6296 /* Various hooks for the DWARF 2 __throw routine. */
6297 case BUILT_IN_UNWIND_INIT:
6298 expand_builtin_unwind_init ();
6299 return const0_rtx;
6300 case BUILT_IN_DWARF_CFA:
6301 return virtual_cfa_rtx;
6302#ifdef DWARF2_UNWIND_INFO
f8f023a5 6303 case BUILT_IN_DWARF_SP_COLUMN:
6304 return expand_builtin_dwarf_sp_column ();
695e919b 6305 case BUILT_IN_INIT_DWARF_REG_SIZES:
c2f47e15 6306 expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
695e919b 6307 return const0_rtx;
53800dbe 6308#endif
6309 case BUILT_IN_FROB_RETURN_ADDR:
c2f47e15 6310 return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6311 case BUILT_IN_EXTRACT_RETURN_ADDR:
c2f47e15 6312 return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6313 case BUILT_IN_EH_RETURN:
c2f47e15 6314 expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
6315 CALL_EXPR_ARG (exp, 1));
53800dbe 6316 return const0_rtx;
df4b504c 6317#ifdef EH_RETURN_DATA_REGNO
6318 case BUILT_IN_EH_RETURN_DATA_REGNO:
c2f47e15 6319 return expand_builtin_eh_return_data_regno (exp);
df4b504c 6320#endif
26093bf4 6321 case BUILT_IN_EXTEND_POINTER:
c2f47e15 6322 return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
e38def9c 6323 case BUILT_IN_EH_POINTER:
6324 return expand_builtin_eh_pointer (exp);
6325 case BUILT_IN_EH_FILTER:
6326 return expand_builtin_eh_filter (exp);
6327 case BUILT_IN_EH_COPY_VALUES:
6328 return expand_builtin_eh_copy_values (exp);
26093bf4 6329
7ccc713a 6330 case BUILT_IN_VA_START:
c2f47e15 6331 return expand_builtin_va_start (exp);
a66c9326 6332 case BUILT_IN_VA_END:
c2f47e15 6333 return expand_builtin_va_end (exp);
a66c9326 6334 case BUILT_IN_VA_COPY:
c2f47e15 6335 return expand_builtin_va_copy (exp);
89cfe6e5 6336 case BUILT_IN_EXPECT:
c2f47e15 6337 return expand_builtin_expect (exp, target);
fca0886c 6338 case BUILT_IN_ASSUME_ALIGNED:
6339 return expand_builtin_assume_aligned (exp, target);
5e3608d8 6340 case BUILT_IN_PREFETCH:
c2f47e15 6341 expand_builtin_prefetch (exp);
5e3608d8 6342 return const0_rtx;
6343
4ee9c684 6344 case BUILT_IN_INIT_TRAMPOLINE:
c307f106 6345 return expand_builtin_init_trampoline (exp, true);
6346 case BUILT_IN_INIT_HEAP_TRAMPOLINE:
6347 return expand_builtin_init_trampoline (exp, false);
4ee9c684 6348 case BUILT_IN_ADJUST_TRAMPOLINE:
c2f47e15 6349 return expand_builtin_adjust_trampoline (exp);
4ee9c684 6350
73673831 6351 case BUILT_IN_FORK:
6352 case BUILT_IN_EXECL:
6353 case BUILT_IN_EXECV:
6354 case BUILT_IN_EXECLP:
6355 case BUILT_IN_EXECLE:
6356 case BUILT_IN_EXECVP:
6357 case BUILT_IN_EXECVE:
c2f47e15 6358 target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
73673831 6359 if (target)
6360 return target;
6361 break;
53800dbe 6362
2797f13a 6363 case BUILT_IN_SYNC_FETCH_AND_ADD_1:
6364 case BUILT_IN_SYNC_FETCH_AND_ADD_2:
6365 case BUILT_IN_SYNC_FETCH_AND_ADD_4:
6366 case BUILT_IN_SYNC_FETCH_AND_ADD_8:
6367 case BUILT_IN_SYNC_FETCH_AND_ADD_16:
6368 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_ADD_1);
1cd6e20d 6369 target = expand_builtin_sync_operation (mode, exp, PLUS, false, target);
b6a5fc45 6370 if (target)
6371 return target;
6372 break;
6373
2797f13a 6374 case BUILT_IN_SYNC_FETCH_AND_SUB_1:
6375 case BUILT_IN_SYNC_FETCH_AND_SUB_2:
6376 case BUILT_IN_SYNC_FETCH_AND_SUB_4:
6377 case BUILT_IN_SYNC_FETCH_AND_SUB_8:
6378 case BUILT_IN_SYNC_FETCH_AND_SUB_16:
6379 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_SUB_1);
1cd6e20d 6380 target = expand_builtin_sync_operation (mode, exp, MINUS, false, target);
b6a5fc45 6381 if (target)
6382 return target;
6383 break;
6384
2797f13a 6385 case BUILT_IN_SYNC_FETCH_AND_OR_1:
6386 case BUILT_IN_SYNC_FETCH_AND_OR_2:
6387 case BUILT_IN_SYNC_FETCH_AND_OR_4:
6388 case BUILT_IN_SYNC_FETCH_AND_OR_8:
6389 case BUILT_IN_SYNC_FETCH_AND_OR_16:
6390 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_OR_1);
1cd6e20d 6391 target = expand_builtin_sync_operation (mode, exp, IOR, false, target);
b6a5fc45 6392 if (target)
6393 return target;
6394 break;
6395
2797f13a 6396 case BUILT_IN_SYNC_FETCH_AND_AND_1:
6397 case BUILT_IN_SYNC_FETCH_AND_AND_2:
6398 case BUILT_IN_SYNC_FETCH_AND_AND_4:
6399 case BUILT_IN_SYNC_FETCH_AND_AND_8:
6400 case BUILT_IN_SYNC_FETCH_AND_AND_16:
6401 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_AND_1);
1cd6e20d 6402 target = expand_builtin_sync_operation (mode, exp, AND, false, target);
b6a5fc45 6403 if (target)
6404 return target;
6405 break;
6406
2797f13a 6407 case BUILT_IN_SYNC_FETCH_AND_XOR_1:
6408 case BUILT_IN_SYNC_FETCH_AND_XOR_2:
6409 case BUILT_IN_SYNC_FETCH_AND_XOR_4:
6410 case BUILT_IN_SYNC_FETCH_AND_XOR_8:
6411 case BUILT_IN_SYNC_FETCH_AND_XOR_16:
6412 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_XOR_1);
1cd6e20d 6413 target = expand_builtin_sync_operation (mode, exp, XOR, false, target);
b6a5fc45 6414 if (target)
6415 return target;
6416 break;
6417
2797f13a 6418 case BUILT_IN_SYNC_FETCH_AND_NAND_1:
6419 case BUILT_IN_SYNC_FETCH_AND_NAND_2:
6420 case BUILT_IN_SYNC_FETCH_AND_NAND_4:
6421 case BUILT_IN_SYNC_FETCH_AND_NAND_8:
6422 case BUILT_IN_SYNC_FETCH_AND_NAND_16:
6423 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_NAND_1);
1cd6e20d 6424 target = expand_builtin_sync_operation (mode, exp, NOT, false, target);
b6a5fc45 6425 if (target)
6426 return target;
6427 break;
6428
2797f13a 6429 case BUILT_IN_SYNC_ADD_AND_FETCH_1:
6430 case BUILT_IN_SYNC_ADD_AND_FETCH_2:
6431 case BUILT_IN_SYNC_ADD_AND_FETCH_4:
6432 case BUILT_IN_SYNC_ADD_AND_FETCH_8:
6433 case BUILT_IN_SYNC_ADD_AND_FETCH_16:
6434 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_ADD_AND_FETCH_1);
1cd6e20d 6435 target = expand_builtin_sync_operation (mode, exp, PLUS, true, target);
b6a5fc45 6436 if (target)
6437 return target;
6438 break;
6439
2797f13a 6440 case BUILT_IN_SYNC_SUB_AND_FETCH_1:
6441 case BUILT_IN_SYNC_SUB_AND_FETCH_2:
6442 case BUILT_IN_SYNC_SUB_AND_FETCH_4:
6443 case BUILT_IN_SYNC_SUB_AND_FETCH_8:
6444 case BUILT_IN_SYNC_SUB_AND_FETCH_16:
6445 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_SUB_AND_FETCH_1);
1cd6e20d 6446 target = expand_builtin_sync_operation (mode, exp, MINUS, true, target);
b6a5fc45 6447 if (target)
6448 return target;
6449 break;
6450
2797f13a 6451 case BUILT_IN_SYNC_OR_AND_FETCH_1:
6452 case BUILT_IN_SYNC_OR_AND_FETCH_2:
6453 case BUILT_IN_SYNC_OR_AND_FETCH_4:
6454 case BUILT_IN_SYNC_OR_AND_FETCH_8:
6455 case BUILT_IN_SYNC_OR_AND_FETCH_16:
6456 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_OR_AND_FETCH_1);
1cd6e20d 6457 target = expand_builtin_sync_operation (mode, exp, IOR, true, target);
b6a5fc45 6458 if (target)
6459 return target;
6460 break;
6461
2797f13a 6462 case BUILT_IN_SYNC_AND_AND_FETCH_1:
6463 case BUILT_IN_SYNC_AND_AND_FETCH_2:
6464 case BUILT_IN_SYNC_AND_AND_FETCH_4:
6465 case BUILT_IN_SYNC_AND_AND_FETCH_8:
6466 case BUILT_IN_SYNC_AND_AND_FETCH_16:
6467 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_AND_AND_FETCH_1);
1cd6e20d 6468 target = expand_builtin_sync_operation (mode, exp, AND, true, target);
b6a5fc45 6469 if (target)
6470 return target;
6471 break;
6472
2797f13a 6473 case BUILT_IN_SYNC_XOR_AND_FETCH_1:
6474 case BUILT_IN_SYNC_XOR_AND_FETCH_2:
6475 case BUILT_IN_SYNC_XOR_AND_FETCH_4:
6476 case BUILT_IN_SYNC_XOR_AND_FETCH_8:
6477 case BUILT_IN_SYNC_XOR_AND_FETCH_16:
6478 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_XOR_AND_FETCH_1);
1cd6e20d 6479 target = expand_builtin_sync_operation (mode, exp, XOR, true, target);
b6a5fc45 6480 if (target)
6481 return target;
6482 break;
6483
2797f13a 6484 case BUILT_IN_SYNC_NAND_AND_FETCH_1:
6485 case BUILT_IN_SYNC_NAND_AND_FETCH_2:
6486 case BUILT_IN_SYNC_NAND_AND_FETCH_4:
6487 case BUILT_IN_SYNC_NAND_AND_FETCH_8:
6488 case BUILT_IN_SYNC_NAND_AND_FETCH_16:
6489 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_NAND_AND_FETCH_1);
1cd6e20d 6490 target = expand_builtin_sync_operation (mode, exp, NOT, true, target);
b6a5fc45 6491 if (target)
6492 return target;
6493 break;
6494
2797f13a 6495 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
6496 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
6497 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
6498 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
6499 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16:
a601d32a 6500 if (mode == VOIDmode)
6501 mode = TYPE_MODE (boolean_type_node);
b6a5fc45 6502 if (!target || !register_operand (target, mode))
6503 target = gen_reg_rtx (mode);
3e272de8 6504
2797f13a 6505 mode = get_builtin_sync_mode
6506 (fcode - BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1);
c2f47e15 6507 target = expand_builtin_compare_and_swap (mode, exp, true, target);
b6a5fc45 6508 if (target)
6509 return target;
6510 break;
6511
2797f13a 6512 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
6513 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
6514 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
6515 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
6516 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
6517 mode = get_builtin_sync_mode
6518 (fcode - BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1);
c2f47e15 6519 target = expand_builtin_compare_and_swap (mode, exp, false, target);
b6a5fc45 6520 if (target)
6521 return target;
6522 break;
6523
2797f13a 6524 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
6525 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
6526 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
6527 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
6528 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16:
6529 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_TEST_AND_SET_1);
6530 target = expand_builtin_sync_lock_test_and_set (mode, exp, target);
b6a5fc45 6531 if (target)
6532 return target;
6533 break;
6534
2797f13a 6535 case BUILT_IN_SYNC_LOCK_RELEASE_1:
6536 case BUILT_IN_SYNC_LOCK_RELEASE_2:
6537 case BUILT_IN_SYNC_LOCK_RELEASE_4:
6538 case BUILT_IN_SYNC_LOCK_RELEASE_8:
6539 case BUILT_IN_SYNC_LOCK_RELEASE_16:
6540 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_RELEASE_1);
6541 expand_builtin_sync_lock_release (mode, exp);
b6a5fc45 6542 return const0_rtx;
6543
2797f13a 6544 case BUILT_IN_SYNC_SYNCHRONIZE:
6545 expand_builtin_sync_synchronize ();
b6a5fc45 6546 return const0_rtx;
6547
1cd6e20d 6548 case BUILT_IN_ATOMIC_EXCHANGE_1:
6549 case BUILT_IN_ATOMIC_EXCHANGE_2:
6550 case BUILT_IN_ATOMIC_EXCHANGE_4:
6551 case BUILT_IN_ATOMIC_EXCHANGE_8:
6552 case BUILT_IN_ATOMIC_EXCHANGE_16:
6553 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_EXCHANGE_1);
6554 target = expand_builtin_atomic_exchange (mode, exp, target);
6555 if (target)
6556 return target;
6557 break;
6558
6559 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1:
6560 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2:
6561 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4:
6562 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8:
6563 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
2c201ad1 6564 {
6565 unsigned int nargs, z;
f1f41a6c 6566 vec<tree, va_gc> *vec;
2c201ad1 6567
6568 mode =
6569 get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1);
6570 target = expand_builtin_atomic_compare_exchange (mode, exp, target);
6571 if (target)
6572 return target;
6573
6574 /* If this is turned into an external library call, the weak parameter
6575 must be dropped to match the expected parameter list. */
6576 nargs = call_expr_nargs (exp);
f1f41a6c 6577 vec_alloc (vec, nargs - 1);
2c201ad1 6578 for (z = 0; z < 3; z++)
f1f41a6c 6579 vec->quick_push (CALL_EXPR_ARG (exp, z));
2c201ad1 6580 /* Skip the boolean weak parameter. */
6581 for (z = 4; z < 6; z++)
f1f41a6c 6582 vec->quick_push (CALL_EXPR_ARG (exp, z));
2c201ad1 6583 exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), vec);
6584 break;
6585 }
1cd6e20d 6586
6587 case BUILT_IN_ATOMIC_LOAD_1:
6588 case BUILT_IN_ATOMIC_LOAD_2:
6589 case BUILT_IN_ATOMIC_LOAD_4:
6590 case BUILT_IN_ATOMIC_LOAD_8:
6591 case BUILT_IN_ATOMIC_LOAD_16:
6592 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_LOAD_1);
6593 target = expand_builtin_atomic_load (mode, exp, target);
6594 if (target)
6595 return target;
6596 break;
6597
6598 case BUILT_IN_ATOMIC_STORE_1:
6599 case BUILT_IN_ATOMIC_STORE_2:
6600 case BUILT_IN_ATOMIC_STORE_4:
6601 case BUILT_IN_ATOMIC_STORE_8:
6602 case BUILT_IN_ATOMIC_STORE_16:
6603 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_STORE_1);
6604 target = expand_builtin_atomic_store (mode, exp);
6605 if (target)
6606 return const0_rtx;
6607 break;
6608
6609 case BUILT_IN_ATOMIC_ADD_FETCH_1:
6610 case BUILT_IN_ATOMIC_ADD_FETCH_2:
6611 case BUILT_IN_ATOMIC_ADD_FETCH_4:
6612 case BUILT_IN_ATOMIC_ADD_FETCH_8:
6613 case BUILT_IN_ATOMIC_ADD_FETCH_16:
6614 {
6615 enum built_in_function lib;
6616 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1);
6617 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_ADD_1 +
6618 (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1));
6619 target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, true,
6620 ignore, lib);
6621 if (target)
6622 return target;
6623 break;
6624 }
6625 case BUILT_IN_ATOMIC_SUB_FETCH_1:
6626 case BUILT_IN_ATOMIC_SUB_FETCH_2:
6627 case BUILT_IN_ATOMIC_SUB_FETCH_4:
6628 case BUILT_IN_ATOMIC_SUB_FETCH_8:
6629 case BUILT_IN_ATOMIC_SUB_FETCH_16:
6630 {
6631 enum built_in_function lib;
6632 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1);
6633 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_SUB_1 +
6634 (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1));
6635 target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, true,
6636 ignore, lib);
6637 if (target)
6638 return target;
6639 break;
6640 }
6641 case BUILT_IN_ATOMIC_AND_FETCH_1:
6642 case BUILT_IN_ATOMIC_AND_FETCH_2:
6643 case BUILT_IN_ATOMIC_AND_FETCH_4:
6644 case BUILT_IN_ATOMIC_AND_FETCH_8:
6645 case BUILT_IN_ATOMIC_AND_FETCH_16:
6646 {
6647 enum built_in_function lib;
6648 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_AND_FETCH_1);
6649 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_AND_1 +
6650 (fcode - BUILT_IN_ATOMIC_AND_FETCH_1));
6651 target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, true,
6652 ignore, lib);
6653 if (target)
6654 return target;
6655 break;
6656 }
6657 case BUILT_IN_ATOMIC_NAND_FETCH_1:
6658 case BUILT_IN_ATOMIC_NAND_FETCH_2:
6659 case BUILT_IN_ATOMIC_NAND_FETCH_4:
6660 case BUILT_IN_ATOMIC_NAND_FETCH_8:
6661 case BUILT_IN_ATOMIC_NAND_FETCH_16:
6662 {
6663 enum built_in_function lib;
6664 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1);
6665 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_NAND_1 +
6666 (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1));
6667 target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, true,
6668 ignore, lib);
6669 if (target)
6670 return target;
6671 break;
6672 }
6673 case BUILT_IN_ATOMIC_XOR_FETCH_1:
6674 case BUILT_IN_ATOMIC_XOR_FETCH_2:
6675 case BUILT_IN_ATOMIC_XOR_FETCH_4:
6676 case BUILT_IN_ATOMIC_XOR_FETCH_8:
6677 case BUILT_IN_ATOMIC_XOR_FETCH_16:
6678 {
6679 enum built_in_function lib;
6680 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1);
6681 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_XOR_1 +
6682 (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1));
6683 target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, true,
6684 ignore, lib);
6685 if (target)
6686 return target;
6687 break;
6688 }
6689 case BUILT_IN_ATOMIC_OR_FETCH_1:
6690 case BUILT_IN_ATOMIC_OR_FETCH_2:
6691 case BUILT_IN_ATOMIC_OR_FETCH_4:
6692 case BUILT_IN_ATOMIC_OR_FETCH_8:
6693 case BUILT_IN_ATOMIC_OR_FETCH_16:
6694 {
6695 enum built_in_function lib;
6696 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_OR_FETCH_1);
6697 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_OR_1 +
6698 (fcode - BUILT_IN_ATOMIC_OR_FETCH_1));
6699 target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, true,
6700 ignore, lib);
6701 if (target)
6702 return target;
6703 break;
6704 }
6705 case BUILT_IN_ATOMIC_FETCH_ADD_1:
6706 case BUILT_IN_ATOMIC_FETCH_ADD_2:
6707 case BUILT_IN_ATOMIC_FETCH_ADD_4:
6708 case BUILT_IN_ATOMIC_FETCH_ADD_8:
6709 case BUILT_IN_ATOMIC_FETCH_ADD_16:
6710 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_ADD_1);
6711 target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, false,
6712 ignore, BUILT_IN_NONE);
6713 if (target)
6714 return target;
6715 break;
6716
6717 case BUILT_IN_ATOMIC_FETCH_SUB_1:
6718 case BUILT_IN_ATOMIC_FETCH_SUB_2:
6719 case BUILT_IN_ATOMIC_FETCH_SUB_4:
6720 case BUILT_IN_ATOMIC_FETCH_SUB_8:
6721 case BUILT_IN_ATOMIC_FETCH_SUB_16:
6722 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_SUB_1);
6723 target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, false,
6724 ignore, BUILT_IN_NONE);
6725 if (target)
6726 return target;
6727 break;
6728
6729 case BUILT_IN_ATOMIC_FETCH_AND_1:
6730 case BUILT_IN_ATOMIC_FETCH_AND_2:
6731 case BUILT_IN_ATOMIC_FETCH_AND_4:
6732 case BUILT_IN_ATOMIC_FETCH_AND_8:
6733 case BUILT_IN_ATOMIC_FETCH_AND_16:
6734 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_AND_1);
6735 target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, false,
6736 ignore, BUILT_IN_NONE);
6737 if (target)
6738 return target;
6739 break;
6740
6741 case BUILT_IN_ATOMIC_FETCH_NAND_1:
6742 case BUILT_IN_ATOMIC_FETCH_NAND_2:
6743 case BUILT_IN_ATOMIC_FETCH_NAND_4:
6744 case BUILT_IN_ATOMIC_FETCH_NAND_8:
6745 case BUILT_IN_ATOMIC_FETCH_NAND_16:
6746 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_NAND_1);
6747 target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, false,
6748 ignore, BUILT_IN_NONE);
6749 if (target)
6750 return target;
6751 break;
6752
6753 case BUILT_IN_ATOMIC_FETCH_XOR_1:
6754 case BUILT_IN_ATOMIC_FETCH_XOR_2:
6755 case BUILT_IN_ATOMIC_FETCH_XOR_4:
6756 case BUILT_IN_ATOMIC_FETCH_XOR_8:
6757 case BUILT_IN_ATOMIC_FETCH_XOR_16:
6758 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_XOR_1);
6759 target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, false,
6760 ignore, BUILT_IN_NONE);
6761 if (target)
6762 return target;
6763 break;
6764
6765 case BUILT_IN_ATOMIC_FETCH_OR_1:
6766 case BUILT_IN_ATOMIC_FETCH_OR_2:
6767 case BUILT_IN_ATOMIC_FETCH_OR_4:
6768 case BUILT_IN_ATOMIC_FETCH_OR_8:
6769 case BUILT_IN_ATOMIC_FETCH_OR_16:
6770 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_OR_1);
6771 target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, false,
6772 ignore, BUILT_IN_NONE);
6773 if (target)
6774 return target;
6775 break;
10b744a3 6776
6777 case BUILT_IN_ATOMIC_TEST_AND_SET:
7821cde1 6778 return expand_builtin_atomic_test_and_set (exp, target);
10b744a3 6779
6780 case BUILT_IN_ATOMIC_CLEAR:
6781 return expand_builtin_atomic_clear (exp);
1cd6e20d 6782
6783 case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
6784 return expand_builtin_atomic_always_lock_free (exp);
6785
6786 case BUILT_IN_ATOMIC_IS_LOCK_FREE:
6787 target = expand_builtin_atomic_is_lock_free (exp);
6788 if (target)
6789 return target;
6790 break;
6791
6792 case BUILT_IN_ATOMIC_THREAD_FENCE:
6793 expand_builtin_atomic_thread_fence (exp);
6794 return const0_rtx;
6795
6796 case BUILT_IN_ATOMIC_SIGNAL_FENCE:
6797 expand_builtin_atomic_signal_fence (exp);
6798 return const0_rtx;
6799
0a39fd54 6800 case BUILT_IN_OBJECT_SIZE:
6801 return expand_builtin_object_size (exp);
6802
6803 case BUILT_IN_MEMCPY_CHK:
6804 case BUILT_IN_MEMPCPY_CHK:
6805 case BUILT_IN_MEMMOVE_CHK:
6806 case BUILT_IN_MEMSET_CHK:
6807 target = expand_builtin_memory_chk (exp, target, mode, fcode);
6808 if (target)
6809 return target;
6810 break;
6811
6812 case BUILT_IN_STRCPY_CHK:
6813 case BUILT_IN_STPCPY_CHK:
6814 case BUILT_IN_STRNCPY_CHK:
1063acde 6815 case BUILT_IN_STPNCPY_CHK:
0a39fd54 6816 case BUILT_IN_STRCAT_CHK:
b356dfef 6817 case BUILT_IN_STRNCAT_CHK:
0a39fd54 6818 case BUILT_IN_SNPRINTF_CHK:
6819 case BUILT_IN_VSNPRINTF_CHK:
6820 maybe_emit_chk_warning (exp, fcode);
6821 break;
6822
6823 case BUILT_IN_SPRINTF_CHK:
6824 case BUILT_IN_VSPRINTF_CHK:
6825 maybe_emit_sprintf_chk_warning (exp, fcode);
6826 break;
6827
2c281b15 6828 case BUILT_IN_FREE:
f74ea1c2 6829 if (warn_free_nonheap_object)
6830 maybe_emit_free_warning (exp);
2c281b15 6831 break;
6832
badaa04c 6833 case BUILT_IN_THREAD_POINTER:
6834 return expand_builtin_thread_pointer (exp, target);
6835
6836 case BUILT_IN_SET_THREAD_POINTER:
6837 expand_builtin_set_thread_pointer (exp);
6838 return const0_rtx;
6839
d037099f 6840 case BUILT_IN_CILK_DETACH:
6841 expand_builtin_cilk_detach (exp);
6842 return const0_rtx;
6843
6844 case BUILT_IN_CILK_POP_FRAME:
6845 expand_builtin_cilk_pop_frame (exp);
6846 return const0_rtx;
6847
92482ee0 6848 default: /* just do library call, if unknown builtin */
146c1b4f 6849 break;
53800dbe 6850 }
6851
6852 /* The switch statement above can drop through to cause the function
6853 to be called normally. */
6854 return expand_call (exp, target, ignore);
6855}
650e4c94 6856
805e22b2 6857/* Determine whether a tree node represents a call to a built-in
52203a9d 6858 function. If the tree T is a call to a built-in function with
6859 the right number of arguments of the appropriate types, return
6860 the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
6861 Otherwise the return value is END_BUILTINS. */
aecda0d6 6862
805e22b2 6863enum built_in_function
b7bf20db 6864builtin_mathfn_code (const_tree t)
805e22b2 6865{
b7bf20db 6866 const_tree fndecl, arg, parmlist;
6867 const_tree argtype, parmtype;
6868 const_call_expr_arg_iterator iter;
805e22b2 6869
6870 if (TREE_CODE (t) != CALL_EXPR
c2f47e15 6871 || TREE_CODE (CALL_EXPR_FN (t)) != ADDR_EXPR)
805e22b2 6872 return END_BUILTINS;
6873
c6e6ecb1 6874 fndecl = get_callee_fndecl (t);
6875 if (fndecl == NULL_TREE
52203a9d 6876 || TREE_CODE (fndecl) != FUNCTION_DECL
805e22b2 6877 || ! DECL_BUILT_IN (fndecl)
6878 || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
6879 return END_BUILTINS;
6880
52203a9d 6881 parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
b7bf20db 6882 init_const_call_expr_arg_iterator (t, &iter);
52203a9d 6883 for (; parmlist; parmlist = TREE_CHAIN (parmlist))
e9f80ff5 6884 {
52203a9d 6885 /* If a function doesn't take a variable number of arguments,
6886 the last element in the list will have type `void'. */
6887 parmtype = TREE_VALUE (parmlist);
6888 if (VOID_TYPE_P (parmtype))
6889 {
b7bf20db 6890 if (more_const_call_expr_args_p (&iter))
52203a9d 6891 return END_BUILTINS;
6892 return DECL_FUNCTION_CODE (fndecl);
6893 }
6894
b7bf20db 6895 if (! more_const_call_expr_args_p (&iter))
e9f80ff5 6896 return END_BUILTINS;
48e1416a 6897
b7bf20db 6898 arg = next_const_call_expr_arg (&iter);
c2f47e15 6899 argtype = TREE_TYPE (arg);
52203a9d 6900
6901 if (SCALAR_FLOAT_TYPE_P (parmtype))
6902 {
6903 if (! SCALAR_FLOAT_TYPE_P (argtype))
6904 return END_BUILTINS;
6905 }
6906 else if (COMPLEX_FLOAT_TYPE_P (parmtype))
6907 {
6908 if (! COMPLEX_FLOAT_TYPE_P (argtype))
6909 return END_BUILTINS;
6910 }
6911 else if (POINTER_TYPE_P (parmtype))
6912 {
6913 if (! POINTER_TYPE_P (argtype))
6914 return END_BUILTINS;
6915 }
6916 else if (INTEGRAL_TYPE_P (parmtype))
6917 {
6918 if (! INTEGRAL_TYPE_P (argtype))
6919 return END_BUILTINS;
6920 }
6921 else
e9f80ff5 6922 return END_BUILTINS;
e9f80ff5 6923 }
6924
52203a9d 6925 /* Variable-length argument list. */
805e22b2 6926 return DECL_FUNCTION_CODE (fndecl);
6927}
6928
c2f47e15 6929/* Fold a call to __builtin_constant_p, if we know its argument ARG will
6930 evaluate to a constant. */
650e4c94 6931
6932static tree
c2f47e15 6933fold_builtin_constant_p (tree arg)
650e4c94 6934{
650e4c94 6935 /* We return 1 for a numeric type that's known to be a constant
6936 value at compile-time or for an aggregate type that's a
6937 literal constant. */
c2f47e15 6938 STRIP_NOPS (arg);
650e4c94 6939
6940 /* If we know this is a constant, emit the constant of one. */
c2f47e15 6941 if (CONSTANT_CLASS_P (arg)
6942 || (TREE_CODE (arg) == CONSTRUCTOR
6943 && TREE_CONSTANT (arg)))
650e4c94 6944 return integer_one_node;
c2f47e15 6945 if (TREE_CODE (arg) == ADDR_EXPR)
adcfa3a3 6946 {
c2f47e15 6947 tree op = TREE_OPERAND (arg, 0);
adcfa3a3 6948 if (TREE_CODE (op) == STRING_CST
6949 || (TREE_CODE (op) == ARRAY_REF
6950 && integer_zerop (TREE_OPERAND (op, 1))
6951 && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
6952 return integer_one_node;
6953 }
650e4c94 6954
1fb4300c 6955 /* If this expression has side effects, show we don't know it to be a
6956 constant. Likewise if it's a pointer or aggregate type since in
6957 those case we only want literals, since those are only optimized
f97c71a1 6958 when generating RTL, not later.
6959 And finally, if we are compiling an initializer, not code, we
6960 need to return a definite result now; there's not going to be any
6961 more optimization done. */
c2f47e15 6962 if (TREE_SIDE_EFFECTS (arg)
6963 || AGGREGATE_TYPE_P (TREE_TYPE (arg))
6964 || POINTER_TYPE_P (TREE_TYPE (arg))
47be647d 6965 || cfun == 0
0b049e15 6966 || folding_initializer
6967 || force_folding_builtin_constant_p)
650e4c94 6968 return integer_zero_node;
6969
c2f47e15 6970 return NULL_TREE;
650e4c94 6971}
6972
76f5a783 6973/* Create builtin_expect with PRED and EXPECTED as its arguments and
6974 return it as a truthvalue. */
4ee9c684 6975
6976static tree
389dd41b 6977build_builtin_expect_predicate (location_t loc, tree pred, tree expected)
4ee9c684 6978{
76f5a783 6979 tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
4ee9c684 6980
b9a16870 6981 fn = builtin_decl_explicit (BUILT_IN_EXPECT);
76f5a783 6982 arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
6983 ret_type = TREE_TYPE (TREE_TYPE (fn));
6984 pred_type = TREE_VALUE (arg_types);
6985 expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
6986
389dd41b 6987 pred = fold_convert_loc (loc, pred_type, pred);
6988 expected = fold_convert_loc (loc, expected_type, expected);
6989 call_expr = build_call_expr_loc (loc, fn, 2, pred, expected);
76f5a783 6990
6991 return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
6992 build_int_cst (ret_type, 0));
6993}
6994
6995/* Fold a call to builtin_expect with arguments ARG0 and ARG1. Return
6996 NULL_TREE if no simplification is possible. */
6997
6998static tree
389dd41b 6999fold_builtin_expect (location_t loc, tree arg0, tree arg1)
76f5a783 7000{
083bada9 7001 tree inner, fndecl, inner_arg0;
76f5a783 7002 enum tree_code code;
7003
083bada9 7004 /* Distribute the expected value over short-circuiting operators.
7005 See through the cast from truthvalue_type_node to long. */
7006 inner_arg0 = arg0;
7007 while (TREE_CODE (inner_arg0) == NOP_EXPR
7008 && INTEGRAL_TYPE_P (TREE_TYPE (inner_arg0))
7009 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner_arg0, 0))))
7010 inner_arg0 = TREE_OPERAND (inner_arg0, 0);
7011
76f5a783 7012 /* If this is a builtin_expect within a builtin_expect keep the
7013 inner one. See through a comparison against a constant. It
7014 might have been added to create a thruthvalue. */
083bada9 7015 inner = inner_arg0;
7016
76f5a783 7017 if (COMPARISON_CLASS_P (inner)
7018 && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST)
7019 inner = TREE_OPERAND (inner, 0);
7020
7021 if (TREE_CODE (inner) == CALL_EXPR
7022 && (fndecl = get_callee_fndecl (inner))
7023 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
7024 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT)
7025 return arg0;
7026
083bada9 7027 inner = inner_arg0;
76f5a783 7028 code = TREE_CODE (inner);
7029 if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
7030 {
7031 tree op0 = TREE_OPERAND (inner, 0);
7032 tree op1 = TREE_OPERAND (inner, 1);
7033
389dd41b 7034 op0 = build_builtin_expect_predicate (loc, op0, arg1);
7035 op1 = build_builtin_expect_predicate (loc, op1, arg1);
76f5a783 7036 inner = build2 (code, TREE_TYPE (inner), op0, op1);
7037
389dd41b 7038 return fold_convert_loc (loc, TREE_TYPE (arg0), inner);
76f5a783 7039 }
7040
7041 /* If the argument isn't invariant then there's nothing else we can do. */
083bada9 7042 if (!TREE_CONSTANT (inner_arg0))
c2f47e15 7043 return NULL_TREE;
4ee9c684 7044
76f5a783 7045 /* If we expect that a comparison against the argument will fold to
7046 a constant return the constant. In practice, this means a true
7047 constant or the address of a non-weak symbol. */
083bada9 7048 inner = inner_arg0;
4ee9c684 7049 STRIP_NOPS (inner);
7050 if (TREE_CODE (inner) == ADDR_EXPR)
7051 {
7052 do
7053 {
7054 inner = TREE_OPERAND (inner, 0);
7055 }
7056 while (TREE_CODE (inner) == COMPONENT_REF
7057 || TREE_CODE (inner) == ARRAY_REF);
062b4460 7058 if ((TREE_CODE (inner) == VAR_DECL
7059 || TREE_CODE (inner) == FUNCTION_DECL)
7060 && DECL_WEAK (inner))
c2f47e15 7061 return NULL_TREE;
4ee9c684 7062 }
7063
76f5a783 7064 /* Otherwise, ARG0 already has the proper type for the return value. */
7065 return arg0;
4ee9c684 7066}
7067
c2f47e15 7068/* Fold a call to __builtin_classify_type with argument ARG. */
27d0c333 7069
539a3a92 7070static tree
c2f47e15 7071fold_builtin_classify_type (tree arg)
539a3a92 7072{
c2f47e15 7073 if (arg == 0)
7002a1c8 7074 return build_int_cst (integer_type_node, no_type_class);
539a3a92 7075
7002a1c8 7076 return build_int_cst (integer_type_node, type_to_class (TREE_TYPE (arg)));
539a3a92 7077}
7078
c2f47e15 7079/* Fold a call to __builtin_strlen with argument ARG. */
e6e27594 7080
7081static tree
c7cbde74 7082fold_builtin_strlen (location_t loc, tree type, tree arg)
e6e27594 7083{
c2f47e15 7084 if (!validate_arg (arg, POINTER_TYPE))
e6e27594 7085 return NULL_TREE;
7086 else
7087 {
c2f47e15 7088 tree len = c_strlen (arg, 0);
e6e27594 7089
7090 if (len)
c7cbde74 7091 return fold_convert_loc (loc, type, len);
e6e27594 7092
7093 return NULL_TREE;
7094 }
7095}
7096
92c43e3c 7097/* Fold a call to __builtin_inf or __builtin_huge_val. */
7098
7099static tree
389dd41b 7100fold_builtin_inf (location_t loc, tree type, int warn)
92c43e3c 7101{
aa870c1b 7102 REAL_VALUE_TYPE real;
7103
40f4dbd5 7104 /* __builtin_inff is intended to be usable to define INFINITY on all
7105 targets. If an infinity is not available, INFINITY expands "to a
7106 positive constant of type float that overflows at translation
7107 time", footnote "In this case, using INFINITY will violate the
7108 constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
7109 Thus we pedwarn to ensure this constraint violation is
7110 diagnosed. */
92c43e3c 7111 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
389dd41b 7112 pedwarn (loc, 0, "target format does not support infinity");
92c43e3c 7113
aa870c1b 7114 real_inf (&real);
7115 return build_real (type, real);
92c43e3c 7116}
7117
c2f47e15 7118/* Fold a call to __builtin_nan or __builtin_nans with argument ARG. */
b0db7939 7119
7120static tree
c2f47e15 7121fold_builtin_nan (tree arg, tree type, int quiet)
b0db7939 7122{
7123 REAL_VALUE_TYPE real;
7124 const char *str;
7125
c2f47e15 7126 if (!validate_arg (arg, POINTER_TYPE))
7127 return NULL_TREE;
7128 str = c_getstr (arg);
b0db7939 7129 if (!str)
c2f47e15 7130 return NULL_TREE;
b0db7939 7131
7132 if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
c2f47e15 7133 return NULL_TREE;
b0db7939 7134
7135 return build_real (type, real);
7136}
7137
277f8dd2 7138/* Return true if the floating point expression T has an integer value.
7139 We also allow +Inf, -Inf and NaN to be considered integer values. */
7140
7141static bool
7142integer_valued_real_p (tree t)
7143{
7144 switch (TREE_CODE (t))
7145 {
7146 case FLOAT_EXPR:
7147 return true;
7148
7149 case ABS_EXPR:
7150 case SAVE_EXPR:
277f8dd2 7151 return integer_valued_real_p (TREE_OPERAND (t, 0));
7152
7153 case COMPOUND_EXPR:
41076ef6 7154 case MODIFY_EXPR:
277f8dd2 7155 case BIND_EXPR:
75a70cf9 7156 return integer_valued_real_p (TREE_OPERAND (t, 1));
277f8dd2 7157
7158 case PLUS_EXPR:
7159 case MINUS_EXPR:
7160 case MULT_EXPR:
7161 case MIN_EXPR:
7162 case MAX_EXPR:
7163 return integer_valued_real_p (TREE_OPERAND (t, 0))
7164 && integer_valued_real_p (TREE_OPERAND (t, 1));
7165
7166 case COND_EXPR:
7167 return integer_valued_real_p (TREE_OPERAND (t, 1))
7168 && integer_valued_real_p (TREE_OPERAND (t, 2));
7169
7170 case REAL_CST:
0570334c 7171 return real_isinteger (TREE_REAL_CST_PTR (t), TYPE_MODE (TREE_TYPE (t)));
277f8dd2 7172
7173 case NOP_EXPR:
7174 {
7175 tree type = TREE_TYPE (TREE_OPERAND (t, 0));
7176 if (TREE_CODE (type) == INTEGER_TYPE)
7177 return true;
7178 if (TREE_CODE (type) == REAL_TYPE)
7179 return integer_valued_real_p (TREE_OPERAND (t, 0));
7180 break;
7181 }
7182
7183 case CALL_EXPR:
7184 switch (builtin_mathfn_code (t))
7185 {
4f35b1fc 7186 CASE_FLT_FN (BUILT_IN_CEIL):
7187 CASE_FLT_FN (BUILT_IN_FLOOR):
7188 CASE_FLT_FN (BUILT_IN_NEARBYINT):
7189 CASE_FLT_FN (BUILT_IN_RINT):
7190 CASE_FLT_FN (BUILT_IN_ROUND):
7191 CASE_FLT_FN (BUILT_IN_TRUNC):
277f8dd2 7192 return true;
7193
d4a43a03 7194 CASE_FLT_FN (BUILT_IN_FMIN):
7195 CASE_FLT_FN (BUILT_IN_FMAX):
c2f47e15 7196 return integer_valued_real_p (CALL_EXPR_ARG (t, 0))
7197 && integer_valued_real_p (CALL_EXPR_ARG (t, 1));
d4a43a03 7198
277f8dd2 7199 default:
7200 break;
7201 }
7202 break;
7203
7204 default:
7205 break;
7206 }
7207 return false;
7208}
7209
c2f47e15 7210/* FNDECL is assumed to be a builtin where truncation can be propagated
6528f4f4 7211 across (for instance floor((double)f) == (double)floorf (f).
c2f47e15 7212 Do the transformation for a call with argument ARG. */
277f8dd2 7213
6528f4f4 7214static tree
389dd41b 7215fold_trunc_transparent_mathfn (location_t loc, tree fndecl, tree arg)
6528f4f4 7216{
6528f4f4 7217 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
277f8dd2 7218
c2f47e15 7219 if (!validate_arg (arg, REAL_TYPE))
7220 return NULL_TREE;
6528f4f4 7221
277f8dd2 7222 /* Integer rounding functions are idempotent. */
7223 if (fcode == builtin_mathfn_code (arg))
7224 return arg;
7225
7226 /* If argument is already integer valued, and we don't need to worry
7227 about setting errno, there's no need to perform rounding. */
7228 if (! flag_errno_math && integer_valued_real_p (arg))
7229 return arg;
7230
7231 if (optimize)
6528f4f4 7232 {
277f8dd2 7233 tree arg0 = strip_float_extensions (arg);
2426241c 7234 tree ftype = TREE_TYPE (TREE_TYPE (fndecl));
6528f4f4 7235 tree newtype = TREE_TYPE (arg0);
7236 tree decl;
7237
7238 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7239 && (decl = mathfn_built_in (newtype, fcode)))
389dd41b 7240 return fold_convert_loc (loc, ftype,
7241 build_call_expr_loc (loc, decl, 1,
7242 fold_convert_loc (loc,
7243 newtype,
7244 arg0)));
6528f4f4 7245 }
c2f47e15 7246 return NULL_TREE;
6528f4f4 7247}
7248
c2f47e15 7249/* FNDECL is assumed to be builtin which can narrow the FP type of
7250 the argument, for instance lround((double)f) -> lroundf (f).
7251 Do the transformation for a call with argument ARG. */
9ed65c7f 7252
7253static tree
389dd41b 7254fold_fixed_mathfn (location_t loc, tree fndecl, tree arg)
9ed65c7f 7255{
9ed65c7f 7256 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9ed65c7f 7257
c2f47e15 7258 if (!validate_arg (arg, REAL_TYPE))
7259 return NULL_TREE;
9ed65c7f 7260
7261 /* If argument is already integer valued, and we don't need to worry
7262 about setting errno, there's no need to perform rounding. */
7263 if (! flag_errno_math && integer_valued_real_p (arg))
389dd41b 7264 return fold_build1_loc (loc, FIX_TRUNC_EXPR,
7265 TREE_TYPE (TREE_TYPE (fndecl)), arg);
9ed65c7f 7266
7267 if (optimize)
7268 {
7269 tree ftype = TREE_TYPE (arg);
7270 tree arg0 = strip_float_extensions (arg);
7271 tree newtype = TREE_TYPE (arg0);
7272 tree decl;
7273
7274 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7275 && (decl = mathfn_built_in (newtype, fcode)))
389dd41b 7276 return build_call_expr_loc (loc, decl, 1,
7277 fold_convert_loc (loc, newtype, arg0));
9ed65c7f 7278 }
73a0da56 7279
80ff6494 7280 /* Canonicalize iround (x) to lround (x) on ILP32 targets where
7281 sizeof (int) == sizeof (long). */
7282 if (TYPE_PRECISION (integer_type_node)
7283 == TYPE_PRECISION (long_integer_type_node))
7284 {
7285 tree newfn = NULL_TREE;
7286 switch (fcode)
7287 {
7288 CASE_FLT_FN (BUILT_IN_ICEIL):
7289 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
7290 break;
7291
7292 CASE_FLT_FN (BUILT_IN_IFLOOR):
7293 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
7294 break;
7295
7296 CASE_FLT_FN (BUILT_IN_IROUND):
7297 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
7298 break;
7299
7300 CASE_FLT_FN (BUILT_IN_IRINT):
7301 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
7302 break;
7303
7304 default:
7305 break;
7306 }
7307
7308 if (newfn)
7309 {
7310 tree newcall = build_call_expr_loc (loc, newfn, 1, arg);
7311 return fold_convert_loc (loc,
7312 TREE_TYPE (TREE_TYPE (fndecl)), newcall);
7313 }
7314 }
7315
73a0da56 7316 /* Canonicalize llround (x) to lround (x) on LP64 targets where
7317 sizeof (long long) == sizeof (long). */
7318 if (TYPE_PRECISION (long_long_integer_type_node)
7319 == TYPE_PRECISION (long_integer_type_node))
7320 {
7321 tree newfn = NULL_TREE;
7322 switch (fcode)
7323 {
7324 CASE_FLT_FN (BUILT_IN_LLCEIL):
7325 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
7326 break;
7327
7328 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7329 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
7330 break;
7331
7332 CASE_FLT_FN (BUILT_IN_LLROUND):
7333 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
7334 break;
7335
7336 CASE_FLT_FN (BUILT_IN_LLRINT):
7337 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
7338 break;
7339
7340 default:
7341 break;
7342 }
7343
7344 if (newfn)
7345 {
389dd41b 7346 tree newcall = build_call_expr_loc (loc, newfn, 1, arg);
7347 return fold_convert_loc (loc,
7348 TREE_TYPE (TREE_TYPE (fndecl)), newcall);
73a0da56 7349 }
7350 }
7351
c2f47e15 7352 return NULL_TREE;
9ed65c7f 7353}
7354
c2f47e15 7355/* Fold call to builtin cabs, cabsf or cabsl with argument ARG. TYPE is the
7356 return type. Return NULL_TREE if no simplification can be made. */
c63f4ad3 7357
7358static tree
389dd41b 7359fold_builtin_cabs (location_t loc, tree arg, tree type, tree fndecl)
c63f4ad3 7360{
c2f47e15 7361 tree res;
c63f4ad3 7362
b0ce8887 7363 if (!validate_arg (arg, COMPLEX_TYPE)
c63f4ad3 7364 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
7365 return NULL_TREE;
7366
b4725390 7367 /* Calculate the result when the argument is a constant. */
7368 if (TREE_CODE (arg) == COMPLEX_CST
7369 && (res = do_mpfr_arg2 (TREE_REALPART (arg), TREE_IMAGPART (arg),
7370 type, mpfr_hypot)))
7371 return res;
48e1416a 7372
1af0d139 7373 if (TREE_CODE (arg) == COMPLEX_EXPR)
7374 {
7375 tree real = TREE_OPERAND (arg, 0);
7376 tree imag = TREE_OPERAND (arg, 1);
48e1416a 7377
1af0d139 7378 /* If either part is zero, cabs is fabs of the other. */
7379 if (real_zerop (real))
389dd41b 7380 return fold_build1_loc (loc, ABS_EXPR, type, imag);
1af0d139 7381 if (real_zerop (imag))
389dd41b 7382 return fold_build1_loc (loc, ABS_EXPR, type, real);
1af0d139 7383
7384 /* cabs(x+xi) -> fabs(x)*sqrt(2). */
7385 if (flag_unsafe_math_optimizations
7386 && operand_equal_p (real, imag, OEP_PURE_SAME))
7387 {
2e7ca27b 7388 const REAL_VALUE_TYPE sqrt2_trunc
7910b2fb 7389 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
1af0d139 7390 STRIP_NOPS (real);
389dd41b 7391 return fold_build2_loc (loc, MULT_EXPR, type,
7392 fold_build1_loc (loc, ABS_EXPR, type, real),
2e7ca27b 7393 build_real (type, sqrt2_trunc));
1af0d139 7394 }
7395 }
c63f4ad3 7396
749891b2 7397 /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */
7398 if (TREE_CODE (arg) == NEGATE_EXPR
7399 || TREE_CODE (arg) == CONJ_EXPR)
389dd41b 7400 return build_call_expr_loc (loc, fndecl, 1, TREE_OPERAND (arg, 0));
749891b2 7401
7d3f6cc7 7402 /* Don't do this when optimizing for size. */
7403 if (flag_unsafe_math_optimizations
0bfd8d5c 7404 && optimize && optimize_function_for_speed_p (cfun))
c63f4ad3 7405 {
0da0dbfa 7406 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
c63f4ad3 7407
7408 if (sqrtfn != NULL_TREE)
7409 {
c2f47e15 7410 tree rpart, ipart, result;
c63f4ad3 7411
4ee9c684 7412 arg = builtin_save_expr (arg);
29a6518e 7413
389dd41b 7414 rpart = fold_build1_loc (loc, REALPART_EXPR, type, arg);
7415 ipart = fold_build1_loc (loc, IMAGPART_EXPR, type, arg);
c63f4ad3 7416
4ee9c684 7417 rpart = builtin_save_expr (rpart);
7418 ipart = builtin_save_expr (ipart);
c63f4ad3 7419
389dd41b 7420 result = fold_build2_loc (loc, PLUS_EXPR, type,
7421 fold_build2_loc (loc, MULT_EXPR, type,
49d00087 7422 rpart, rpart),
389dd41b 7423 fold_build2_loc (loc, MULT_EXPR, type,
49d00087 7424 ipart, ipart));
c63f4ad3 7425
389dd41b 7426 return build_call_expr_loc (loc, sqrtfn, 1, result);
c63f4ad3 7427 }
7428 }
7429
7430 return NULL_TREE;
7431}
7432
c2373fdb 7433/* Build a complex (inf +- 0i) for the result of cproj. TYPE is the
7434 complex tree type of the result. If NEG is true, the imaginary
7435 zero is negative. */
7436
7437static tree
7438build_complex_cproj (tree type, bool neg)
7439{
7440 REAL_VALUE_TYPE rinf, rzero = dconst0;
7441
7442 real_inf (&rinf);
7443 rzero.sign = neg;
7444 return build_complex (type, build_real (TREE_TYPE (type), rinf),
7445 build_real (TREE_TYPE (type), rzero));
7446}
7447
7448/* Fold call to builtin cproj, cprojf or cprojl with argument ARG. TYPE is the
7449 return type. Return NULL_TREE if no simplification can be made. */
7450
7451static tree
7452fold_builtin_cproj (location_t loc, tree arg, tree type)
7453{
7454 if (!validate_arg (arg, COMPLEX_TYPE)
7455 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
7456 return NULL_TREE;
7457
7458 /* If there are no infinities, return arg. */
7459 if (! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (type))))
7460 return non_lvalue_loc (loc, arg);
7461
7462 /* Calculate the result when the argument is a constant. */
7463 if (TREE_CODE (arg) == COMPLEX_CST)
7464 {
7465 const REAL_VALUE_TYPE *real = TREE_REAL_CST_PTR (TREE_REALPART (arg));
7466 const REAL_VALUE_TYPE *imag = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
7467
7468 if (real_isinf (real) || real_isinf (imag))
7469 return build_complex_cproj (type, imag->sign);
7470 else
7471 return arg;
7472 }
b4c7e601 7473 else if (TREE_CODE (arg) == COMPLEX_EXPR)
7474 {
7475 tree real = TREE_OPERAND (arg, 0);
7476 tree imag = TREE_OPERAND (arg, 1);
7477
7478 STRIP_NOPS (real);
7479 STRIP_NOPS (imag);
7480
7481 /* If the real part is inf and the imag part is known to be
7482 nonnegative, return (inf + 0i). Remember side-effects are
7483 possible in the imag part. */
7484 if (TREE_CODE (real) == REAL_CST
7485 && real_isinf (TREE_REAL_CST_PTR (real))
7486 && tree_expr_nonnegative_p (imag))
7487 return omit_one_operand_loc (loc, type,
7488 build_complex_cproj (type, false),
7489 arg);
7490
7491 /* If the imag part is inf, return (inf+I*copysign(0,imag)).
7492 Remember side-effects are possible in the real part. */
7493 if (TREE_CODE (imag) == REAL_CST
7494 && real_isinf (TREE_REAL_CST_PTR (imag)))
7495 return
7496 omit_one_operand_loc (loc, type,
7497 build_complex_cproj (type, TREE_REAL_CST_PTR
7498 (imag)->sign), arg);
7499 }
c2373fdb 7500
7501 return NULL_TREE;
7502}
7503
c2f47e15 7504/* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG.
7505 Return NULL_TREE if no simplification can be made. */
e6e27594 7506
7507static tree
389dd41b 7508fold_builtin_sqrt (location_t loc, tree arg, tree type)
e6e27594 7509{
7510
7511 enum built_in_function fcode;
b4e8ab0c 7512 tree res;
c2f47e15 7513
7514 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7515 return NULL_TREE;
7516
b4e8ab0c 7517 /* Calculate the result when the argument is a constant. */
7518 if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
7519 return res;
48e1416a 7520
e6e27594 7521 /* Optimize sqrt(expN(x)) = expN(x*0.5). */
7522 fcode = builtin_mathfn_code (arg);
7523 if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
7524 {
c2f47e15 7525 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
389dd41b 7526 arg = fold_build2_loc (loc, MULT_EXPR, type,
c2f47e15 7527 CALL_EXPR_ARG (arg, 0),
49d00087 7528 build_real (type, dconsthalf));
389dd41b 7529 return build_call_expr_loc (loc, expfn, 1, arg);
e6e27594 7530 }
7531
7532 /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */
7533 if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
7534 {
7535 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7536
7537 if (powfn)
7538 {
c2f47e15 7539 tree arg0 = CALL_EXPR_ARG (arg, 0);
e6e27594 7540 tree tree_root;
7541 /* The inner root was either sqrt or cbrt. */
57510da6 7542 /* This was a conditional expression but it triggered a bug
18381619 7543 in Sun C 5.5. */
ce6cd837 7544 REAL_VALUE_TYPE dconstroot;
7545 if (BUILTIN_SQRT_P (fcode))
7546 dconstroot = dconsthalf;
7547 else
7548 dconstroot = dconst_third ();
e6e27594 7549
7550 /* Adjust for the outer root. */
7551 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7552 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7553 tree_root = build_real (type, dconstroot);
389dd41b 7554 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
e6e27594 7555 }
7556 }
7557
bc33117f 7558 /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
e6e27594 7559 if (flag_unsafe_math_optimizations
7560 && (fcode == BUILT_IN_POW
7561 || fcode == BUILT_IN_POWF
7562 || fcode == BUILT_IN_POWL))
7563 {
c2f47e15 7564 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
7565 tree arg0 = CALL_EXPR_ARG (arg, 0);
7566 tree arg1 = CALL_EXPR_ARG (arg, 1);
bc33117f 7567 tree narg1;
7568 if (!tree_expr_nonnegative_p (arg0))
7569 arg0 = build1 (ABS_EXPR, type, arg0);
389dd41b 7570 narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 7571 build_real (type, dconsthalf));
389dd41b 7572 return build_call_expr_loc (loc, powfn, 2, arg0, narg1);
e6e27594 7573 }
7574
7575 return NULL_TREE;
7576}
7577
c2f47e15 7578/* Fold a builtin function call to cbrt, cbrtf, or cbrtl with argument ARG.
7579 Return NULL_TREE if no simplification can be made. */
7580
e6e27594 7581static tree
389dd41b 7582fold_builtin_cbrt (location_t loc, tree arg, tree type)
e6e27594 7583{
e6e27594 7584 const enum built_in_function fcode = builtin_mathfn_code (arg);
29f4cd78 7585 tree res;
e6e27594 7586
c2f47e15 7587 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7588 return NULL_TREE;
7589
29f4cd78 7590 /* Calculate the result when the argument is a constant. */
7591 if ((res = do_mpfr_arg1 (arg, type, mpfr_cbrt, NULL, NULL, 0)))
7592 return res;
e6e27594 7593
cdfeb715 7594 if (flag_unsafe_math_optimizations)
e6e27594 7595 {
cdfeb715 7596 /* Optimize cbrt(expN(x)) -> expN(x/3). */
7597 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 7598 {
c2f47e15 7599 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7600 const REAL_VALUE_TYPE third_trunc =
7910b2fb 7601 real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 7602 arg = fold_build2_loc (loc, MULT_EXPR, type,
c2f47e15 7603 CALL_EXPR_ARG (arg, 0),
49d00087 7604 build_real (type, third_trunc));
389dd41b 7605 return build_call_expr_loc (loc, expfn, 1, arg);
cdfeb715 7606 }
e6e27594 7607
cdfeb715 7608 /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */
7609 if (BUILTIN_SQRT_P (fcode))
a0c938f0 7610 {
cdfeb715 7611 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
e6e27594 7612
cdfeb715 7613 if (powfn)
7614 {
c2f47e15 7615 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7616 tree tree_root;
7910b2fb 7617 REAL_VALUE_TYPE dconstroot = dconst_third ();
cdfeb715 7618
7619 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7620 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7621 tree_root = build_real (type, dconstroot);
389dd41b 7622 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
cdfeb715 7623 }
e6e27594 7624 }
7625
cdfeb715 7626 /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */
7627 if (BUILTIN_CBRT_P (fcode))
a0c938f0 7628 {
c2f47e15 7629 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7630 if (tree_expr_nonnegative_p (arg0))
7631 {
7632 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7633
7634 if (powfn)
a0c938f0 7635 {
cdfeb715 7636 tree tree_root;
7637 REAL_VALUE_TYPE dconstroot;
a0c938f0 7638
3fa759a9 7639 real_arithmetic (&dconstroot, MULT_EXPR,
7910b2fb 7640 dconst_third_ptr (), dconst_third_ptr ());
cdfeb715 7641 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7642 tree_root = build_real (type, dconstroot);
389dd41b 7643 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
cdfeb715 7644 }
7645 }
7646 }
a0c938f0 7647
cdfeb715 7648 /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */
48e1416a 7649 if (fcode == BUILT_IN_POW
c2f47e15 7650 || fcode == BUILT_IN_POWF
cdfeb715 7651 || fcode == BUILT_IN_POWL)
a0c938f0 7652 {
c2f47e15 7653 tree arg00 = CALL_EXPR_ARG (arg, 0);
7654 tree arg01 = CALL_EXPR_ARG (arg, 1);
cdfeb715 7655 if (tree_expr_nonnegative_p (arg00))
7656 {
c2f47e15 7657 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7658 const REAL_VALUE_TYPE dconstroot
7910b2fb 7659 = real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 7660 tree narg01 = fold_build2_loc (loc, MULT_EXPR, type, arg01,
49d00087 7661 build_real (type, dconstroot));
389dd41b 7662 return build_call_expr_loc (loc, powfn, 2, arg00, narg01);
cdfeb715 7663 }
7664 }
e6e27594 7665 }
7666 return NULL_TREE;
7667}
7668
c2f47e15 7669/* Fold function call to builtin cos, cosf, or cosl with argument ARG.
7670 TYPE is the type of the return value. Return NULL_TREE if no
7671 simplification can be made. */
7672
e6e27594 7673static tree
389dd41b 7674fold_builtin_cos (location_t loc,
7675 tree arg, tree type, tree fndecl)
e6e27594 7676{
e6ab33d8 7677 tree res, narg;
e6e27594 7678
c2f47e15 7679 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7680 return NULL_TREE;
7681
bffb7645 7682 /* Calculate the result when the argument is a constant. */
728bac60 7683 if ((res = do_mpfr_arg1 (arg, type, mpfr_cos, NULL, NULL, 0)))
bffb7645 7684 return res;
48e1416a 7685
e6e27594 7686 /* Optimize cos(-x) into cos (x). */
e6ab33d8 7687 if ((narg = fold_strip_sign_ops (arg)))
389dd41b 7688 return build_call_expr_loc (loc, fndecl, 1, narg);
e6e27594 7689
7690 return NULL_TREE;
7691}
7692
c2f47e15 7693/* Fold function call to builtin cosh, coshf, or coshl with argument ARG.
7694 Return NULL_TREE if no simplification can be made. */
7695
cacdc1af 7696static tree
389dd41b 7697fold_builtin_cosh (location_t loc, tree arg, tree type, tree fndecl)
cacdc1af 7698{
c2f47e15 7699 if (validate_arg (arg, REAL_TYPE))
cacdc1af 7700 {
cacdc1af 7701 tree res, narg;
7702
7703 /* Calculate the result when the argument is a constant. */
7704 if ((res = do_mpfr_arg1 (arg, type, mpfr_cosh, NULL, NULL, 0)))
7705 return res;
48e1416a 7706
cacdc1af 7707 /* Optimize cosh(-x) into cosh (x). */
7708 if ((narg = fold_strip_sign_ops (arg)))
389dd41b 7709 return build_call_expr_loc (loc, fndecl, 1, narg);
cacdc1af 7710 }
48e1416a 7711
cacdc1af 7712 return NULL_TREE;
7713}
7714
239d491a 7715/* Fold function call to builtin ccos (or ccosh if HYPER is TRUE) with
7716 argument ARG. TYPE is the type of the return value. Return
7717 NULL_TREE if no simplification can be made. */
7718
7719static tree
965d0f29 7720fold_builtin_ccos (location_t loc, tree arg, tree type, tree fndecl,
7721 bool hyper)
239d491a 7722{
7723 if (validate_arg (arg, COMPLEX_TYPE)
7724 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
7725 {
7726 tree tmp;
7727
239d491a 7728 /* Calculate the result when the argument is a constant. */
7729 if ((tmp = do_mpc_arg1 (arg, type, (hyper ? mpc_cosh : mpc_cos))))
7730 return tmp;
48e1416a 7731
239d491a 7732 /* Optimize fn(-x) into fn(x). */
7733 if ((tmp = fold_strip_sign_ops (arg)))
389dd41b 7734 return build_call_expr_loc (loc, fndecl, 1, tmp);
239d491a 7735 }
7736
7737 return NULL_TREE;
7738}
7739
c2f47e15 7740/* Fold function call to builtin tan, tanf, or tanl with argument ARG.
7741 Return NULL_TREE if no simplification can be made. */
7742
e6e27594 7743static tree
c2f47e15 7744fold_builtin_tan (tree arg, tree type)
e6e27594 7745{
7746 enum built_in_function fcode;
29f4cd78 7747 tree res;
e6e27594 7748
c2f47e15 7749 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7750 return NULL_TREE;
7751
bffb7645 7752 /* Calculate the result when the argument is a constant. */
728bac60 7753 if ((res = do_mpfr_arg1 (arg, type, mpfr_tan, NULL, NULL, 0)))
bffb7645 7754 return res;
48e1416a 7755
e6e27594 7756 /* Optimize tan(atan(x)) = x. */
7757 fcode = builtin_mathfn_code (arg);
7758 if (flag_unsafe_math_optimizations
7759 && (fcode == BUILT_IN_ATAN
7760 || fcode == BUILT_IN_ATANF
7761 || fcode == BUILT_IN_ATANL))
c2f47e15 7762 return CALL_EXPR_ARG (arg, 0);
e6e27594 7763
7764 return NULL_TREE;
7765}
7766
d735c391 7767/* Fold function call to builtin sincos, sincosf, or sincosl. Return
7768 NULL_TREE if no simplification can be made. */
7769
7770static tree
389dd41b 7771fold_builtin_sincos (location_t loc,
7772 tree arg0, tree arg1, tree arg2)
d735c391 7773{
c2f47e15 7774 tree type;
d735c391 7775 tree res, fn, call;
7776
c2f47e15 7777 if (!validate_arg (arg0, REAL_TYPE)
7778 || !validate_arg (arg1, POINTER_TYPE)
7779 || !validate_arg (arg2, POINTER_TYPE))
d735c391 7780 return NULL_TREE;
7781
d735c391 7782 type = TREE_TYPE (arg0);
d735c391 7783
7784 /* Calculate the result when the argument is a constant. */
7785 if ((res = do_mpfr_sincos (arg0, arg1, arg2)))
7786 return res;
7787
7788 /* Canonicalize sincos to cexpi. */
30f690e0 7789 if (!targetm.libc_has_function (function_c99_math_complex))
2a6b4c77 7790 return NULL_TREE;
d735c391 7791 fn = mathfn_built_in (type, BUILT_IN_CEXPI);
7792 if (!fn)
7793 return NULL_TREE;
7794
389dd41b 7795 call = build_call_expr_loc (loc, fn, 1, arg0);
d735c391 7796 call = builtin_save_expr (call);
7797
a75b1c71 7798 return build2 (COMPOUND_EXPR, void_type_node,
d735c391 7799 build2 (MODIFY_EXPR, void_type_node,
389dd41b 7800 build_fold_indirect_ref_loc (loc, arg1),
d735c391 7801 build1 (IMAGPART_EXPR, type, call)),
7802 build2 (MODIFY_EXPR, void_type_node,
389dd41b 7803 build_fold_indirect_ref_loc (loc, arg2),
d735c391 7804 build1 (REALPART_EXPR, type, call)));
7805}
7806
c5bb2c4b 7807/* Fold function call to builtin cexp, cexpf, or cexpl. Return
7808 NULL_TREE if no simplification can be made. */
7809
7810static tree
389dd41b 7811fold_builtin_cexp (location_t loc, tree arg0, tree type)
c5bb2c4b 7812{
c2f47e15 7813 tree rtype;
c5bb2c4b 7814 tree realp, imagp, ifn;
239d491a 7815 tree res;
c5bb2c4b 7816
239d491a 7817 if (!validate_arg (arg0, COMPLEX_TYPE)
b0ce8887 7818 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) != REAL_TYPE)
c5bb2c4b 7819 return NULL_TREE;
7820
239d491a 7821 /* Calculate the result when the argument is a constant. */
7822 if ((res = do_mpc_arg1 (arg0, type, mpc_exp)))
7823 return res;
48e1416a 7824
c5bb2c4b 7825 rtype = TREE_TYPE (TREE_TYPE (arg0));
7826
7827 /* In case we can figure out the real part of arg0 and it is constant zero
7828 fold to cexpi. */
30f690e0 7829 if (!targetm.libc_has_function (function_c99_math_complex))
2a6b4c77 7830 return NULL_TREE;
c5bb2c4b 7831 ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI);
7832 if (!ifn)
7833 return NULL_TREE;
7834
389dd41b 7835 if ((realp = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0))
c5bb2c4b 7836 && real_zerop (realp))
7837 {
389dd41b 7838 tree narg = fold_build1_loc (loc, IMAGPART_EXPR, rtype, arg0);
7839 return build_call_expr_loc (loc, ifn, 1, narg);
c5bb2c4b 7840 }
7841
7842 /* In case we can easily decompose real and imaginary parts split cexp
7843 to exp (r) * cexpi (i). */
7844 if (flag_unsafe_math_optimizations
7845 && realp)
7846 {
7847 tree rfn, rcall, icall;
7848
7849 rfn = mathfn_built_in (rtype, BUILT_IN_EXP);
7850 if (!rfn)
7851 return NULL_TREE;
7852
389dd41b 7853 imagp = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
c5bb2c4b 7854 if (!imagp)
7855 return NULL_TREE;
7856
389dd41b 7857 icall = build_call_expr_loc (loc, ifn, 1, imagp);
c5bb2c4b 7858 icall = builtin_save_expr (icall);
389dd41b 7859 rcall = build_call_expr_loc (loc, rfn, 1, realp);
c5bb2c4b 7860 rcall = builtin_save_expr (rcall);
389dd41b 7861 return fold_build2_loc (loc, COMPLEX_EXPR, type,
7862 fold_build2_loc (loc, MULT_EXPR, rtype,
71bf42bb 7863 rcall,
389dd41b 7864 fold_build1_loc (loc, REALPART_EXPR,
7865 rtype, icall)),
7866 fold_build2_loc (loc, MULT_EXPR, rtype,
71bf42bb 7867 rcall,
389dd41b 7868 fold_build1_loc (loc, IMAGPART_EXPR,
7869 rtype, icall)));
c5bb2c4b 7870 }
7871
7872 return NULL_TREE;
7873}
7874
c2f47e15 7875/* Fold function call to builtin trunc, truncf or truncl with argument ARG.
7876 Return NULL_TREE if no simplification can be made. */
277f8dd2 7877
7878static tree
389dd41b 7879fold_builtin_trunc (location_t loc, tree fndecl, tree arg)
277f8dd2 7880{
c2f47e15 7881 if (!validate_arg (arg, REAL_TYPE))
7882 return NULL_TREE;
277f8dd2 7883
7884 /* Optimize trunc of constant value. */
f96bd2bf 7885 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7886 {
7887 REAL_VALUE_TYPE r, x;
2426241c 7888 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7889
7890 x = TREE_REAL_CST (arg);
7891 real_trunc (&r, TYPE_MODE (type), &x);
7892 return build_real (type, r);
7893 }
7894
389dd41b 7895 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7896}
7897
c2f47e15 7898/* Fold function call to builtin floor, floorf or floorl with argument ARG.
7899 Return NULL_TREE if no simplification can be made. */
277f8dd2 7900
7901static tree
389dd41b 7902fold_builtin_floor (location_t loc, tree fndecl, tree arg)
277f8dd2 7903{
c2f47e15 7904 if (!validate_arg (arg, REAL_TYPE))
7905 return NULL_TREE;
277f8dd2 7906
7907 /* Optimize floor of constant value. */
f96bd2bf 7908 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7909 {
7910 REAL_VALUE_TYPE x;
7911
7912 x = TREE_REAL_CST (arg);
7913 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7914 {
2426241c 7915 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7916 REAL_VALUE_TYPE r;
7917
7918 real_floor (&r, TYPE_MODE (type), &x);
7919 return build_real (type, r);
7920 }
7921 }
7922
acc2b92e 7923 /* Fold floor (x) where x is nonnegative to trunc (x). */
7924 if (tree_expr_nonnegative_p (arg))
30fe8286 7925 {
7926 tree truncfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_TRUNC);
7927 if (truncfn)
389dd41b 7928 return build_call_expr_loc (loc, truncfn, 1, arg);
30fe8286 7929 }
acc2b92e 7930
389dd41b 7931 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7932}
7933
c2f47e15 7934/* Fold function call to builtin ceil, ceilf or ceill with argument ARG.
7935 Return NULL_TREE if no simplification can be made. */
277f8dd2 7936
7937static tree
389dd41b 7938fold_builtin_ceil (location_t loc, tree fndecl, tree arg)
277f8dd2 7939{
c2f47e15 7940 if (!validate_arg (arg, REAL_TYPE))
7941 return NULL_TREE;
277f8dd2 7942
7943 /* Optimize ceil of constant value. */
f96bd2bf 7944 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7945 {
7946 REAL_VALUE_TYPE x;
7947
7948 x = TREE_REAL_CST (arg);
7949 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7950 {
2426241c 7951 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7952 REAL_VALUE_TYPE r;
7953
7954 real_ceil (&r, TYPE_MODE (type), &x);
7955 return build_real (type, r);
7956 }
7957 }
7958
389dd41b 7959 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7960}
7961
c2f47e15 7962/* Fold function call to builtin round, roundf or roundl with argument ARG.
7963 Return NULL_TREE if no simplification can be made. */
89ab3887 7964
7965static tree
389dd41b 7966fold_builtin_round (location_t loc, tree fndecl, tree arg)
89ab3887 7967{
c2f47e15 7968 if (!validate_arg (arg, REAL_TYPE))
7969 return NULL_TREE;
89ab3887 7970
34f17811 7971 /* Optimize round of constant value. */
f96bd2bf 7972 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
89ab3887 7973 {
7974 REAL_VALUE_TYPE x;
7975
7976 x = TREE_REAL_CST (arg);
7977 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7978 {
2426241c 7979 tree type = TREE_TYPE (TREE_TYPE (fndecl));
89ab3887 7980 REAL_VALUE_TYPE r;
7981
7982 real_round (&r, TYPE_MODE (type), &x);
7983 return build_real (type, r);
7984 }
7985 }
7986
389dd41b 7987 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
89ab3887 7988}
7989
34f17811 7990/* Fold function call to builtin lround, lroundf or lroundl (or the
c2f47e15 7991 corresponding long long versions) and other rounding functions. ARG
7992 is the argument to the call. Return NULL_TREE if no simplification
7993 can be made. */
34f17811 7994
7995static tree
389dd41b 7996fold_builtin_int_roundingfn (location_t loc, tree fndecl, tree arg)
34f17811 7997{
c2f47e15 7998 if (!validate_arg (arg, REAL_TYPE))
7999 return NULL_TREE;
34f17811 8000
8001 /* Optimize lround of constant value. */
f96bd2bf 8002 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
34f17811 8003 {
8004 const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
8005
776a7bab 8006 if (real_isfinite (&x))
34f17811 8007 {
2426241c 8008 tree itype = TREE_TYPE (TREE_TYPE (fndecl));
ca9b061d 8009 tree ftype = TREE_TYPE (arg);
34f17811 8010 REAL_VALUE_TYPE r;
e913b5cd 8011 bool fail = false;
34f17811 8012
ad52b9b7 8013 switch (DECL_FUNCTION_CODE (fndecl))
8014 {
80ff6494 8015 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 8016 CASE_FLT_FN (BUILT_IN_LFLOOR):
8017 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 8018 real_floor (&r, TYPE_MODE (ftype), &x);
8019 break;
8020
80ff6494 8021 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 8022 CASE_FLT_FN (BUILT_IN_LCEIL):
8023 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 8024 real_ceil (&r, TYPE_MODE (ftype), &x);
8025 break;
8026
80ff6494 8027 CASE_FLT_FN (BUILT_IN_IROUND):
4f35b1fc 8028 CASE_FLT_FN (BUILT_IN_LROUND):
8029 CASE_FLT_FN (BUILT_IN_LLROUND):
ad52b9b7 8030 real_round (&r, TYPE_MODE (ftype), &x);
8031 break;
8032
8033 default:
8034 gcc_unreachable ();
8035 }
8036
ab2c1de8 8037 wide_int val = real_to_integer (&r, &fail, TYPE_PRECISION (itype));
e913b5cd 8038 if (!fail)
8039 return wide_int_to_tree (itype, val);
34f17811 8040 }
8041 }
8042
acc2b92e 8043 switch (DECL_FUNCTION_CODE (fndecl))
8044 {
8045 CASE_FLT_FN (BUILT_IN_LFLOOR):
8046 CASE_FLT_FN (BUILT_IN_LLFLOOR):
8047 /* Fold lfloor (x) where x is nonnegative to FIX_TRUNC (x). */
8048 if (tree_expr_nonnegative_p (arg))
389dd41b 8049 return fold_build1_loc (loc, FIX_TRUNC_EXPR,
8050 TREE_TYPE (TREE_TYPE (fndecl)), arg);
acc2b92e 8051 break;
8052 default:;
8053 }
8054
389dd41b 8055 return fold_fixed_mathfn (loc, fndecl, arg);
34f17811 8056}
8057
70fb4c07 8058/* Fold function call to builtin ffs, clz, ctz, popcount and parity
c2f47e15 8059 and their long and long long variants (i.e. ffsl and ffsll). ARG is
8060 the argument to the call. Return NULL_TREE if no simplification can
8061 be made. */
70fb4c07 8062
8063static tree
c2f47e15 8064fold_builtin_bitop (tree fndecl, tree arg)
70fb4c07 8065{
c2f47e15 8066 if (!validate_arg (arg, INTEGER_TYPE))
70fb4c07 8067 return NULL_TREE;
8068
8069 /* Optimize for constant argument. */
f96bd2bf 8070 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
70fb4c07 8071 {
796b6678 8072 int result;
70fb4c07 8073
8074 switch (DECL_FUNCTION_CODE (fndecl))
8075 {
4f35b1fc 8076 CASE_INT_FN (BUILT_IN_FFS):
ab2c1de8 8077 result = wi::ffs (arg);
70fb4c07 8078 break;
8079
4f35b1fc 8080 CASE_INT_FN (BUILT_IN_CLZ):
ab2c1de8 8081 result = wi::clz (arg);
70fb4c07 8082 break;
8083
4f35b1fc 8084 CASE_INT_FN (BUILT_IN_CTZ):
ab2c1de8 8085 result = wi::ctz (arg);
70fb4c07 8086 break;
8087
6aaa1f9e 8088 CASE_INT_FN (BUILT_IN_CLRSB):
ab2c1de8 8089 result = wi::clrsb (arg);
6aaa1f9e 8090 break;
8091
4f35b1fc 8092 CASE_INT_FN (BUILT_IN_POPCOUNT):
ab2c1de8 8093 result = wi::popcount (arg);
70fb4c07 8094 break;
8095
4f35b1fc 8096 CASE_INT_FN (BUILT_IN_PARITY):
ab2c1de8 8097 result = wi::parity (arg);
70fb4c07 8098 break;
8099
8100 default:
64db345d 8101 gcc_unreachable ();
70fb4c07 8102 }
8103
796b6678 8104 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
70fb4c07 8105 }
8106
8107 return NULL_TREE;
8108}
8109
74bdbe96 8110/* Fold function call to builtin_bswap and the short, long and long long
42791117 8111 variants. Return NULL_TREE if no simplification can be made. */
8112static tree
c2f47e15 8113fold_builtin_bswap (tree fndecl, tree arg)
42791117 8114{
c2f47e15 8115 if (! validate_arg (arg, INTEGER_TYPE))
8116 return NULL_TREE;
42791117 8117
8118 /* Optimize constant value. */
f96bd2bf 8119 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
42791117 8120 {
74bdbe96 8121 tree type = TREE_TYPE (TREE_TYPE (fndecl));
42791117 8122
42791117 8123 switch (DECL_FUNCTION_CODE (fndecl))
8124 {
74bdbe96 8125 case BUILT_IN_BSWAP16:
42791117 8126 case BUILT_IN_BSWAP32:
8127 case BUILT_IN_BSWAP64:
8128 {
e913b5cd 8129 signop sgn = TYPE_SIGN (type);
ddb1be65 8130 tree result =
796b6678 8131 wide_int_to_tree (type,
8132 wide_int::from (arg, TYPE_PRECISION (type),
8133 sgn).bswap ());
e913b5cd 8134 return result;
42791117 8135 }
42791117 8136 default:
8137 gcc_unreachable ();
8138 }
42791117 8139 }
8140
8141 return NULL_TREE;
8142}
c2f47e15 8143
8918c507 8144/* A subroutine of fold_builtin to fold the various logarithmic
29f4cd78 8145 functions. Return NULL_TREE if no simplification can me made.
8146 FUNC is the corresponding MPFR logarithm function. */
8918c507 8147
8148static tree
389dd41b 8149fold_builtin_logarithm (location_t loc, tree fndecl, tree arg,
29f4cd78 8150 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8151{
c2f47e15 8152 if (validate_arg (arg, REAL_TYPE))
8918c507 8153 {
8918c507 8154 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8155 tree res;
8918c507 8156 const enum built_in_function fcode = builtin_mathfn_code (arg);
0862b7e9 8157
29f4cd78 8158 /* Calculate the result when the argument is a constant. */
8159 if ((res = do_mpfr_arg1 (arg, type, func, &dconst0, NULL, false)))
8160 return res;
8161
8918c507 8162 /* Special case, optimize logN(expN(x)) = x. */
8163 if (flag_unsafe_math_optimizations
29f4cd78 8164 && ((func == mpfr_log
8918c507 8165 && (fcode == BUILT_IN_EXP
8166 || fcode == BUILT_IN_EXPF
8167 || fcode == BUILT_IN_EXPL))
29f4cd78 8168 || (func == mpfr_log2
8918c507 8169 && (fcode == BUILT_IN_EXP2
8170 || fcode == BUILT_IN_EXP2F
8171 || fcode == BUILT_IN_EXP2L))
29f4cd78 8172 || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode)))))
389dd41b 8173 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
8918c507 8174
ca273d4a 8175 /* Optimize logN(func()) for various exponential functions. We
a0c938f0 8176 want to determine the value "x" and the power "exponent" in
8177 order to transform logN(x**exponent) into exponent*logN(x). */
8918c507 8178 if (flag_unsafe_math_optimizations)
a0c938f0 8179 {
8918c507 8180 tree exponent = 0, x = 0;
0862b7e9 8181
8918c507 8182 switch (fcode)
8183 {
4f35b1fc 8184 CASE_FLT_FN (BUILT_IN_EXP):
8918c507 8185 /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
48e1416a 8186 x = build_real (type, real_value_truncate (TYPE_MODE (type),
7910b2fb 8187 dconst_e ()));
c2f47e15 8188 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8189 break;
4f35b1fc 8190 CASE_FLT_FN (BUILT_IN_EXP2):
8918c507 8191 /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */
8192 x = build_real (type, dconst2);
c2f47e15 8193 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8194 break;
4f35b1fc 8195 CASE_FLT_FN (BUILT_IN_EXP10):
8196 CASE_FLT_FN (BUILT_IN_POW10):
8918c507 8197 /* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */
3fa759a9 8198 {
8199 REAL_VALUE_TYPE dconst10;
e913b5cd 8200 real_from_integer (&dconst10, VOIDmode, 10, SIGNED);
3fa759a9 8201 x = build_real (type, dconst10);
8202 }
c2f47e15 8203 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8204 break;
4f35b1fc 8205 CASE_FLT_FN (BUILT_IN_SQRT):
8918c507 8206 /* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */
c2f47e15 8207 x = CALL_EXPR_ARG (arg, 0);
8918c507 8208 exponent = build_real (type, dconsthalf);
8209 break;
4f35b1fc 8210 CASE_FLT_FN (BUILT_IN_CBRT):
8918c507 8211 /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */
c2f47e15 8212 x = CALL_EXPR_ARG (arg, 0);
8918c507 8213 exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
7910b2fb 8214 dconst_third ()));
8918c507 8215 break;
4f35b1fc 8216 CASE_FLT_FN (BUILT_IN_POW):
8918c507 8217 /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x). */
c2f47e15 8218 x = CALL_EXPR_ARG (arg, 0);
8219 exponent = CALL_EXPR_ARG (arg, 1);
8918c507 8220 break;
8221 default:
8222 break;
8223 }
8224
8225 /* Now perform the optimization. */
8226 if (x && exponent)
8227 {
389dd41b 8228 tree logfn = build_call_expr_loc (loc, fndecl, 1, x);
8229 return fold_build2_loc (loc, MULT_EXPR, type, exponent, logfn);
8918c507 8230 }
8231 }
8232 }
8233
c2f47e15 8234 return NULL_TREE;
8918c507 8235}
0862b7e9 8236
f0c477f2 8237/* Fold a builtin function call to hypot, hypotf, or hypotl. Return
8238 NULL_TREE if no simplification can be made. */
8239
8240static tree
389dd41b 8241fold_builtin_hypot (location_t loc, tree fndecl,
8242 tree arg0, tree arg1, tree type)
f0c477f2 8243{
e6ab33d8 8244 tree res, narg0, narg1;
f0c477f2 8245
c2f47e15 8246 if (!validate_arg (arg0, REAL_TYPE)
8247 || !validate_arg (arg1, REAL_TYPE))
f0c477f2 8248 return NULL_TREE;
8249
8250 /* Calculate the result when the argument is a constant. */
8251 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot)))
8252 return res;
48e1416a 8253
6c95f21c 8254 /* If either argument to hypot has a negate or abs, strip that off.
8255 E.g. hypot(-x,fabs(y)) -> hypot(x,y). */
e6ab33d8 8256 narg0 = fold_strip_sign_ops (arg0);
8257 narg1 = fold_strip_sign_ops (arg1);
8258 if (narg0 || narg1)
8259 {
48e1416a 8260 return build_call_expr_loc (loc, fndecl, 2, narg0 ? narg0 : arg0,
c2f47e15 8261 narg1 ? narg1 : arg1);
6c95f21c 8262 }
48e1416a 8263
f0c477f2 8264 /* If either argument is zero, hypot is fabs of the other. */
8265 if (real_zerop (arg0))
389dd41b 8266 return fold_build1_loc (loc, ABS_EXPR, type, arg1);
f0c477f2 8267 else if (real_zerop (arg1))
389dd41b 8268 return fold_build1_loc (loc, ABS_EXPR, type, arg0);
48e1416a 8269
6c95f21c 8270 /* hypot(x,x) -> fabs(x)*sqrt(2). */
8271 if (flag_unsafe_math_optimizations
8272 && operand_equal_p (arg0, arg1, OEP_PURE_SAME))
f0c477f2 8273 {
2e7ca27b 8274 const REAL_VALUE_TYPE sqrt2_trunc
7910b2fb 8275 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
389dd41b 8276 return fold_build2_loc (loc, MULT_EXPR, type,
8277 fold_build1_loc (loc, ABS_EXPR, type, arg0),
2e7ca27b 8278 build_real (type, sqrt2_trunc));
f0c477f2 8279 }
8280
f0c477f2 8281 return NULL_TREE;
8282}
8283
8284
e6e27594 8285/* Fold a builtin function call to pow, powf, or powl. Return
8286 NULL_TREE if no simplification can be made. */
8287static tree
389dd41b 8288fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
e6e27594 8289{
f0c477f2 8290 tree res;
e6e27594 8291
c2f47e15 8292 if (!validate_arg (arg0, REAL_TYPE)
8293 || !validate_arg (arg1, REAL_TYPE))
e6e27594 8294 return NULL_TREE;
8295
f0c477f2 8296 /* Calculate the result when the argument is a constant. */
8297 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_pow)))
8298 return res;
8299
e6e27594 8300 /* Optimize pow(1.0,y) = 1.0. */
8301 if (real_onep (arg0))
389dd41b 8302 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
e6e27594 8303
8304 if (TREE_CODE (arg1) == REAL_CST
f96bd2bf 8305 && !TREE_OVERFLOW (arg1))
e6e27594 8306 {
198d9bbe 8307 REAL_VALUE_TYPE cint;
e6e27594 8308 REAL_VALUE_TYPE c;
198d9bbe 8309 HOST_WIDE_INT n;
8310
e6e27594 8311 c = TREE_REAL_CST (arg1);
8312
8313 /* Optimize pow(x,0.0) = 1.0. */
8314 if (REAL_VALUES_EQUAL (c, dconst0))
389dd41b 8315 return omit_one_operand_loc (loc, type, build_real (type, dconst1),
e6e27594 8316 arg0);
8317
8318 /* Optimize pow(x,1.0) = x. */
8319 if (REAL_VALUES_EQUAL (c, dconst1))
8320 return arg0;
8321
8322 /* Optimize pow(x,-1.0) = 1.0/x. */
8323 if (REAL_VALUES_EQUAL (c, dconstm1))
389dd41b 8324 return fold_build2_loc (loc, RDIV_EXPR, type,
49d00087 8325 build_real (type, dconst1), arg0);
e6e27594 8326
8327 /* Optimize pow(x,0.5) = sqrt(x). */
8328 if (flag_unsafe_math_optimizations
8329 && REAL_VALUES_EQUAL (c, dconsthalf))
8330 {
8331 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
8332
8333 if (sqrtfn != NULL_TREE)
389dd41b 8334 return build_call_expr_loc (loc, sqrtfn, 1, arg0);
e6e27594 8335 }
8336
feb5b3eb 8337 /* Optimize pow(x,1.0/3.0) = cbrt(x). */
8338 if (flag_unsafe_math_optimizations)
8339 {
8340 const REAL_VALUE_TYPE dconstroot
7910b2fb 8341 = real_value_truncate (TYPE_MODE (type), dconst_third ());
feb5b3eb 8342
8343 if (REAL_VALUES_EQUAL (c, dconstroot))
8344 {
8345 tree cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT);
8346 if (cbrtfn != NULL_TREE)
389dd41b 8347 return build_call_expr_loc (loc, cbrtfn, 1, arg0);
feb5b3eb 8348 }
8349 }
8350
198d9bbe 8351 /* Check for an integer exponent. */
8352 n = real_to_integer (&c);
e913b5cd 8353 real_from_integer (&cint, VOIDmode, n, SIGNED);
198d9bbe 8354 if (real_identical (&c, &cint))
e6e27594 8355 {
a2b30b48 8356 /* Attempt to evaluate pow at compile-time, unless this should
8357 raise an exception. */
198d9bbe 8358 if (TREE_CODE (arg0) == REAL_CST
a2b30b48 8359 && !TREE_OVERFLOW (arg0)
8360 && (n > 0
8361 || (!flag_trapping_math && !flag_errno_math)
8362 || !REAL_VALUES_EQUAL (TREE_REAL_CST (arg0), dconst0)))
e6e27594 8363 {
8364 REAL_VALUE_TYPE x;
8365 bool inexact;
8366
8367 x = TREE_REAL_CST (arg0);
8368 inexact = real_powi (&x, TYPE_MODE (type), &x, n);
8369 if (flag_unsafe_math_optimizations || !inexact)
8370 return build_real (type, x);
8371 }
198d9bbe 8372
8373 /* Strip sign ops from even integer powers. */
8374 if ((n & 1) == 0 && flag_unsafe_math_optimizations)
8375 {
8376 tree narg0 = fold_strip_sign_ops (arg0);
8377 if (narg0)
389dd41b 8378 return build_call_expr_loc (loc, fndecl, 2, narg0, arg1);
198d9bbe 8379 }
e6e27594 8380 }
8381 }
8382
cdfeb715 8383 if (flag_unsafe_math_optimizations)
e6e27594 8384 {
cdfeb715 8385 const enum built_in_function fcode = builtin_mathfn_code (arg0);
e6e27594 8386
cdfeb715 8387 /* Optimize pow(expN(x),y) = expN(x*y). */
8388 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 8389 {
c2f47e15 8390 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
8391 tree arg = CALL_EXPR_ARG (arg0, 0);
389dd41b 8392 arg = fold_build2_loc (loc, MULT_EXPR, type, arg, arg1);
8393 return build_call_expr_loc (loc, expfn, 1, arg);
cdfeb715 8394 }
e6e27594 8395
cdfeb715 8396 /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
8397 if (BUILTIN_SQRT_P (fcode))
a0c938f0 8398 {
c2f47e15 8399 tree narg0 = CALL_EXPR_ARG (arg0, 0);
389dd41b 8400 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 8401 build_real (type, dconsthalf));
389dd41b 8402 return build_call_expr_loc (loc, fndecl, 2, narg0, narg1);
cdfeb715 8403 }
8404
8405 /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */
8406 if (BUILTIN_CBRT_P (fcode))
a0c938f0 8407 {
c2f47e15 8408 tree arg = CALL_EXPR_ARG (arg0, 0);
cdfeb715 8409 if (tree_expr_nonnegative_p (arg))
8410 {
8411 const REAL_VALUE_TYPE dconstroot
7910b2fb 8412 = real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 8413 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 8414 build_real (type, dconstroot));
389dd41b 8415 return build_call_expr_loc (loc, fndecl, 2, arg, narg1);
cdfeb715 8416 }
8417 }
a0c938f0 8418
49e436b5 8419 /* Optimize pow(pow(x,y),z) = pow(x,y*z) iff x is nonnegative. */
c2f47e15 8420 if (fcode == BUILT_IN_POW
8421 || fcode == BUILT_IN_POWF
8422 || fcode == BUILT_IN_POWL)
a0c938f0 8423 {
c2f47e15 8424 tree arg00 = CALL_EXPR_ARG (arg0, 0);
49e436b5 8425 if (tree_expr_nonnegative_p (arg00))
8426 {
8427 tree arg01 = CALL_EXPR_ARG (arg0, 1);
8428 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg01, arg1);
8429 return build_call_expr_loc (loc, fndecl, 2, arg00, narg1);
8430 }
cdfeb715 8431 }
e6e27594 8432 }
cdfeb715 8433
e6e27594 8434 return NULL_TREE;
8435}
8436
c2f47e15 8437/* Fold a builtin function call to powi, powif, or powil with argument ARG.
8438 Return NULL_TREE if no simplification can be made. */
b4d0c20c 8439static tree
389dd41b 8440fold_builtin_powi (location_t loc, tree fndecl ATTRIBUTE_UNUSED,
c2f47e15 8441 tree arg0, tree arg1, tree type)
b4d0c20c 8442{
c2f47e15 8443 if (!validate_arg (arg0, REAL_TYPE)
8444 || !validate_arg (arg1, INTEGER_TYPE))
b4d0c20c 8445 return NULL_TREE;
8446
8447 /* Optimize pow(1.0,y) = 1.0. */
8448 if (real_onep (arg0))
389dd41b 8449 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
b4d0c20c 8450
e913b5cd 8451 if (tree_fits_shwi_p (arg1))
b4d0c20c 8452 {
e913b5cd 8453 HOST_WIDE_INT c = tree_to_shwi (arg1);
b4d0c20c 8454
8455 /* Evaluate powi at compile-time. */
8456 if (TREE_CODE (arg0) == REAL_CST
f96bd2bf 8457 && !TREE_OVERFLOW (arg0))
b4d0c20c 8458 {
8459 REAL_VALUE_TYPE x;
8460 x = TREE_REAL_CST (arg0);
8461 real_powi (&x, TYPE_MODE (type), &x, c);
8462 return build_real (type, x);
8463 }
8464
8465 /* Optimize pow(x,0) = 1.0. */
8466 if (c == 0)
389dd41b 8467 return omit_one_operand_loc (loc, type, build_real (type, dconst1),
b4d0c20c 8468 arg0);
8469
8470 /* Optimize pow(x,1) = x. */
8471 if (c == 1)
8472 return arg0;
8473
8474 /* Optimize pow(x,-1) = 1.0/x. */
8475 if (c == -1)
389dd41b 8476 return fold_build2_loc (loc, RDIV_EXPR, type,
49d00087 8477 build_real (type, dconst1), arg0);
b4d0c20c 8478 }
8479
8480 return NULL_TREE;
8481}
8482
8918c507 8483/* A subroutine of fold_builtin to fold the various exponent
c2f47e15 8484 functions. Return NULL_TREE if no simplification can be made.
debf9994 8485 FUNC is the corresponding MPFR exponent function. */
8918c507 8486
8487static tree
389dd41b 8488fold_builtin_exponent (location_t loc, tree fndecl, tree arg,
debf9994 8489 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8490{
c2f47e15 8491 if (validate_arg (arg, REAL_TYPE))
8918c507 8492 {
8918c507 8493 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8494 tree res;
48e1416a 8495
debf9994 8496 /* Calculate the result when the argument is a constant. */
728bac60 8497 if ((res = do_mpfr_arg1 (arg, type, func, NULL, NULL, 0)))
debf9994 8498 return res;
8918c507 8499
8500 /* Optimize expN(logN(x)) = x. */
8501 if (flag_unsafe_math_optimizations)
a0c938f0 8502 {
8918c507 8503 const enum built_in_function fcode = builtin_mathfn_code (arg);
8504
debf9994 8505 if ((func == mpfr_exp
8918c507 8506 && (fcode == BUILT_IN_LOG
8507 || fcode == BUILT_IN_LOGF
8508 || fcode == BUILT_IN_LOGL))
debf9994 8509 || (func == mpfr_exp2
8918c507 8510 && (fcode == BUILT_IN_LOG2
8511 || fcode == BUILT_IN_LOG2F
8512 || fcode == BUILT_IN_LOG2L))
debf9994 8513 || (func == mpfr_exp10
8918c507 8514 && (fcode == BUILT_IN_LOG10
8515 || fcode == BUILT_IN_LOG10F
8516 || fcode == BUILT_IN_LOG10L)))
389dd41b 8517 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
8918c507 8518 }
8519 }
8520
c2f47e15 8521 return NULL_TREE;
8918c507 8522}
8523
e973ffcc 8524/* Return true if VAR is a VAR_DECL or a component thereof. */
8525
8526static bool
8527var_decl_component_p (tree var)
8528{
8529 tree inner = var;
8530 while (handled_component_p (inner))
8531 inner = TREE_OPERAND (inner, 0);
8532 return SSA_VAR_P (inner);
8533}
8534
4f46f2b9 8535/* Fold function call to builtin memset. Return
9c8a1629 8536 NULL_TREE if no simplification can be made. */
8537
8538static tree
389dd41b 8539fold_builtin_memset (location_t loc, tree dest, tree c, tree len,
8540 tree type, bool ignore)
9c8a1629 8541{
45bb3afb 8542 tree var, ret, etype;
4f46f2b9 8543 unsigned HOST_WIDE_INT length, cval;
9c8a1629 8544
c2f47e15 8545 if (! validate_arg (dest, POINTER_TYPE)
8546 || ! validate_arg (c, INTEGER_TYPE)
8547 || ! validate_arg (len, INTEGER_TYPE))
8548 return NULL_TREE;
9c8a1629 8549
e913b5cd 8550 if (! tree_fits_uhwi_p (len))
c2f47e15 8551 return NULL_TREE;
4f46f2b9 8552
9c8a1629 8553 /* If the LEN parameter is zero, return DEST. */
8554 if (integer_zerop (len))
389dd41b 8555 return omit_one_operand_loc (loc, type, dest, c);
9c8a1629 8556
d5d2f74a 8557 if (TREE_CODE (c) != INTEGER_CST || TREE_SIDE_EFFECTS (dest))
c2f47e15 8558 return NULL_TREE;
9c8a1629 8559
4f46f2b9 8560 var = dest;
8561 STRIP_NOPS (var);
8562 if (TREE_CODE (var) != ADDR_EXPR)
c2f47e15 8563 return NULL_TREE;
4f46f2b9 8564
8565 var = TREE_OPERAND (var, 0);
8566 if (TREE_THIS_VOLATILE (var))
c2f47e15 8567 return NULL_TREE;
4f46f2b9 8568
45bb3afb 8569 etype = TREE_TYPE (var);
8570 if (TREE_CODE (etype) == ARRAY_TYPE)
8571 etype = TREE_TYPE (etype);
8572
8573 if (!INTEGRAL_TYPE_P (etype)
8574 && !POINTER_TYPE_P (etype))
c2f47e15 8575 return NULL_TREE;
4f46f2b9 8576
e973ffcc 8577 if (! var_decl_component_p (var))
c2f47e15 8578 return NULL_TREE;
e973ffcc 8579
e913b5cd 8580 length = tree_to_uhwi (len);
45bb3afb 8581 if (GET_MODE_SIZE (TYPE_MODE (etype)) != length
957d0361 8582 || get_pointer_alignment (dest) / BITS_PER_UNIT < length)
c2f47e15 8583 return NULL_TREE;
4f46f2b9 8584
8585 if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT)
c2f47e15 8586 return NULL_TREE;
4f46f2b9 8587
8588 if (integer_zerop (c))
8589 cval = 0;
8590 else
8591 {
8592 if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64)
c2f47e15 8593 return NULL_TREE;
4f46f2b9 8594
f9ae6f95 8595 cval = TREE_INT_CST_LOW (c);
4f46f2b9 8596 cval &= 0xff;
8597 cval |= cval << 8;
8598 cval |= cval << 16;
8599 cval |= (cval << 31) << 1;
8600 }
8601
45bb3afb 8602 ret = build_int_cst_type (etype, cval);
389dd41b 8603 var = build_fold_indirect_ref_loc (loc,
8604 fold_convert_loc (loc,
8605 build_pointer_type (etype),
8606 dest));
45bb3afb 8607 ret = build2 (MODIFY_EXPR, etype, var, ret);
4f46f2b9 8608 if (ignore)
8609 return ret;
8610
389dd41b 8611 return omit_one_operand_loc (loc, type, dest, ret);
9c8a1629 8612}
8613
4f46f2b9 8614/* Fold function call to builtin memset. Return
9c8a1629 8615 NULL_TREE if no simplification can be made. */
8616
8617static tree
389dd41b 8618fold_builtin_bzero (location_t loc, tree dest, tree size, bool ignore)
9c8a1629 8619{
c2f47e15 8620 if (! validate_arg (dest, POINTER_TYPE)
8621 || ! validate_arg (size, INTEGER_TYPE))
8622 return NULL_TREE;
9c8a1629 8623
4f46f2b9 8624 if (!ignore)
c2f47e15 8625 return NULL_TREE;
a0c938f0 8626
4f46f2b9 8627 /* New argument list transforming bzero(ptr x, int y) to
8628 memset(ptr x, int 0, size_t y). This is done this way
8629 so that if it isn't expanded inline, we fallback to
8630 calling bzero instead of memset. */
8631
389dd41b 8632 return fold_builtin_memset (loc, dest, integer_zero_node,
a0553bff 8633 fold_convert_loc (loc, size_type_node, size),
c2f47e15 8634 void_type_node, ignore);
9c8a1629 8635}
8636
4f46f2b9 8637/* Fold function call to builtin mem{{,p}cpy,move}. Return
8638 NULL_TREE if no simplification can be made.
8639 If ENDP is 0, return DEST (like memcpy).
8640 If ENDP is 1, return DEST+LEN (like mempcpy).
8641 If ENDP is 2, return DEST+LEN-1 (like stpcpy).
8642 If ENDP is 3, return DEST, additionally *SRC and *DEST may overlap
8643 (memmove). */
9c8a1629 8644
8645static tree
389dd41b 8646fold_builtin_memory_op (location_t loc, tree dest, tree src,
8647 tree len, tree type, bool ignore, int endp)
9c8a1629 8648{
c2f47e15 8649 tree destvar, srcvar, expr;
9c8a1629 8650
c2f47e15 8651 if (! validate_arg (dest, POINTER_TYPE)
8652 || ! validate_arg (src, POINTER_TYPE)
8653 || ! validate_arg (len, INTEGER_TYPE))
8654 return NULL_TREE;
9c8a1629 8655
8656 /* If the LEN parameter is zero, return DEST. */
8657 if (integer_zerop (len))
389dd41b 8658 return omit_one_operand_loc (loc, type, dest, src);
9c8a1629 8659
4f46f2b9 8660 /* If SRC and DEST are the same (and not volatile), return
8661 DEST{,+LEN,+LEN-1}. */
9c8a1629 8662 if (operand_equal_p (src, dest, 0))
4f46f2b9 8663 expr = len;
8664 else
8665 {
5a84fdd6 8666 tree srctype, desttype;
153c3b50 8667 unsigned int src_align, dest_align;
182cf5a9 8668 tree off0;
5383fb56 8669
3b1757a2 8670 if (endp == 3)
8671 {
957d0361 8672 src_align = get_pointer_alignment (src);
8673 dest_align = get_pointer_alignment (dest);
5a84fdd6 8674
48e1416a 8675 /* Both DEST and SRC must be pointer types.
3b1757a2 8676 ??? This is what old code did. Is the testing for pointer types
8677 really mandatory?
8678
8679 If either SRC is readonly or length is 1, we can use memcpy. */
3f95c690 8680 if (!dest_align || !src_align)
8681 return NULL_TREE;
8682 if (readonly_data_expr (src)
e913b5cd 8683 || (tree_fits_uhwi_p (len)
3f95c690 8684 && (MIN (src_align, dest_align) / BITS_PER_UNIT
aa59f000 8685 >= tree_to_uhwi (len))))
3b1757a2 8686 {
b9a16870 8687 tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
3b1757a2 8688 if (!fn)
c2f47e15 8689 return NULL_TREE;
389dd41b 8690 return build_call_expr_loc (loc, fn, 3, dest, src, len);
3b1757a2 8691 }
3f95c690 8692
8693 /* If *src and *dest can't overlap, optimize into memcpy as well. */
182cf5a9 8694 if (TREE_CODE (src) == ADDR_EXPR
8695 && TREE_CODE (dest) == ADDR_EXPR)
3f95c690 8696 {
f85fb819 8697 tree src_base, dest_base, fn;
8698 HOST_WIDE_INT src_offset = 0, dest_offset = 0;
8699 HOST_WIDE_INT size = -1;
8700 HOST_WIDE_INT maxsize = -1;
8701
182cf5a9 8702 srcvar = TREE_OPERAND (src, 0);
8703 src_base = get_ref_base_and_extent (srcvar, &src_offset,
8704 &size, &maxsize);
8705 destvar = TREE_OPERAND (dest, 0);
8706 dest_base = get_ref_base_and_extent (destvar, &dest_offset,
8707 &size, &maxsize);
e913b5cd 8708 if (tree_fits_uhwi_p (len))
8709 maxsize = tree_to_uhwi (len);
f85fb819 8710 else
8711 maxsize = -1;
182cf5a9 8712 src_offset /= BITS_PER_UNIT;
8713 dest_offset /= BITS_PER_UNIT;
f85fb819 8714 if (SSA_VAR_P (src_base)
8715 && SSA_VAR_P (dest_base))
8716 {
8717 if (operand_equal_p (src_base, dest_base, 0)
8718 && ranges_overlap_p (src_offset, maxsize,
8719 dest_offset, maxsize))
8720 return NULL_TREE;
8721 }
182cf5a9 8722 else if (TREE_CODE (src_base) == MEM_REF
8723 && TREE_CODE (dest_base) == MEM_REF)
f85fb819 8724 {
8725 if (! operand_equal_p (TREE_OPERAND (src_base, 0),
182cf5a9 8726 TREE_OPERAND (dest_base, 0), 0))
8727 return NULL_TREE;
ab2c1de8 8728 offset_int off = mem_ref_offset (src_base) + src_offset;
796b6678 8729 if (!wi::fits_shwi_p (off))
182cf5a9 8730 return NULL_TREE;
e913b5cd 8731 src_offset = off.to_shwi ();
8732
8733 off = mem_ref_offset (dest_base) + dest_offset;
796b6678 8734 if (!wi::fits_shwi_p (off))
182cf5a9 8735 return NULL_TREE;
e913b5cd 8736 dest_offset = off.to_shwi ();
182cf5a9 8737 if (ranges_overlap_p (src_offset, maxsize,
8738 dest_offset, maxsize))
f85fb819 8739 return NULL_TREE;
8740 }
8741 else
8742 return NULL_TREE;
8743
b9a16870 8744 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
3f95c690 8745 if (!fn)
8746 return NULL_TREE;
389dd41b 8747 return build_call_expr_loc (loc, fn, 3, dest, src, len);
3f95c690 8748 }
c4222b63 8749
8750 /* If the destination and source do not alias optimize into
8751 memcpy as well. */
8752 if ((is_gimple_min_invariant (dest)
8753 || TREE_CODE (dest) == SSA_NAME)
8754 && (is_gimple_min_invariant (src)
8755 || TREE_CODE (src) == SSA_NAME))
8756 {
8757 ao_ref destr, srcr;
8758 ao_ref_init_from_ptr_and_size (&destr, dest, len);
8759 ao_ref_init_from_ptr_and_size (&srcr, src, len);
8760 if (!refs_may_alias_p_1 (&destr, &srcr, false))
8761 {
8762 tree fn;
b9a16870 8763 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
c4222b63 8764 if (!fn)
8765 return NULL_TREE;
8766 return build_call_expr_loc (loc, fn, 3, dest, src, len);
8767 }
8768 }
8769
c2f47e15 8770 return NULL_TREE;
3b1757a2 8771 }
4f46f2b9 8772
e913b5cd 8773 if (!tree_fits_shwi_p (len))
c2f47e15 8774 return NULL_TREE;
5a84fdd6 8775 /* FIXME:
8776 This logic lose for arguments like (type *)malloc (sizeof (type)),
8777 since we strip the casts of up to VOID return value from malloc.
8778 Perhaps we ought to inherit type from non-VOID argument here? */
8779 STRIP_NOPS (src);
8780 STRIP_NOPS (dest);
e07c7898 8781 if (!POINTER_TYPE_P (TREE_TYPE (src))
8782 || !POINTER_TYPE_P (TREE_TYPE (dest)))
8783 return NULL_TREE;
45bb3afb 8784 /* As we fold (void *)(p + CST) to (void *)p + CST undo this here. */
8785 if (TREE_CODE (src) == POINTER_PLUS_EXPR)
8786 {
8787 tree tem = TREE_OPERAND (src, 0);
8788 STRIP_NOPS (tem);
8789 if (tem != TREE_OPERAND (src, 0))
8790 src = build1 (NOP_EXPR, TREE_TYPE (tem), src);
8791 }
8792 if (TREE_CODE (dest) == POINTER_PLUS_EXPR)
8793 {
8794 tree tem = TREE_OPERAND (dest, 0);
8795 STRIP_NOPS (tem);
8796 if (tem != TREE_OPERAND (dest, 0))
8797 dest = build1 (NOP_EXPR, TREE_TYPE (tem), dest);
8798 }
5a84fdd6 8799 srctype = TREE_TYPE (TREE_TYPE (src));
e07c7898 8800 if (TREE_CODE (srctype) == ARRAY_TYPE
97d4c6a6 8801 && !tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
45bb3afb 8802 {
8803 srctype = TREE_TYPE (srctype);
8804 STRIP_NOPS (src);
8805 src = build1 (NOP_EXPR, build_pointer_type (srctype), src);
8806 }
5a84fdd6 8807 desttype = TREE_TYPE (TREE_TYPE (dest));
e07c7898 8808 if (TREE_CODE (desttype) == ARRAY_TYPE
97d4c6a6 8809 && !tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
45bb3afb 8810 {
8811 desttype = TREE_TYPE (desttype);
8812 STRIP_NOPS (dest);
8813 dest = build1 (NOP_EXPR, build_pointer_type (desttype), dest);
8814 }
e07c7898 8815 if (TREE_ADDRESSABLE (srctype)
8816 || TREE_ADDRESSABLE (desttype))
c2f47e15 8817 return NULL_TREE;
4f46f2b9 8818
957d0361 8819 src_align = get_pointer_alignment (src);
8820 dest_align = get_pointer_alignment (dest);
153c3b50 8821 if (dest_align < TYPE_ALIGN (desttype)
8822 || src_align < TYPE_ALIGN (srctype))
c2f47e15 8823 return NULL_TREE;
e973ffcc 8824
5a84fdd6 8825 if (!ignore)
8826 dest = builtin_save_expr (dest);
4f46f2b9 8827
182cf5a9 8828 /* Build accesses at offset zero with a ref-all character type. */
8829 off0 = build_int_cst (build_pointer_type_for_mode (char_type_node,
8830 ptr_mode, true), 0);
4f46f2b9 8831
ec08f7b0 8832 /* For -fsanitize={bool,enum} make sure the load isn't performed in
8833 the bool or enum type. */
8834 if (((flag_sanitize & SANITIZE_BOOL)
8835 && TREE_CODE (desttype) == BOOLEAN_TYPE)
8836 || ((flag_sanitize & SANITIZE_ENUM)
8837 && TREE_CODE (desttype) == ENUMERAL_TYPE))
8838 {
8839 tree destitype
8840 = lang_hooks.types.type_for_mode (TYPE_MODE (desttype),
8841 TYPE_UNSIGNED (desttype));
8842 desttype = build_aligned_type (destitype, TYPE_ALIGN (desttype));
8843 }
8844 if (((flag_sanitize & SANITIZE_BOOL)
8845 && TREE_CODE (srctype) == BOOLEAN_TYPE)
8846 || ((flag_sanitize & SANITIZE_ENUM)
8847 && TREE_CODE (srctype) == ENUMERAL_TYPE))
8848 {
8849 tree srcitype
8850 = lang_hooks.types.type_for_mode (TYPE_MODE (srctype),
8851 TYPE_UNSIGNED (srctype));
8852 srctype = build_aligned_type (srcitype, TYPE_ALIGN (srctype));
8853 }
8854
182cf5a9 8855 destvar = dest;
8856 STRIP_NOPS (destvar);
8857 if (TREE_CODE (destvar) == ADDR_EXPR
8858 && var_decl_component_p (TREE_OPERAND (destvar, 0))
8859 && tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
8860 destvar = fold_build2 (MEM_REF, desttype, destvar, off0);
8861 else
8862 destvar = NULL_TREE;
8863
8864 srcvar = src;
8865 STRIP_NOPS (srcvar);
8866 if (TREE_CODE (srcvar) == ADDR_EXPR
8867 && var_decl_component_p (TREE_OPERAND (srcvar, 0))
5b99ff01 8868 && tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
8869 {
8870 if (!destvar
8871 || src_align >= TYPE_ALIGN (desttype))
8872 srcvar = fold_build2 (MEM_REF, destvar ? desttype : srctype,
8873 srcvar, off0);
8874 else if (!STRICT_ALIGNMENT)
8875 {
8876 srctype = build_aligned_type (TYPE_MAIN_VARIANT (desttype),
8877 src_align);
8878 srcvar = fold_build2 (MEM_REF, srctype, srcvar, off0);
8879 }
8880 else
8881 srcvar = NULL_TREE;
8882 }
182cf5a9 8883 else
8884 srcvar = NULL_TREE;
5383fb56 8885
8886 if (srcvar == NULL_TREE && destvar == NULL_TREE)
c2f47e15 8887 return NULL_TREE;
4f46f2b9 8888
5383fb56 8889 if (srcvar == NULL_TREE)
8890 {
182cf5a9 8891 STRIP_NOPS (src);
5b99ff01 8892 if (src_align >= TYPE_ALIGN (desttype))
8893 srcvar = fold_build2 (MEM_REF, desttype, src, off0);
8894 else
8895 {
8896 if (STRICT_ALIGNMENT)
8897 return NULL_TREE;
8898 srctype = build_aligned_type (TYPE_MAIN_VARIANT (desttype),
8899 src_align);
8900 srcvar = fold_build2 (MEM_REF, srctype, src, off0);
8901 }
5383fb56 8902 }
8903 else if (destvar == NULL_TREE)
8904 {
182cf5a9 8905 STRIP_NOPS (dest);
5b99ff01 8906 if (dest_align >= TYPE_ALIGN (srctype))
8907 destvar = fold_build2 (MEM_REF, srctype, dest, off0);
8908 else
8909 {
8910 if (STRICT_ALIGNMENT)
8911 return NULL_TREE;
8912 desttype = build_aligned_type (TYPE_MAIN_VARIANT (srctype),
8913 dest_align);
8914 destvar = fold_build2 (MEM_REF, desttype, dest, off0);
8915 }
5383fb56 8916 }
8917
182cf5a9 8918 expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, srcvar);
4f46f2b9 8919 }
8920
8921 if (ignore)
8922 return expr;
8923
8924 if (endp == 0 || endp == 3)
389dd41b 8925 return omit_one_operand_loc (loc, type, dest, expr);
4f46f2b9 8926
8927 if (expr == len)
c2f47e15 8928 expr = NULL_TREE;
4f46f2b9 8929
8930 if (endp == 2)
389dd41b 8931 len = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (len), len,
4f46f2b9 8932 ssize_int (1));
8933
2cc66f2a 8934 dest = fold_build_pointer_plus_loc (loc, dest, len);
389dd41b 8935 dest = fold_convert_loc (loc, type, dest);
4f46f2b9 8936 if (expr)
389dd41b 8937 dest = omit_one_operand_loc (loc, type, dest, expr);
4f46f2b9 8938 return dest;
8939}
8940
c2f47e15 8941/* Fold function call to builtin strcpy with arguments DEST and SRC.
8942 If LEN is not NULL, it represents the length of the string to be
8943 copied. Return NULL_TREE if no simplification can be made. */
9c8a1629 8944
f0613857 8945tree
389dd41b 8946fold_builtin_strcpy (location_t loc, tree fndecl, tree dest, tree src, tree len)
9c8a1629 8947{
c2f47e15 8948 tree fn;
9c8a1629 8949
c2f47e15 8950 if (!validate_arg (dest, POINTER_TYPE)
8951 || !validate_arg (src, POINTER_TYPE))
8952 return NULL_TREE;
9c8a1629 8953
8954 /* If SRC and DEST are the same (and not volatile), return DEST. */
8955 if (operand_equal_p (src, dest, 0))
389dd41b 8956 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
9c8a1629 8957
0bfd8d5c 8958 if (optimize_function_for_size_p (cfun))
c2f47e15 8959 return NULL_TREE;
f0613857 8960
b9a16870 8961 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
f0613857 8962 if (!fn)
c2f47e15 8963 return NULL_TREE;
f0613857 8964
8965 if (!len)
8966 {
8967 len = c_strlen (src, 1);
8968 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 8969 return NULL_TREE;
f0613857 8970 }
8971
bd6dcc04 8972 len = fold_convert_loc (loc, size_type_node, len);
8973 len = size_binop_loc (loc, PLUS_EXPR, len, build_int_cst (size_type_node, 1));
389dd41b 8974 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
8975 build_call_expr_loc (loc, fn, 3, dest, src, len));
9c8a1629 8976}
8977
a65c4d64 8978/* Fold function call to builtin stpcpy with arguments DEST and SRC.
8979 Return NULL_TREE if no simplification can be made. */
8980
8981static tree
8982fold_builtin_stpcpy (location_t loc, tree fndecl, tree dest, tree src)
8983{
8984 tree fn, len, lenp1, call, type;
8985
8986 if (!validate_arg (dest, POINTER_TYPE)
8987 || !validate_arg (src, POINTER_TYPE))
8988 return NULL_TREE;
8989
8990 len = c_strlen (src, 1);
8991 if (!len
8992 || TREE_CODE (len) != INTEGER_CST)
8993 return NULL_TREE;
8994
8995 if (optimize_function_for_size_p (cfun)
8996 /* If length is zero it's small enough. */
8997 && !integer_zerop (len))
8998 return NULL_TREE;
8999
b9a16870 9000 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
a65c4d64 9001 if (!fn)
9002 return NULL_TREE;
9003
bd6dcc04 9004 lenp1 = size_binop_loc (loc, PLUS_EXPR,
9005 fold_convert_loc (loc, size_type_node, len),
9006 build_int_cst (size_type_node, 1));
a65c4d64 9007 /* We use dest twice in building our expression. Save it from
9008 multiple expansions. */
9009 dest = builtin_save_expr (dest);
9010 call = build_call_expr_loc (loc, fn, 3, dest, src, lenp1);
9011
9012 type = TREE_TYPE (TREE_TYPE (fndecl));
2cc66f2a 9013 dest = fold_build_pointer_plus_loc (loc, dest, len);
a65c4d64 9014 dest = fold_convert_loc (loc, type, dest);
9015 dest = omit_one_operand_loc (loc, type, dest, call);
9016 return dest;
9017}
9018
c2f47e15 9019/* Fold function call to builtin strncpy with arguments DEST, SRC, and LEN.
9020 If SLEN is not NULL, it represents the length of the source string.
9021 Return NULL_TREE if no simplification can be made. */
9c8a1629 9022
f0613857 9023tree
389dd41b 9024fold_builtin_strncpy (location_t loc, tree fndecl, tree dest,
9025 tree src, tree len, tree slen)
9c8a1629 9026{
c2f47e15 9027 tree fn;
9c8a1629 9028
c2f47e15 9029 if (!validate_arg (dest, POINTER_TYPE)
9030 || !validate_arg (src, POINTER_TYPE)
9031 || !validate_arg (len, INTEGER_TYPE))
9032 return NULL_TREE;
9c8a1629 9033
9034 /* If the LEN parameter is zero, return DEST. */
9035 if (integer_zerop (len))
389dd41b 9036 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
9c8a1629 9037
19226313 9038 /* We can't compare slen with len as constants below if len is not a
9039 constant. */
9040 if (len == 0 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 9041 return NULL_TREE;
19226313 9042
f0613857 9043 if (!slen)
9044 slen = c_strlen (src, 1);
9045
9046 /* Now, we must be passed a constant src ptr parameter. */
9047 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
c2f47e15 9048 return NULL_TREE;
f0613857 9049
389dd41b 9050 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
f0613857 9051
9052 /* We do not support simplification of this case, though we do
9053 support it when expanding trees into RTL. */
9054 /* FIXME: generate a call to __builtin_memset. */
9055 if (tree_int_cst_lt (slen, len))
c2f47e15 9056 return NULL_TREE;
f0613857 9057
9058 /* OK transform into builtin memcpy. */
b9a16870 9059 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
f0613857 9060 if (!fn)
c2f47e15 9061 return NULL_TREE;
bd6dcc04 9062
9063 len = fold_convert_loc (loc, size_type_node, len);
389dd41b 9064 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
9065 build_call_expr_loc (loc, fn, 3, dest, src, len));
9c8a1629 9066}
9067
7959b13b 9068/* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the
9069 arguments to the call, and TYPE is its return type.
9070 Return NULL_TREE if no simplification can be made. */
9071
9072static tree
389dd41b 9073fold_builtin_memchr (location_t loc, tree arg1, tree arg2, tree len, tree type)
7959b13b 9074{
9075 if (!validate_arg (arg1, POINTER_TYPE)
9076 || !validate_arg (arg2, INTEGER_TYPE)
9077 || !validate_arg (len, INTEGER_TYPE))
9078 return NULL_TREE;
9079 else
9080 {
9081 const char *p1;
9082
9083 if (TREE_CODE (arg2) != INTEGER_CST
e913b5cd 9084 || !tree_fits_uhwi_p (len))
7959b13b 9085 return NULL_TREE;
9086
9087 p1 = c_getstr (arg1);
9088 if (p1 && compare_tree_int (len, strlen (p1) + 1) <= 0)
9089 {
9090 char c;
9091 const char *r;
9092 tree tem;
9093
9094 if (target_char_cast (arg2, &c))
9095 return NULL_TREE;
9096
e913b5cd 9097 r = (const char *) memchr (p1, c, tree_to_uhwi (len));
7959b13b 9098
9099 if (r == NULL)
9100 return build_int_cst (TREE_TYPE (arg1), 0);
9101
2cc66f2a 9102 tem = fold_build_pointer_plus_hwi_loc (loc, arg1, r - p1);
389dd41b 9103 return fold_convert_loc (loc, type, tem);
7959b13b 9104 }
9105 return NULL_TREE;
9106 }
9107}
9108
c2f47e15 9109/* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
9110 Return NULL_TREE if no simplification can be made. */
9c8a1629 9111
9112static tree
389dd41b 9113fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
9c8a1629 9114{
c4fef134 9115 const char *p1, *p2;
9c8a1629 9116
c2f47e15 9117 if (!validate_arg (arg1, POINTER_TYPE)
9118 || !validate_arg (arg2, POINTER_TYPE)
9119 || !validate_arg (len, INTEGER_TYPE))
9120 return NULL_TREE;
9c8a1629 9121
9122 /* If the LEN parameter is zero, return zero. */
9123 if (integer_zerop (len))
389dd41b 9124 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
c4fef134 9125 arg1, arg2);
9c8a1629 9126
9127 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9128 if (operand_equal_p (arg1, arg2, 0))
389dd41b 9129 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
c4fef134 9130
9131 p1 = c_getstr (arg1);
9132 p2 = c_getstr (arg2);
9133
9134 /* If all arguments are constant, and the value of len is not greater
9135 than the lengths of arg1 and arg2, evaluate at compile-time. */
e913b5cd 9136 if (tree_fits_uhwi_p (len) && p1 && p2
c4fef134 9137 && compare_tree_int (len, strlen (p1) + 1) <= 0
9138 && compare_tree_int (len, strlen (p2) + 1) <= 0)
9139 {
e913b5cd 9140 const int r = memcmp (p1, p2, tree_to_uhwi (len));
c4fef134 9141
9142 if (r > 0)
9143 return integer_one_node;
9144 else if (r < 0)
9145 return integer_minus_one_node;
9146 else
9147 return integer_zero_node;
9148 }
9149
9150 /* If len parameter is one, return an expression corresponding to
9151 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
e913b5cd 9152 if (tree_fits_uhwi_p (len) && tree_to_uhwi (len) == 1)
c4fef134 9153 {
9154 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9155 tree cst_uchar_ptr_node
9156 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9157
389dd41b 9158 tree ind1
9159 = fold_convert_loc (loc, integer_type_node,
9160 build1 (INDIRECT_REF, cst_uchar_node,
9161 fold_convert_loc (loc,
9162 cst_uchar_ptr_node,
c4fef134 9163 arg1)));
389dd41b 9164 tree ind2
9165 = fold_convert_loc (loc, integer_type_node,
9166 build1 (INDIRECT_REF, cst_uchar_node,
9167 fold_convert_loc (loc,
9168 cst_uchar_ptr_node,
c4fef134 9169 arg2)));
389dd41b 9170 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
c4fef134 9171 }
9c8a1629 9172
c2f47e15 9173 return NULL_TREE;
9c8a1629 9174}
9175
c2f47e15 9176/* Fold function call to builtin strcmp with arguments ARG1 and ARG2.
9177 Return NULL_TREE if no simplification can be made. */
9c8a1629 9178
9179static tree
389dd41b 9180fold_builtin_strcmp (location_t loc, tree arg1, tree arg2)
9c8a1629 9181{
9c8a1629 9182 const char *p1, *p2;
9183
c2f47e15 9184 if (!validate_arg (arg1, POINTER_TYPE)
9185 || !validate_arg (arg2, POINTER_TYPE))
9186 return NULL_TREE;
9c8a1629 9187
9188 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9189 if (operand_equal_p (arg1, arg2, 0))
c4fef134 9190 return integer_zero_node;
9c8a1629 9191
9192 p1 = c_getstr (arg1);
9193 p2 = c_getstr (arg2);
9194
9195 if (p1 && p2)
9196 {
9c8a1629 9197 const int i = strcmp (p1, p2);
9198 if (i < 0)
c4fef134 9199 return integer_minus_one_node;
9c8a1629 9200 else if (i > 0)
c4fef134 9201 return integer_one_node;
9c8a1629 9202 else
c4fef134 9203 return integer_zero_node;
9204 }
9205
9206 /* If the second arg is "", return *(const unsigned char*)arg1. */
9207 if (p2 && *p2 == '\0')
9208 {
9209 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9210 tree cst_uchar_ptr_node
9211 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9212
389dd41b 9213 return fold_convert_loc (loc, integer_type_node,
9214 build1 (INDIRECT_REF, cst_uchar_node,
9215 fold_convert_loc (loc,
9216 cst_uchar_ptr_node,
9217 arg1)));
c4fef134 9218 }
9219
9220 /* If the first arg is "", return -*(const unsigned char*)arg2. */
9221 if (p1 && *p1 == '\0')
9222 {
9223 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9224 tree cst_uchar_ptr_node
9225 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9226
389dd41b 9227 tree temp
9228 = fold_convert_loc (loc, integer_type_node,
9229 build1 (INDIRECT_REF, cst_uchar_node,
9230 fold_convert_loc (loc,
9231 cst_uchar_ptr_node,
c4fef134 9232 arg2)));
389dd41b 9233 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp);
9c8a1629 9234 }
9235
c2f47e15 9236 return NULL_TREE;
9c8a1629 9237}
9238
c2f47e15 9239/* Fold function call to builtin strncmp with arguments ARG1, ARG2, and LEN.
9240 Return NULL_TREE if no simplification can be made. */
9c8a1629 9241
9242static tree
389dd41b 9243fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len)
9c8a1629 9244{
9c8a1629 9245 const char *p1, *p2;
9246
c2f47e15 9247 if (!validate_arg (arg1, POINTER_TYPE)
9248 || !validate_arg (arg2, POINTER_TYPE)
9249 || !validate_arg (len, INTEGER_TYPE))
9250 return NULL_TREE;
9c8a1629 9251
9252 /* If the LEN parameter is zero, return zero. */
9253 if (integer_zerop (len))
389dd41b 9254 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
c4fef134 9255 arg1, arg2);
9c8a1629 9256
9257 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9258 if (operand_equal_p (arg1, arg2, 0))
389dd41b 9259 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
9c8a1629 9260
9261 p1 = c_getstr (arg1);
9262 p2 = c_getstr (arg2);
9263
e913b5cd 9264 if (tree_fits_uhwi_p (len) && p1 && p2)
9c8a1629 9265 {
e913b5cd 9266 const int i = strncmp (p1, p2, tree_to_uhwi (len));
c4fef134 9267 if (i > 0)
9268 return integer_one_node;
9269 else if (i < 0)
9270 return integer_minus_one_node;
9c8a1629 9271 else
c4fef134 9272 return integer_zero_node;
9273 }
9274
9275 /* If the second arg is "", and the length is greater than zero,
9276 return *(const unsigned char*)arg1. */
9277 if (p2 && *p2 == '\0'
9278 && TREE_CODE (len) == INTEGER_CST
9279 && tree_int_cst_sgn (len) == 1)
9280 {
9281 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9282 tree cst_uchar_ptr_node
9283 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9284
389dd41b 9285 return fold_convert_loc (loc, integer_type_node,
9286 build1 (INDIRECT_REF, cst_uchar_node,
9287 fold_convert_loc (loc,
9288 cst_uchar_ptr_node,
9289 arg1)));
c4fef134 9290 }
9291
9292 /* If the first arg is "", and the length is greater than zero,
9293 return -*(const unsigned char*)arg2. */
9294 if (p1 && *p1 == '\0'
9295 && TREE_CODE (len) == INTEGER_CST
9296 && tree_int_cst_sgn (len) == 1)
9297 {
9298 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9299 tree cst_uchar_ptr_node
9300 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9301
389dd41b 9302 tree temp = fold_convert_loc (loc, integer_type_node,
9303 build1 (INDIRECT_REF, cst_uchar_node,
9304 fold_convert_loc (loc,
9305 cst_uchar_ptr_node,
9306 arg2)));
9307 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp);
c4fef134 9308 }
9309
9310 /* If len parameter is one, return an expression corresponding to
9311 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
e913b5cd 9312 if (tree_fits_uhwi_p (len) && tree_to_uhwi (len) == 1)
c4fef134 9313 {
9314 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9315 tree cst_uchar_ptr_node
9316 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9317
389dd41b 9318 tree ind1 = fold_convert_loc (loc, integer_type_node,
9319 build1 (INDIRECT_REF, cst_uchar_node,
9320 fold_convert_loc (loc,
9321 cst_uchar_ptr_node,
9322 arg1)));
9323 tree ind2 = fold_convert_loc (loc, integer_type_node,
9324 build1 (INDIRECT_REF, cst_uchar_node,
9325 fold_convert_loc (loc,
9326 cst_uchar_ptr_node,
9327 arg2)));
9328 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
9c8a1629 9329 }
9330
c2f47e15 9331 return NULL_TREE;
9c8a1629 9332}
9333
c2f47e15 9334/* Fold function call to builtin signbit, signbitf or signbitl with argument
9335 ARG. Return NULL_TREE if no simplification can be made. */
27f261ef 9336
9337static tree
389dd41b 9338fold_builtin_signbit (location_t loc, tree arg, tree type)
27f261ef 9339{
c2f47e15 9340 if (!validate_arg (arg, REAL_TYPE))
27f261ef 9341 return NULL_TREE;
9342
27f261ef 9343 /* If ARG is a compile-time constant, determine the result. */
9344 if (TREE_CODE (arg) == REAL_CST
f96bd2bf 9345 && !TREE_OVERFLOW (arg))
27f261ef 9346 {
9347 REAL_VALUE_TYPE c;
9348
9349 c = TREE_REAL_CST (arg);
385f3f36 9350 return (REAL_VALUE_NEGATIVE (c)
9351 ? build_one_cst (type)
9352 : build_zero_cst (type));
27f261ef 9353 }
9354
9355 /* If ARG is non-negative, the result is always zero. */
9356 if (tree_expr_nonnegative_p (arg))
389dd41b 9357 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
27f261ef 9358
9359 /* If ARG's format doesn't have signed zeros, return "arg < 0.0". */
9360 if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
de67cbb8 9361 return fold_convert (type,
9362 fold_build2_loc (loc, LT_EXPR, boolean_type_node, arg,
9363 build_real (TREE_TYPE (arg), dconst0)));
27f261ef 9364
9365 return NULL_TREE;
9366}
9367
c2f47e15 9368/* Fold function call to builtin copysign, copysignf or copysignl with
9369 arguments ARG1 and ARG2. Return NULL_TREE if no simplification can
9370 be made. */
467214fd 9371
9372static tree
389dd41b 9373fold_builtin_copysign (location_t loc, tree fndecl,
9374 tree arg1, tree arg2, tree type)
467214fd 9375{
c2f47e15 9376 tree tem;
467214fd 9377
c2f47e15 9378 if (!validate_arg (arg1, REAL_TYPE)
9379 || !validate_arg (arg2, REAL_TYPE))
467214fd 9380 return NULL_TREE;
9381
467214fd 9382 /* copysign(X,X) is X. */
9383 if (operand_equal_p (arg1, arg2, 0))
389dd41b 9384 return fold_convert_loc (loc, type, arg1);
467214fd 9385
9386 /* If ARG1 and ARG2 are compile-time constants, determine the result. */
9387 if (TREE_CODE (arg1) == REAL_CST
9388 && TREE_CODE (arg2) == REAL_CST
f96bd2bf 9389 && !TREE_OVERFLOW (arg1)
9390 && !TREE_OVERFLOW (arg2))
467214fd 9391 {
9392 REAL_VALUE_TYPE c1, c2;
9393
9394 c1 = TREE_REAL_CST (arg1);
9395 c2 = TREE_REAL_CST (arg2);
749680e2 9396 /* c1.sign := c2.sign. */
467214fd 9397 real_copysign (&c1, &c2);
9398 return build_real (type, c1);
467214fd 9399 }
9400
9401 /* copysign(X, Y) is fabs(X) when Y is always non-negative.
9402 Remember to evaluate Y for side-effects. */
9403 if (tree_expr_nonnegative_p (arg2))
389dd41b 9404 return omit_one_operand_loc (loc, type,
9405 fold_build1_loc (loc, ABS_EXPR, type, arg1),
467214fd 9406 arg2);
9407
198d9bbe 9408 /* Strip sign changing operations for the first argument. */
9409 tem = fold_strip_sign_ops (arg1);
9410 if (tem)
389dd41b 9411 return build_call_expr_loc (loc, fndecl, 2, tem, arg2);
198d9bbe 9412
467214fd 9413 return NULL_TREE;
9414}
9415
c2f47e15 9416/* Fold a call to builtin isascii with argument ARG. */
d49367d4 9417
9418static tree
389dd41b 9419fold_builtin_isascii (location_t loc, tree arg)
d49367d4 9420{
c2f47e15 9421 if (!validate_arg (arg, INTEGER_TYPE))
9422 return NULL_TREE;
d49367d4 9423 else
9424 {
9425 /* Transform isascii(c) -> ((c & ~0x7f) == 0). */
c90b5d40 9426 arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
7002a1c8 9427 build_int_cst (integer_type_node,
c90b5d40 9428 ~ (unsigned HOST_WIDE_INT) 0x7f));
389dd41b 9429 return fold_build2_loc (loc, EQ_EXPR, integer_type_node,
7002a1c8 9430 arg, integer_zero_node);
d49367d4 9431 }
9432}
9433
c2f47e15 9434/* Fold a call to builtin toascii with argument ARG. */
d49367d4 9435
9436static tree
389dd41b 9437fold_builtin_toascii (location_t loc, tree arg)
d49367d4 9438{
c2f47e15 9439 if (!validate_arg (arg, INTEGER_TYPE))
9440 return NULL_TREE;
48e1416a 9441
c2f47e15 9442 /* Transform toascii(c) -> (c & 0x7f). */
389dd41b 9443 return fold_build2_loc (loc, BIT_AND_EXPR, integer_type_node, arg,
7002a1c8 9444 build_int_cst (integer_type_node, 0x7f));
d49367d4 9445}
9446
c2f47e15 9447/* Fold a call to builtin isdigit with argument ARG. */
df1cf42e 9448
9449static tree
389dd41b 9450fold_builtin_isdigit (location_t loc, tree arg)
df1cf42e 9451{
c2f47e15 9452 if (!validate_arg (arg, INTEGER_TYPE))
9453 return NULL_TREE;
df1cf42e 9454 else
9455 {
9456 /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */
624d37a6 9457 /* According to the C standard, isdigit is unaffected by locale.
9458 However, it definitely is affected by the target character set. */
624d37a6 9459 unsigned HOST_WIDE_INT target_digit0
9460 = lang_hooks.to_target_charset ('0');
9461
9462 if (target_digit0 == 0)
9463 return NULL_TREE;
9464
389dd41b 9465 arg = fold_convert_loc (loc, unsigned_type_node, arg);
c90b5d40 9466 arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg,
9467 build_int_cst (unsigned_type_node, target_digit0));
389dd41b 9468 return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg,
f2532264 9469 build_int_cst (unsigned_type_node, 9));
df1cf42e 9470 }
9471}
27f261ef 9472
c2f47e15 9473/* Fold a call to fabs, fabsf or fabsl with argument ARG. */
d1aade50 9474
9475static tree
389dd41b 9476fold_builtin_fabs (location_t loc, tree arg, tree type)
d1aade50 9477{
c2f47e15 9478 if (!validate_arg (arg, REAL_TYPE))
9479 return NULL_TREE;
d1aade50 9480
389dd41b 9481 arg = fold_convert_loc (loc, type, arg);
d1aade50 9482 if (TREE_CODE (arg) == REAL_CST)
9483 return fold_abs_const (arg, type);
389dd41b 9484 return fold_build1_loc (loc, ABS_EXPR, type, arg);
d1aade50 9485}
9486
c2f47e15 9487/* Fold a call to abs, labs, llabs or imaxabs with argument ARG. */
d1aade50 9488
9489static tree
389dd41b 9490fold_builtin_abs (location_t loc, tree arg, tree type)
d1aade50 9491{
c2f47e15 9492 if (!validate_arg (arg, INTEGER_TYPE))
9493 return NULL_TREE;
d1aade50 9494
389dd41b 9495 arg = fold_convert_loc (loc, type, arg);
d1aade50 9496 if (TREE_CODE (arg) == INTEGER_CST)
9497 return fold_abs_const (arg, type);
389dd41b 9498 return fold_build1_loc (loc, ABS_EXPR, type, arg);
d1aade50 9499}
9500
b9be572e 9501/* Fold a fma operation with arguments ARG[012]. */
9502
9503tree
9504fold_fma (location_t loc ATTRIBUTE_UNUSED,
9505 tree type, tree arg0, tree arg1, tree arg2)
9506{
9507 if (TREE_CODE (arg0) == REAL_CST
9508 && TREE_CODE (arg1) == REAL_CST
9509 && TREE_CODE (arg2) == REAL_CST)
9510 return do_mpfr_arg3 (arg0, arg1, arg2, type, mpfr_fma);
9511
9512 return NULL_TREE;
9513}
9514
9515/* Fold a call to fma, fmaf, or fmal with arguments ARG[012]. */
9516
9517static tree
9518fold_builtin_fma (location_t loc, tree arg0, tree arg1, tree arg2, tree type)
9519{
9520 if (validate_arg (arg0, REAL_TYPE)
9af5ce0c 9521 && validate_arg (arg1, REAL_TYPE)
9522 && validate_arg (arg2, REAL_TYPE))
b9be572e 9523 {
9524 tree tem = fold_fma (loc, type, arg0, arg1, arg2);
9525 if (tem)
9526 return tem;
9527
9528 /* ??? Only expand to FMA_EXPR if it's directly supported. */
9529 if (optab_handler (fma_optab, TYPE_MODE (type)) != CODE_FOR_nothing)
9530 return fold_build3_loc (loc, FMA_EXPR, type, arg0, arg1, arg2);
9531 }
9532 return NULL_TREE;
9533}
9534
d4a43a03 9535/* Fold a call to builtin fmin or fmax. */
9536
9537static tree
389dd41b 9538fold_builtin_fmin_fmax (location_t loc, tree arg0, tree arg1,
9539 tree type, bool max)
d4a43a03 9540{
c2f47e15 9541 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, REAL_TYPE))
d4a43a03 9542 {
d4a43a03 9543 /* Calculate the result when the argument is a constant. */
9544 tree res = do_mpfr_arg2 (arg0, arg1, type, (max ? mpfr_max : mpfr_min));
9545
9546 if (res)
9547 return res;
9548
61fe3555 9549 /* If either argument is NaN, return the other one. Avoid the
9550 transformation if we get (and honor) a signalling NaN. Using
9551 omit_one_operand() ensures we create a non-lvalue. */
9552 if (TREE_CODE (arg0) == REAL_CST
9553 && real_isnan (&TREE_REAL_CST (arg0))
9554 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
9555 || ! TREE_REAL_CST (arg0).signalling))
389dd41b 9556 return omit_one_operand_loc (loc, type, arg1, arg0);
61fe3555 9557 if (TREE_CODE (arg1) == REAL_CST
9558 && real_isnan (&TREE_REAL_CST (arg1))
9559 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
9560 || ! TREE_REAL_CST (arg1).signalling))
389dd41b 9561 return omit_one_operand_loc (loc, type, arg0, arg1);
61fe3555 9562
d4a43a03 9563 /* Transform fmin/fmax(x,x) -> x. */
9564 if (operand_equal_p (arg0, arg1, OEP_PURE_SAME))
389dd41b 9565 return omit_one_operand_loc (loc, type, arg0, arg1);
48e1416a 9566
d4a43a03 9567 /* Convert fmin/fmax to MIN_EXPR/MAX_EXPR. C99 requires these
9568 functions to return the numeric arg if the other one is NaN.
9569 These tree codes don't honor that, so only transform if
9570 -ffinite-math-only is set. C99 doesn't require -0.0 to be
9571 handled, so we don't have to worry about it either. */
9572 if (flag_finite_math_only)
389dd41b 9573 return fold_build2_loc (loc, (max ? MAX_EXPR : MIN_EXPR), type,
9574 fold_convert_loc (loc, type, arg0),
9575 fold_convert_loc (loc, type, arg1));
d4a43a03 9576 }
9577 return NULL_TREE;
9578}
9579
abe4dcf6 9580/* Fold a call to builtin carg(a+bi) -> atan2(b,a). */
9581
9582static tree
389dd41b 9583fold_builtin_carg (location_t loc, tree arg, tree type)
abe4dcf6 9584{
239d491a 9585 if (validate_arg (arg, COMPLEX_TYPE)
9586 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
abe4dcf6 9587 {
9588 tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
48e1416a 9589
abe4dcf6 9590 if (atan2_fn)
9591 {
c2f47e15 9592 tree new_arg = builtin_save_expr (arg);
389dd41b 9593 tree r_arg = fold_build1_loc (loc, REALPART_EXPR, type, new_arg);
9594 tree i_arg = fold_build1_loc (loc, IMAGPART_EXPR, type, new_arg);
9595 return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg);
abe4dcf6 9596 }
9597 }
48e1416a 9598
abe4dcf6 9599 return NULL_TREE;
9600}
9601
cb2b9385 9602/* Fold a call to builtin logb/ilogb. */
9603
9604static tree
389dd41b 9605fold_builtin_logb (location_t loc, tree arg, tree rettype)
cb2b9385 9606{
9607 if (! validate_arg (arg, REAL_TYPE))
9608 return NULL_TREE;
48e1416a 9609
cb2b9385 9610 STRIP_NOPS (arg);
48e1416a 9611
cb2b9385 9612 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9613 {
9614 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
48e1416a 9615
cb2b9385 9616 switch (value->cl)
9617 {
9618 case rvc_nan:
9619 case rvc_inf:
9620 /* If arg is Inf or NaN and we're logb, return it. */
9621 if (TREE_CODE (rettype) == REAL_TYPE)
7695fea9 9622 {
9623 /* For logb(-Inf) we have to return +Inf. */
9624 if (real_isinf (value) && real_isneg (value))
9625 {
9626 REAL_VALUE_TYPE tem;
9627 real_inf (&tem);
9628 return build_real (rettype, tem);
9629 }
9630 return fold_convert_loc (loc, rettype, arg);
9631 }
cb2b9385 9632 /* Fall through... */
9633 case rvc_zero:
9634 /* Zero may set errno and/or raise an exception for logb, also
9635 for ilogb we don't know FP_ILOGB0. */
9636 return NULL_TREE;
9637 case rvc_normal:
9638 /* For normal numbers, proceed iff radix == 2. In GCC,
9639 normalized significands are in the range [0.5, 1.0). We
9640 want the exponent as if they were [1.0, 2.0) so get the
9641 exponent and subtract 1. */
9642 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
389dd41b 9643 return fold_convert_loc (loc, rettype,
7002a1c8 9644 build_int_cst (integer_type_node,
389dd41b 9645 REAL_EXP (value)-1));
cb2b9385 9646 break;
9647 }
9648 }
48e1416a 9649
cb2b9385 9650 return NULL_TREE;
9651}
9652
9653/* Fold a call to builtin significand, if radix == 2. */
9654
9655static tree
389dd41b 9656fold_builtin_significand (location_t loc, tree arg, tree rettype)
cb2b9385 9657{
9658 if (! validate_arg (arg, REAL_TYPE))
9659 return NULL_TREE;
48e1416a 9660
cb2b9385 9661 STRIP_NOPS (arg);
48e1416a 9662
cb2b9385 9663 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9664 {
9665 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
48e1416a 9666
cb2b9385 9667 switch (value->cl)
9668 {
9669 case rvc_zero:
9670 case rvc_nan:
9671 case rvc_inf:
9672 /* If arg is +-0, +-Inf or +-NaN, then return it. */
389dd41b 9673 return fold_convert_loc (loc, rettype, arg);
cb2b9385 9674 case rvc_normal:
9675 /* For normal numbers, proceed iff radix == 2. */
9676 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
9677 {
9678 REAL_VALUE_TYPE result = *value;
9679 /* In GCC, normalized significands are in the range [0.5,
9680 1.0). We want them to be [1.0, 2.0) so set the
9681 exponent to 1. */
9682 SET_REAL_EXP (&result, 1);
9683 return build_real (rettype, result);
9684 }
9685 break;
9686 }
9687 }
48e1416a 9688
cb2b9385 9689 return NULL_TREE;
9690}
9691
3838b9ae 9692/* Fold a call to builtin frexp, we can assume the base is 2. */
9693
9694static tree
389dd41b 9695fold_builtin_frexp (location_t loc, tree arg0, tree arg1, tree rettype)
3838b9ae 9696{
9697 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9698 return NULL_TREE;
48e1416a 9699
3838b9ae 9700 STRIP_NOPS (arg0);
48e1416a 9701
3838b9ae 9702 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9703 return NULL_TREE;
48e1416a 9704
389dd41b 9705 arg1 = build_fold_indirect_ref_loc (loc, arg1);
3838b9ae 9706
9707 /* Proceed if a valid pointer type was passed in. */
9708 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
9709 {
9710 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9711 tree frac, exp;
48e1416a 9712
3838b9ae 9713 switch (value->cl)
9714 {
9715 case rvc_zero:
9716 /* For +-0, return (*exp = 0, +-0). */
9717 exp = integer_zero_node;
9718 frac = arg0;
9719 break;
9720 case rvc_nan:
9721 case rvc_inf:
9722 /* For +-NaN or +-Inf, *exp is unspecified, return arg0. */
389dd41b 9723 return omit_one_operand_loc (loc, rettype, arg0, arg1);
3838b9ae 9724 case rvc_normal:
9725 {
9726 /* Since the frexp function always expects base 2, and in
9727 GCC normalized significands are already in the range
9728 [0.5, 1.0), we have exactly what frexp wants. */
9729 REAL_VALUE_TYPE frac_rvt = *value;
9730 SET_REAL_EXP (&frac_rvt, 0);
9731 frac = build_real (rettype, frac_rvt);
7002a1c8 9732 exp = build_int_cst (integer_type_node, REAL_EXP (value));
3838b9ae 9733 }
9734 break;
9735 default:
9736 gcc_unreachable ();
9737 }
48e1416a 9738
3838b9ae 9739 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
389dd41b 9740 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, exp);
3838b9ae 9741 TREE_SIDE_EFFECTS (arg1) = 1;
389dd41b 9742 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1, frac);
3838b9ae 9743 }
9744
9745 return NULL_TREE;
9746}
9747
7587301b 9748/* Fold a call to builtin ldexp or scalbn/scalbln. If LDEXP is true
9749 then we can assume the base is two. If it's false, then we have to
9750 check the mode of the TYPE parameter in certain cases. */
9751
9752static tree
389dd41b 9753fold_builtin_load_exponent (location_t loc, tree arg0, tree arg1,
9754 tree type, bool ldexp)
7587301b 9755{
9756 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, INTEGER_TYPE))
9757 {
9758 STRIP_NOPS (arg0);
9759 STRIP_NOPS (arg1);
9760
9761 /* If arg0 is 0, Inf or NaN, or if arg1 is 0, then return arg0. */
9762 if (real_zerop (arg0) || integer_zerop (arg1)
9763 || (TREE_CODE (arg0) == REAL_CST
776a7bab 9764 && !real_isfinite (&TREE_REAL_CST (arg0))))
389dd41b 9765 return omit_one_operand_loc (loc, type, arg0, arg1);
48e1416a 9766
7587301b 9767 /* If both arguments are constant, then try to evaluate it. */
9768 if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2)
9769 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
e913b5cd 9770 && tree_fits_shwi_p (arg1))
7587301b 9771 {
9772 /* Bound the maximum adjustment to twice the range of the
9773 mode's valid exponents. Use abs to ensure the range is
9774 positive as a sanity check. */
48e1416a 9775 const long max_exp_adj = 2 *
7587301b 9776 labs (REAL_MODE_FORMAT (TYPE_MODE (type))->emax
9777 - REAL_MODE_FORMAT (TYPE_MODE (type))->emin);
9778
9779 /* Get the user-requested adjustment. */
e913b5cd 9780 const HOST_WIDE_INT req_exp_adj = tree_to_shwi (arg1);
48e1416a 9781
7587301b 9782 /* The requested adjustment must be inside this range. This
9783 is a preliminary cap to avoid things like overflow, we
9784 may still fail to compute the result for other reasons. */
9785 if (-max_exp_adj < req_exp_adj && req_exp_adj < max_exp_adj)
9786 {
9787 REAL_VALUE_TYPE initial_result;
48e1416a 9788
7587301b 9789 real_ldexp (&initial_result, &TREE_REAL_CST (arg0), req_exp_adj);
9790
9791 /* Ensure we didn't overflow. */
9792 if (! real_isinf (&initial_result))
9793 {
9794 const REAL_VALUE_TYPE trunc_result
9795 = real_value_truncate (TYPE_MODE (type), initial_result);
48e1416a 9796
7587301b 9797 /* Only proceed if the target mode can hold the
9798 resulting value. */
9799 if (REAL_VALUES_EQUAL (initial_result, trunc_result))
9800 return build_real (type, trunc_result);
9801 }
9802 }
9803 }
9804 }
9805
9806 return NULL_TREE;
9807}
9808
ebf8b4f5 9809/* Fold a call to builtin modf. */
9810
9811static tree
389dd41b 9812fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
ebf8b4f5 9813{
9814 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9815 return NULL_TREE;
48e1416a 9816
ebf8b4f5 9817 STRIP_NOPS (arg0);
48e1416a 9818
ebf8b4f5 9819 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9820 return NULL_TREE;
48e1416a 9821
389dd41b 9822 arg1 = build_fold_indirect_ref_loc (loc, arg1);
ebf8b4f5 9823
9824 /* Proceed if a valid pointer type was passed in. */
9825 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
9826 {
9827 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9828 REAL_VALUE_TYPE trunc, frac;
9829
9830 switch (value->cl)
9831 {
9832 case rvc_nan:
9833 case rvc_zero:
9834 /* For +-NaN or +-0, return (*arg1 = arg0, arg0). */
9835 trunc = frac = *value;
9836 break;
9837 case rvc_inf:
9838 /* For +-Inf, return (*arg1 = arg0, +-0). */
9839 frac = dconst0;
9840 frac.sign = value->sign;
9841 trunc = *value;
9842 break;
9843 case rvc_normal:
9844 /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)). */
9845 real_trunc (&trunc, VOIDmode, value);
9846 real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
9847 /* If the original number was negative and already
9848 integral, then the fractional part is -0.0. */
9849 if (value->sign && frac.cl == rvc_zero)
9850 frac.sign = value->sign;
9851 break;
9852 }
48e1416a 9853
ebf8b4f5 9854 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
389dd41b 9855 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1,
ebf8b4f5 9856 build_real (rettype, trunc));
9857 TREE_SIDE_EFFECTS (arg1) = 1;
389dd41b 9858 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1,
ebf8b4f5 9859 build_real (rettype, frac));
9860 }
48e1416a 9861
ebf8b4f5 9862 return NULL_TREE;
9863}
9864
a65c4d64 9865/* Given a location LOC, an interclass builtin function decl FNDECL
9866 and its single argument ARG, return an folded expression computing
9867 the same, or NULL_TREE if we either couldn't or didn't want to fold
9868 (the latter happen if there's an RTL instruction available). */
9869
9870static tree
9871fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
9872{
9873 enum machine_mode mode;
9874
9875 if (!validate_arg (arg, REAL_TYPE))
9876 return NULL_TREE;
9877
9878 if (interclass_mathfn_icode (arg, fndecl) != CODE_FOR_nothing)
9879 return NULL_TREE;
9880
9881 mode = TYPE_MODE (TREE_TYPE (arg));
9882
9883 /* If there is no optab, try generic code. */
9884 switch (DECL_FUNCTION_CODE (fndecl))
9885 {
9886 tree result;
9887
9888 CASE_FLT_FN (BUILT_IN_ISINF):
9889 {
9890 /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
b9a16870 9891 tree const isgr_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
a65c4d64 9892 tree const type = TREE_TYPE (arg);
9893 REAL_VALUE_TYPE r;
9894 char buf[128];
9895
9896 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9897 real_from_string (&r, buf);
9898 result = build_call_expr (isgr_fn, 2,
9899 fold_build1_loc (loc, ABS_EXPR, type, arg),
9900 build_real (type, r));
9901 return result;
9902 }
9903 CASE_FLT_FN (BUILT_IN_FINITE):
9904 case BUILT_IN_ISFINITE:
9905 {
9906 /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
b9a16870 9907 tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
a65c4d64 9908 tree const type = TREE_TYPE (arg);
9909 REAL_VALUE_TYPE r;
9910 char buf[128];
9911
9912 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9913 real_from_string (&r, buf);
9914 result = build_call_expr (isle_fn, 2,
9915 fold_build1_loc (loc, ABS_EXPR, type, arg),
9916 build_real (type, r));
9917 /*result = fold_build2_loc (loc, UNGT_EXPR,
9918 TREE_TYPE (TREE_TYPE (fndecl)),
9919 fold_build1_loc (loc, ABS_EXPR, type, arg),
9920 build_real (type, r));
9921 result = fold_build1_loc (loc, TRUTH_NOT_EXPR,
9922 TREE_TYPE (TREE_TYPE (fndecl)),
9923 result);*/
9924 return result;
9925 }
9926 case BUILT_IN_ISNORMAL:
9927 {
9928 /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
9929 islessequal(fabs(x),DBL_MAX). */
b9a16870 9930 tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
9931 tree const isge_fn = builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL);
a65c4d64 9932 tree const type = TREE_TYPE (arg);
9933 REAL_VALUE_TYPE rmax, rmin;
9934 char buf[128];
9935
9936 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9937 real_from_string (&rmax, buf);
9938 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
9939 real_from_string (&rmin, buf);
9940 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
9941 result = build_call_expr (isle_fn, 2, arg,
9942 build_real (type, rmax));
9943 result = fold_build2 (BIT_AND_EXPR, integer_type_node, result,
9944 build_call_expr (isge_fn, 2, arg,
9945 build_real (type, rmin)));
9946 return result;
9947 }
9948 default:
9949 break;
9950 }
9951
9952 return NULL_TREE;
9953}
9954
726069ba 9955/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
c2f47e15 9956 ARG is the argument for the call. */
726069ba 9957
9958static tree
389dd41b 9959fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
726069ba 9960{
726069ba 9961 tree type = TREE_TYPE (TREE_TYPE (fndecl));
726069ba 9962 REAL_VALUE_TYPE r;
9963
c2f47e15 9964 if (!validate_arg (arg, REAL_TYPE))
d43cee80 9965 return NULL_TREE;
726069ba 9966
726069ba 9967 switch (builtin_index)
9968 {
9969 case BUILT_IN_ISINF:
b70bfd00 9970 if (!HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 9971 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
726069ba 9972
9973 if (TREE_CODE (arg) == REAL_CST)
9974 {
9975 r = TREE_REAL_CST (arg);
9976 if (real_isinf (&r))
9977 return real_compare (GT_EXPR, &r, &dconst0)
9978 ? integer_one_node : integer_minus_one_node;
9979 else
9980 return integer_zero_node;
9981 }
9982
9983 return NULL_TREE;
9984
c319d56a 9985 case BUILT_IN_ISINF_SIGN:
9986 {
9987 /* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */
9988 /* In a boolean context, GCC will fold the inner COND_EXPR to
9989 1. So e.g. "if (isinf_sign(x))" would be folded to just
9990 "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
9991 tree signbit_fn = mathfn_built_in_1 (TREE_TYPE (arg), BUILT_IN_SIGNBIT, 0);
b9a16870 9992 tree isinf_fn = builtin_decl_explicit (BUILT_IN_ISINF);
c319d56a 9993 tree tmp = NULL_TREE;
9994
9995 arg = builtin_save_expr (arg);
9996
9997 if (signbit_fn && isinf_fn)
9998 {
389dd41b 9999 tree signbit_call = build_call_expr_loc (loc, signbit_fn, 1, arg);
10000 tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg);
c319d56a 10001
389dd41b 10002 signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
c319d56a 10003 signbit_call, integer_zero_node);
389dd41b 10004 isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
c319d56a 10005 isinf_call, integer_zero_node);
48e1416a 10006
389dd41b 10007 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call,
c319d56a 10008 integer_minus_one_node, integer_one_node);
389dd41b 10009 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
10010 isinf_call, tmp,
c319d56a 10011 integer_zero_node);
10012 }
10013
10014 return tmp;
10015 }
10016
cde061c1 10017 case BUILT_IN_ISFINITE:
b70bfd00 10018 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
10019 && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 10020 return omit_one_operand_loc (loc, type, integer_one_node, arg);
726069ba 10021
10022 if (TREE_CODE (arg) == REAL_CST)
10023 {
10024 r = TREE_REAL_CST (arg);
776a7bab 10025 return real_isfinite (&r) ? integer_one_node : integer_zero_node;
726069ba 10026 }
10027
10028 return NULL_TREE;
10029
10030 case BUILT_IN_ISNAN:
b70bfd00 10031 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 10032 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
726069ba 10033
10034 if (TREE_CODE (arg) == REAL_CST)
10035 {
10036 r = TREE_REAL_CST (arg);
10037 return real_isnan (&r) ? integer_one_node : integer_zero_node;
10038 }
10039
10040 arg = builtin_save_expr (arg);
389dd41b 10041 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
726069ba 10042
10043 default:
64db345d 10044 gcc_unreachable ();
726069ba 10045 }
10046}
10047
19fbe3a4 10048/* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...).
10049 This builtin will generate code to return the appropriate floating
10050 point classification depending on the value of the floating point
10051 number passed in. The possible return values must be supplied as
921b27c0 10052 int arguments to the call in the following order: FP_NAN, FP_INFINITE,
19fbe3a4 10053 FP_NORMAL, FP_SUBNORMAL and FP_ZERO. The ellipses is for exactly
10054 one floating point argument which is "type generic". */
10055
10056static tree
389dd41b 10057fold_builtin_fpclassify (location_t loc, tree exp)
19fbe3a4 10058{
921b27c0 10059 tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
10060 arg, type, res, tmp;
19fbe3a4 10061 enum machine_mode mode;
10062 REAL_VALUE_TYPE r;
10063 char buf[128];
48e1416a 10064
19fbe3a4 10065 /* Verify the required arguments in the original call. */
10066 if (!validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE,
10067 INTEGER_TYPE, INTEGER_TYPE,
10068 INTEGER_TYPE, REAL_TYPE, VOID_TYPE))
10069 return NULL_TREE;
48e1416a 10070
19fbe3a4 10071 fp_nan = CALL_EXPR_ARG (exp, 0);
921b27c0 10072 fp_infinite = CALL_EXPR_ARG (exp, 1);
19fbe3a4 10073 fp_normal = CALL_EXPR_ARG (exp, 2);
10074 fp_subnormal = CALL_EXPR_ARG (exp, 3);
10075 fp_zero = CALL_EXPR_ARG (exp, 4);
10076 arg = CALL_EXPR_ARG (exp, 5);
10077 type = TREE_TYPE (arg);
10078 mode = TYPE_MODE (type);
389dd41b 10079 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
19fbe3a4 10080
48e1416a 10081 /* fpclassify(x) ->
19fbe3a4 10082 isnan(x) ? FP_NAN :
921b27c0 10083 (fabs(x) == Inf ? FP_INFINITE :
19fbe3a4 10084 (fabs(x) >= DBL_MIN ? FP_NORMAL :
10085 (x == 0 ? FP_ZERO : FP_SUBNORMAL))). */
48e1416a 10086
389dd41b 10087 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
19fbe3a4 10088 build_real (type, dconst0));
389dd41b 10089 res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
10090 tmp, fp_zero, fp_subnormal);
19fbe3a4 10091
10092 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
10093 real_from_string (&r, buf);
389dd41b 10094 tmp = fold_build2_loc (loc, GE_EXPR, integer_type_node,
10095 arg, build_real (type, r));
10096 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, fp_normal, res);
48e1416a 10097
19fbe3a4 10098 if (HONOR_INFINITIES (mode))
10099 {
10100 real_inf (&r);
389dd41b 10101 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
19fbe3a4 10102 build_real (type, r));
389dd41b 10103 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
10104 fp_infinite, res);
19fbe3a4 10105 }
10106
10107 if (HONOR_NANS (mode))
10108 {
389dd41b 10109 tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
10110 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, res, fp_nan);
19fbe3a4 10111 }
48e1416a 10112
19fbe3a4 10113 return res;
10114}
10115
9bc9f15f 10116/* Fold a call to an unordered comparison function such as
d5019fe8 10117 __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function
c2f47e15 10118 being called and ARG0 and ARG1 are the arguments for the call.
726069ba 10119 UNORDERED_CODE and ORDERED_CODE are comparison codes that give
10120 the opposite of the desired result. UNORDERED_CODE is used
10121 for modes that can hold NaNs and ORDERED_CODE is used for
10122 the rest. */
9bc9f15f 10123
10124static tree
389dd41b 10125fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
9bc9f15f 10126 enum tree_code unordered_code,
10127 enum tree_code ordered_code)
10128{
859f903a 10129 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9bc9f15f 10130 enum tree_code code;
6978db0d 10131 tree type0, type1;
10132 enum tree_code code0, code1;
10133 tree cmp_type = NULL_TREE;
9bc9f15f 10134
6978db0d 10135 type0 = TREE_TYPE (arg0);
10136 type1 = TREE_TYPE (arg1);
a0c938f0 10137
6978db0d 10138 code0 = TREE_CODE (type0);
10139 code1 = TREE_CODE (type1);
a0c938f0 10140
6978db0d 10141 if (code0 == REAL_TYPE && code1 == REAL_TYPE)
10142 /* Choose the wider of two real types. */
10143 cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
10144 ? type0 : type1;
10145 else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
10146 cmp_type = type0;
10147 else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
10148 cmp_type = type1;
a0c938f0 10149
389dd41b 10150 arg0 = fold_convert_loc (loc, cmp_type, arg0);
10151 arg1 = fold_convert_loc (loc, cmp_type, arg1);
859f903a 10152
10153 if (unordered_code == UNORDERED_EXPR)
10154 {
b70bfd00 10155 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
389dd41b 10156 return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
10157 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
859f903a 10158 }
9bc9f15f 10159
b70bfd00 10160 code = HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
10161 : ordered_code;
389dd41b 10162 return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
10163 fold_build2_loc (loc, code, type, arg0, arg1));
9bc9f15f 10164}
10165
c2f47e15 10166/* Fold a call to built-in function FNDECL with 0 arguments.
10167 IGNORE is true if the result of the function call is ignored. This
10168 function returns NULL_TREE if no simplification was possible. */
650e4c94 10169
4ee9c684 10170static tree
389dd41b 10171fold_builtin_0 (location_t loc, tree fndecl, bool ignore ATTRIBUTE_UNUSED)
650e4c94 10172{
e9f80ff5 10173 tree type = TREE_TYPE (TREE_TYPE (fndecl));
c2f47e15 10174 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
189b3398 10175 switch (fcode)
650e4c94 10176 {
c2f47e15 10177 CASE_FLT_FN (BUILT_IN_INF):
10178 case BUILT_IN_INFD32:
10179 case BUILT_IN_INFD64:
10180 case BUILT_IN_INFD128:
389dd41b 10181 return fold_builtin_inf (loc, type, true);
7c2f0500 10182
c2f47e15 10183 CASE_FLT_FN (BUILT_IN_HUGE_VAL):
389dd41b 10184 return fold_builtin_inf (loc, type, false);
7c2f0500 10185
c2f47e15 10186 case BUILT_IN_CLASSIFY_TYPE:
10187 return fold_builtin_classify_type (NULL_TREE);
7c2f0500 10188
9e46467d 10189 case BUILT_IN_UNREACHABLE:
05f893e1 10190 if (flag_sanitize & SANITIZE_UNREACHABLE
10191 && (current_function_decl == NULL
10192 || !lookup_attribute ("no_sanitize_undefined",
10193 DECL_ATTRIBUTES (current_function_decl))))
9e46467d 10194 return ubsan_instrument_unreachable (loc);
10195 break;
10196
c2f47e15 10197 default:
10198 break;
10199 }
10200 return NULL_TREE;
10201}
7c2f0500 10202
c2f47e15 10203/* Fold a call to built-in function FNDECL with 1 argument, ARG0.
10204 IGNORE is true if the result of the function call is ignored. This
10205 function returns NULL_TREE if no simplification was possible. */
7c2f0500 10206
c2f47e15 10207static tree
389dd41b 10208fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
c2f47e15 10209{
10210 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10211 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10212 switch (fcode)
10213 {
650e4c94 10214 case BUILT_IN_CONSTANT_P:
7c2f0500 10215 {
c2f47e15 10216 tree val = fold_builtin_constant_p (arg0);
7c2f0500 10217
7c2f0500 10218 /* Gimplification will pull the CALL_EXPR for the builtin out of
10219 an if condition. When not optimizing, we'll not CSE it back.
10220 To avoid link error types of regressions, return false now. */
10221 if (!val && !optimize)
10222 val = integer_zero_node;
10223
10224 return val;
10225 }
650e4c94 10226
539a3a92 10227 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 10228 return fold_builtin_classify_type (arg0);
539a3a92 10229
650e4c94 10230 case BUILT_IN_STRLEN:
c7cbde74 10231 return fold_builtin_strlen (loc, type, arg0);
650e4c94 10232
4f35b1fc 10233 CASE_FLT_FN (BUILT_IN_FABS):
8aa32773 10234 case BUILT_IN_FABSD32:
10235 case BUILT_IN_FABSD64:
10236 case BUILT_IN_FABSD128:
389dd41b 10237 return fold_builtin_fabs (loc, arg0, type);
d1aade50 10238
10239 case BUILT_IN_ABS:
10240 case BUILT_IN_LABS:
10241 case BUILT_IN_LLABS:
10242 case BUILT_IN_IMAXABS:
389dd41b 10243 return fold_builtin_abs (loc, arg0, type);
c63f4ad3 10244
4f35b1fc 10245 CASE_FLT_FN (BUILT_IN_CONJ):
239d491a 10246 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10247 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10248 return fold_build1_loc (loc, CONJ_EXPR, type, arg0);
c2f47e15 10249 break;
36d3581d 10250
4f35b1fc 10251 CASE_FLT_FN (BUILT_IN_CREAL):
239d491a 10252 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10253 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10254 return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));;
c2f47e15 10255 break;
36d3581d 10256
4f35b1fc 10257 CASE_FLT_FN (BUILT_IN_CIMAG):
b0ce8887 10258 if (validate_arg (arg0, COMPLEX_TYPE)
10259 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10260 return non_lvalue_loc (loc, fold_build1_loc (loc, IMAGPART_EXPR, type, arg0));
c2f47e15 10261 break;
36d3581d 10262
503733d5 10263 CASE_FLT_FN (BUILT_IN_CCOS):
9af5ce0c 10264 return fold_builtin_ccos (loc, arg0, type, fndecl, /*hyper=*/ false);
48e1416a 10265
503733d5 10266 CASE_FLT_FN (BUILT_IN_CCOSH):
9af5ce0c 10267 return fold_builtin_ccos (loc, arg0, type, fndecl, /*hyper=*/ true);
48e1416a 10268
c2373fdb 10269 CASE_FLT_FN (BUILT_IN_CPROJ):
9af5ce0c 10270 return fold_builtin_cproj (loc, arg0, type);
c2373fdb 10271
239d491a 10272 CASE_FLT_FN (BUILT_IN_CSIN):
10273 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10274 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10275 return do_mpc_arg1 (arg0, type, mpc_sin);
c2f47e15 10276 break;
48e1416a 10277
239d491a 10278 CASE_FLT_FN (BUILT_IN_CSINH):
10279 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10280 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10281 return do_mpc_arg1 (arg0, type, mpc_sinh);
10282 break;
48e1416a 10283
239d491a 10284 CASE_FLT_FN (BUILT_IN_CTAN):
10285 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10286 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10287 return do_mpc_arg1 (arg0, type, mpc_tan);
10288 break;
48e1416a 10289
239d491a 10290 CASE_FLT_FN (BUILT_IN_CTANH):
10291 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10292 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10293 return do_mpc_arg1 (arg0, type, mpc_tanh);
10294 break;
48e1416a 10295
239d491a 10296 CASE_FLT_FN (BUILT_IN_CLOG):
10297 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10298 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10299 return do_mpc_arg1 (arg0, type, mpc_log);
10300 break;
48e1416a 10301
239d491a 10302 CASE_FLT_FN (BUILT_IN_CSQRT):
10303 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10304 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10305 return do_mpc_arg1 (arg0, type, mpc_sqrt);
10306 break;
48e1416a 10307
0e7e6e7f 10308 CASE_FLT_FN (BUILT_IN_CASIN):
10309 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10310 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10311 return do_mpc_arg1 (arg0, type, mpc_asin);
10312 break;
48e1416a 10313
0e7e6e7f 10314 CASE_FLT_FN (BUILT_IN_CACOS):
10315 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10316 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10317 return do_mpc_arg1 (arg0, type, mpc_acos);
10318 break;
48e1416a 10319
0e7e6e7f 10320 CASE_FLT_FN (BUILT_IN_CATAN):
10321 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10322 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10323 return do_mpc_arg1 (arg0, type, mpc_atan);
10324 break;
48e1416a 10325
0e7e6e7f 10326 CASE_FLT_FN (BUILT_IN_CASINH):
10327 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10328 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10329 return do_mpc_arg1 (arg0, type, mpc_asinh);
10330 break;
48e1416a 10331
0e7e6e7f 10332 CASE_FLT_FN (BUILT_IN_CACOSH):
10333 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10334 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10335 return do_mpc_arg1 (arg0, type, mpc_acosh);
10336 break;
48e1416a 10337
0e7e6e7f 10338 CASE_FLT_FN (BUILT_IN_CATANH):
10339 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10340 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10341 return do_mpc_arg1 (arg0, type, mpc_atanh);
10342 break;
48e1416a 10343
4f35b1fc 10344 CASE_FLT_FN (BUILT_IN_CABS):
389dd41b 10345 return fold_builtin_cabs (loc, arg0, type, fndecl);
c63f4ad3 10346
abe4dcf6 10347 CASE_FLT_FN (BUILT_IN_CARG):
389dd41b 10348 return fold_builtin_carg (loc, arg0, type);
abe4dcf6 10349
4f35b1fc 10350 CASE_FLT_FN (BUILT_IN_SQRT):
389dd41b 10351 return fold_builtin_sqrt (loc, arg0, type);
805e22b2 10352
4f35b1fc 10353 CASE_FLT_FN (BUILT_IN_CBRT):
389dd41b 10354 return fold_builtin_cbrt (loc, arg0, type);
3bc5c41b 10355
728bac60 10356 CASE_FLT_FN (BUILT_IN_ASIN):
c2f47e15 10357 if (validate_arg (arg0, REAL_TYPE))
10358 return do_mpfr_arg1 (arg0, type, mpfr_asin,
728bac60 10359 &dconstm1, &dconst1, true);
10360 break;
10361
10362 CASE_FLT_FN (BUILT_IN_ACOS):
c2f47e15 10363 if (validate_arg (arg0, REAL_TYPE))
10364 return do_mpfr_arg1 (arg0, type, mpfr_acos,
728bac60 10365 &dconstm1, &dconst1, true);
10366 break;
10367
10368 CASE_FLT_FN (BUILT_IN_ATAN):
c2f47e15 10369 if (validate_arg (arg0, REAL_TYPE))
10370 return do_mpfr_arg1 (arg0, type, mpfr_atan, NULL, NULL, 0);
728bac60 10371 break;
10372
10373 CASE_FLT_FN (BUILT_IN_ASINH):
c2f47e15 10374 if (validate_arg (arg0, REAL_TYPE))
10375 return do_mpfr_arg1 (arg0, type, mpfr_asinh, NULL, NULL, 0);
728bac60 10376 break;
10377
10378 CASE_FLT_FN (BUILT_IN_ACOSH):
c2f47e15 10379 if (validate_arg (arg0, REAL_TYPE))
10380 return do_mpfr_arg1 (arg0, type, mpfr_acosh,
728bac60 10381 &dconst1, NULL, true);
10382 break;
10383
10384 CASE_FLT_FN (BUILT_IN_ATANH):
c2f47e15 10385 if (validate_arg (arg0, REAL_TYPE))
10386 return do_mpfr_arg1 (arg0, type, mpfr_atanh,
728bac60 10387 &dconstm1, &dconst1, false);
10388 break;
10389
4f35b1fc 10390 CASE_FLT_FN (BUILT_IN_SIN):
c2f47e15 10391 if (validate_arg (arg0, REAL_TYPE))
10392 return do_mpfr_arg1 (arg0, type, mpfr_sin, NULL, NULL, 0);
728bac60 10393 break;
77e89269 10394
4f35b1fc 10395 CASE_FLT_FN (BUILT_IN_COS):
389dd41b 10396 return fold_builtin_cos (loc, arg0, type, fndecl);
77e89269 10397
728bac60 10398 CASE_FLT_FN (BUILT_IN_TAN):
c2f47e15 10399 return fold_builtin_tan (arg0, type);
d735c391 10400
c5bb2c4b 10401 CASE_FLT_FN (BUILT_IN_CEXP):
389dd41b 10402 return fold_builtin_cexp (loc, arg0, type);
c5bb2c4b 10403
d735c391 10404 CASE_FLT_FN (BUILT_IN_CEXPI):
c2f47e15 10405 if (validate_arg (arg0, REAL_TYPE))
10406 return do_mpfr_sincos (arg0, NULL_TREE, NULL_TREE);
10407 break;
d92f994c 10408
728bac60 10409 CASE_FLT_FN (BUILT_IN_SINH):
c2f47e15 10410 if (validate_arg (arg0, REAL_TYPE))
10411 return do_mpfr_arg1 (arg0, type, mpfr_sinh, NULL, NULL, 0);
728bac60 10412 break;
10413
10414 CASE_FLT_FN (BUILT_IN_COSH):
389dd41b 10415 return fold_builtin_cosh (loc, arg0, type, fndecl);
728bac60 10416
10417 CASE_FLT_FN (BUILT_IN_TANH):
c2f47e15 10418 if (validate_arg (arg0, REAL_TYPE))
10419 return do_mpfr_arg1 (arg0, type, mpfr_tanh, NULL, NULL, 0);
728bac60 10420 break;
10421
29f4cd78 10422 CASE_FLT_FN (BUILT_IN_ERF):
c2f47e15 10423 if (validate_arg (arg0, REAL_TYPE))
10424 return do_mpfr_arg1 (arg0, type, mpfr_erf, NULL, NULL, 0);
29f4cd78 10425 break;
10426
10427 CASE_FLT_FN (BUILT_IN_ERFC):
c2f47e15 10428 if (validate_arg (arg0, REAL_TYPE))
10429 return do_mpfr_arg1 (arg0, type, mpfr_erfc, NULL, NULL, 0);
29f4cd78 10430 break;
10431
32dba52b 10432 CASE_FLT_FN (BUILT_IN_TGAMMA):
c2f47e15 10433 if (validate_arg (arg0, REAL_TYPE))
10434 return do_mpfr_arg1 (arg0, type, mpfr_gamma, NULL, NULL, 0);
32dba52b 10435 break;
48e1416a 10436
4f35b1fc 10437 CASE_FLT_FN (BUILT_IN_EXP):
389dd41b 10438 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp);
467214fd 10439
4f35b1fc 10440 CASE_FLT_FN (BUILT_IN_EXP2):
389dd41b 10441 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp2);
467214fd 10442
4f35b1fc 10443 CASE_FLT_FN (BUILT_IN_EXP10):
10444 CASE_FLT_FN (BUILT_IN_POW10):
389dd41b 10445 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp10);
467214fd 10446
29f4cd78 10447 CASE_FLT_FN (BUILT_IN_EXPM1):
c2f47e15 10448 if (validate_arg (arg0, REAL_TYPE))
10449 return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0);
29f4cd78 10450 break;
48e1416a 10451
4f35b1fc 10452 CASE_FLT_FN (BUILT_IN_LOG):
389dd41b 10453 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log);
467214fd 10454
4f35b1fc 10455 CASE_FLT_FN (BUILT_IN_LOG2):
389dd41b 10456 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log2);
467214fd 10457
4f35b1fc 10458 CASE_FLT_FN (BUILT_IN_LOG10):
389dd41b 10459 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log10);
29f4cd78 10460
10461 CASE_FLT_FN (BUILT_IN_LOG1P):
c2f47e15 10462 if (validate_arg (arg0, REAL_TYPE))
10463 return do_mpfr_arg1 (arg0, type, mpfr_log1p,
29f4cd78 10464 &dconstm1, NULL, false);
10465 break;
805e22b2 10466
65dd1378 10467 CASE_FLT_FN (BUILT_IN_J0):
10468 if (validate_arg (arg0, REAL_TYPE))
10469 return do_mpfr_arg1 (arg0, type, mpfr_j0,
10470 NULL, NULL, 0);
10471 break;
10472
10473 CASE_FLT_FN (BUILT_IN_J1):
10474 if (validate_arg (arg0, REAL_TYPE))
10475 return do_mpfr_arg1 (arg0, type, mpfr_j1,
10476 NULL, NULL, 0);
10477 break;
6ff9eeff 10478
10479 CASE_FLT_FN (BUILT_IN_Y0):
10480 if (validate_arg (arg0, REAL_TYPE))
10481 return do_mpfr_arg1 (arg0, type, mpfr_y0,
10482 &dconst0, NULL, false);
10483 break;
10484
10485 CASE_FLT_FN (BUILT_IN_Y1):
10486 if (validate_arg (arg0, REAL_TYPE))
10487 return do_mpfr_arg1 (arg0, type, mpfr_y1,
10488 &dconst0, NULL, false);
10489 break;
65dd1378 10490
4f35b1fc 10491 CASE_FLT_FN (BUILT_IN_NAN):
c4503c0a 10492 case BUILT_IN_NAND32:
10493 case BUILT_IN_NAND64:
10494 case BUILT_IN_NAND128:
c2f47e15 10495 return fold_builtin_nan (arg0, type, true);
b0db7939 10496
4f35b1fc 10497 CASE_FLT_FN (BUILT_IN_NANS):
c2f47e15 10498 return fold_builtin_nan (arg0, type, false);
b0db7939 10499
4f35b1fc 10500 CASE_FLT_FN (BUILT_IN_FLOOR):
389dd41b 10501 return fold_builtin_floor (loc, fndecl, arg0);
277f8dd2 10502
4f35b1fc 10503 CASE_FLT_FN (BUILT_IN_CEIL):
389dd41b 10504 return fold_builtin_ceil (loc, fndecl, arg0);
277f8dd2 10505
4f35b1fc 10506 CASE_FLT_FN (BUILT_IN_TRUNC):
389dd41b 10507 return fold_builtin_trunc (loc, fndecl, arg0);
277f8dd2 10508
4f35b1fc 10509 CASE_FLT_FN (BUILT_IN_ROUND):
389dd41b 10510 return fold_builtin_round (loc, fndecl, arg0);
89ab3887 10511
4f35b1fc 10512 CASE_FLT_FN (BUILT_IN_NEARBYINT):
10513 CASE_FLT_FN (BUILT_IN_RINT):
389dd41b 10514 return fold_trunc_transparent_mathfn (loc, fndecl, arg0);
6528f4f4 10515
80ff6494 10516 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 10517 CASE_FLT_FN (BUILT_IN_LCEIL):
10518 CASE_FLT_FN (BUILT_IN_LLCEIL):
10519 CASE_FLT_FN (BUILT_IN_LFLOOR):
80ff6494 10520 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 10521 CASE_FLT_FN (BUILT_IN_LLFLOOR):
80ff6494 10522 CASE_FLT_FN (BUILT_IN_IROUND):
a0c938f0 10523 CASE_FLT_FN (BUILT_IN_LROUND):
4f35b1fc 10524 CASE_FLT_FN (BUILT_IN_LLROUND):
389dd41b 10525 return fold_builtin_int_roundingfn (loc, fndecl, arg0);
34f17811 10526
80ff6494 10527 CASE_FLT_FN (BUILT_IN_IRINT):
4f35b1fc 10528 CASE_FLT_FN (BUILT_IN_LRINT):
10529 CASE_FLT_FN (BUILT_IN_LLRINT):
389dd41b 10530 return fold_fixed_mathfn (loc, fndecl, arg0);
9ed65c7f 10531
74bdbe96 10532 case BUILT_IN_BSWAP16:
42791117 10533 case BUILT_IN_BSWAP32:
10534 case BUILT_IN_BSWAP64:
c2f47e15 10535 return fold_builtin_bswap (fndecl, arg0);
42791117 10536
4f35b1fc 10537 CASE_INT_FN (BUILT_IN_FFS):
10538 CASE_INT_FN (BUILT_IN_CLZ):
10539 CASE_INT_FN (BUILT_IN_CTZ):
6aaa1f9e 10540 CASE_INT_FN (BUILT_IN_CLRSB):
4f35b1fc 10541 CASE_INT_FN (BUILT_IN_POPCOUNT):
10542 CASE_INT_FN (BUILT_IN_PARITY):
c2f47e15 10543 return fold_builtin_bitop (fndecl, arg0);
9c8a1629 10544
4f35b1fc 10545 CASE_FLT_FN (BUILT_IN_SIGNBIT):
389dd41b 10546 return fold_builtin_signbit (loc, arg0, type);
27f261ef 10547
cb2b9385 10548 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
389dd41b 10549 return fold_builtin_significand (loc, arg0, type);
cb2b9385 10550
10551 CASE_FLT_FN (BUILT_IN_ILOGB):
10552 CASE_FLT_FN (BUILT_IN_LOGB):
389dd41b 10553 return fold_builtin_logb (loc, arg0, type);
cb2b9385 10554
d49367d4 10555 case BUILT_IN_ISASCII:
389dd41b 10556 return fold_builtin_isascii (loc, arg0);
d49367d4 10557
10558 case BUILT_IN_TOASCII:
389dd41b 10559 return fold_builtin_toascii (loc, arg0);
d49367d4 10560
df1cf42e 10561 case BUILT_IN_ISDIGIT:
389dd41b 10562 return fold_builtin_isdigit (loc, arg0);
467214fd 10563
4f35b1fc 10564 CASE_FLT_FN (BUILT_IN_FINITE):
c4503c0a 10565 case BUILT_IN_FINITED32:
10566 case BUILT_IN_FINITED64:
10567 case BUILT_IN_FINITED128:
cde061c1 10568 case BUILT_IN_ISFINITE:
a65c4d64 10569 {
10570 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISFINITE);
10571 if (ret)
10572 return ret;
10573 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10574 }
726069ba 10575
4f35b1fc 10576 CASE_FLT_FN (BUILT_IN_ISINF):
c4503c0a 10577 case BUILT_IN_ISINFD32:
10578 case BUILT_IN_ISINFD64:
10579 case BUILT_IN_ISINFD128:
a65c4d64 10580 {
10581 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF);
10582 if (ret)
10583 return ret;
10584 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10585 }
10586
10587 case BUILT_IN_ISNORMAL:
10588 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
726069ba 10589
c319d56a 10590 case BUILT_IN_ISINF_SIGN:
389dd41b 10591 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF_SIGN);
c319d56a 10592
4f35b1fc 10593 CASE_FLT_FN (BUILT_IN_ISNAN):
c4503c0a 10594 case BUILT_IN_ISNAND32:
10595 case BUILT_IN_ISNAND64:
10596 case BUILT_IN_ISNAND128:
389dd41b 10597 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
c2f47e15 10598
10599 case BUILT_IN_PRINTF:
10600 case BUILT_IN_PRINTF_UNLOCKED:
10601 case BUILT_IN_VPRINTF:
389dd41b 10602 return fold_builtin_printf (loc, fndecl, arg0, NULL_TREE, ignore, fcode);
c2f47e15 10603
663870fc 10604 case BUILT_IN_FREE:
10605 if (integer_zerop (arg0))
10606 return build_empty_stmt (loc);
10607 break;
10608
c2f47e15 10609 default:
10610 break;
10611 }
10612
10613 return NULL_TREE;
10614
10615}
10616
10617/* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1.
10618 IGNORE is true if the result of the function call is ignored. This
10619 function returns NULL_TREE if no simplification was possible. */
10620
10621static tree
389dd41b 10622fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore)
c2f47e15 10623{
10624 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10625 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10626
10627 switch (fcode)
10628 {
65dd1378 10629 CASE_FLT_FN (BUILT_IN_JN):
10630 if (validate_arg (arg0, INTEGER_TYPE)
10631 && validate_arg (arg1, REAL_TYPE))
10632 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_jn, NULL, 0);
10633 break;
6ff9eeff 10634
10635 CASE_FLT_FN (BUILT_IN_YN):
10636 if (validate_arg (arg0, INTEGER_TYPE)
10637 && validate_arg (arg1, REAL_TYPE))
10638 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_yn,
10639 &dconst0, false);
10640 break;
e5407ca6 10641
10642 CASE_FLT_FN (BUILT_IN_DREM):
10643 CASE_FLT_FN (BUILT_IN_REMAINDER):
10644 if (validate_arg (arg0, REAL_TYPE)
9af5ce0c 10645 && validate_arg (arg1, REAL_TYPE))
e5407ca6 10646 return do_mpfr_arg2 (arg0, arg1, type, mpfr_remainder);
10647 break;
e84da7c1 10648
10649 CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
10650 CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
10651 if (validate_arg (arg0, REAL_TYPE)
9af5ce0c 10652 && validate_arg (arg1, POINTER_TYPE))
e84da7c1 10653 return do_mpfr_lgamma_r (arg0, arg1, type);
10654 break;
c2f47e15 10655
10656 CASE_FLT_FN (BUILT_IN_ATAN2):
10657 if (validate_arg (arg0, REAL_TYPE)
9af5ce0c 10658 && validate_arg (arg1, REAL_TYPE))
c2f47e15 10659 return do_mpfr_arg2 (arg0, arg1, type, mpfr_atan2);
10660 break;
10661
10662 CASE_FLT_FN (BUILT_IN_FDIM):
10663 if (validate_arg (arg0, REAL_TYPE)
9af5ce0c 10664 && validate_arg (arg1, REAL_TYPE))
c2f47e15 10665 return do_mpfr_arg2 (arg0, arg1, type, mpfr_dim);
10666 break;
10667
10668 CASE_FLT_FN (BUILT_IN_HYPOT):
389dd41b 10669 return fold_builtin_hypot (loc, fndecl, arg0, arg1, type);
c2f47e15 10670
c699fab8 10671 CASE_FLT_FN (BUILT_IN_CPOW):
10672 if (validate_arg (arg0, COMPLEX_TYPE)
10673 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
10674 && validate_arg (arg1, COMPLEX_TYPE)
48e1416a 10675 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE)
652d9409 10676 return do_mpc_arg2 (arg0, arg1, type, /*do_nonfinite=*/ 0, mpc_pow);
c699fab8 10677 break;
c699fab8 10678
7587301b 10679 CASE_FLT_FN (BUILT_IN_LDEXP):
389dd41b 10680 return fold_builtin_load_exponent (loc, arg0, arg1, type, /*ldexp=*/true);
7587301b 10681 CASE_FLT_FN (BUILT_IN_SCALBN):
10682 CASE_FLT_FN (BUILT_IN_SCALBLN):
389dd41b 10683 return fold_builtin_load_exponent (loc, arg0, arg1,
10684 type, /*ldexp=*/false);
7587301b 10685
3838b9ae 10686 CASE_FLT_FN (BUILT_IN_FREXP):
389dd41b 10687 return fold_builtin_frexp (loc, arg0, arg1, type);
3838b9ae 10688
ebf8b4f5 10689 CASE_FLT_FN (BUILT_IN_MODF):
389dd41b 10690 return fold_builtin_modf (loc, arg0, arg1, type);
ebf8b4f5 10691
c2f47e15 10692 case BUILT_IN_BZERO:
389dd41b 10693 return fold_builtin_bzero (loc, arg0, arg1, ignore);
c2f47e15 10694
10695 case BUILT_IN_FPUTS:
389dd41b 10696 return fold_builtin_fputs (loc, arg0, arg1, ignore, false, NULL_TREE);
c2f47e15 10697
10698 case BUILT_IN_FPUTS_UNLOCKED:
389dd41b 10699 return fold_builtin_fputs (loc, arg0, arg1, ignore, true, NULL_TREE);
c2f47e15 10700
10701 case BUILT_IN_STRSTR:
389dd41b 10702 return fold_builtin_strstr (loc, arg0, arg1, type);
c2f47e15 10703
10704 case BUILT_IN_STRCAT:
389dd41b 10705 return fold_builtin_strcat (loc, arg0, arg1);
c2f47e15 10706
10707 case BUILT_IN_STRSPN:
389dd41b 10708 return fold_builtin_strspn (loc, arg0, arg1);
c2f47e15 10709
10710 case BUILT_IN_STRCSPN:
389dd41b 10711 return fold_builtin_strcspn (loc, arg0, arg1);
c2f47e15 10712
10713 case BUILT_IN_STRCHR:
10714 case BUILT_IN_INDEX:
389dd41b 10715 return fold_builtin_strchr (loc, arg0, arg1, type);
c2f47e15 10716
10717 case BUILT_IN_STRRCHR:
10718 case BUILT_IN_RINDEX:
389dd41b 10719 return fold_builtin_strrchr (loc, arg0, arg1, type);
c2f47e15 10720
10721 case BUILT_IN_STRCPY:
389dd41b 10722 return fold_builtin_strcpy (loc, fndecl, arg0, arg1, NULL_TREE);
c2f47e15 10723
c8b17b2e 10724 case BUILT_IN_STPCPY:
10725 if (ignore)
10726 {
b9a16870 10727 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
c8b17b2e 10728 if (!fn)
10729 break;
10730
389dd41b 10731 return build_call_expr_loc (loc, fn, 2, arg0, arg1);
c8b17b2e 10732 }
a65c4d64 10733 else
10734 return fold_builtin_stpcpy (loc, fndecl, arg0, arg1);
c8b17b2e 10735 break;
10736
c2f47e15 10737 case BUILT_IN_STRCMP:
389dd41b 10738 return fold_builtin_strcmp (loc, arg0, arg1);
c2f47e15 10739
10740 case BUILT_IN_STRPBRK:
389dd41b 10741 return fold_builtin_strpbrk (loc, arg0, arg1, type);
c2f47e15 10742
10743 case BUILT_IN_EXPECT:
389dd41b 10744 return fold_builtin_expect (loc, arg0, arg1);
c2f47e15 10745
10746 CASE_FLT_FN (BUILT_IN_POW):
389dd41b 10747 return fold_builtin_pow (loc, fndecl, arg0, arg1, type);
c2f47e15 10748
10749 CASE_FLT_FN (BUILT_IN_POWI):
389dd41b 10750 return fold_builtin_powi (loc, fndecl, arg0, arg1, type);
c2f47e15 10751
10752 CASE_FLT_FN (BUILT_IN_COPYSIGN):
389dd41b 10753 return fold_builtin_copysign (loc, fndecl, arg0, arg1, type);
c2f47e15 10754
10755 CASE_FLT_FN (BUILT_IN_FMIN):
389dd41b 10756 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/false);
c2f47e15 10757
10758 CASE_FLT_FN (BUILT_IN_FMAX):
389dd41b 10759 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/true);
726069ba 10760
9bc9f15f 10761 case BUILT_IN_ISGREATER:
389dd41b 10762 return fold_builtin_unordered_cmp (loc, fndecl,
10763 arg0, arg1, UNLE_EXPR, LE_EXPR);
9bc9f15f 10764 case BUILT_IN_ISGREATEREQUAL:
389dd41b 10765 return fold_builtin_unordered_cmp (loc, fndecl,
10766 arg0, arg1, UNLT_EXPR, LT_EXPR);
9bc9f15f 10767 case BUILT_IN_ISLESS:
389dd41b 10768 return fold_builtin_unordered_cmp (loc, fndecl,
10769 arg0, arg1, UNGE_EXPR, GE_EXPR);
9bc9f15f 10770 case BUILT_IN_ISLESSEQUAL:
389dd41b 10771 return fold_builtin_unordered_cmp (loc, fndecl,
10772 arg0, arg1, UNGT_EXPR, GT_EXPR);
9bc9f15f 10773 case BUILT_IN_ISLESSGREATER:
389dd41b 10774 return fold_builtin_unordered_cmp (loc, fndecl,
10775 arg0, arg1, UNEQ_EXPR, EQ_EXPR);
9bc9f15f 10776 case BUILT_IN_ISUNORDERED:
389dd41b 10777 return fold_builtin_unordered_cmp (loc, fndecl,
10778 arg0, arg1, UNORDERED_EXPR,
d5019fe8 10779 NOP_EXPR);
9bc9f15f 10780
7c2f0500 10781 /* We do the folding for va_start in the expander. */
10782 case BUILT_IN_VA_START:
10783 break;
f0613857 10784
c2f47e15 10785 case BUILT_IN_SPRINTF:
389dd41b 10786 return fold_builtin_sprintf (loc, arg0, arg1, NULL_TREE, ignore);
c2f47e15 10787
0a39fd54 10788 case BUILT_IN_OBJECT_SIZE:
c2f47e15 10789 return fold_builtin_object_size (arg0, arg1);
0a39fd54 10790
10791 case BUILT_IN_PRINTF:
10792 case BUILT_IN_PRINTF_UNLOCKED:
10793 case BUILT_IN_VPRINTF:
389dd41b 10794 return fold_builtin_printf (loc, fndecl, arg0, arg1, ignore, fcode);
c2f47e15 10795
0a39fd54 10796 case BUILT_IN_PRINTF_CHK:
10797 case BUILT_IN_VPRINTF_CHK:
c2f47e15 10798 if (!validate_arg (arg0, INTEGER_TYPE)
10799 || TREE_SIDE_EFFECTS (arg0))
10800 return NULL_TREE;
10801 else
389dd41b 10802 return fold_builtin_printf (loc, fndecl,
10803 arg1, NULL_TREE, ignore, fcode);
c2f47e15 10804 break;
0a39fd54 10805
10806 case BUILT_IN_FPRINTF:
10807 case BUILT_IN_FPRINTF_UNLOCKED:
10808 case BUILT_IN_VFPRINTF:
389dd41b 10809 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, NULL_TREE,
c2f47e15 10810 ignore, fcode);
10811
1cd6e20d 10812 case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
10813 return fold_builtin_atomic_always_lock_free (arg0, arg1);
10814
10815 case BUILT_IN_ATOMIC_IS_LOCK_FREE:
10816 return fold_builtin_atomic_is_lock_free (arg0, arg1);
10817
c2f47e15 10818 default:
10819 break;
10820 }
10821 return NULL_TREE;
10822}
10823
10824/* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
10825 and ARG2. IGNORE is true if the result of the function call is ignored.
10826 This function returns NULL_TREE if no simplification was possible. */
10827
10828static tree
389dd41b 10829fold_builtin_3 (location_t loc, tree fndecl,
10830 tree arg0, tree arg1, tree arg2, bool ignore)
c2f47e15 10831{
10832 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10833 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10834 switch (fcode)
10835 {
10836
10837 CASE_FLT_FN (BUILT_IN_SINCOS):
389dd41b 10838 return fold_builtin_sincos (loc, arg0, arg1, arg2);
c2f47e15 10839
10840 CASE_FLT_FN (BUILT_IN_FMA):
b9be572e 10841 return fold_builtin_fma (loc, arg0, arg1, arg2, type);
c2f47e15 10842 break;
10843
e5407ca6 10844 CASE_FLT_FN (BUILT_IN_REMQUO):
10845 if (validate_arg (arg0, REAL_TYPE)
9af5ce0c 10846 && validate_arg (arg1, REAL_TYPE)
10847 && validate_arg (arg2, POINTER_TYPE))
e5407ca6 10848 return do_mpfr_remquo (arg0, arg1, arg2);
10849 break;
e5407ca6 10850
c2f47e15 10851 case BUILT_IN_MEMSET:
389dd41b 10852 return fold_builtin_memset (loc, arg0, arg1, arg2, type, ignore);
c2f47e15 10853
10854 case BUILT_IN_BCOPY:
389dd41b 10855 return fold_builtin_memory_op (loc, arg1, arg0, arg2,
10856 void_type_node, true, /*endp=*/3);
c2f47e15 10857
10858 case BUILT_IN_MEMCPY:
389dd41b 10859 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10860 type, ignore, /*endp=*/0);
c2f47e15 10861
10862 case BUILT_IN_MEMPCPY:
389dd41b 10863 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10864 type, ignore, /*endp=*/1);
c2f47e15 10865
10866 case BUILT_IN_MEMMOVE:
389dd41b 10867 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10868 type, ignore, /*endp=*/3);
c2f47e15 10869
10870 case BUILT_IN_STRNCAT:
389dd41b 10871 return fold_builtin_strncat (loc, arg0, arg1, arg2);
c2f47e15 10872
10873 case BUILT_IN_STRNCPY:
389dd41b 10874 return fold_builtin_strncpy (loc, fndecl, arg0, arg1, arg2, NULL_TREE);
c2f47e15 10875
10876 case BUILT_IN_STRNCMP:
389dd41b 10877 return fold_builtin_strncmp (loc, arg0, arg1, arg2);
c2f47e15 10878
7959b13b 10879 case BUILT_IN_MEMCHR:
389dd41b 10880 return fold_builtin_memchr (loc, arg0, arg1, arg2, type);
7959b13b 10881
c2f47e15 10882 case BUILT_IN_BCMP:
10883 case BUILT_IN_MEMCMP:
389dd41b 10884 return fold_builtin_memcmp (loc, arg0, arg1, arg2);;
c2f47e15 10885
10886 case BUILT_IN_SPRINTF:
389dd41b 10887 return fold_builtin_sprintf (loc, arg0, arg1, arg2, ignore);
c2f47e15 10888
750d7b16 10889 case BUILT_IN_SNPRINTF:
10890 return fold_builtin_snprintf (loc, arg0, arg1, arg2, NULL_TREE, ignore);
10891
c2f47e15 10892 case BUILT_IN_STRCPY_CHK:
10893 case BUILT_IN_STPCPY_CHK:
389dd41b 10894 return fold_builtin_stxcpy_chk (loc, fndecl, arg0, arg1, arg2, NULL_TREE,
c2f47e15 10895 ignore, fcode);
10896
10897 case BUILT_IN_STRCAT_CHK:
389dd41b 10898 return fold_builtin_strcat_chk (loc, fndecl, arg0, arg1, arg2);
c2f47e15 10899
10900 case BUILT_IN_PRINTF_CHK:
10901 case BUILT_IN_VPRINTF_CHK:
10902 if (!validate_arg (arg0, INTEGER_TYPE)
10903 || TREE_SIDE_EFFECTS (arg0))
10904 return NULL_TREE;
10905 else
389dd41b 10906 return fold_builtin_printf (loc, fndecl, arg1, arg2, ignore, fcode);
c2f47e15 10907 break;
10908
10909 case BUILT_IN_FPRINTF:
10910 case BUILT_IN_FPRINTF_UNLOCKED:
10911 case BUILT_IN_VFPRINTF:
389dd41b 10912 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, arg2,
10913 ignore, fcode);
c2f47e15 10914
0a39fd54 10915 case BUILT_IN_FPRINTF_CHK:
10916 case BUILT_IN_VFPRINTF_CHK:
c2f47e15 10917 if (!validate_arg (arg1, INTEGER_TYPE)
10918 || TREE_SIDE_EFFECTS (arg1))
10919 return NULL_TREE;
10920 else
389dd41b 10921 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, NULL_TREE,
c2f47e15 10922 ignore, fcode);
0a39fd54 10923
650e4c94 10924 default:
10925 break;
10926 }
c2f47e15 10927 return NULL_TREE;
10928}
650e4c94 10929
c2f47e15 10930/* Fold a call to built-in function FNDECL with 4 arguments, ARG0, ARG1,
10931 ARG2, and ARG3. IGNORE is true if the result of the function call is
10932 ignored. This function returns NULL_TREE if no simplification was
10933 possible. */
48e1416a 10934
c2f47e15 10935static tree
389dd41b 10936fold_builtin_4 (location_t loc, tree fndecl,
10937 tree arg0, tree arg1, tree arg2, tree arg3, bool ignore)
c2f47e15 10938{
10939 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10940
10941 switch (fcode)
10942 {
10943 case BUILT_IN_MEMCPY_CHK:
10944 case BUILT_IN_MEMPCPY_CHK:
10945 case BUILT_IN_MEMMOVE_CHK:
10946 case BUILT_IN_MEMSET_CHK:
389dd41b 10947 return fold_builtin_memory_chk (loc, fndecl, arg0, arg1, arg2, arg3,
c2f47e15 10948 NULL_TREE, ignore,
10949 DECL_FUNCTION_CODE (fndecl));
10950
10951 case BUILT_IN_STRNCPY_CHK:
1063acde 10952 case BUILT_IN_STPNCPY_CHK:
10953 return fold_builtin_stxncpy_chk (loc, arg0, arg1, arg2, arg3, NULL_TREE,
10954 ignore, fcode);
c2f47e15 10955
10956 case BUILT_IN_STRNCAT_CHK:
389dd41b 10957 return fold_builtin_strncat_chk (loc, fndecl, arg0, arg1, arg2, arg3);
c2f47e15 10958
750d7b16 10959 case BUILT_IN_SNPRINTF:
10960 return fold_builtin_snprintf (loc, arg0, arg1, arg2, arg3, ignore);
10961
c2f47e15 10962 case BUILT_IN_FPRINTF_CHK:
10963 case BUILT_IN_VFPRINTF_CHK:
10964 if (!validate_arg (arg1, INTEGER_TYPE)
10965 || TREE_SIDE_EFFECTS (arg1))
10966 return NULL_TREE;
10967 else
389dd41b 10968 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, arg3,
c2f47e15 10969 ignore, fcode);
10970 break;
10971
10972 default:
10973 break;
10974 }
10975 return NULL_TREE;
10976}
10977
10978/* Fold a call to built-in function FNDECL. ARGS is an array of NARGS
10979 arguments, where NARGS <= 4. IGNORE is true if the result of the
10980 function call is ignored. This function returns NULL_TREE if no
10981 simplification was possible. Note that this only folds builtins with
10982 fixed argument patterns. Foldings that do varargs-to-varargs
10983 transformations, or that match calls with more than 4 arguments,
10984 need to be handled with fold_builtin_varargs instead. */
48e1416a 10985
c2f47e15 10986#define MAX_ARGS_TO_FOLD_BUILTIN 4
48e1416a 10987
c2f47e15 10988static tree
389dd41b 10989fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool ignore)
c2f47e15 10990{
10991 tree ret = NULL_TREE;
a7f5bb2d 10992
c2f47e15 10993 switch (nargs)
10994 {
10995 case 0:
389dd41b 10996 ret = fold_builtin_0 (loc, fndecl, ignore);
c2f47e15 10997 break;
10998 case 1:
389dd41b 10999 ret = fold_builtin_1 (loc, fndecl, args[0], ignore);
c2f47e15 11000 break;
11001 case 2:
389dd41b 11002 ret = fold_builtin_2 (loc, fndecl, args[0], args[1], ignore);
c2f47e15 11003 break;
11004 case 3:
389dd41b 11005 ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2], ignore);
c2f47e15 11006 break;
11007 case 4:
389dd41b 11008 ret = fold_builtin_4 (loc, fndecl, args[0], args[1], args[2], args[3],
c2f47e15 11009 ignore);
11010 break;
11011 default:
11012 break;
11013 }
11014 if (ret)
11015 {
75a70cf9 11016 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
389dd41b 11017 SET_EXPR_LOCATION (ret, loc);
c2f47e15 11018 TREE_NO_WARNING (ret) = 1;
11019 return ret;
11020 }
11021 return NULL_TREE;
11022}
11023
0e80b01d 11024/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
11025 list ARGS along with N new arguments in NEWARGS. SKIP is the number
11026 of arguments in ARGS to be omitted. OLDNARGS is the number of
11027 elements in ARGS. */
c2f47e15 11028
11029static tree
0e80b01d 11030rewrite_call_expr_valist (location_t loc, int oldnargs, tree *args,
11031 int skip, tree fndecl, int n, va_list newargs)
c2f47e15 11032{
0e80b01d 11033 int nargs = oldnargs - skip + n;
11034 tree *buffer;
c2f47e15 11035
0e80b01d 11036 if (n > 0)
c2f47e15 11037 {
0e80b01d 11038 int i, j;
c2f47e15 11039
0e80b01d 11040 buffer = XALLOCAVEC (tree, nargs);
11041 for (i = 0; i < n; i++)
11042 buffer[i] = va_arg (newargs, tree);
11043 for (j = skip; j < oldnargs; j++, i++)
11044 buffer[i] = args[j];
11045 }
11046 else
11047 buffer = args + skip;
19fbe3a4 11048
0e80b01d 11049 return build_call_expr_loc_array (loc, fndecl, nargs, buffer);
11050}
c2f47e15 11051
0e80b01d 11052/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
11053 list ARGS along with N new arguments specified as the "..."
11054 parameters. SKIP is the number of arguments in ARGS to be omitted.
11055 OLDNARGS is the number of elements in ARGS. */
11056
11057static tree
11058rewrite_call_expr_array (location_t loc, int oldnargs, tree *args,
11059 int skip, tree fndecl, int n, ...)
11060{
11061 va_list ap;
11062 tree t;
11063
11064 va_start (ap, n);
11065 t = rewrite_call_expr_valist (loc, oldnargs, args, skip, fndecl, n, ap);
11066 va_end (ap);
11067
11068 return t;
650e4c94 11069}
7e15618b 11070
198622c0 11071/* Return true if FNDECL shouldn't be folded right now.
11072 If a built-in function has an inline attribute always_inline
11073 wrapper, defer folding it after always_inline functions have
11074 been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
11075 might not be performed. */
11076
51d2c51e 11077bool
198622c0 11078avoid_folding_inline_builtin (tree fndecl)
11079{
11080 return (DECL_DECLARED_INLINE_P (fndecl)
11081 && DECL_DISREGARD_INLINE_LIMITS (fndecl)
11082 && cfun
11083 && !cfun->always_inline_functions_inlined
11084 && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)));
11085}
11086
4ee9c684 11087/* A wrapper function for builtin folding that prevents warnings for
491e04ef 11088 "statement without effect" and the like, caused by removing the
4ee9c684 11089 call node earlier than the warning is generated. */
11090
11091tree
389dd41b 11092fold_call_expr (location_t loc, tree exp, bool ignore)
4ee9c684 11093{
c2f47e15 11094 tree ret = NULL_TREE;
11095 tree fndecl = get_callee_fndecl (exp);
11096 if (fndecl
11097 && TREE_CODE (fndecl) == FUNCTION_DECL
48dc2227 11098 && DECL_BUILT_IN (fndecl)
11099 /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
11100 yet. Defer folding until we see all the arguments
11101 (after inlining). */
11102 && !CALL_EXPR_VA_ARG_PACK (exp))
11103 {
11104 int nargs = call_expr_nargs (exp);
11105
11106 /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
11107 instead last argument is __builtin_va_arg_pack (). Defer folding
11108 even in that case, until arguments are finalized. */
11109 if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
11110 {
11111 tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1));
11112 if (fndecl2
11113 && TREE_CODE (fndecl2) == FUNCTION_DECL
11114 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
11115 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
11116 return NULL_TREE;
11117 }
11118
198622c0 11119 if (avoid_folding_inline_builtin (fndecl))
11120 return NULL_TREE;
11121
c2f47e15 11122 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
97d67146 11123 return targetm.fold_builtin (fndecl, call_expr_nargs (exp),
11124 CALL_EXPR_ARGP (exp), ignore);
c2f47e15 11125 else
11126 {
c2f47e15 11127 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
11128 {
11129 tree *args = CALL_EXPR_ARGP (exp);
389dd41b 11130 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
c2f47e15 11131 }
11132 if (!ret)
389dd41b 11133 ret = fold_builtin_varargs (loc, fndecl, exp, ignore);
c2f47e15 11134 if (ret)
389dd41b 11135 return ret;
c2f47e15 11136 }
4ee9c684 11137 }
c2f47e15 11138 return NULL_TREE;
11139}
48e1416a 11140
c2f47e15 11141/* Conveniently construct a function call expression. FNDECL names the
414c3a2c 11142 function to be called and N arguments are passed in the array
11143 ARGARRAY. */
48e1416a 11144
c2f47e15 11145tree
414c3a2c 11146build_call_expr_loc_array (location_t loc, tree fndecl, int n, tree *argarray)
c2f47e15 11147{
11148 tree fntype = TREE_TYPE (fndecl);
11149 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
414c3a2c 11150
389dd41b 11151 return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray);
c2f47e15 11152}
11153
414c3a2c 11154/* Conveniently construct a function call expression. FNDECL names the
11155 function to be called and the arguments are passed in the vector
11156 VEC. */
11157
11158tree
f1f41a6c 11159build_call_expr_loc_vec (location_t loc, tree fndecl, vec<tree, va_gc> *vec)
414c3a2c 11160{
f1f41a6c 11161 return build_call_expr_loc_array (loc, fndecl, vec_safe_length (vec),
11162 vec_safe_address (vec));
414c3a2c 11163}
11164
11165
c2f47e15 11166/* Conveniently construct a function call expression. FNDECL names the
11167 function to be called, N is the number of arguments, and the "..."
11168 parameters are the argument expressions. */
48e1416a 11169
c2f47e15 11170tree
389dd41b 11171build_call_expr_loc (location_t loc, tree fndecl, int n, ...)
c2f47e15 11172{
11173 va_list ap;
414c3a2c 11174 tree *argarray = XALLOCAVEC (tree, n);
d01f58f9 11175 int i;
c2f47e15 11176
11177 va_start (ap, n);
d01f58f9 11178 for (i = 0; i < n; i++)
11179 argarray[i] = va_arg (ap, tree);
c2f47e15 11180 va_end (ap);
414c3a2c 11181 return build_call_expr_loc_array (loc, fndecl, n, argarray);
4ee9c684 11182}
11183
0568e9c1 11184/* Like build_call_expr_loc (UNKNOWN_LOCATION, ...). Duplicated because
11185 varargs macros aren't supported by all bootstrap compilers. */
11186
11187tree
11188build_call_expr (tree fndecl, int n, ...)
11189{
11190 va_list ap;
414c3a2c 11191 tree *argarray = XALLOCAVEC (tree, n);
0568e9c1 11192 int i;
11193
11194 va_start (ap, n);
11195 for (i = 0; i < n; i++)
11196 argarray[i] = va_arg (ap, tree);
11197 va_end (ap);
414c3a2c 11198 return build_call_expr_loc_array (UNKNOWN_LOCATION, fndecl, n, argarray);
0568e9c1 11199}
11200
c2f47e15 11201/* Construct a CALL_EXPR with type TYPE with FN as the function expression.
d01f58f9 11202 N arguments are passed in the array ARGARRAY. */
805e22b2 11203
11204tree
389dd41b 11205fold_builtin_call_array (location_t loc, tree type,
d01f58f9 11206 tree fn,
11207 int n,
11208 tree *argarray)
7e15618b 11209{
c2f47e15 11210 tree ret = NULL_TREE;
c2f47e15 11211 tree exp;
11212
11213 if (TREE_CODE (fn) == ADDR_EXPR)
11214 {
11215 tree fndecl = TREE_OPERAND (fn, 0);
11216 if (TREE_CODE (fndecl) == FUNCTION_DECL
11217 && DECL_BUILT_IN (fndecl))
11218 {
48dc2227 11219 /* If last argument is __builtin_va_arg_pack (), arguments to this
11220 function are not finalized yet. Defer folding until they are. */
11221 if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
11222 {
11223 tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
11224 if (fndecl2
11225 && TREE_CODE (fndecl2) == FUNCTION_DECL
11226 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
11227 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
389dd41b 11228 return build_call_array_loc (loc, type, fn, n, argarray);
48dc2227 11229 }
198622c0 11230 if (avoid_folding_inline_builtin (fndecl))
389dd41b 11231 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 11232 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
11233 {
97d67146 11234 ret = targetm.fold_builtin (fndecl, n, argarray, false);
11235 if (ret)
11236 return ret;
11237
389dd41b 11238 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 11239 }
11240 else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
11241 {
11242 /* First try the transformations that don't require consing up
11243 an exp. */
389dd41b 11244 ret = fold_builtin_n (loc, fndecl, argarray, n, false);
c2f47e15 11245 if (ret)
11246 return ret;
11247 }
11248
11249 /* If we got this far, we need to build an exp. */
389dd41b 11250 exp = build_call_array_loc (loc, type, fn, n, argarray);
11251 ret = fold_builtin_varargs (loc, fndecl, exp, false);
c2f47e15 11252 return ret ? ret : exp;
11253 }
11254 }
11255
389dd41b 11256 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 11257}
11258
af1409ad 11259/* Construct a new CALL_EXPR using the tail of the argument list of EXP
11260 along with N new arguments specified as the "..." parameters. SKIP
11261 is the number of arguments in EXP to be omitted. This function is used
11262 to do varargs-to-varargs transformations. */
11263
11264static tree
11265rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...)
11266{
11267 va_list ap;
11268 tree t;
11269
11270 va_start (ap, n);
11271 t = rewrite_call_expr_valist (loc, call_expr_nargs (exp),
11272 CALL_EXPR_ARGP (exp), skip, fndecl, n, ap);
11273 va_end (ap);
c2f47e15 11274
af1409ad 11275 return t;
c2f47e15 11276}
11277
11278/* Validate a single argument ARG against a tree code CODE representing
11279 a type. */
48e1416a 11280
c2f47e15 11281static bool
b7bf20db 11282validate_arg (const_tree arg, enum tree_code code)
c2f47e15 11283{
11284 if (!arg)
11285 return false;
11286 else if (code == POINTER_TYPE)
11287 return POINTER_TYPE_P (TREE_TYPE (arg));
c7f617c2 11288 else if (code == INTEGER_TYPE)
11289 return INTEGRAL_TYPE_P (TREE_TYPE (arg));
c2f47e15 11290 return code == TREE_CODE (TREE_TYPE (arg));
7e15618b 11291}
0eb671f7 11292
75a70cf9 11293/* This function validates the types of a function call argument list
11294 against a specified list of tree_codes. If the last specifier is a 0,
11295 that represents an ellipses, otherwise the last specifier must be a
11296 VOID_TYPE.
11297
11298 This is the GIMPLE version of validate_arglist. Eventually we want to
11299 completely convert builtins.c to work from GIMPLEs and the tree based
11300 validate_arglist will then be removed. */
11301
11302bool
11303validate_gimple_arglist (const_gimple call, ...)
11304{
11305 enum tree_code code;
11306 bool res = 0;
11307 va_list ap;
11308 const_tree arg;
11309 size_t i;
11310
11311 va_start (ap, call);
11312 i = 0;
11313
11314 do
11315 {
d62e827b 11316 code = (enum tree_code) va_arg (ap, int);
75a70cf9 11317 switch (code)
11318 {
11319 case 0:
11320 /* This signifies an ellipses, any further arguments are all ok. */
11321 res = true;
11322 goto end;
11323 case VOID_TYPE:
11324 /* This signifies an endlink, if no arguments remain, return
11325 true, otherwise return false. */
11326 res = (i == gimple_call_num_args (call));
11327 goto end;
11328 default:
11329 /* If no parameters remain or the parameter's code does not
11330 match the specified code, return false. Otherwise continue
11331 checking any remaining arguments. */
11332 arg = gimple_call_arg (call, i++);
11333 if (!validate_arg (arg, code))
11334 goto end;
11335 break;
11336 }
11337 }
11338 while (1);
11339
11340 /* We need gotos here since we can only have one VA_CLOSE in a
11341 function. */
11342 end: ;
11343 va_end (ap);
11344
11345 return res;
11346}
11347
fc2a2dcb 11348/* Default target-specific builtin expander that does nothing. */
11349
11350rtx
aecda0d6 11351default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
11352 rtx target ATTRIBUTE_UNUSED,
11353 rtx subtarget ATTRIBUTE_UNUSED,
11354 enum machine_mode mode ATTRIBUTE_UNUSED,
11355 int ignore ATTRIBUTE_UNUSED)
fc2a2dcb 11356{
11357 return NULL_RTX;
11358}
c7926a82 11359
01537105 11360/* Returns true is EXP represents data that would potentially reside
11361 in a readonly section. */
11362
11363static bool
11364readonly_data_expr (tree exp)
11365{
11366 STRIP_NOPS (exp);
11367
9ff0637e 11368 if (TREE_CODE (exp) != ADDR_EXPR)
11369 return false;
11370
11371 exp = get_base_address (TREE_OPERAND (exp, 0));
11372 if (!exp)
11373 return false;
11374
11375 /* Make sure we call decl_readonly_section only for trees it
11376 can handle (since it returns true for everything it doesn't
11377 understand). */
491e04ef 11378 if (TREE_CODE (exp) == STRING_CST
9ff0637e 11379 || TREE_CODE (exp) == CONSTRUCTOR
11380 || (TREE_CODE (exp) == VAR_DECL && TREE_STATIC (exp)))
11381 return decl_readonly_section (exp, 0);
01537105 11382 else
11383 return false;
11384}
4ee9c684 11385
c2f47e15 11386/* Simplify a call to the strstr builtin. S1 and S2 are the arguments
11387 to the call, and TYPE is its return type.
4ee9c684 11388
c2f47e15 11389 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11390 simplified form of the call as a tree.
11391
11392 The simplified form may be a constant or other expression which
11393 computes the same value, but in a more efficient manner (including
11394 calls to other builtin functions).
11395
11396 The call may contain arguments which need to be evaluated, but
11397 which are not useful to determine the result of the call. In
11398 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11399 COMPOUND_EXPR will be an argument which must be evaluated.
11400 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11401 COMPOUND_EXPR in the chain will contain the tree for the simplified
11402 form of the builtin function call. */
11403
11404static tree
389dd41b 11405fold_builtin_strstr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11406{
c2f47e15 11407 if (!validate_arg (s1, POINTER_TYPE)
11408 || !validate_arg (s2, POINTER_TYPE))
11409 return NULL_TREE;
4ee9c684 11410 else
11411 {
4ee9c684 11412 tree fn;
11413 const char *p1, *p2;
11414
11415 p2 = c_getstr (s2);
11416 if (p2 == NULL)
c2f47e15 11417 return NULL_TREE;
4ee9c684 11418
11419 p1 = c_getstr (s1);
11420 if (p1 != NULL)
11421 {
11422 const char *r = strstr (p1, p2);
daa1d5f5 11423 tree tem;
4ee9c684 11424
4ee9c684 11425 if (r == NULL)
779b4c41 11426 return build_int_cst (TREE_TYPE (s1), 0);
c0c67e38 11427
11428 /* Return an offset into the constant string argument. */
2cc66f2a 11429 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11430 return fold_convert_loc (loc, type, tem);
4ee9c684 11431 }
11432
7efa231c 11433 /* The argument is const char *, and the result is char *, so we need
11434 a type conversion here to avoid a warning. */
4ee9c684 11435 if (p2[0] == '\0')
389dd41b 11436 return fold_convert_loc (loc, type, s1);
4ee9c684 11437
11438 if (p2[1] != '\0')
c2f47e15 11439 return NULL_TREE;
4ee9c684 11440
b9a16870 11441 fn = builtin_decl_implicit (BUILT_IN_STRCHR);
4ee9c684 11442 if (!fn)
c2f47e15 11443 return NULL_TREE;
4ee9c684 11444
11445 /* New argument list transforming strstr(s1, s2) to
11446 strchr(s1, s2[0]). */
7002a1c8 11447 return build_call_expr_loc (loc, fn, 2, s1,
11448 build_int_cst (integer_type_node, p2[0]));
4ee9c684 11449 }
11450}
11451
c2f47e15 11452/* Simplify a call to the strchr builtin. S1 and S2 are the arguments to
11453 the call, and TYPE is its return type.
4ee9c684 11454
c2f47e15 11455 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11456 simplified form of the call as a tree.
11457
11458 The simplified form may be a constant or other expression which
11459 computes the same value, but in a more efficient manner (including
11460 calls to other builtin functions).
11461
11462 The call may contain arguments which need to be evaluated, but
11463 which are not useful to determine the result of the call. In
11464 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11465 COMPOUND_EXPR will be an argument which must be evaluated.
11466 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11467 COMPOUND_EXPR in the chain will contain the tree for the simplified
11468 form of the builtin function call. */
11469
11470static tree
389dd41b 11471fold_builtin_strchr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11472{
c2f47e15 11473 if (!validate_arg (s1, POINTER_TYPE)
11474 || !validate_arg (s2, INTEGER_TYPE))
11475 return NULL_TREE;
4ee9c684 11476 else
11477 {
4ee9c684 11478 const char *p1;
11479
11480 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 11481 return NULL_TREE;
4ee9c684 11482
11483 p1 = c_getstr (s1);
11484 if (p1 != NULL)
11485 {
11486 char c;
11487 const char *r;
daa1d5f5 11488 tree tem;
4ee9c684 11489
11490 if (target_char_cast (s2, &c))
c2f47e15 11491 return NULL_TREE;
4ee9c684 11492
11493 r = strchr (p1, c);
11494
11495 if (r == NULL)
779b4c41 11496 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11497
11498 /* Return an offset into the constant string argument. */
2cc66f2a 11499 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11500 return fold_convert_loc (loc, type, tem);
4ee9c684 11501 }
c2f47e15 11502 return NULL_TREE;
4ee9c684 11503 }
11504}
11505
c2f47e15 11506/* Simplify a call to the strrchr builtin. S1 and S2 are the arguments to
11507 the call, and TYPE is its return type.
4ee9c684 11508
c2f47e15 11509 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11510 simplified form of the call as a tree.
11511
11512 The simplified form may be a constant or other expression which
11513 computes the same value, but in a more efficient manner (including
11514 calls to other builtin functions).
11515
11516 The call may contain arguments which need to be evaluated, but
11517 which are not useful to determine the result of the call. In
11518 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11519 COMPOUND_EXPR will be an argument which must be evaluated.
11520 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11521 COMPOUND_EXPR in the chain will contain the tree for the simplified
11522 form of the builtin function call. */
11523
11524static tree
389dd41b 11525fold_builtin_strrchr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11526{
c2f47e15 11527 if (!validate_arg (s1, POINTER_TYPE)
11528 || !validate_arg (s2, INTEGER_TYPE))
11529 return NULL_TREE;
4ee9c684 11530 else
11531 {
4ee9c684 11532 tree fn;
11533 const char *p1;
11534
11535 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 11536 return NULL_TREE;
4ee9c684 11537
11538 p1 = c_getstr (s1);
11539 if (p1 != NULL)
11540 {
11541 char c;
11542 const char *r;
daa1d5f5 11543 tree tem;
4ee9c684 11544
11545 if (target_char_cast (s2, &c))
c2f47e15 11546 return NULL_TREE;
4ee9c684 11547
11548 r = strrchr (p1, c);
11549
11550 if (r == NULL)
779b4c41 11551 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11552
11553 /* Return an offset into the constant string argument. */
2cc66f2a 11554 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11555 return fold_convert_loc (loc, type, tem);
4ee9c684 11556 }
11557
11558 if (! integer_zerop (s2))
c2f47e15 11559 return NULL_TREE;
4ee9c684 11560
b9a16870 11561 fn = builtin_decl_implicit (BUILT_IN_STRCHR);
4ee9c684 11562 if (!fn)
c2f47e15 11563 return NULL_TREE;
4ee9c684 11564
11565 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
389dd41b 11566 return build_call_expr_loc (loc, fn, 2, s1, s2);
4ee9c684 11567 }
11568}
11569
c2f47e15 11570/* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments
11571 to the call, and TYPE is its return type.
4ee9c684 11572
c2f47e15 11573 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11574 simplified form of the call as a tree.
11575
11576 The simplified form may be a constant or other expression which
11577 computes the same value, but in a more efficient manner (including
11578 calls to other builtin functions).
11579
11580 The call may contain arguments which need to be evaluated, but
11581 which are not useful to determine the result of the call. In
11582 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11583 COMPOUND_EXPR will be an argument which must be evaluated.
11584 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11585 COMPOUND_EXPR in the chain will contain the tree for the simplified
11586 form of the builtin function call. */
11587
11588static tree
389dd41b 11589fold_builtin_strpbrk (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11590{
c2f47e15 11591 if (!validate_arg (s1, POINTER_TYPE)
11592 || !validate_arg (s2, POINTER_TYPE))
11593 return NULL_TREE;
4ee9c684 11594 else
11595 {
4ee9c684 11596 tree fn;
11597 const char *p1, *p2;
11598
11599 p2 = c_getstr (s2);
11600 if (p2 == NULL)
c2f47e15 11601 return NULL_TREE;
4ee9c684 11602
11603 p1 = c_getstr (s1);
11604 if (p1 != NULL)
11605 {
11606 const char *r = strpbrk (p1, p2);
daa1d5f5 11607 tree tem;
4ee9c684 11608
11609 if (r == NULL)
779b4c41 11610 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11611
11612 /* Return an offset into the constant string argument. */
2cc66f2a 11613 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11614 return fold_convert_loc (loc, type, tem);
4ee9c684 11615 }
11616
11617 if (p2[0] == '\0')
05abc81b 11618 /* strpbrk(x, "") == NULL.
11619 Evaluate and ignore s1 in case it had side-effects. */
389dd41b 11620 return omit_one_operand_loc (loc, TREE_TYPE (s1), integer_zero_node, s1);
4ee9c684 11621
11622 if (p2[1] != '\0')
c2f47e15 11623 return NULL_TREE; /* Really call strpbrk. */
4ee9c684 11624
b9a16870 11625 fn = builtin_decl_implicit (BUILT_IN_STRCHR);
4ee9c684 11626 if (!fn)
c2f47e15 11627 return NULL_TREE;
4ee9c684 11628
11629 /* New argument list transforming strpbrk(s1, s2) to
11630 strchr(s1, s2[0]). */
7002a1c8 11631 return build_call_expr_loc (loc, fn, 2, s1,
11632 build_int_cst (integer_type_node, p2[0]));
4ee9c684 11633 }
11634}
11635
c2f47e15 11636/* Simplify a call to the strcat builtin. DST and SRC are the arguments
11637 to the call.
4ee9c684 11638
c2f47e15 11639 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11640 simplified form of the call as a tree.
11641
11642 The simplified form may be a constant or other expression which
11643 computes the same value, but in a more efficient manner (including
11644 calls to other builtin functions).
11645
11646 The call may contain arguments which need to be evaluated, but
11647 which are not useful to determine the result of the call. In
11648 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11649 COMPOUND_EXPR will be an argument which must be evaluated.
11650 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11651 COMPOUND_EXPR in the chain will contain the tree for the simplified
11652 form of the builtin function call. */
11653
11654static tree
389dd41b 11655fold_builtin_strcat (location_t loc ATTRIBUTE_UNUSED, tree dst, tree src)
4ee9c684 11656{
c2f47e15 11657 if (!validate_arg (dst, POINTER_TYPE)
11658 || !validate_arg (src, POINTER_TYPE))
11659 return NULL_TREE;
4ee9c684 11660 else
11661 {
4ee9c684 11662 const char *p = c_getstr (src);
11663
11664 /* If the string length is zero, return the dst parameter. */
11665 if (p && *p == '\0')
11666 return dst;
11667
a65c4d64 11668 if (optimize_insn_for_speed_p ())
11669 {
11670 /* See if we can store by pieces into (dst + strlen(dst)). */
11671 tree newdst, call;
b9a16870 11672 tree strlen_fn = builtin_decl_implicit (BUILT_IN_STRLEN);
11673 tree strcpy_fn = builtin_decl_implicit (BUILT_IN_STRCPY);
a65c4d64 11674
11675 if (!strlen_fn || !strcpy_fn)
11676 return NULL_TREE;
11677
11678 /* If we don't have a movstr we don't want to emit an strcpy
11679 call. We have to do that if the length of the source string
11680 isn't computable (in that case we can use memcpy probably
48e1416a 11681 later expanding to a sequence of mov instructions). If we
a65c4d64 11682 have movstr instructions we can emit strcpy calls. */
11683 if (!HAVE_movstr)
11684 {
11685 tree len = c_strlen (src, 1);
11686 if (! len || TREE_SIDE_EFFECTS (len))
11687 return NULL_TREE;
11688 }
11689
11690 /* Stabilize the argument list. */
11691 dst = builtin_save_expr (dst);
11692
11693 /* Create strlen (dst). */
11694 newdst = build_call_expr_loc (loc, strlen_fn, 1, dst);
11695 /* Create (dst p+ strlen (dst)). */
11696
2cc66f2a 11697 newdst = fold_build_pointer_plus_loc (loc, dst, newdst);
a65c4d64 11698 newdst = builtin_save_expr (newdst);
11699
11700 call = build_call_expr_loc (loc, strcpy_fn, 2, newdst, src);
11701 return build2 (COMPOUND_EXPR, TREE_TYPE (dst), call, dst);
11702 }
c2f47e15 11703 return NULL_TREE;
4ee9c684 11704 }
11705}
11706
c2f47e15 11707/* Simplify a call to the strncat builtin. DST, SRC, and LEN are the
11708 arguments to the call.
4ee9c684 11709
c2f47e15 11710 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11711 simplified form of the call as a tree.
11712
11713 The simplified form may be a constant or other expression which
11714 computes the same value, but in a more efficient manner (including
11715 calls to other builtin functions).
11716
11717 The call may contain arguments which need to be evaluated, but
11718 which are not useful to determine the result of the call. In
11719 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11720 COMPOUND_EXPR will be an argument which must be evaluated.
11721 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11722 COMPOUND_EXPR in the chain will contain the tree for the simplified
11723 form of the builtin function call. */
11724
11725static tree
389dd41b 11726fold_builtin_strncat (location_t loc, tree dst, tree src, tree len)
4ee9c684 11727{
c2f47e15 11728 if (!validate_arg (dst, POINTER_TYPE)
11729 || !validate_arg (src, POINTER_TYPE)
11730 || !validate_arg (len, INTEGER_TYPE))
11731 return NULL_TREE;
4ee9c684 11732 else
11733 {
4ee9c684 11734 const char *p = c_getstr (src);
11735
11736 /* If the requested length is zero, or the src parameter string
0a39fd54 11737 length is zero, return the dst parameter. */
4ee9c684 11738 if (integer_zerop (len) || (p && *p == '\0'))
389dd41b 11739 return omit_two_operands_loc (loc, TREE_TYPE (dst), dst, src, len);
4ee9c684 11740
11741 /* If the requested len is greater than or equal to the string
a0c938f0 11742 length, call strcat. */
4ee9c684 11743 if (TREE_CODE (len) == INTEGER_CST && p
11744 && compare_tree_int (len, strlen (p)) >= 0)
11745 {
b9a16870 11746 tree fn = builtin_decl_implicit (BUILT_IN_STRCAT);
4ee9c684 11747
11748 /* If the replacement _DECL isn't initialized, don't do the
11749 transformation. */
11750 if (!fn)
c2f47e15 11751 return NULL_TREE;
4ee9c684 11752
389dd41b 11753 return build_call_expr_loc (loc, fn, 2, dst, src);
4ee9c684 11754 }
c2f47e15 11755 return NULL_TREE;
4ee9c684 11756 }
11757}
11758
c2f47e15 11759/* Simplify a call to the strspn builtin. S1 and S2 are the arguments
11760 to the call.
4ee9c684 11761
c2f47e15 11762 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11763 simplified form of the call as a tree.
11764
11765 The simplified form may be a constant or other expression which
11766 computes the same value, but in a more efficient manner (including
11767 calls to other builtin functions).
11768
11769 The call may contain arguments which need to be evaluated, but
11770 which are not useful to determine the result of the call. In
11771 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11772 COMPOUND_EXPR will be an argument which must be evaluated.
11773 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11774 COMPOUND_EXPR in the chain will contain the tree for the simplified
11775 form of the builtin function call. */
11776
11777static tree
389dd41b 11778fold_builtin_strspn (location_t loc, tree s1, tree s2)
4ee9c684 11779{
c2f47e15 11780 if (!validate_arg (s1, POINTER_TYPE)
11781 || !validate_arg (s2, POINTER_TYPE))
11782 return NULL_TREE;
4ee9c684 11783 else
11784 {
4ee9c684 11785 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11786
11787 /* If both arguments are constants, evaluate at compile-time. */
11788 if (p1 && p2)
11789 {
11790 const size_t r = strspn (p1, p2);
547b938d 11791 return build_int_cst (size_type_node, r);
4ee9c684 11792 }
11793
c2f47e15 11794 /* If either argument is "", return NULL_TREE. */
4ee9c684 11795 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9bc9f15f 11796 /* Evaluate and ignore both arguments in case either one has
11797 side-effects. */
389dd41b 11798 return omit_two_operands_loc (loc, size_type_node, size_zero_node,
9bc9f15f 11799 s1, s2);
c2f47e15 11800 return NULL_TREE;
4ee9c684 11801 }
11802}
11803
c2f47e15 11804/* Simplify a call to the strcspn builtin. S1 and S2 are the arguments
11805 to the call.
4ee9c684 11806
c2f47e15 11807 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11808 simplified form of the call as a tree.
11809
11810 The simplified form may be a constant or other expression which
11811 computes the same value, but in a more efficient manner (including
11812 calls to other builtin functions).
11813
11814 The call may contain arguments which need to be evaluated, but
11815 which are not useful to determine the result of the call. In
11816 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11817 COMPOUND_EXPR will be an argument which must be evaluated.
11818 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11819 COMPOUND_EXPR in the chain will contain the tree for the simplified
11820 form of the builtin function call. */
11821
11822static tree
389dd41b 11823fold_builtin_strcspn (location_t loc, tree s1, tree s2)
4ee9c684 11824{
c2f47e15 11825 if (!validate_arg (s1, POINTER_TYPE)
11826 || !validate_arg (s2, POINTER_TYPE))
11827 return NULL_TREE;
4ee9c684 11828 else
11829 {
4ee9c684 11830 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11831
11832 /* If both arguments are constants, evaluate at compile-time. */
11833 if (p1 && p2)
11834 {
11835 const size_t r = strcspn (p1, p2);
547b938d 11836 return build_int_cst (size_type_node, r);
4ee9c684 11837 }
11838
c2f47e15 11839 /* If the first argument is "", return NULL_TREE. */
4ee9c684 11840 if (p1 && *p1 == '\0')
11841 {
11842 /* Evaluate and ignore argument s2 in case it has
11843 side-effects. */
389dd41b 11844 return omit_one_operand_loc (loc, size_type_node,
39761420 11845 size_zero_node, s2);
4ee9c684 11846 }
11847
11848 /* If the second argument is "", return __builtin_strlen(s1). */
11849 if (p2 && *p2 == '\0')
11850 {
b9a16870 11851 tree fn = builtin_decl_implicit (BUILT_IN_STRLEN);
4ee9c684 11852
11853 /* If the replacement _DECL isn't initialized, don't do the
11854 transformation. */
11855 if (!fn)
c2f47e15 11856 return NULL_TREE;
4ee9c684 11857
389dd41b 11858 return build_call_expr_loc (loc, fn, 1, s1);
4ee9c684 11859 }
c2f47e15 11860 return NULL_TREE;
4ee9c684 11861 }
11862}
11863
c2f47e15 11864/* Fold a call to the fputs builtin. ARG0 and ARG1 are the arguments
11865 to the call. IGNORE is true if the value returned
f0613857 11866 by the builtin will be ignored. UNLOCKED is true is true if this
11867 actually a call to fputs_unlocked. If LEN in non-NULL, it represents
11868 the known length of the string. Return NULL_TREE if no simplification
11869 was possible. */
4ee9c684 11870
11871tree
389dd41b 11872fold_builtin_fputs (location_t loc, tree arg0, tree arg1,
11873 bool ignore, bool unlocked, tree len)
4ee9c684 11874{
6d77ed92 11875 /* If we're using an unlocked function, assume the other unlocked
11876 functions exist explicitly. */
b9a16870 11877 tree const fn_fputc = (unlocked
11878 ? builtin_decl_explicit (BUILT_IN_FPUTC_UNLOCKED)
11879 : builtin_decl_implicit (BUILT_IN_FPUTC));
11880 tree const fn_fwrite = (unlocked
11881 ? builtin_decl_explicit (BUILT_IN_FWRITE_UNLOCKED)
11882 : builtin_decl_implicit (BUILT_IN_FWRITE));
4ee9c684 11883
c403edd4 11884 /* If the return value is used, don't do the transformation. */
11885 if (!ignore)
c2f47e15 11886 return NULL_TREE;
4ee9c684 11887
11888 /* Verify the arguments in the original call. */
c2f47e15 11889 if (!validate_arg (arg0, POINTER_TYPE)
11890 || !validate_arg (arg1, POINTER_TYPE))
11891 return NULL_TREE;
4ee9c684 11892
f0613857 11893 if (! len)
c2f47e15 11894 len = c_strlen (arg0, 0);
4ee9c684 11895
11896 /* Get the length of the string passed to fputs. If the length
11897 can't be determined, punt. */
11898 if (!len
11899 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 11900 return NULL_TREE;
4ee9c684 11901
11902 switch (compare_tree_int (len, 1))
11903 {
11904 case -1: /* length is 0, delete the call entirely . */
389dd41b 11905 return omit_one_operand_loc (loc, integer_type_node,
11906 integer_zero_node, arg1);;
05abc81b 11907
4ee9c684 11908 case 0: /* length is 1, call fputc. */
11909 {
c2f47e15 11910 const char *p = c_getstr (arg0);
4ee9c684 11911
11912 if (p != NULL)
11913 {
c2f47e15 11914 if (fn_fputc)
389dd41b 11915 return build_call_expr_loc (loc, fn_fputc, 2,
7002a1c8 11916 build_int_cst
11917 (integer_type_node, p[0]), arg1);
c2f47e15 11918 else
11919 return NULL_TREE;
4ee9c684 11920 }
11921 }
11922 /* FALLTHROUGH */
11923 case 1: /* length is greater than 1, call fwrite. */
11924 {
0bed3869 11925 /* If optimizing for size keep fputs. */
0bfd8d5c 11926 if (optimize_function_for_size_p (cfun))
c2f47e15 11927 return NULL_TREE;
4ee9c684 11928 /* New argument list transforming fputs(string, stream) to
11929 fwrite(string, 1, len, stream). */
c2f47e15 11930 if (fn_fwrite)
389dd41b 11931 return build_call_expr_loc (loc, fn_fwrite, 4, arg0,
11932 size_one_node, len, arg1);
c2f47e15 11933 else
11934 return NULL_TREE;
4ee9c684 11935 }
11936 default:
64db345d 11937 gcc_unreachable ();
4ee9c684 11938 }
c2f47e15 11939 return NULL_TREE;
4ee9c684 11940}
11941
c2f47e15 11942/* Fold the next_arg or va_start call EXP. Returns true if there was an error
743b0c6a 11943 produced. False otherwise. This is done so that we don't output the error
11944 or warning twice or three times. */
75a70cf9 11945
743b0c6a 11946bool
c2f47e15 11947fold_builtin_next_arg (tree exp, bool va_start_p)
4ee9c684 11948{
11949 tree fntype = TREE_TYPE (current_function_decl);
c2f47e15 11950 int nargs = call_expr_nargs (exp);
11951 tree arg;
d98fd4a4 11952 /* There is good chance the current input_location points inside the
11953 definition of the va_start macro (perhaps on the token for
11954 builtin) in a system header, so warnings will not be emitted.
11955 Use the location in real source code. */
11956 source_location current_location =
11957 linemap_unwind_to_first_non_reserved_loc (line_table, input_location,
11958 NULL);
4ee9c684 11959
257d99c3 11960 if (!stdarg_p (fntype))
743b0c6a 11961 {
11962 error ("%<va_start%> used in function with fixed args");
11963 return true;
11964 }
c2f47e15 11965
11966 if (va_start_p)
79012a9d 11967 {
c2f47e15 11968 if (va_start_p && (nargs != 2))
11969 {
11970 error ("wrong number of arguments to function %<va_start%>");
11971 return true;
11972 }
11973 arg = CALL_EXPR_ARG (exp, 1);
79012a9d 11974 }
11975 /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
11976 when we checked the arguments and if needed issued a warning. */
c2f47e15 11977 else
4ee9c684 11978 {
c2f47e15 11979 if (nargs == 0)
11980 {
11981 /* Evidently an out of date version of <stdarg.h>; can't validate
11982 va_start's second argument, but can still work as intended. */
d98fd4a4 11983 warning_at (current_location,
7edb1062 11984 OPT_Wvarargs,
11985 "%<__builtin_next_arg%> called without an argument");
c2f47e15 11986 return true;
11987 }
11988 else if (nargs > 1)
a0c938f0 11989 {
c2f47e15 11990 error ("wrong number of arguments to function %<__builtin_next_arg%>");
a0c938f0 11991 return true;
11992 }
c2f47e15 11993 arg = CALL_EXPR_ARG (exp, 0);
11994 }
11995
a8dd994c 11996 if (TREE_CODE (arg) == SSA_NAME)
11997 arg = SSA_NAME_VAR (arg);
11998
c2f47e15 11999 /* We destructively modify the call to be __builtin_va_start (ap, 0)
48e1416a 12000 or __builtin_next_arg (0) the first time we see it, after checking
c2f47e15 12001 the arguments and if needed issuing a warning. */
12002 if (!integer_zerop (arg))
12003 {
12004 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
79012a9d 12005
4ee9c684 12006 /* Strip off all nops for the sake of the comparison. This
12007 is not quite the same as STRIP_NOPS. It does more.
12008 We must also strip off INDIRECT_EXPR for C++ reference
12009 parameters. */
72dd6141 12010 while (CONVERT_EXPR_P (arg)
4ee9c684 12011 || TREE_CODE (arg) == INDIRECT_REF)
12012 arg = TREE_OPERAND (arg, 0);
12013 if (arg != last_parm)
a0c938f0 12014 {
b08cf617 12015 /* FIXME: Sometimes with the tree optimizers we can get the
12016 not the last argument even though the user used the last
12017 argument. We just warn and set the arg to be the last
12018 argument so that we will get wrong-code because of
12019 it. */
d98fd4a4 12020 warning_at (current_location,
7edb1062 12021 OPT_Wvarargs,
d98fd4a4 12022 "second parameter of %<va_start%> not last named argument");
743b0c6a 12023 }
24158ad7 12024
12025 /* Undefined by C99 7.15.1.4p4 (va_start):
12026 "If the parameter parmN is declared with the register storage
12027 class, with a function or array type, or with a type that is
12028 not compatible with the type that results after application of
12029 the default argument promotions, the behavior is undefined."
12030 */
12031 else if (DECL_REGISTER (arg))
d98fd4a4 12032 {
12033 warning_at (current_location,
7edb1062 12034 OPT_Wvarargs,
d98fd4a4 12035 "undefined behaviour when second parameter of "
12036 "%<va_start%> is declared with %<register%> storage");
12037 }
24158ad7 12038
79012a9d 12039 /* We want to verify the second parameter just once before the tree
a0c938f0 12040 optimizers are run and then avoid keeping it in the tree,
12041 as otherwise we could warn even for correct code like:
12042 void foo (int i, ...)
12043 { va_list ap; i++; va_start (ap, i); va_end (ap); } */
c2f47e15 12044 if (va_start_p)
12045 CALL_EXPR_ARG (exp, 1) = integer_zero_node;
12046 else
12047 CALL_EXPR_ARG (exp, 0) = integer_zero_node;
743b0c6a 12048 }
12049 return false;
4ee9c684 12050}
12051
12052
c2f47e15 12053/* Simplify a call to the sprintf builtin with arguments DEST, FMT, and ORIG.
12054 ORIG may be null if this is a 2-argument call. We don't attempt to
12055 simplify calls with more than 3 arguments.
4ee9c684 12056
c2f47e15 12057 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 12058 simplified form of the call as a tree. If IGNORED is true, it means that
12059 the caller does not use the returned value of the function. */
12060
12061static tree
389dd41b 12062fold_builtin_sprintf (location_t loc, tree dest, tree fmt,
12063 tree orig, int ignored)
4ee9c684 12064{
c2f47e15 12065 tree call, retval;
4ee9c684 12066 const char *fmt_str = NULL;
12067
12068 /* Verify the required arguments in the original call. We deal with two
12069 types of sprintf() calls: 'sprintf (str, fmt)' and
12070 'sprintf (dest, "%s", orig)'. */
c2f47e15 12071 if (!validate_arg (dest, POINTER_TYPE)
12072 || !validate_arg (fmt, POINTER_TYPE))
12073 return NULL_TREE;
12074 if (orig && !validate_arg (orig, POINTER_TYPE))
4ee9c684 12075 return NULL_TREE;
4ee9c684 12076
12077 /* Check whether the format is a literal string constant. */
12078 fmt_str = c_getstr (fmt);
12079 if (fmt_str == NULL)
12080 return NULL_TREE;
12081
12082 call = NULL_TREE;
12083 retval = NULL_TREE;
12084
d4473c84 12085 if (!init_target_chars ())
c2f47e15 12086 return NULL_TREE;
99eabcc1 12087
4ee9c684 12088 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 12089 if (strchr (fmt_str, target_percent) == NULL)
4ee9c684 12090 {
b9a16870 12091 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
4ee9c684 12092
12093 if (!fn)
12094 return NULL_TREE;
12095
72dfb3f2 12096 /* Don't optimize sprintf (buf, "abc", ptr++). */
c2f47e15 12097 if (orig)
72dfb3f2 12098 return NULL_TREE;
12099
4ee9c684 12100 /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
12101 'format' is known to contain no % formats. */
389dd41b 12102 call = build_call_expr_loc (loc, fn, 2, dest, fmt);
4ee9c684 12103 if (!ignored)
7002a1c8 12104 retval = build_int_cst (integer_type_node, strlen (fmt_str));
4ee9c684 12105 }
12106
12107 /* If the format is "%s", use strcpy if the result isn't used. */
99eabcc1 12108 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
4ee9c684 12109 {
c2f47e15 12110 tree fn;
b9a16870 12111 fn = builtin_decl_implicit (BUILT_IN_STRCPY);
4ee9c684 12112
12113 if (!fn)
12114 return NULL_TREE;
12115
72dfb3f2 12116 /* Don't crash on sprintf (str1, "%s"). */
c2f47e15 12117 if (!orig)
72dfb3f2 12118 return NULL_TREE;
12119
4ee9c684 12120 /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2). */
4ee9c684 12121 if (!ignored)
12122 {
12123 retval = c_strlen (orig, 1);
12124 if (!retval || TREE_CODE (retval) != INTEGER_CST)
12125 return NULL_TREE;
12126 }
389dd41b 12127 call = build_call_expr_loc (loc, fn, 2, dest, orig);
4ee9c684 12128 }
12129
12130 if (call && retval)
12131 {
389dd41b 12132 retval = fold_convert_loc
b9a16870 12133 (loc, TREE_TYPE (TREE_TYPE (builtin_decl_implicit (BUILT_IN_SPRINTF))),
4ee9c684 12134 retval);
05abc81b 12135 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
4ee9c684 12136 }
12137 else
12138 return call;
12139}
0a39fd54 12140
750d7b16 12141/* Simplify a call to the snprintf builtin with arguments DEST, DESTSIZE,
12142 FMT, and ORIG. ORIG may be null if this is a 3-argument call. We don't
12143 attempt to simplify calls with more than 4 arguments.
12144
12145 Return NULL_TREE if no simplification was possible, otherwise return the
12146 simplified form of the call as a tree. If IGNORED is true, it means that
12147 the caller does not use the returned value of the function. */
12148
12149static tree
12150fold_builtin_snprintf (location_t loc, tree dest, tree destsize, tree fmt,
12151 tree orig, int ignored)
12152{
12153 tree call, retval;
12154 const char *fmt_str = NULL;
12155 unsigned HOST_WIDE_INT destlen;
12156
12157 /* Verify the required arguments in the original call. We deal with two
12158 types of snprintf() calls: 'snprintf (str, cst, fmt)' and
12159 'snprintf (dest, cst, "%s", orig)'. */
12160 if (!validate_arg (dest, POINTER_TYPE)
12161 || !validate_arg (destsize, INTEGER_TYPE)
12162 || !validate_arg (fmt, POINTER_TYPE))
12163 return NULL_TREE;
12164 if (orig && !validate_arg (orig, POINTER_TYPE))
12165 return NULL_TREE;
12166
e913b5cd 12167 if (!tree_fits_uhwi_p (destsize))
750d7b16 12168 return NULL_TREE;
12169
12170 /* Check whether the format is a literal string constant. */
12171 fmt_str = c_getstr (fmt);
12172 if (fmt_str == NULL)
12173 return NULL_TREE;
12174
12175 call = NULL_TREE;
12176 retval = NULL_TREE;
12177
12178 if (!init_target_chars ())
12179 return NULL_TREE;
12180
e913b5cd 12181 destlen = tree_to_uhwi (destsize);
750d7b16 12182
12183 /* If the format doesn't contain % args or %%, use strcpy. */
12184 if (strchr (fmt_str, target_percent) == NULL)
12185 {
b9a16870 12186 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
750d7b16 12187 size_t len = strlen (fmt_str);
12188
12189 /* Don't optimize snprintf (buf, 4, "abc", ptr++). */
12190 if (orig)
12191 return NULL_TREE;
12192
12193 /* We could expand this as
12194 memcpy (str, fmt, cst - 1); str[cst - 1] = '\0';
12195 or to
12196 memcpy (str, fmt_with_nul_at_cstm1, cst);
12197 but in the former case that might increase code size
12198 and in the latter case grow .rodata section too much.
12199 So punt for now. */
12200 if (len >= destlen)
12201 return NULL_TREE;
12202
12203 if (!fn)
12204 return NULL_TREE;
12205
12206 /* Convert snprintf (str, cst, fmt) into strcpy (str, fmt) when
12207 'format' is known to contain no % formats and
12208 strlen (fmt) < cst. */
12209 call = build_call_expr_loc (loc, fn, 2, dest, fmt);
12210
12211 if (!ignored)
7002a1c8 12212 retval = build_int_cst (integer_type_node, strlen (fmt_str));
750d7b16 12213 }
12214
12215 /* If the format is "%s", use strcpy if the result isn't used. */
12216 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
12217 {
b9a16870 12218 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
750d7b16 12219 unsigned HOST_WIDE_INT origlen;
12220
12221 /* Don't crash on snprintf (str1, cst, "%s"). */
12222 if (!orig)
12223 return NULL_TREE;
12224
12225 retval = c_strlen (orig, 1);
cd4547bf 12226 if (!retval || !tree_fits_uhwi_p (retval))
750d7b16 12227 return NULL_TREE;
12228
e913b5cd 12229 origlen = tree_to_uhwi (retval);
750d7b16 12230 /* We could expand this as
12231 memcpy (str1, str2, cst - 1); str1[cst - 1] = '\0';
12232 or to
12233 memcpy (str1, str2_with_nul_at_cstm1, cst);
12234 but in the former case that might increase code size
12235 and in the latter case grow .rodata section too much.
12236 So punt for now. */
12237 if (origlen >= destlen)
12238 return NULL_TREE;
12239
12240 /* Convert snprintf (str1, cst, "%s", str2) into
12241 strcpy (str1, str2) if strlen (str2) < cst. */
12242 if (!fn)
12243 return NULL_TREE;
12244
12245 call = build_call_expr_loc (loc, fn, 2, dest, orig);
12246
12247 if (ignored)
12248 retval = NULL_TREE;
12249 }
12250
12251 if (call && retval)
12252 {
b9a16870 12253 tree fn = builtin_decl_explicit (BUILT_IN_SNPRINTF);
1914d98e 12254 retval = fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fn)), retval);
750d7b16 12255 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
12256 }
12257 else
12258 return call;
12259}
12260
c2f47e15 12261/* Expand a call EXP to __builtin_object_size. */
0a39fd54 12262
12263rtx
12264expand_builtin_object_size (tree exp)
12265{
12266 tree ost;
12267 int object_size_type;
12268 tree fndecl = get_callee_fndecl (exp);
0a39fd54 12269
c2f47e15 12270 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
0a39fd54 12271 {
b8c23db3 12272 error ("%Kfirst argument of %D must be a pointer, second integer constant",
12273 exp, fndecl);
0a39fd54 12274 expand_builtin_trap ();
12275 return const0_rtx;
12276 }
12277
c2f47e15 12278 ost = CALL_EXPR_ARG (exp, 1);
0a39fd54 12279 STRIP_NOPS (ost);
12280
12281 if (TREE_CODE (ost) != INTEGER_CST
12282 || tree_int_cst_sgn (ost) < 0
12283 || compare_tree_int (ost, 3) > 0)
12284 {
b8c23db3 12285 error ("%Klast argument of %D is not integer constant between 0 and 3",
12286 exp, fndecl);
0a39fd54 12287 expand_builtin_trap ();
12288 return const0_rtx;
12289 }
12290
e913b5cd 12291 object_size_type = tree_to_shwi (ost);
0a39fd54 12292
12293 return object_size_type < 2 ? constm1_rtx : const0_rtx;
12294}
12295
12296/* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
12297 FCODE is the BUILT_IN_* to use.
c2f47e15 12298 Return NULL_RTX if we failed; the caller should emit a normal call,
0a39fd54 12299 otherwise try to get the result in TARGET, if convenient (and in
12300 mode MODE if that's convenient). */
12301
12302static rtx
12303expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
12304 enum built_in_function fcode)
12305{
0a39fd54 12306 tree dest, src, len, size;
12307
c2f47e15 12308 if (!validate_arglist (exp,
0a39fd54 12309 POINTER_TYPE,
12310 fcode == BUILT_IN_MEMSET_CHK
12311 ? INTEGER_TYPE : POINTER_TYPE,
12312 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
c2f47e15 12313 return NULL_RTX;
0a39fd54 12314
c2f47e15 12315 dest = CALL_EXPR_ARG (exp, 0);
12316 src = CALL_EXPR_ARG (exp, 1);
12317 len = CALL_EXPR_ARG (exp, 2);
12318 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 12319
e913b5cd 12320 if (! tree_fits_uhwi_p (size))
c2f47e15 12321 return NULL_RTX;
0a39fd54 12322
e913b5cd 12323 if (tree_fits_uhwi_p (len) || integer_all_onesp (size))
0a39fd54 12324 {
12325 tree fn;
12326
12327 if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
12328 {
b430e8d9 12329 warning_at (tree_nonartificial_location (exp),
12330 0, "%Kcall to %D will always overflow destination buffer",
12331 exp, get_callee_fndecl (exp));
c2f47e15 12332 return NULL_RTX;
0a39fd54 12333 }
12334
0a39fd54 12335 fn = NULL_TREE;
12336 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
12337 mem{cpy,pcpy,move,set} is available. */
12338 switch (fcode)
12339 {
12340 case BUILT_IN_MEMCPY_CHK:
b9a16870 12341 fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
0a39fd54 12342 break;
12343 case BUILT_IN_MEMPCPY_CHK:
b9a16870 12344 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
0a39fd54 12345 break;
12346 case BUILT_IN_MEMMOVE_CHK:
b9a16870 12347 fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
0a39fd54 12348 break;
12349 case BUILT_IN_MEMSET_CHK:
b9a16870 12350 fn = builtin_decl_explicit (BUILT_IN_MEMSET);
0a39fd54 12351 break;
12352 default:
12353 break;
12354 }
12355
12356 if (! fn)
c2f47e15 12357 return NULL_RTX;
0a39fd54 12358
0568e9c1 12359 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 3, dest, src, len);
a65c4d64 12360 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
12361 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0a39fd54 12362 return expand_expr (fn, target, mode, EXPAND_NORMAL);
12363 }
12364 else if (fcode == BUILT_IN_MEMSET_CHK)
c2f47e15 12365 return NULL_RTX;
0a39fd54 12366 else
12367 {
957d0361 12368 unsigned int dest_align = get_pointer_alignment (dest);
0a39fd54 12369
12370 /* If DEST is not a pointer type, call the normal function. */
12371 if (dest_align == 0)
c2f47e15 12372 return NULL_RTX;
0a39fd54 12373
12374 /* If SRC and DEST are the same (and not volatile), do nothing. */
12375 if (operand_equal_p (src, dest, 0))
12376 {
12377 tree expr;
12378
12379 if (fcode != BUILT_IN_MEMPCPY_CHK)
12380 {
12381 /* Evaluate and ignore LEN in case it has side-effects. */
12382 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
12383 return expand_expr (dest, target, mode, EXPAND_NORMAL);
12384 }
12385
2cc66f2a 12386 expr = fold_build_pointer_plus (dest, len);
0a39fd54 12387 return expand_expr (expr, target, mode, EXPAND_NORMAL);
12388 }
12389
12390 /* __memmove_chk special case. */
12391 if (fcode == BUILT_IN_MEMMOVE_CHK)
12392 {
957d0361 12393 unsigned int src_align = get_pointer_alignment (src);
0a39fd54 12394
12395 if (src_align == 0)
c2f47e15 12396 return NULL_RTX;
0a39fd54 12397
12398 /* If src is categorized for a readonly section we can use
12399 normal __memcpy_chk. */
12400 if (readonly_data_expr (src))
12401 {
b9a16870 12402 tree fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
0a39fd54 12403 if (!fn)
c2f47e15 12404 return NULL_RTX;
0568e9c1 12405 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 4,
12406 dest, src, len, size);
a65c4d64 12407 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
12408 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0a39fd54 12409 return expand_expr (fn, target, mode, EXPAND_NORMAL);
12410 }
12411 }
c2f47e15 12412 return NULL_RTX;
0a39fd54 12413 }
12414}
12415
12416/* Emit warning if a buffer overflow is detected at compile time. */
12417
12418static void
12419maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
12420{
c2f47e15 12421 int is_strlen = 0;
0a39fd54 12422 tree len, size;
b430e8d9 12423 location_t loc = tree_nonartificial_location (exp);
0a39fd54 12424
12425 switch (fcode)
12426 {
12427 case BUILT_IN_STRCPY_CHK:
12428 case BUILT_IN_STPCPY_CHK:
12429 /* For __strcat_chk the warning will be emitted only if overflowing
12430 by at least strlen (dest) + 1 bytes. */
12431 case BUILT_IN_STRCAT_CHK:
c2f47e15 12432 len = CALL_EXPR_ARG (exp, 1);
12433 size = CALL_EXPR_ARG (exp, 2);
0a39fd54 12434 is_strlen = 1;
12435 break;
b356dfef 12436 case BUILT_IN_STRNCAT_CHK:
0a39fd54 12437 case BUILT_IN_STRNCPY_CHK:
1063acde 12438 case BUILT_IN_STPNCPY_CHK:
c2f47e15 12439 len = CALL_EXPR_ARG (exp, 2);
12440 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 12441 break;
12442 case BUILT_IN_SNPRINTF_CHK:
12443 case BUILT_IN_VSNPRINTF_CHK:
c2f47e15 12444 len = CALL_EXPR_ARG (exp, 1);
12445 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 12446 break;
12447 default:
12448 gcc_unreachable ();
12449 }
12450
0a39fd54 12451 if (!len || !size)
12452 return;
12453
e913b5cd 12454 if (! tree_fits_uhwi_p (size) || integer_all_onesp (size))
0a39fd54 12455 return;
12456
12457 if (is_strlen)
12458 {
12459 len = c_strlen (len, 1);
e913b5cd 12460 if (! len || ! tree_fits_uhwi_p (len) || tree_int_cst_lt (len, size))
0a39fd54 12461 return;
12462 }
b356dfef 12463 else if (fcode == BUILT_IN_STRNCAT_CHK)
12464 {
c2f47e15 12465 tree src = CALL_EXPR_ARG (exp, 1);
e913b5cd 12466 if (! src || ! tree_fits_uhwi_p (len) || tree_int_cst_lt (len, size))
b356dfef 12467 return;
12468 src = c_strlen (src, 1);
e913b5cd 12469 if (! src || ! tree_fits_uhwi_p (src))
b356dfef 12470 {
b430e8d9 12471 warning_at (loc, 0, "%Kcall to %D might overflow destination buffer",
12472 exp, get_callee_fndecl (exp));
b356dfef 12473 return;
12474 }
12475 else if (tree_int_cst_lt (src, size))
12476 return;
12477 }
e913b5cd 12478 else if (! tree_fits_uhwi_p (len) || ! tree_int_cst_lt (size, len))
0a39fd54 12479 return;
12480
b430e8d9 12481 warning_at (loc, 0, "%Kcall to %D will always overflow destination buffer",
12482 exp, get_callee_fndecl (exp));
0a39fd54 12483}
12484
12485/* Emit warning if a buffer overflow is detected at compile time
12486 in __sprintf_chk/__vsprintf_chk calls. */
12487
12488static void
12489maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
12490{
1e4adcfc 12491 tree size, len, fmt;
0a39fd54 12492 const char *fmt_str;
c2f47e15 12493 int nargs = call_expr_nargs (exp);
0a39fd54 12494
12495 /* Verify the required arguments in the original call. */
48e1416a 12496
c2f47e15 12497 if (nargs < 4)
0a39fd54 12498 return;
c2f47e15 12499 size = CALL_EXPR_ARG (exp, 2);
12500 fmt = CALL_EXPR_ARG (exp, 3);
0a39fd54 12501
e913b5cd 12502 if (! tree_fits_uhwi_p (size) || integer_all_onesp (size))
0a39fd54 12503 return;
12504
12505 /* Check whether the format is a literal string constant. */
12506 fmt_str = c_getstr (fmt);
12507 if (fmt_str == NULL)
12508 return;
12509
d4473c84 12510 if (!init_target_chars ())
99eabcc1 12511 return;
12512
0a39fd54 12513 /* If the format doesn't contain % args or %%, we know its size. */
99eabcc1 12514 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 12515 len = build_int_cstu (size_type_node, strlen (fmt_str));
12516 /* If the format is "%s" and first ... argument is a string literal,
12517 we know it too. */
c2f47e15 12518 else if (fcode == BUILT_IN_SPRINTF_CHK
12519 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12520 {
12521 tree arg;
12522
c2f47e15 12523 if (nargs < 5)
0a39fd54 12524 return;
c2f47e15 12525 arg = CALL_EXPR_ARG (exp, 4);
0a39fd54 12526 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
12527 return;
12528
12529 len = c_strlen (arg, 1);
e913b5cd 12530 if (!len || ! tree_fits_uhwi_p (len))
0a39fd54 12531 return;
12532 }
12533 else
12534 return;
12535
12536 if (! tree_int_cst_lt (len, size))
b430e8d9 12537 warning_at (tree_nonartificial_location (exp),
12538 0, "%Kcall to %D will always overflow destination buffer",
12539 exp, get_callee_fndecl (exp));
0a39fd54 12540}
12541
2c281b15 12542/* Emit warning if a free is called with address of a variable. */
12543
12544static void
12545maybe_emit_free_warning (tree exp)
12546{
12547 tree arg = CALL_EXPR_ARG (exp, 0);
12548
12549 STRIP_NOPS (arg);
12550 if (TREE_CODE (arg) != ADDR_EXPR)
12551 return;
12552
12553 arg = get_base_address (TREE_OPERAND (arg, 0));
182cf5a9 12554 if (arg == NULL || INDIRECT_REF_P (arg) || TREE_CODE (arg) == MEM_REF)
2c281b15 12555 return;
12556
12557 if (SSA_VAR_P (arg))
f74ea1c2 12558 warning_at (tree_nonartificial_location (exp), OPT_Wfree_nonheap_object,
12559 "%Kattempt to free a non-heap object %qD", exp, arg);
2c281b15 12560 else
f74ea1c2 12561 warning_at (tree_nonartificial_location (exp), OPT_Wfree_nonheap_object,
12562 "%Kattempt to free a non-heap object", exp);
2c281b15 12563}
12564
c2f47e15 12565/* Fold a call to __builtin_object_size with arguments PTR and OST,
12566 if possible. */
0a39fd54 12567
12568tree
c2f47e15 12569fold_builtin_object_size (tree ptr, tree ost)
0a39fd54 12570{
a6caa15f 12571 unsigned HOST_WIDE_INT bytes;
0a39fd54 12572 int object_size_type;
12573
c2f47e15 12574 if (!validate_arg (ptr, POINTER_TYPE)
12575 || !validate_arg (ost, INTEGER_TYPE))
12576 return NULL_TREE;
0a39fd54 12577
0a39fd54 12578 STRIP_NOPS (ost);
12579
12580 if (TREE_CODE (ost) != INTEGER_CST
12581 || tree_int_cst_sgn (ost) < 0
12582 || compare_tree_int (ost, 3) > 0)
c2f47e15 12583 return NULL_TREE;
0a39fd54 12584
e913b5cd 12585 object_size_type = tree_to_shwi (ost);
0a39fd54 12586
12587 /* __builtin_object_size doesn't evaluate side-effects in its arguments;
12588 if there are any side-effects, it returns (size_t) -1 for types 0 and 1
12589 and (size_t) 0 for types 2 and 3. */
12590 if (TREE_SIDE_EFFECTS (ptr))
697bbc3f 12591 return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
0a39fd54 12592
12593 if (TREE_CODE (ptr) == ADDR_EXPR)
a6caa15f 12594 {
6da74b21 12595 bytes = compute_builtin_object_size (ptr, object_size_type);
12596 if (wi::fits_to_tree_p (bytes, size_type_node))
12597 return build_int_cstu (size_type_node, bytes);
a6caa15f 12598 }
0a39fd54 12599 else if (TREE_CODE (ptr) == SSA_NAME)
12600 {
0a39fd54 12601 /* If object size is not known yet, delay folding until
12602 later. Maybe subsequent passes will help determining
12603 it. */
12604 bytes = compute_builtin_object_size (ptr, object_size_type);
a6caa15f 12605 if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2 ? -1 : 0)
6da74b21 12606 && wi::fits_to_tree_p (bytes, size_type_node))
12607 return build_int_cstu (size_type_node, bytes);
0a39fd54 12608 }
12609
a6caa15f 12610 return NULL_TREE;
0a39fd54 12611}
12612
12613/* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
c2f47e15 12614 DEST, SRC, LEN, and SIZE are the arguments to the call.
0a39fd54 12615 IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_*
12616 code of the builtin. If MAXLEN is not NULL, it is maximum length
12617 passed as third argument. */
12618
12619tree
389dd41b 12620fold_builtin_memory_chk (location_t loc, tree fndecl,
c2f47e15 12621 tree dest, tree src, tree len, tree size,
12622 tree maxlen, bool ignore,
0a39fd54 12623 enum built_in_function fcode)
12624{
c2f47e15 12625 tree fn;
0a39fd54 12626
c2f47e15 12627 if (!validate_arg (dest, POINTER_TYPE)
12628 || !validate_arg (src,
12629 (fcode == BUILT_IN_MEMSET_CHK
12630 ? INTEGER_TYPE : POINTER_TYPE))
12631 || !validate_arg (len, INTEGER_TYPE)
12632 || !validate_arg (size, INTEGER_TYPE))
12633 return NULL_TREE;
0a39fd54 12634
12635 /* If SRC and DEST are the same (and not volatile), return DEST
12636 (resp. DEST+LEN for __mempcpy_chk). */
12637 if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
12638 {
12639 if (fcode != BUILT_IN_MEMPCPY_CHK)
389dd41b 12640 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
12641 dest, len);
0a39fd54 12642 else
12643 {
2cc66f2a 12644 tree temp = fold_build_pointer_plus_loc (loc, dest, len);
389dd41b 12645 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), temp);
0a39fd54 12646 }
12647 }
12648
e913b5cd 12649 if (! tree_fits_uhwi_p (size))
c2f47e15 12650 return NULL_TREE;
0a39fd54 12651
12652 if (! integer_all_onesp (size))
12653 {
e913b5cd 12654 if (! tree_fits_uhwi_p (len))
0a39fd54 12655 {
12656 /* If LEN is not constant, try MAXLEN too.
12657 For MAXLEN only allow optimizing into non-_ocs function
12658 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
e913b5cd 12659 if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen))
0a39fd54 12660 {
12661 if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
12662 {
12663 /* (void) __mempcpy_chk () can be optimized into
12664 (void) __memcpy_chk (). */
b9a16870 12665 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
0a39fd54 12666 if (!fn)
c2f47e15 12667 return NULL_TREE;
0a39fd54 12668
389dd41b 12669 return build_call_expr_loc (loc, fn, 4, dest, src, len, size);
0a39fd54 12670 }
c2f47e15 12671 return NULL_TREE;
0a39fd54 12672 }
0a39fd54 12673 }
ad89623c 12674 else
12675 maxlen = len;
0a39fd54 12676
ad89623c 12677 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12678 return NULL_TREE;
0a39fd54 12679 }
12680
0a39fd54 12681 fn = NULL_TREE;
12682 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
12683 mem{cpy,pcpy,move,set} is available. */
12684 switch (fcode)
12685 {
12686 case BUILT_IN_MEMCPY_CHK:
b9a16870 12687 fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
0a39fd54 12688 break;
12689 case BUILT_IN_MEMPCPY_CHK:
b9a16870 12690 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
0a39fd54 12691 break;
12692 case BUILT_IN_MEMMOVE_CHK:
b9a16870 12693 fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
0a39fd54 12694 break;
12695 case BUILT_IN_MEMSET_CHK:
b9a16870 12696 fn = builtin_decl_explicit (BUILT_IN_MEMSET);
0a39fd54 12697 break;
12698 default:
12699 break;
12700 }
12701
12702 if (!fn)
c2f47e15 12703 return NULL_TREE;
0a39fd54 12704
389dd41b 12705 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12706}
12707
12708/* Fold a call to the __st[rp]cpy_chk builtin.
c2f47e15 12709 DEST, SRC, and SIZE are the arguments to the call.
12710 IGNORE is true if return value can be ignored. FCODE is the BUILT_IN_*
0a39fd54 12711 code of the builtin. If MAXLEN is not NULL, it is maximum length of
12712 strings passed as second argument. */
12713
12714tree
389dd41b 12715fold_builtin_stxcpy_chk (location_t loc, tree fndecl, tree dest,
12716 tree src, tree size,
c2f47e15 12717 tree maxlen, bool ignore,
0a39fd54 12718 enum built_in_function fcode)
12719{
c2f47e15 12720 tree len, fn;
0a39fd54 12721
c2f47e15 12722 if (!validate_arg (dest, POINTER_TYPE)
12723 || !validate_arg (src, POINTER_TYPE)
12724 || !validate_arg (size, INTEGER_TYPE))
12725 return NULL_TREE;
0a39fd54 12726
12727 /* If SRC and DEST are the same (and not volatile), return DEST. */
12728 if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
389dd41b 12729 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
a0c938f0 12730
e913b5cd 12731 if (! tree_fits_uhwi_p (size))
c2f47e15 12732 return NULL_TREE;
0a39fd54 12733
12734 if (! integer_all_onesp (size))
12735 {
12736 len = c_strlen (src, 1);
e913b5cd 12737 if (! len || ! tree_fits_uhwi_p (len))
0a39fd54 12738 {
12739 /* If LEN is not constant, try MAXLEN too.
12740 For MAXLEN only allow optimizing into non-_ocs function
12741 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
e913b5cd 12742 if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen))
0a39fd54 12743 {
12744 if (fcode == BUILT_IN_STPCPY_CHK)
12745 {
12746 if (! ignore)
c2f47e15 12747 return NULL_TREE;
0a39fd54 12748
12749 /* If return value of __stpcpy_chk is ignored,
12750 optimize into __strcpy_chk. */
b9a16870 12751 fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
0a39fd54 12752 if (!fn)
c2f47e15 12753 return NULL_TREE;
0a39fd54 12754
389dd41b 12755 return build_call_expr_loc (loc, fn, 3, dest, src, size);
0a39fd54 12756 }
12757
12758 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 12759 return NULL_TREE;
0a39fd54 12760
12761 /* If c_strlen returned something, but not a constant,
12762 transform __strcpy_chk into __memcpy_chk. */
b9a16870 12763 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
0a39fd54 12764 if (!fn)
c2f47e15 12765 return NULL_TREE;
0a39fd54 12766
bd6dcc04 12767 len = fold_convert_loc (loc, size_type_node, len);
12768 len = size_binop_loc (loc, PLUS_EXPR, len,
12769 build_int_cst (size_type_node, 1));
389dd41b 12770 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
12771 build_call_expr_loc (loc, fn, 4,
12772 dest, src, len, size));
0a39fd54 12773 }
0a39fd54 12774 }
ad89623c 12775 else
12776 maxlen = len;
12777
12778 if (! tree_int_cst_lt (maxlen, size))
c2f47e15 12779 return NULL_TREE;
0a39fd54 12780 }
12781
0a39fd54 12782 /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available. */
b9a16870 12783 fn = builtin_decl_explicit (fcode == BUILT_IN_STPCPY_CHK
12784 ? BUILT_IN_STPCPY : BUILT_IN_STRCPY);
0a39fd54 12785 if (!fn)
c2f47e15 12786 return NULL_TREE;
0a39fd54 12787
389dd41b 12788 return build_call_expr_loc (loc, fn, 2, dest, src);
0a39fd54 12789}
12790
1063acde 12791/* Fold a call to the __st{r,p}ncpy_chk builtin. DEST, SRC, LEN, and SIZE
c2f47e15 12792 are the arguments to the call. If MAXLEN is not NULL, it is maximum
1063acde 12793 length passed as third argument. IGNORE is true if return value can be
12794 ignored. FCODE is the BUILT_IN_* code of the builtin. */
0a39fd54 12795
12796tree
1063acde 12797fold_builtin_stxncpy_chk (location_t loc, tree dest, tree src,
12798 tree len, tree size, tree maxlen, bool ignore,
12799 enum built_in_function fcode)
0a39fd54 12800{
c2f47e15 12801 tree fn;
0a39fd54 12802
c2f47e15 12803 if (!validate_arg (dest, POINTER_TYPE)
12804 || !validate_arg (src, POINTER_TYPE)
12805 || !validate_arg (len, INTEGER_TYPE)
12806 || !validate_arg (size, INTEGER_TYPE))
12807 return NULL_TREE;
0a39fd54 12808
1063acde 12809 if (fcode == BUILT_IN_STPNCPY_CHK && ignore)
12810 {
12811 /* If return value of __stpncpy_chk is ignored,
12812 optimize into __strncpy_chk. */
12813 fn = builtin_decl_explicit (BUILT_IN_STRNCPY_CHK);
12814 if (fn)
12815 return build_call_expr_loc (loc, fn, 4, dest, src, len, size);
12816 }
12817
e913b5cd 12818 if (! tree_fits_uhwi_p (size))
c2f47e15 12819 return NULL_TREE;
0a39fd54 12820
12821 if (! integer_all_onesp (size))
12822 {
e913b5cd 12823 if (! tree_fits_uhwi_p (len))
0a39fd54 12824 {
12825 /* If LEN is not constant, try MAXLEN too.
12826 For MAXLEN only allow optimizing into non-_ocs function
12827 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
e913b5cd 12828 if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen))
c2f47e15 12829 return NULL_TREE;
0a39fd54 12830 }
ad89623c 12831 else
12832 maxlen = len;
0a39fd54 12833
ad89623c 12834 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12835 return NULL_TREE;
0a39fd54 12836 }
12837
1063acde 12838 /* If __builtin_st{r,p}ncpy_chk is used, assume st{r,p}ncpy is available. */
12839 fn = builtin_decl_explicit (fcode == BUILT_IN_STPNCPY_CHK
12840 ? BUILT_IN_STPNCPY : BUILT_IN_STRNCPY);
0a39fd54 12841 if (!fn)
c2f47e15 12842 return NULL_TREE;
0a39fd54 12843
389dd41b 12844 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12845}
12846
c2f47e15 12847/* Fold a call to the __strcat_chk builtin FNDECL. DEST, SRC, and SIZE
12848 are the arguments to the call. */
0a39fd54 12849
12850static tree
389dd41b 12851fold_builtin_strcat_chk (location_t loc, tree fndecl, tree dest,
12852 tree src, tree size)
0a39fd54 12853{
c2f47e15 12854 tree fn;
0a39fd54 12855 const char *p;
12856
c2f47e15 12857 if (!validate_arg (dest, POINTER_TYPE)
12858 || !validate_arg (src, POINTER_TYPE)
12859 || !validate_arg (size, INTEGER_TYPE))
12860 return NULL_TREE;
0a39fd54 12861
12862 p = c_getstr (src);
12863 /* If the SRC parameter is "", return DEST. */
12864 if (p && *p == '\0')
389dd41b 12865 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
0a39fd54 12866
e913b5cd 12867 if (! tree_fits_uhwi_p (size) || ! integer_all_onesp (size))
c2f47e15 12868 return NULL_TREE;
0a39fd54 12869
12870 /* If __builtin_strcat_chk is used, assume strcat is available. */
b9a16870 12871 fn = builtin_decl_explicit (BUILT_IN_STRCAT);
0a39fd54 12872 if (!fn)
c2f47e15 12873 return NULL_TREE;
0a39fd54 12874
389dd41b 12875 return build_call_expr_loc (loc, fn, 2, dest, src);
0a39fd54 12876}
12877
c2f47e15 12878/* Fold a call to the __strncat_chk builtin with arguments DEST, SRC,
12879 LEN, and SIZE. */
0a39fd54 12880
12881static tree
389dd41b 12882fold_builtin_strncat_chk (location_t loc, tree fndecl,
c2f47e15 12883 tree dest, tree src, tree len, tree size)
0a39fd54 12884{
c2f47e15 12885 tree fn;
0a39fd54 12886 const char *p;
12887
c2f47e15 12888 if (!validate_arg (dest, POINTER_TYPE)
12889 || !validate_arg (src, POINTER_TYPE)
12890 || !validate_arg (size, INTEGER_TYPE)
12891 || !validate_arg (size, INTEGER_TYPE))
12892 return NULL_TREE;
0a39fd54 12893
12894 p = c_getstr (src);
12895 /* If the SRC parameter is "" or if LEN is 0, return DEST. */
12896 if (p && *p == '\0')
389dd41b 12897 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
0a39fd54 12898 else if (integer_zerop (len))
389dd41b 12899 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
0a39fd54 12900
e913b5cd 12901 if (! tree_fits_uhwi_p (size))
c2f47e15 12902 return NULL_TREE;
0a39fd54 12903
12904 if (! integer_all_onesp (size))
12905 {
12906 tree src_len = c_strlen (src, 1);
12907 if (src_len
e913b5cd 12908 && tree_fits_uhwi_p (src_len)
12909 && tree_fits_uhwi_p (len)
0a39fd54 12910 && ! tree_int_cst_lt (len, src_len))
12911 {
12912 /* If LEN >= strlen (SRC), optimize into __strcat_chk. */
b9a16870 12913 fn = builtin_decl_explicit (BUILT_IN_STRCAT_CHK);
0a39fd54 12914 if (!fn)
c2f47e15 12915 return NULL_TREE;
0a39fd54 12916
389dd41b 12917 return build_call_expr_loc (loc, fn, 3, dest, src, size);
0a39fd54 12918 }
c2f47e15 12919 return NULL_TREE;
0a39fd54 12920 }
12921
0a39fd54 12922 /* If __builtin_strncat_chk is used, assume strncat is available. */
b9a16870 12923 fn = builtin_decl_explicit (BUILT_IN_STRNCAT);
0a39fd54 12924 if (!fn)
c2f47e15 12925 return NULL_TREE;
0a39fd54 12926
389dd41b 12927 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12928}
12929
af1409ad 12930/* Fold a call EXP to __{,v}sprintf_chk having NARGS passed as ARGS.
12931 Return NULL_TREE if a normal call should be emitted rather than
12932 expanding the function inline. FCODE is either BUILT_IN_SPRINTF_CHK
12933 or BUILT_IN_VSPRINTF_CHK. */
0a39fd54 12934
12935static tree
af1409ad 12936fold_builtin_sprintf_chk_1 (location_t loc, int nargs, tree *args,
12937 enum built_in_function fcode)
0a39fd54 12938{
12939 tree dest, size, len, fn, fmt, flag;
12940 const char *fmt_str;
12941
12942 /* Verify the required arguments in the original call. */
c2f47e15 12943 if (nargs < 4)
12944 return NULL_TREE;
af1409ad 12945 dest = args[0];
c2f47e15 12946 if (!validate_arg (dest, POINTER_TYPE))
12947 return NULL_TREE;
af1409ad 12948 flag = args[1];
c2f47e15 12949 if (!validate_arg (flag, INTEGER_TYPE))
12950 return NULL_TREE;
af1409ad 12951 size = args[2];
c2f47e15 12952 if (!validate_arg (size, INTEGER_TYPE))
12953 return NULL_TREE;
af1409ad 12954 fmt = args[3];
c2f47e15 12955 if (!validate_arg (fmt, POINTER_TYPE))
12956 return NULL_TREE;
0a39fd54 12957
e913b5cd 12958 if (! tree_fits_uhwi_p (size))
c2f47e15 12959 return NULL_TREE;
0a39fd54 12960
12961 len = NULL_TREE;
12962
d4473c84 12963 if (!init_target_chars ())
c2f47e15 12964 return NULL_TREE;
99eabcc1 12965
0a39fd54 12966 /* Check whether the format is a literal string constant. */
12967 fmt_str = c_getstr (fmt);
12968 if (fmt_str != NULL)
12969 {
12970 /* If the format doesn't contain % args or %%, we know the size. */
99eabcc1 12971 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 12972 {
c2f47e15 12973 if (fcode != BUILT_IN_SPRINTF_CHK || nargs == 4)
0a39fd54 12974 len = build_int_cstu (size_type_node, strlen (fmt_str));
12975 }
12976 /* If the format is "%s" and first ... argument is a string literal,
12977 we know the size too. */
c2f47e15 12978 else if (fcode == BUILT_IN_SPRINTF_CHK
12979 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12980 {
12981 tree arg;
12982
c2f47e15 12983 if (nargs == 5)
0a39fd54 12984 {
af1409ad 12985 arg = args[4];
c2f47e15 12986 if (validate_arg (arg, POINTER_TYPE))
0a39fd54 12987 {
12988 len = c_strlen (arg, 1);
e913b5cd 12989 if (! len || ! tree_fits_uhwi_p (len))
0a39fd54 12990 len = NULL_TREE;
12991 }
12992 }
12993 }
12994 }
12995
12996 if (! integer_all_onesp (size))
12997 {
12998 if (! len || ! tree_int_cst_lt (len, size))
c2f47e15 12999 return NULL_TREE;
0a39fd54 13000 }
13001
13002 /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
13003 or if format doesn't contain % chars or is "%s". */
13004 if (! integer_zerop (flag))
13005 {
13006 if (fmt_str == NULL)
c2f47e15 13007 return NULL_TREE;
13008 if (strchr (fmt_str, target_percent) != NULL
13009 && strcmp (fmt_str, target_percent_s))
13010 return NULL_TREE;
0a39fd54 13011 }
13012
0a39fd54 13013 /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
b9a16870 13014 fn = builtin_decl_explicit (fcode == BUILT_IN_VSPRINTF_CHK
13015 ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF);
0a39fd54 13016 if (!fn)
c2f47e15 13017 return NULL_TREE;
0a39fd54 13018
af1409ad 13019 return rewrite_call_expr_array (loc, nargs, args, 4, fn, 2, dest, fmt);
0a39fd54 13020}
13021
af1409ad 13022/* Fold a call EXP to __{,v}sprintf_chk. Return NULL_TREE if
0a39fd54 13023 a normal call should be emitted rather than expanding the function
af1409ad 13024 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
13025
13026static tree
13027fold_builtin_sprintf_chk (location_t loc, tree exp,
13028 enum built_in_function fcode)
13029{
13030 return fold_builtin_sprintf_chk_1 (loc, call_expr_nargs (exp),
13031 CALL_EXPR_ARGP (exp), fcode);
13032}
13033
13034/* Fold a call EXP to {,v}snprintf having NARGS passed as ARGS. Return
13035 NULL_TREE if a normal call should be emitted rather than expanding
13036 the function inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
0a39fd54 13037 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
13038 passed as second argument. */
13039
af1409ad 13040static tree
13041fold_builtin_snprintf_chk_1 (location_t loc, int nargs, tree *args,
13042 tree maxlen, enum built_in_function fcode)
0a39fd54 13043{
13044 tree dest, size, len, fn, fmt, flag;
13045 const char *fmt_str;
13046
13047 /* Verify the required arguments in the original call. */
af1409ad 13048 if (nargs < 5)
c2f47e15 13049 return NULL_TREE;
af1409ad 13050 dest = args[0];
c2f47e15 13051 if (!validate_arg (dest, POINTER_TYPE))
13052 return NULL_TREE;
af1409ad 13053 len = args[1];
c2f47e15 13054 if (!validate_arg (len, INTEGER_TYPE))
13055 return NULL_TREE;
af1409ad 13056 flag = args[2];
c2f47e15 13057 if (!validate_arg (flag, INTEGER_TYPE))
13058 return NULL_TREE;
af1409ad 13059 size = args[3];
c2f47e15 13060 if (!validate_arg (size, INTEGER_TYPE))
13061 return NULL_TREE;
af1409ad 13062 fmt = args[4];
c2f47e15 13063 if (!validate_arg (fmt, POINTER_TYPE))
13064 return NULL_TREE;
0a39fd54 13065
e913b5cd 13066 if (! tree_fits_uhwi_p (size))
c2f47e15 13067 return NULL_TREE;
0a39fd54 13068
13069 if (! integer_all_onesp (size))
13070 {
e913b5cd 13071 if (! tree_fits_uhwi_p (len))
0a39fd54 13072 {
13073 /* If LEN is not constant, try MAXLEN too.
13074 For MAXLEN only allow optimizing into non-_ocs function
13075 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
e913b5cd 13076 if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen))
c2f47e15 13077 return NULL_TREE;
0a39fd54 13078 }
ad89623c 13079 else
13080 maxlen = len;
0a39fd54 13081
ad89623c 13082 if (tree_int_cst_lt (size, maxlen))
c2f47e15 13083 return NULL_TREE;
0a39fd54 13084 }
13085
d4473c84 13086 if (!init_target_chars ())
c2f47e15 13087 return NULL_TREE;
99eabcc1 13088
0a39fd54 13089 /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
13090 or if format doesn't contain % chars or is "%s". */
13091 if (! integer_zerop (flag))
13092 {
13093 fmt_str = c_getstr (fmt);
13094 if (fmt_str == NULL)
c2f47e15 13095 return NULL_TREE;
13096 if (strchr (fmt_str, target_percent) != NULL
13097 && strcmp (fmt_str, target_percent_s))
13098 return NULL_TREE;
0a39fd54 13099 }
13100
0a39fd54 13101 /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
13102 available. */
b9a16870 13103 fn = builtin_decl_explicit (fcode == BUILT_IN_VSNPRINTF_CHK
13104 ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF);
0a39fd54 13105 if (!fn)
c2f47e15 13106 return NULL_TREE;
0a39fd54 13107
af1409ad 13108 return rewrite_call_expr_array (loc, nargs, args, 5, fn, 3, dest, len, fmt);
13109}
13110
13111/* Fold a call EXP to {,v}snprintf. Return NULL_TREE if
13112 a normal call should be emitted rather than expanding the function
13113 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
13114 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
13115 passed as second argument. */
13116
0e80b01d 13117static tree
af1409ad 13118fold_builtin_snprintf_chk (location_t loc, tree exp, tree maxlen,
13119 enum built_in_function fcode)
13120{
13121 return fold_builtin_snprintf_chk_1 (loc, call_expr_nargs (exp),
13122 CALL_EXPR_ARGP (exp), maxlen, fcode);
0a39fd54 13123}
13124
0e80b01d 13125/* Builtins with folding operations that operate on "..." arguments
13126 need special handling; we need to store the arguments in a convenient
13127 data structure before attempting any folding. Fortunately there are
13128 only a few builtins that fall into this category. FNDECL is the
13129 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
13130 result of the function call is ignored. */
13131
13132static tree
13133fold_builtin_varargs (location_t loc, tree fndecl, tree exp,
13134 bool ignore ATTRIBUTE_UNUSED)
13135{
13136 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
13137 tree ret = NULL_TREE;
13138
13139 switch (fcode)
13140 {
13141 case BUILT_IN_SPRINTF_CHK:
13142 case BUILT_IN_VSPRINTF_CHK:
13143 ret = fold_builtin_sprintf_chk (loc, exp, fcode);
13144 break;
13145
13146 case BUILT_IN_SNPRINTF_CHK:
13147 case BUILT_IN_VSNPRINTF_CHK:
13148 ret = fold_builtin_snprintf_chk (loc, exp, NULL_TREE, fcode);
13149 break;
13150
13151 case BUILT_IN_FPCLASSIFY:
13152 ret = fold_builtin_fpclassify (loc, exp);
13153 break;
13154
13155 default:
13156 break;
13157 }
13158 if (ret)
13159 {
13160 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
13161 SET_EXPR_LOCATION (ret, loc);
13162 TREE_NO_WARNING (ret) = 1;
13163 return ret;
13164 }
13165 return NULL_TREE;
13166}
13167
0a39fd54 13168/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 13169 FMT and ARG are the arguments to the call; we don't fold cases with
13170 more than 2 arguments, and ARG may be null if this is a 1-argument case.
0a39fd54 13171
c2f47e15 13172 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 13173 simplified form of the call as a tree. FCODE is the BUILT_IN_*
13174 code of the function to be simplified. */
13175
13176static tree
389dd41b 13177fold_builtin_printf (location_t loc, tree fndecl, tree fmt,
13178 tree arg, bool ignore,
0a39fd54 13179 enum built_in_function fcode)
13180{
c2f47e15 13181 tree fn_putchar, fn_puts, newarg, call = NULL_TREE;
0a39fd54 13182 const char *fmt_str = NULL;
13183
13184 /* If the return value is used, don't do the transformation. */
13185 if (! ignore)
c2f47e15 13186 return NULL_TREE;
0a39fd54 13187
13188 /* Verify the required arguments in the original call. */
c2f47e15 13189 if (!validate_arg (fmt, POINTER_TYPE))
13190 return NULL_TREE;
0a39fd54 13191
13192 /* Check whether the format is a literal string constant. */
13193 fmt_str = c_getstr (fmt);
13194 if (fmt_str == NULL)
13195 return NULL_TREE;
13196
13197 if (fcode == BUILT_IN_PRINTF_UNLOCKED)
13198 {
6d77ed92 13199 /* If we're using an unlocked function, assume the other
13200 unlocked functions exist explicitly. */
b9a16870 13201 fn_putchar = builtin_decl_explicit (BUILT_IN_PUTCHAR_UNLOCKED);
13202 fn_puts = builtin_decl_explicit (BUILT_IN_PUTS_UNLOCKED);
0a39fd54 13203 }
13204 else
13205 {
b9a16870 13206 fn_putchar = builtin_decl_implicit (BUILT_IN_PUTCHAR);
13207 fn_puts = builtin_decl_implicit (BUILT_IN_PUTS);
0a39fd54 13208 }
13209
d4473c84 13210 if (!init_target_chars ())
c2f47e15 13211 return NULL_TREE;
a0c938f0 13212
c2f47e15 13213 if (strcmp (fmt_str, target_percent_s) == 0
13214 || strchr (fmt_str, target_percent) == NULL)
0a39fd54 13215 {
13216 const char *str;
13217
99eabcc1 13218 if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 13219 {
13220 if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 13221 return NULL_TREE;
0a39fd54 13222
c2f47e15 13223 if (!arg || !validate_arg (arg, POINTER_TYPE))
13224 return NULL_TREE;
0a39fd54 13225
c2f47e15 13226 str = c_getstr (arg);
0a39fd54 13227 if (str == NULL)
c2f47e15 13228 return NULL_TREE;
0a39fd54 13229 }
13230 else
13231 {
13232 /* The format specifier doesn't contain any '%' characters. */
13233 if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
c2f47e15 13234 && arg)
13235 return NULL_TREE;
0a39fd54 13236 str = fmt_str;
13237 }
13238
13239 /* If the string was "", printf does nothing. */
13240 if (str[0] == '\0')
13241 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
13242
13243 /* If the string has length of 1, call putchar. */
13244 if (str[1] == '\0')
13245 {
13246 /* Given printf("c"), (where c is any one character,)
13247 convert "c"[0] to an int and pass that to the replacement
13248 function. */
7002a1c8 13249 newarg = build_int_cst (integer_type_node, str[0]);
c2f47e15 13250 if (fn_putchar)
389dd41b 13251 call = build_call_expr_loc (loc, fn_putchar, 1, newarg);
0a39fd54 13252 }
13253 else
13254 {
13255 /* If the string was "string\n", call puts("string"). */
13256 size_t len = strlen (str);
663dbd5e 13257 if ((unsigned char)str[len - 1] == target_newline
13258 && (size_t) (int) len == len
13259 && (int) len > 0)
0a39fd54 13260 {
663dbd5e 13261 char *newstr;
13262 tree offset_node, string_cst;
13263
0a39fd54 13264 /* Create a NUL-terminated string that's one char shorter
13265 than the original, stripping off the trailing '\n'. */
663dbd5e 13266 newarg = build_string_literal (len, str);
13267 string_cst = string_constant (newarg, &offset_node);
13268 gcc_checking_assert (string_cst
13269 && (TREE_STRING_LENGTH (string_cst)
13270 == (int) len)
13271 && integer_zerop (offset_node)
13272 && (unsigned char)
13273 TREE_STRING_POINTER (string_cst)[len - 1]
13274 == target_newline);
13275 /* build_string_literal creates a new STRING_CST,
13276 modify it in place to avoid double copying. */
13277 newstr = CONST_CAST (char *, TREE_STRING_POINTER (string_cst));
13278 newstr[len - 1] = '\0';
c2f47e15 13279 if (fn_puts)
389dd41b 13280 call = build_call_expr_loc (loc, fn_puts, 1, newarg);
0a39fd54 13281 }
13282 else
13283 /* We'd like to arrange to call fputs(string,stdout) here,
13284 but we need stdout and don't have a way to get it yet. */
c2f47e15 13285 return NULL_TREE;
0a39fd54 13286 }
13287 }
13288
13289 /* The other optimizations can be done only on the non-va_list variants. */
13290 else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 13291 return NULL_TREE;
0a39fd54 13292
13293 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
99eabcc1 13294 else if (strcmp (fmt_str, target_percent_s_newline) == 0)
0a39fd54 13295 {
c2f47e15 13296 if (!arg || !validate_arg (arg, POINTER_TYPE))
13297 return NULL_TREE;
13298 if (fn_puts)
389dd41b 13299 call = build_call_expr_loc (loc, fn_puts, 1, arg);
0a39fd54 13300 }
13301
13302 /* If the format specifier was "%c", call __builtin_putchar(arg). */
99eabcc1 13303 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 13304 {
c2f47e15 13305 if (!arg || !validate_arg (arg, INTEGER_TYPE))
13306 return NULL_TREE;
13307 if (fn_putchar)
389dd41b 13308 call = build_call_expr_loc (loc, fn_putchar, 1, arg);
0a39fd54 13309 }
13310
c2f47e15 13311 if (!call)
13312 return NULL_TREE;
0a39fd54 13313
389dd41b 13314 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
0a39fd54 13315}
13316
13317/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 13318 FP, FMT, and ARG are the arguments to the call. We don't fold calls with
13319 more than 3 arguments, and ARG may be null in the 2-argument case.
0a39fd54 13320
c2f47e15 13321 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 13322 simplified form of the call as a tree. FCODE is the BUILT_IN_*
13323 code of the function to be simplified. */
13324
13325static tree
389dd41b 13326fold_builtin_fprintf (location_t loc, tree fndecl, tree fp,
13327 tree fmt, tree arg, bool ignore,
0a39fd54 13328 enum built_in_function fcode)
13329{
c2f47e15 13330 tree fn_fputc, fn_fputs, call = NULL_TREE;
0a39fd54 13331 const char *fmt_str = NULL;
13332
13333 /* If the return value is used, don't do the transformation. */
13334 if (! ignore)
c2f47e15 13335 return NULL_TREE;
0a39fd54 13336
13337 /* Verify the required arguments in the original call. */
c2f47e15 13338 if (!validate_arg (fp, POINTER_TYPE))
13339 return NULL_TREE;
13340 if (!validate_arg (fmt, POINTER_TYPE))
13341 return NULL_TREE;
0a39fd54 13342
13343 /* Check whether the format is a literal string constant. */
13344 fmt_str = c_getstr (fmt);
13345 if (fmt_str == NULL)
13346 return NULL_TREE;
13347
13348 if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
13349 {
6d77ed92 13350 /* If we're using an unlocked function, assume the other
13351 unlocked functions exist explicitly. */
b9a16870 13352 fn_fputc = builtin_decl_explicit (BUILT_IN_FPUTC_UNLOCKED);
13353 fn_fputs = builtin_decl_explicit (BUILT_IN_FPUTS_UNLOCKED);
0a39fd54 13354 }
13355 else
13356 {
b9a16870 13357 fn_fputc = builtin_decl_implicit (BUILT_IN_FPUTC);
13358 fn_fputs = builtin_decl_implicit (BUILT_IN_FPUTS);
0a39fd54 13359 }
13360
d4473c84 13361 if (!init_target_chars ())
c2f47e15 13362 return NULL_TREE;
a0c938f0 13363
0a39fd54 13364 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 13365 if (strchr (fmt_str, target_percent) == NULL)
0a39fd54 13366 {
13367 if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
c2f47e15 13368 && arg)
13369 return NULL_TREE;
0a39fd54 13370
13371 /* If the format specifier was "", fprintf does nothing. */
13372 if (fmt_str[0] == '\0')
13373 {
13374 /* If FP has side-effects, just wait until gimplification is
13375 done. */
13376 if (TREE_SIDE_EFFECTS (fp))
c2f47e15 13377 return NULL_TREE;
0a39fd54 13378
13379 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
13380 }
13381
13382 /* When "string" doesn't contain %, replace all cases of
13383 fprintf (fp, string) with fputs (string, fp). The fputs
13384 builtin will take care of special cases like length == 1. */
c2f47e15 13385 if (fn_fputs)
389dd41b 13386 call = build_call_expr_loc (loc, fn_fputs, 2, fmt, fp);
0a39fd54 13387 }
13388
13389 /* The other optimizations can be done only on the non-va_list variants. */
13390 else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
c2f47e15 13391 return NULL_TREE;
0a39fd54 13392
13393 /* If the format specifier was "%s", call __builtin_fputs (arg, fp). */
99eabcc1 13394 else if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 13395 {
c2f47e15 13396 if (!arg || !validate_arg (arg, POINTER_TYPE))
13397 return NULL_TREE;
13398 if (fn_fputs)
389dd41b 13399 call = build_call_expr_loc (loc, fn_fputs, 2, arg, fp);
0a39fd54 13400 }
13401
13402 /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */
99eabcc1 13403 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 13404 {
c2f47e15 13405 if (!arg || !validate_arg (arg, INTEGER_TYPE))
13406 return NULL_TREE;
13407 if (fn_fputc)
389dd41b 13408 call = build_call_expr_loc (loc, fn_fputc, 2, arg, fp);
0a39fd54 13409 }
13410
c2f47e15 13411 if (!call)
13412 return NULL_TREE;
389dd41b 13413 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
0a39fd54 13414}
99eabcc1 13415
13416/* Initialize format string characters in the target charset. */
13417
13418static bool
13419init_target_chars (void)
13420{
13421 static bool init;
13422 if (!init)
13423 {
13424 target_newline = lang_hooks.to_target_charset ('\n');
13425 target_percent = lang_hooks.to_target_charset ('%');
13426 target_c = lang_hooks.to_target_charset ('c');
13427 target_s = lang_hooks.to_target_charset ('s');
13428 if (target_newline == 0 || target_percent == 0 || target_c == 0
13429 || target_s == 0)
13430 return false;
13431
13432 target_percent_c[0] = target_percent;
13433 target_percent_c[1] = target_c;
13434 target_percent_c[2] = '\0';
13435
13436 target_percent_s[0] = target_percent;
13437 target_percent_s[1] = target_s;
13438 target_percent_s[2] = '\0';
13439
13440 target_percent_s_newline[0] = target_percent;
13441 target_percent_s_newline[1] = target_s;
13442 target_percent_s_newline[2] = target_newline;
13443 target_percent_s_newline[3] = '\0';
a0c938f0 13444
99eabcc1 13445 init = true;
13446 }
13447 return true;
13448}
bffb7645 13449
f0c477f2 13450/* Helper function for do_mpfr_arg*(). Ensure M is a normal number
13451 and no overflow/underflow occurred. INEXACT is true if M was not
fa7637bd 13452 exactly calculated. TYPE is the tree type for the result. This
f0c477f2 13453 function assumes that you cleared the MPFR flags and then
13454 calculated M to see if anything subsequently set a flag prior to
13455 entering this function. Return NULL_TREE if any checks fail. */
13456
13457static tree
d4473c84 13458do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
f0c477f2 13459{
13460 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
13461 overflow/underflow occurred. If -frounding-math, proceed iff the
13462 result of calling FUNC was exact. */
d4473c84 13463 if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
f0c477f2 13464 && (!flag_rounding_math || !inexact))
13465 {
13466 REAL_VALUE_TYPE rr;
13467
66fa16e6 13468 real_from_mpfr (&rr, m, type, GMP_RNDN);
f0c477f2 13469 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
13470 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
13471 but the mpft_t is not, then we underflowed in the
13472 conversion. */
776a7bab 13473 if (real_isfinite (&rr)
f0c477f2 13474 && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
13475 {
13476 REAL_VALUE_TYPE rmode;
13477
13478 real_convert (&rmode, TYPE_MODE (type), &rr);
13479 /* Proceed iff the specified mode can hold the value. */
13480 if (real_identical (&rmode, &rr))
13481 return build_real (type, rmode);
13482 }
13483 }
13484 return NULL_TREE;
13485}
13486
239d491a 13487/* Helper function for do_mpc_arg*(). Ensure M is a normal complex
13488 number and no overflow/underflow occurred. INEXACT is true if M
13489 was not exactly calculated. TYPE is the tree type for the result.
13490 This function assumes that you cleared the MPFR flags and then
13491 calculated M to see if anything subsequently set a flag prior to
652d9409 13492 entering this function. Return NULL_TREE if any checks fail, if
13493 FORCE_CONVERT is true, then bypass the checks. */
239d491a 13494
13495static tree
652d9409 13496do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert)
239d491a 13497{
13498 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
13499 overflow/underflow occurred. If -frounding-math, proceed iff the
13500 result of calling FUNC was exact. */
652d9409 13501 if (force_convert
13502 || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m))
13503 && !mpfr_overflow_p () && !mpfr_underflow_p ()
13504 && (!flag_rounding_math || !inexact)))
239d491a 13505 {
13506 REAL_VALUE_TYPE re, im;
13507
b0e7c4d4 13508 real_from_mpfr (&re, mpc_realref (m), TREE_TYPE (type), GMP_RNDN);
13509 real_from_mpfr (&im, mpc_imagref (m), TREE_TYPE (type), GMP_RNDN);
239d491a 13510 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
13511 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
13512 but the mpft_t is not, then we underflowed in the
13513 conversion. */
652d9409 13514 if (force_convert
13515 || (real_isfinite (&re) && real_isfinite (&im)
13516 && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0)
13517 && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0)))
239d491a 13518 {
13519 REAL_VALUE_TYPE re_mode, im_mode;
13520
13521 real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re);
13522 real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im);
13523 /* Proceed iff the specified mode can hold the value. */
652d9409 13524 if (force_convert
13525 || (real_identical (&re_mode, &re)
13526 && real_identical (&im_mode, &im)))
239d491a 13527 return build_complex (type, build_real (TREE_TYPE (type), re_mode),
13528 build_real (TREE_TYPE (type), im_mode));
13529 }
13530 }
13531 return NULL_TREE;
13532}
239d491a 13533
bffb7645 13534/* If argument ARG is a REAL_CST, call the one-argument mpfr function
13535 FUNC on it and return the resulting value as a tree with type TYPE.
728bac60 13536 If MIN and/or MAX are not NULL, then the supplied ARG must be
13537 within those bounds. If INCLUSIVE is true, then MIN/MAX are
13538 acceptable values, otherwise they are not. The mpfr precision is
13539 set to the precision of TYPE. We assume that function FUNC returns
13540 zero if the result could be calculated exactly within the requested
13541 precision. */
bffb7645 13542
13543static tree
728bac60 13544do_mpfr_arg1 (tree arg, tree type, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
13545 const REAL_VALUE_TYPE *min, const REAL_VALUE_TYPE *max,
13546 bool inclusive)
bffb7645 13547{
13548 tree result = NULL_TREE;
48e1416a 13549
bffb7645 13550 STRIP_NOPS (arg);
13551
bd7d6fa4 13552 /* To proceed, MPFR must exactly represent the target floating point
13553 format, which only happens when the target base equals two. */
13554 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13555 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
bffb7645 13556 {
f0c477f2 13557 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
bffb7645 13558
776a7bab 13559 if (real_isfinite (ra)
f0c477f2 13560 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min))
13561 && (!max || real_compare (inclusive ? LE_EXPR: LT_EXPR , ra, max)))
bffb7645 13562 {
e2eb2b7f 13563 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13564 const int prec = fmt->p;
13565 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
debf9994 13566 int inexact;
bffb7645 13567 mpfr_t m;
13568
13569 mpfr_init2 (m, prec);
66fa16e6 13570 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 13571 mpfr_clear_flags ();
e2eb2b7f 13572 inexact = func (m, m, rnd);
f0c477f2 13573 result = do_mpfr_ckconv (m, type, inexact);
bffb7645 13574 mpfr_clear (m);
13575 }
13576 }
48e1416a 13577
bffb7645 13578 return result;
13579}
f0c477f2 13580
13581/* If argument ARG is a REAL_CST, call the two-argument mpfr function
13582 FUNC on it and return the resulting value as a tree with type TYPE.
13583 The mpfr precision is set to the precision of TYPE. We assume that
13584 function FUNC returns zero if the result could be calculated
13585 exactly within the requested precision. */
13586
13587static tree
13588do_mpfr_arg2 (tree arg1, tree arg2, tree type,
13589 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
13590{
13591 tree result = NULL_TREE;
48e1416a 13592
f0c477f2 13593 STRIP_NOPS (arg1);
13594 STRIP_NOPS (arg2);
13595
bd7d6fa4 13596 /* To proceed, MPFR must exactly represent the target floating point
13597 format, which only happens when the target base equals two. */
13598 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13599 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
13600 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
f0c477f2 13601 {
13602 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
13603 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
13604
776a7bab 13605 if (real_isfinite (ra1) && real_isfinite (ra2))
f0c477f2 13606 {
e2eb2b7f 13607 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13608 const int prec = fmt->p;
13609 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
f0c477f2 13610 int inexact;
13611 mpfr_t m1, m2;
13612
13613 mpfr_inits2 (prec, m1, m2, NULL);
66fa16e6 13614 mpfr_from_real (m1, ra1, GMP_RNDN);
13615 mpfr_from_real (m2, ra2, GMP_RNDN);
d4473c84 13616 mpfr_clear_flags ();
e2eb2b7f 13617 inexact = func (m1, m1, m2, rnd);
f0c477f2 13618 result = do_mpfr_ckconv (m1, type, inexact);
13619 mpfr_clears (m1, m2, NULL);
13620 }
13621 }
48e1416a 13622
f0c477f2 13623 return result;
13624}
d92f994c 13625
9917422b 13626/* If argument ARG is a REAL_CST, call the three-argument mpfr function
13627 FUNC on it and return the resulting value as a tree with type TYPE.
13628 The mpfr precision is set to the precision of TYPE. We assume that
13629 function FUNC returns zero if the result could be calculated
13630 exactly within the requested precision. */
13631
13632static tree
13633do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type,
13634 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
13635{
13636 tree result = NULL_TREE;
48e1416a 13637
9917422b 13638 STRIP_NOPS (arg1);
13639 STRIP_NOPS (arg2);
13640 STRIP_NOPS (arg3);
13641
bd7d6fa4 13642 /* To proceed, MPFR must exactly represent the target floating point
13643 format, which only happens when the target base equals two. */
13644 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13645 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
13646 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2)
13647 && TREE_CODE (arg3) == REAL_CST && !TREE_OVERFLOW (arg3))
9917422b 13648 {
13649 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
13650 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
13651 const REAL_VALUE_TYPE *const ra3 = &TREE_REAL_CST (arg3);
13652
776a7bab 13653 if (real_isfinite (ra1) && real_isfinite (ra2) && real_isfinite (ra3))
9917422b 13654 {
e2eb2b7f 13655 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13656 const int prec = fmt->p;
13657 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
9917422b 13658 int inexact;
13659 mpfr_t m1, m2, m3;
13660
13661 mpfr_inits2 (prec, m1, m2, m3, NULL);
66fa16e6 13662 mpfr_from_real (m1, ra1, GMP_RNDN);
13663 mpfr_from_real (m2, ra2, GMP_RNDN);
13664 mpfr_from_real (m3, ra3, GMP_RNDN);
d4473c84 13665 mpfr_clear_flags ();
e2eb2b7f 13666 inexact = func (m1, m1, m2, m3, rnd);
9917422b 13667 result = do_mpfr_ckconv (m1, type, inexact);
13668 mpfr_clears (m1, m2, m3, NULL);
13669 }
13670 }
48e1416a 13671
9917422b 13672 return result;
13673}
13674
d92f994c 13675/* If argument ARG is a REAL_CST, call mpfr_sin_cos() on it and set
13676 the pointers *(ARG_SINP) and *(ARG_COSP) to the resulting values.
d735c391 13677 If ARG_SINP and ARG_COSP are NULL then the result is returned
13678 as a complex value.
d92f994c 13679 The type is taken from the type of ARG and is used for setting the
13680 precision of the calculation and results. */
13681
13682static tree
13683do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp)
13684{
bd7d6fa4 13685 tree const type = TREE_TYPE (arg);
d92f994c 13686 tree result = NULL_TREE;
48e1416a 13687
d92f994c 13688 STRIP_NOPS (arg);
48e1416a 13689
bd7d6fa4 13690 /* To proceed, MPFR must exactly represent the target floating point
13691 format, which only happens when the target base equals two. */
13692 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13693 && TREE_CODE (arg) == REAL_CST
13694 && !TREE_OVERFLOW (arg))
d92f994c 13695 {
13696 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
13697
776a7bab 13698 if (real_isfinite (ra))
d92f994c 13699 {
e2eb2b7f 13700 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13701 const int prec = fmt->p;
13702 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
d92f994c 13703 tree result_s, result_c;
13704 int inexact;
13705 mpfr_t m, ms, mc;
13706
13707 mpfr_inits2 (prec, m, ms, mc, NULL);
66fa16e6 13708 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 13709 mpfr_clear_flags ();
e2eb2b7f 13710 inexact = mpfr_sin_cos (ms, mc, m, rnd);
d92f994c 13711 result_s = do_mpfr_ckconv (ms, type, inexact);
13712 result_c = do_mpfr_ckconv (mc, type, inexact);
13713 mpfr_clears (m, ms, mc, NULL);
13714 if (result_s && result_c)
13715 {
d735c391 13716 /* If we are to return in a complex value do so. */
13717 if (!arg_sinp && !arg_cosp)
13718 return build_complex (build_complex_type (type),
13719 result_c, result_s);
13720
d92f994c 13721 /* Dereference the sin/cos pointer arguments. */
13722 arg_sinp = build_fold_indirect_ref (arg_sinp);
13723 arg_cosp = build_fold_indirect_ref (arg_cosp);
13724 /* Proceed if valid pointer type were passed in. */
13725 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_sinp)) == TYPE_MAIN_VARIANT (type)
13726 && TYPE_MAIN_VARIANT (TREE_TYPE (arg_cosp)) == TYPE_MAIN_VARIANT (type))
13727 {
13728 /* Set the values. */
41076ef6 13729 result_s = fold_build2 (MODIFY_EXPR, type, arg_sinp,
35cc02b5 13730 result_s);
d92f994c 13731 TREE_SIDE_EFFECTS (result_s) = 1;
41076ef6 13732 result_c = fold_build2 (MODIFY_EXPR, type, arg_cosp,
35cc02b5 13733 result_c);
d92f994c 13734 TREE_SIDE_EFFECTS (result_c) = 1;
13735 /* Combine the assignments into a compound expr. */
13736 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13737 result_s, result_c));
13738 }
13739 }
13740 }
13741 }
13742 return result;
13743}
65dd1378 13744
65dd1378 13745/* If argument ARG1 is an INTEGER_CST and ARG2 is a REAL_CST, call the
13746 two-argument mpfr order N Bessel function FUNC on them and return
13747 the resulting value as a tree with type TYPE. The mpfr precision
13748 is set to the precision of TYPE. We assume that function FUNC
13749 returns zero if the result could be calculated exactly within the
13750 requested precision. */
13751static tree
13752do_mpfr_bessel_n (tree arg1, tree arg2, tree type,
13753 int (*func)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
13754 const REAL_VALUE_TYPE *min, bool inclusive)
13755{
13756 tree result = NULL_TREE;
13757
13758 STRIP_NOPS (arg1);
13759 STRIP_NOPS (arg2);
13760
13761 /* To proceed, MPFR must exactly represent the target floating point
13762 format, which only happens when the target base equals two. */
13763 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
e913b5cd 13764 && tree_fits_shwi_p (arg1)
65dd1378 13765 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
13766 {
e913b5cd 13767 const HOST_WIDE_INT n = tree_to_shwi (arg1);
65dd1378 13768 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg2);
13769
13770 if (n == (long)n
776a7bab 13771 && real_isfinite (ra)
65dd1378 13772 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min)))
13773 {
e2eb2b7f 13774 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13775 const int prec = fmt->p;
13776 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
65dd1378 13777 int inexact;
13778 mpfr_t m;
13779
13780 mpfr_init2 (m, prec);
13781 mpfr_from_real (m, ra, GMP_RNDN);
13782 mpfr_clear_flags ();
e2eb2b7f 13783 inexact = func (m, n, m, rnd);
65dd1378 13784 result = do_mpfr_ckconv (m, type, inexact);
13785 mpfr_clear (m);
13786 }
13787 }
48e1416a 13788
65dd1378 13789 return result;
13790}
e5407ca6 13791
13792/* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
13793 the pointer *(ARG_QUO) and return the result. The type is taken
13794 from the type of ARG0 and is used for setting the precision of the
13795 calculation and results. */
13796
13797static tree
13798do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
13799{
13800 tree const type = TREE_TYPE (arg0);
13801 tree result = NULL_TREE;
48e1416a 13802
e5407ca6 13803 STRIP_NOPS (arg0);
13804 STRIP_NOPS (arg1);
48e1416a 13805
e5407ca6 13806 /* To proceed, MPFR must exactly represent the target floating point
13807 format, which only happens when the target base equals two. */
13808 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13809 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
13810 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
13811 {
13812 const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
13813 const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
13814
776a7bab 13815 if (real_isfinite (ra0) && real_isfinite (ra1))
e5407ca6 13816 {
e2eb2b7f 13817 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13818 const int prec = fmt->p;
13819 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
e5407ca6 13820 tree result_rem;
13821 long integer_quo;
13822 mpfr_t m0, m1;
13823
13824 mpfr_inits2 (prec, m0, m1, NULL);
13825 mpfr_from_real (m0, ra0, GMP_RNDN);
13826 mpfr_from_real (m1, ra1, GMP_RNDN);
13827 mpfr_clear_flags ();
e2eb2b7f 13828 mpfr_remquo (m0, &integer_quo, m0, m1, rnd);
e5407ca6 13829 /* Remquo is independent of the rounding mode, so pass
13830 inexact=0 to do_mpfr_ckconv(). */
13831 result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
13832 mpfr_clears (m0, m1, NULL);
13833 if (result_rem)
13834 {
13835 /* MPFR calculates quo in the host's long so it may
13836 return more bits in quo than the target int can hold
13837 if sizeof(host long) > sizeof(target int). This can
13838 happen even for native compilers in LP64 mode. In
13839 these cases, modulo the quo value with the largest
13840 number that the target int can hold while leaving one
13841 bit for the sign. */
13842 if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
13843 integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
13844
13845 /* Dereference the quo pointer argument. */
13846 arg_quo = build_fold_indirect_ref (arg_quo);
13847 /* Proceed iff a valid pointer type was passed in. */
13848 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
13849 {
13850 /* Set the value. */
7002a1c8 13851 tree result_quo
13852 = fold_build2 (MODIFY_EXPR, TREE_TYPE (arg_quo), arg_quo,
13853 build_int_cst (TREE_TYPE (arg_quo),
13854 integer_quo));
e5407ca6 13855 TREE_SIDE_EFFECTS (result_quo) = 1;
13856 /* Combine the quo assignment with the rem. */
13857 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13858 result_quo, result_rem));
13859 }
13860 }
13861 }
13862 }
13863 return result;
13864}
e84da7c1 13865
13866/* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
13867 resulting value as a tree with type TYPE. The mpfr precision is
13868 set to the precision of TYPE. We assume that this mpfr function
13869 returns zero if the result could be calculated exactly within the
13870 requested precision. In addition, the integer pointer represented
13871 by ARG_SG will be dereferenced and set to the appropriate signgam
13872 (-1,1) value. */
13873
13874static tree
13875do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
13876{
13877 tree result = NULL_TREE;
13878
13879 STRIP_NOPS (arg);
48e1416a 13880
e84da7c1 13881 /* To proceed, MPFR must exactly represent the target floating point
13882 format, which only happens when the target base equals two. Also
13883 verify ARG is a constant and that ARG_SG is an int pointer. */
13884 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13885 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
13886 && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
13887 && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
13888 {
13889 const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
13890
13891 /* In addition to NaN and Inf, the argument cannot be zero or a
13892 negative integer. */
776a7bab 13893 if (real_isfinite (ra)
e84da7c1 13894 && ra->cl != rvc_zero
9af5ce0c 13895 && !(real_isneg (ra) && real_isinteger (ra, TYPE_MODE (type))))
e84da7c1 13896 {
e2eb2b7f 13897 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13898 const int prec = fmt->p;
13899 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
e84da7c1 13900 int inexact, sg;
13901 mpfr_t m;
13902 tree result_lg;
13903
13904 mpfr_init2 (m, prec);
13905 mpfr_from_real (m, ra, GMP_RNDN);
13906 mpfr_clear_flags ();
e2eb2b7f 13907 inexact = mpfr_lgamma (m, &sg, m, rnd);
e84da7c1 13908 result_lg = do_mpfr_ckconv (m, type, inexact);
13909 mpfr_clear (m);
13910 if (result_lg)
13911 {
13912 tree result_sg;
13913
13914 /* Dereference the arg_sg pointer argument. */
13915 arg_sg = build_fold_indirect_ref (arg_sg);
13916 /* Assign the signgam value into *arg_sg. */
13917 result_sg = fold_build2 (MODIFY_EXPR,
13918 TREE_TYPE (arg_sg), arg_sg,
7002a1c8 13919 build_int_cst (TREE_TYPE (arg_sg), sg));
e84da7c1 13920 TREE_SIDE_EFFECTS (result_sg) = 1;
13921 /* Combine the signgam assignment with the lgamma result. */
13922 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13923 result_sg, result_lg));
13924 }
13925 }
13926 }
13927
13928 return result;
13929}
75a70cf9 13930
239d491a 13931/* If argument ARG is a COMPLEX_CST, call the one-argument mpc
13932 function FUNC on it and return the resulting value as a tree with
13933 type TYPE. The mpfr precision is set to the precision of TYPE. We
13934 assume that function FUNC returns zero if the result could be
13935 calculated exactly within the requested precision. */
13936
13937static tree
13938do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t))
13939{
13940 tree result = NULL_TREE;
48e1416a 13941
239d491a 13942 STRIP_NOPS (arg);
13943
13944 /* To proceed, MPFR must exactly represent the target floating point
13945 format, which only happens when the target base equals two. */
13946 if (TREE_CODE (arg) == COMPLEX_CST && !TREE_OVERFLOW (arg)
13947 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE
13948 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))))->b == 2)
13949 {
13950 const REAL_VALUE_TYPE *const re = TREE_REAL_CST_PTR (TREE_REALPART (arg));
13951 const REAL_VALUE_TYPE *const im = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
13952
13953 if (real_isfinite (re) && real_isfinite (im))
13954 {
13955 const struct real_format *const fmt =
13956 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
13957 const int prec = fmt->p;
13958 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
44d89feb 13959 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
239d491a 13960 int inexact;
13961 mpc_t m;
48e1416a 13962
239d491a 13963 mpc_init2 (m, prec);
9af5ce0c 13964 mpfr_from_real (mpc_realref (m), re, rnd);
13965 mpfr_from_real (mpc_imagref (m), im, rnd);
239d491a 13966 mpfr_clear_flags ();
44d89feb 13967 inexact = func (m, m, crnd);
652d9409 13968 result = do_mpc_ckconv (m, type, inexact, /*force_convert=*/ 0);
239d491a 13969 mpc_clear (m);
13970 }
13971 }
13972
13973 return result;
13974}
c699fab8 13975
13976/* If arguments ARG0 and ARG1 are a COMPLEX_CST, call the two-argument
13977 mpc function FUNC on it and return the resulting value as a tree
13978 with type TYPE. The mpfr precision is set to the precision of
13979 TYPE. We assume that function FUNC returns zero if the result
652d9409 13980 could be calculated exactly within the requested precision. If
13981 DO_NONFINITE is true, then fold expressions containing Inf or NaN
13982 in the arguments and/or results. */
c699fab8 13983
63e89698 13984tree
652d9409 13985do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
c699fab8 13986 int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
13987{
13988 tree result = NULL_TREE;
48e1416a 13989
c699fab8 13990 STRIP_NOPS (arg0);
13991 STRIP_NOPS (arg1);
13992
13993 /* To proceed, MPFR must exactly represent the target floating point
13994 format, which only happens when the target base equals two. */
13995 if (TREE_CODE (arg0) == COMPLEX_CST && !TREE_OVERFLOW (arg0)
13996 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
13997 && TREE_CODE (arg1) == COMPLEX_CST && !TREE_OVERFLOW (arg1)
13998 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE
13999 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))))->b == 2)
14000 {
14001 const REAL_VALUE_TYPE *const re0 = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
14002 const REAL_VALUE_TYPE *const im0 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
14003 const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1));
14004 const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1));
14005
652d9409 14006 if (do_nonfinite
14007 || (real_isfinite (re0) && real_isfinite (im0)
14008 && real_isfinite (re1) && real_isfinite (im1)))
c699fab8 14009 {
14010 const struct real_format *const fmt =
14011 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
14012 const int prec = fmt->p;
14013 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
14014 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
14015 int inexact;
14016 mpc_t m0, m1;
48e1416a 14017
c699fab8 14018 mpc_init2 (m0, prec);
14019 mpc_init2 (m1, prec);
9af5ce0c 14020 mpfr_from_real (mpc_realref (m0), re0, rnd);
14021 mpfr_from_real (mpc_imagref (m0), im0, rnd);
14022 mpfr_from_real (mpc_realref (m1), re1, rnd);
14023 mpfr_from_real (mpc_imagref (m1), im1, rnd);
c699fab8 14024 mpfr_clear_flags ();
14025 inexact = func (m0, m0, m1, crnd);
652d9409 14026 result = do_mpc_ckconv (m0, type, inexact, do_nonfinite);
c699fab8 14027 mpc_clear (m0);
14028 mpc_clear (m1);
14029 }
14030 }
14031
14032 return result;
14033}
239d491a 14034
75a70cf9 14035/* Fold a call STMT to __{,v}sprintf_chk. Return NULL_TREE if
14036 a normal call should be emitted rather than expanding the function
14037 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
14038
14039static tree
14040gimple_fold_builtin_sprintf_chk (gimple stmt, enum built_in_function fcode)
14041{
75a70cf9 14042 int nargs = gimple_call_num_args (stmt);
14043
af1409ad 14044 return fold_builtin_sprintf_chk_1 (gimple_location (stmt), nargs,
14045 (nargs > 0
14046 ? gimple_call_arg_ptr (stmt, 0)
14047 : &error_mark_node), fcode);
75a70cf9 14048}
14049
14050/* Fold a call STMT to {,v}snprintf. Return NULL_TREE if
14051 a normal call should be emitted rather than expanding the function
14052 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
14053 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
14054 passed as second argument. */
14055
14056tree
14057gimple_fold_builtin_snprintf_chk (gimple stmt, tree maxlen,
14058 enum built_in_function fcode)
14059{
af1409ad 14060 int nargs = gimple_call_num_args (stmt);
75a70cf9 14061
af1409ad 14062 return fold_builtin_snprintf_chk_1 (gimple_location (stmt), nargs,
14063 (nargs > 0
14064 ? gimple_call_arg_ptr (stmt, 0)
14065 : &error_mark_node), maxlen, fcode);
75a70cf9 14066}
14067
14068/* Builtins with folding operations that operate on "..." arguments
14069 need special handling; we need to store the arguments in a convenient
14070 data structure before attempting any folding. Fortunately there are
14071 only a few builtins that fall into this category. FNDECL is the
14072 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
14073 result of the function call is ignored. */
14074
14075static tree
389dd41b 14076gimple_fold_builtin_varargs (tree fndecl, gimple stmt,
14077 bool ignore ATTRIBUTE_UNUSED)
75a70cf9 14078{
14079 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
14080 tree ret = NULL_TREE;
14081
14082 switch (fcode)
14083 {
14084 case BUILT_IN_SPRINTF_CHK:
14085 case BUILT_IN_VSPRINTF_CHK:
14086 ret = gimple_fold_builtin_sprintf_chk (stmt, fcode);
14087 break;
14088
14089 case BUILT_IN_SNPRINTF_CHK:
14090 case BUILT_IN_VSNPRINTF_CHK:
14091 ret = gimple_fold_builtin_snprintf_chk (stmt, NULL_TREE, fcode);
14092
14093 default:
14094 break;
14095 }
14096 if (ret)
14097 {
14098 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
14099 TREE_NO_WARNING (ret) = 1;
14100 return ret;
14101 }
14102 return NULL_TREE;
14103}
14104
14105/* A wrapper function for builtin folding that prevents warnings for
14106 "statement without effect" and the like, caused by removing the
14107 call node earlier than the warning is generated. */
14108
14109tree
14110fold_call_stmt (gimple stmt, bool ignore)
14111{
14112 tree ret = NULL_TREE;
14113 tree fndecl = gimple_call_fndecl (stmt);
389dd41b 14114 location_t loc = gimple_location (stmt);
75a70cf9 14115 if (fndecl
14116 && TREE_CODE (fndecl) == FUNCTION_DECL
14117 && DECL_BUILT_IN (fndecl)
14118 && !gimple_call_va_arg_pack_p (stmt))
14119 {
14120 int nargs = gimple_call_num_args (stmt);
9845fb99 14121 tree *args = (nargs > 0
14122 ? gimple_call_arg_ptr (stmt, 0)
14123 : &error_mark_node);
75a70cf9 14124
198622c0 14125 if (avoid_folding_inline_builtin (fndecl))
14126 return NULL_TREE;
75a70cf9 14127 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
14128 {
9845fb99 14129 return targetm.fold_builtin (fndecl, nargs, args, ignore);
75a70cf9 14130 }
14131 else
14132 {
14133 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
9845fb99 14134 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
75a70cf9 14135 if (!ret)
14136 ret = gimple_fold_builtin_varargs (fndecl, stmt, ignore);
14137 if (ret)
14138 {
14139 /* Propagate location information from original call to
14140 expansion of builtin. Otherwise things like
14141 maybe_emit_chk_warning, that operate on the expansion
14142 of a builtin, will use the wrong location information. */
14143 if (gimple_has_location (stmt))
14144 {
14145 tree realret = ret;
14146 if (TREE_CODE (ret) == NOP_EXPR)
14147 realret = TREE_OPERAND (ret, 0);
14148 if (CAN_HAVE_LOCATION_P (realret)
14149 && !EXPR_HAS_LOCATION (realret))
389dd41b 14150 SET_EXPR_LOCATION (realret, loc);
75a70cf9 14151 return realret;
14152 }
14153 return ret;
14154 }
14155 }
14156 }
14157 return NULL_TREE;
14158}
7bfefa9d 14159
b9a16870 14160/* Look up the function in builtin_decl that corresponds to DECL
7bfefa9d 14161 and set ASMSPEC as its user assembler name. DECL must be a
14162 function decl that declares a builtin. */
14163
14164void
14165set_builtin_user_assembler_name (tree decl, const char *asmspec)
14166{
14167 tree builtin;
14168 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
14169 && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
14170 && asmspec != 0);
14171
b9a16870 14172 builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
4d8e0d6d 14173 set_user_assembler_name (builtin, asmspec);
7bfefa9d 14174 switch (DECL_FUNCTION_CODE (decl))
14175 {
14176 case BUILT_IN_MEMCPY:
14177 init_block_move_fn (asmspec);
14178 memcpy_libfunc = set_user_assembler_libfunc ("memcpy", asmspec);
14179 break;
14180 case BUILT_IN_MEMSET:
14181 init_block_clear_fn (asmspec);
14182 memset_libfunc = set_user_assembler_libfunc ("memset", asmspec);
14183 break;
14184 case BUILT_IN_MEMMOVE:
14185 memmove_libfunc = set_user_assembler_libfunc ("memmove", asmspec);
14186 break;
14187 case BUILT_IN_MEMCMP:
14188 memcmp_libfunc = set_user_assembler_libfunc ("memcmp", asmspec);
14189 break;
14190 case BUILT_IN_ABORT:
14191 abort_libfunc = set_user_assembler_libfunc ("abort", asmspec);
14192 break;
5a80a58b 14193 case BUILT_IN_FFS:
14194 if (INT_TYPE_SIZE < BITS_PER_WORD)
14195 {
14196 set_user_assembler_libfunc ("ffs", asmspec);
14197 set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE,
14198 MODE_INT, 0), "ffs");
14199 }
14200 break;
7bfefa9d 14201 default:
14202 break;
14203 }
14204}
a6b74a67 14205
14206/* Return true if DECL is a builtin that expands to a constant or similarly
14207 simple code. */
14208bool
14209is_simple_builtin (tree decl)
14210{
14211 if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
14212 switch (DECL_FUNCTION_CODE (decl))
14213 {
14214 /* Builtins that expand to constants. */
14215 case BUILT_IN_CONSTANT_P:
14216 case BUILT_IN_EXPECT:
14217 case BUILT_IN_OBJECT_SIZE:
14218 case BUILT_IN_UNREACHABLE:
14219 /* Simple register moves or loads from stack. */
fca0886c 14220 case BUILT_IN_ASSUME_ALIGNED:
a6b74a67 14221 case BUILT_IN_RETURN_ADDRESS:
14222 case BUILT_IN_EXTRACT_RETURN_ADDR:
14223 case BUILT_IN_FROB_RETURN_ADDR:
14224 case BUILT_IN_RETURN:
14225 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
14226 case BUILT_IN_FRAME_ADDRESS:
14227 case BUILT_IN_VA_END:
14228 case BUILT_IN_STACK_SAVE:
14229 case BUILT_IN_STACK_RESTORE:
14230 /* Exception state returns or moves registers around. */
14231 case BUILT_IN_EH_FILTER:
14232 case BUILT_IN_EH_POINTER:
14233 case BUILT_IN_EH_COPY_VALUES:
14234 return true;
14235
14236 default:
14237 return false;
14238 }
14239
14240 return false;
14241}
14242
14243/* Return true if DECL is a builtin that is not expensive, i.e., they are
14244 most probably expanded inline into reasonably simple code. This is a
14245 superset of is_simple_builtin. */
14246bool
14247is_inexpensive_builtin (tree decl)
14248{
14249 if (!decl)
14250 return false;
14251 else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_MD)
14252 return true;
14253 else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
14254 switch (DECL_FUNCTION_CODE (decl))
14255 {
14256 case BUILT_IN_ABS:
14257 case BUILT_IN_ALLOCA:
581bf1c2 14258 case BUILT_IN_ALLOCA_WITH_ALIGN:
74bdbe96 14259 case BUILT_IN_BSWAP16:
a6b74a67 14260 case BUILT_IN_BSWAP32:
14261 case BUILT_IN_BSWAP64:
14262 case BUILT_IN_CLZ:
14263 case BUILT_IN_CLZIMAX:
14264 case BUILT_IN_CLZL:
14265 case BUILT_IN_CLZLL:
14266 case BUILT_IN_CTZ:
14267 case BUILT_IN_CTZIMAX:
14268 case BUILT_IN_CTZL:
14269 case BUILT_IN_CTZLL:
14270 case BUILT_IN_FFS:
14271 case BUILT_IN_FFSIMAX:
14272 case BUILT_IN_FFSL:
14273 case BUILT_IN_FFSLL:
14274 case BUILT_IN_IMAXABS:
14275 case BUILT_IN_FINITE:
14276 case BUILT_IN_FINITEF:
14277 case BUILT_IN_FINITEL:
14278 case BUILT_IN_FINITED32:
14279 case BUILT_IN_FINITED64:
14280 case BUILT_IN_FINITED128:
14281 case BUILT_IN_FPCLASSIFY:
14282 case BUILT_IN_ISFINITE:
14283 case BUILT_IN_ISINF_SIGN:
14284 case BUILT_IN_ISINF:
14285 case BUILT_IN_ISINFF:
14286 case BUILT_IN_ISINFL:
14287 case BUILT_IN_ISINFD32:
14288 case BUILT_IN_ISINFD64:
14289 case BUILT_IN_ISINFD128:
14290 case BUILT_IN_ISNAN:
14291 case BUILT_IN_ISNANF:
14292 case BUILT_IN_ISNANL:
14293 case BUILT_IN_ISNAND32:
14294 case BUILT_IN_ISNAND64:
14295 case BUILT_IN_ISNAND128:
14296 case BUILT_IN_ISNORMAL:
14297 case BUILT_IN_ISGREATER:
14298 case BUILT_IN_ISGREATEREQUAL:
14299 case BUILT_IN_ISLESS:
14300 case BUILT_IN_ISLESSEQUAL:
14301 case BUILT_IN_ISLESSGREATER:
14302 case BUILT_IN_ISUNORDERED:
14303 case BUILT_IN_VA_ARG_PACK:
14304 case BUILT_IN_VA_ARG_PACK_LEN:
14305 case BUILT_IN_VA_COPY:
14306 case BUILT_IN_TRAP:
14307 case BUILT_IN_SAVEREGS:
14308 case BUILT_IN_POPCOUNTL:
14309 case BUILT_IN_POPCOUNTLL:
14310 case BUILT_IN_POPCOUNTIMAX:
14311 case BUILT_IN_POPCOUNT:
14312 case BUILT_IN_PARITYL:
14313 case BUILT_IN_PARITYLL:
14314 case BUILT_IN_PARITYIMAX:
14315 case BUILT_IN_PARITY:
14316 case BUILT_IN_LABS:
14317 case BUILT_IN_LLABS:
14318 case BUILT_IN_PREFETCH:
14319 return true;
14320
14321 default:
14322 return is_simple_builtin (decl);
14323 }
14324
14325 return false;
14326}