]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/builtins.c
Factor unrelated declarations out of tree.h.
[thirdparty/gcc.git] / gcc / builtins.c
CommitLineData
53800dbe 1/* Expand builtin functions.
711789cc 2 Copyright (C) 1988-2013 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"
75a70cf9 33#include "gimple.h"
53800dbe 34#include "flags.h"
35#include "regs.h"
36#include "hard-reg-set.h"
37#include "except.h"
38#include "function.h"
53800dbe 39#include "insn-config.h"
40#include "expr.h"
d8fc4d0b 41#include "optabs.h"
42#include "libfuncs.h"
53800dbe 43#include "recog.h"
44#include "output.h"
45#include "typeclass.h"
689df48e 46#include "predict.h"
1dd6c958 47#include "tm_p.h"
fc2a2dcb 48#include "target.h"
63c62881 49#include "langhooks.h"
0ec80471 50#include "basic-block.h"
073c1fd5 51#include "tree-ssanames.h"
52#include "tree-dfa.h"
162719b3 53#include "value-prof.h"
852f689e 54#include "diagnostic-core.h"
3b9c3a16 55#include "builtins.h"
9e46467d 56#include "ubsan.h"
d037099f 57#include "cilk.h"
53800dbe 58
5383fb56 59
239d491a 60static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_rnd_t));
726e2588 61
3b9c3a16 62struct target_builtins default_target_builtins;
63#if SWITCHABLE_TARGET
64struct target_builtins *this_target_builtins = &default_target_builtins;
65#endif
66
ab7943b9 67/* Define the names of the builtin function types and codes. */
96423453 68const char *const built_in_class_names[BUILT_IN_LAST]
ab7943b9 69 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
70
9cfddb70 71#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
0dfc45b5 72const char * built_in_names[(int) END_BUILTINS] =
4e9d90c7 73{
74#include "builtins.def"
75};
76#undef DEF_BUILTIN
ab7943b9 77
df94cd3b 78/* Setup an array of _DECL trees, make sure each element is
79 initialized to NULL_TREE. */
b9a16870 80builtin_info_type builtin_info;
df94cd3b 81
0b049e15 82/* Non-zero if __builtin_constant_p should be folded right away. */
83bool force_folding_builtin_constant_p;
84
aecda0d6 85static const char *c_getstr (tree);
86static rtx c_readstr (const char *, enum machine_mode);
87static int target_char_cast (tree, char *);
d8ae1baa 88static rtx get_memory_rtx (tree, tree);
aecda0d6 89static int apply_args_size (void);
90static int apply_result_size (void);
d8c9779c 91#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
aecda0d6 92static rtx result_vector (int, rtx);
d8c9779c 93#endif
843d08a9 94static void expand_builtin_update_setjmp_buf (rtx);
aecda0d6 95static void expand_builtin_prefetch (tree);
96static rtx expand_builtin_apply_args (void);
97static rtx expand_builtin_apply_args_1 (void);
98static rtx expand_builtin_apply (rtx, rtx, rtx);
99static void expand_builtin_return (rtx);
100static enum type_class type_to_class (tree);
101static rtx expand_builtin_classify_type (tree);
102static void expand_errno_check (tree, rtx);
103static rtx expand_builtin_mathfn (tree, rtx, rtx);
104static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
6b43bae4 105static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
7e0713b1 106static rtx expand_builtin_mathfn_ternary (tree, rtx, rtx);
f97eea22 107static rtx expand_builtin_interclass_mathfn (tree, rtx);
c3147c1a 108static rtx expand_builtin_sincos (tree);
f97eea22 109static rtx expand_builtin_cexpi (tree, rtx);
ff1b14e4 110static rtx expand_builtin_int_roundingfn (tree, rtx);
111static rtx expand_builtin_int_roundingfn_2 (tree, rtx);
79012a9d 112static rtx expand_builtin_next_arg (void);
aecda0d6 113static rtx expand_builtin_va_start (tree);
114static rtx expand_builtin_va_end (tree);
115static rtx expand_builtin_va_copy (tree);
c2f47e15 116static rtx expand_builtin_memcmp (tree, rtx, enum machine_mode);
a65c4d64 117static rtx expand_builtin_strcmp (tree, rtx);
aecda0d6 118static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
119static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
a65c4d64 120static rtx expand_builtin_memcpy (tree, rtx);
c2f47e15 121static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode);
48e1416a 122static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx,
c2f47e15 123 enum machine_mode, int);
a65c4d64 124static rtx expand_builtin_strcpy (tree, rtx);
125static rtx expand_builtin_strcpy_args (tree, tree, rtx);
aecda0d6 126static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
a65c4d64 127static rtx expand_builtin_strncpy (tree, rtx);
aecda0d6 128static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
c2f47e15 129static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
130static rtx expand_builtin_memset_args (tree, tree, tree, rtx, enum machine_mode, tree);
aecda0d6 131static rtx expand_builtin_bzero (tree);
132static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
5be42b39 133static rtx expand_builtin_alloca (tree, bool);
aecda0d6 134static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
135static rtx expand_builtin_frame_address (tree, tree);
389dd41b 136static tree stabilize_va_list_loc (location_t, tree, int);
aecda0d6 137static rtx expand_builtin_expect (tree, rtx);
138static tree fold_builtin_constant_p (tree);
389dd41b 139static tree fold_builtin_expect (location_t, tree, tree);
aecda0d6 140static tree fold_builtin_classify_type (tree);
c7cbde74 141static tree fold_builtin_strlen (location_t, tree, tree);
389dd41b 142static tree fold_builtin_inf (location_t, tree, int);
aecda0d6 143static tree fold_builtin_nan (tree, tree, int);
389dd41b 144static tree rewrite_call_expr (location_t, tree, int, tree, int, ...);
b7bf20db 145static bool validate_arg (const_tree, enum tree_code code);
277f8dd2 146static bool integer_valued_real_p (tree);
389dd41b 147static tree fold_trunc_transparent_mathfn (location_t, tree, tree);
aecda0d6 148static bool readonly_data_expr (tree);
149static rtx expand_builtin_fabs (tree, rtx, rtx);
27f261ef 150static rtx expand_builtin_signbit (tree, rtx);
389dd41b 151static tree fold_builtin_sqrt (location_t, tree, tree);
152static tree fold_builtin_cbrt (location_t, tree, tree);
153static tree fold_builtin_pow (location_t, tree, tree, tree, tree);
154static tree fold_builtin_powi (location_t, tree, tree, tree, tree);
155static tree fold_builtin_cos (location_t, tree, tree, tree);
156static tree fold_builtin_cosh (location_t, tree, tree, tree);
bffb7645 157static tree fold_builtin_tan (tree, tree);
389dd41b 158static tree fold_builtin_trunc (location_t, tree, tree);
159static tree fold_builtin_floor (location_t, tree, tree);
160static tree fold_builtin_ceil (location_t, tree, tree);
161static tree fold_builtin_round (location_t, tree, tree);
162static tree fold_builtin_int_roundingfn (location_t, tree, tree);
10b9666f 163static tree fold_builtin_bitop (tree, tree);
389dd41b 164static tree fold_builtin_memory_op (location_t, tree, tree, tree, tree, bool, int);
165static tree fold_builtin_strchr (location_t, tree, tree, tree);
166static tree fold_builtin_memchr (location_t, tree, tree, tree, tree);
167static tree fold_builtin_memcmp (location_t, tree, tree, tree);
168static tree fold_builtin_strcmp (location_t, tree, tree);
169static tree fold_builtin_strncmp (location_t, tree, tree, tree);
170static tree fold_builtin_signbit (location_t, tree, tree);
171static tree fold_builtin_copysign (location_t, tree, tree, tree, tree);
172static tree fold_builtin_isascii (location_t, tree);
173static tree fold_builtin_toascii (location_t, tree);
174static tree fold_builtin_isdigit (location_t, tree);
175static tree fold_builtin_fabs (location_t, tree, tree);
176static tree fold_builtin_abs (location_t, tree, tree);
177static tree fold_builtin_unordered_cmp (location_t, tree, tree, tree, enum tree_code,
d5019fe8 178 enum tree_code);
389dd41b 179static tree fold_builtin_n (location_t, tree, tree *, int, bool);
180static tree fold_builtin_0 (location_t, tree, bool);
181static tree fold_builtin_1 (location_t, tree, tree, bool);
182static tree fold_builtin_2 (location_t, tree, tree, tree, bool);
183static tree fold_builtin_3 (location_t, tree, tree, tree, tree, bool);
184static tree fold_builtin_4 (location_t, tree, tree, tree, tree, tree, bool);
185static tree fold_builtin_varargs (location_t, tree, tree, bool);
186
187static tree fold_builtin_strpbrk (location_t, tree, tree, tree);
188static tree fold_builtin_strstr (location_t, tree, tree, tree);
189static tree fold_builtin_strrchr (location_t, tree, tree, tree);
190static tree fold_builtin_strcat (location_t, tree, tree);
191static tree fold_builtin_strncat (location_t, tree, tree, tree);
192static tree fold_builtin_strspn (location_t, tree, tree);
193static tree fold_builtin_strcspn (location_t, tree, tree);
194static tree fold_builtin_sprintf (location_t, tree, tree, tree, int);
750d7b16 195static tree fold_builtin_snprintf (location_t, tree, tree, tree, tree, int);
4ee9c684 196
0a39fd54 197static rtx expand_builtin_object_size (tree);
198static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
199 enum built_in_function);
200static void maybe_emit_chk_warning (tree, enum built_in_function);
201static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
2c281b15 202static void maybe_emit_free_warning (tree);
c2f47e15 203static tree fold_builtin_object_size (tree, tree);
389dd41b 204static tree fold_builtin_strcat_chk (location_t, tree, tree, tree, tree);
205static tree fold_builtin_strncat_chk (location_t, tree, tree, tree, tree, tree);
206static tree fold_builtin_sprintf_chk (location_t, tree, enum built_in_function);
207static tree fold_builtin_printf (location_t, tree, tree, tree, bool, enum built_in_function);
208static tree fold_builtin_fprintf (location_t, tree, tree, tree, tree, bool,
c2f47e15 209 enum built_in_function);
99eabcc1 210static bool init_target_chars (void);
211
212static unsigned HOST_WIDE_INT target_newline;
213static unsigned HOST_WIDE_INT target_percent;
214static unsigned HOST_WIDE_INT target_c;
215static unsigned HOST_WIDE_INT target_s;
216static char target_percent_c[3];
217static char target_percent_s[3];
218static char target_percent_s_newline[4];
728bac60 219static tree do_mpfr_arg1 (tree, tree, int (*)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
220 const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, bool);
f0c477f2 221static tree do_mpfr_arg2 (tree, tree, tree,
222 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
9917422b 223static tree do_mpfr_arg3 (tree, tree, tree, tree,
224 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
d92f994c 225static tree do_mpfr_sincos (tree, tree, tree);
65dd1378 226static tree do_mpfr_bessel_n (tree, tree, tree,
227 int (*)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
228 const REAL_VALUE_TYPE *, bool);
e5407ca6 229static tree do_mpfr_remquo (tree, tree, tree);
e84da7c1 230static tree do_mpfr_lgamma_r (tree, tree, tree);
1cd6e20d 231static void expand_builtin_sync_synchronize (void);
0a39fd54 232
7bfefa9d 233/* Return true if NAME starts with __builtin_ or __sync_. */
234
b29139ad 235static bool
1c47b3e8 236is_builtin_name (const char *name)
b6a5fc45 237{
b6a5fc45 238 if (strncmp (name, "__builtin_", 10) == 0)
239 return true;
240 if (strncmp (name, "__sync_", 7) == 0)
241 return true;
1cd6e20d 242 if (strncmp (name, "__atomic_", 9) == 0)
243 return true;
d037099f 244 if (flag_enable_cilkplus
245 && (!strcmp (name, "__cilkrts_detach")
246 || !strcmp (name, "__cilkrts_pop_frame")))
247 return true;
b6a5fc45 248 return false;
249}
4ee9c684 250
7bfefa9d 251
252/* Return true if DECL is a function symbol representing a built-in. */
253
254bool
255is_builtin_fn (tree decl)
256{
257 return TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl);
258}
259
30f690e0 260/* By default we assume that c99 functions are present at the runtime,
261 but sincos is not. */
262bool
263default_libc_has_function (enum function_class fn_class)
264{
265 if (fn_class == function_c94
266 || fn_class == function_c99_misc
267 || fn_class == function_c99_math_complex)
268 return true;
269
270 return false;
271}
272
273bool
274gnu_libc_has_function (enum function_class fn_class ATTRIBUTE_UNUSED)
275{
276 return true;
277}
278
279bool
280no_c99_libc_has_function (enum function_class fn_class ATTRIBUTE_UNUSED)
281{
282 return false;
283}
7bfefa9d 284
1c47b3e8 285/* Return true if NODE should be considered for inline expansion regardless
286 of the optimization level. This means whenever a function is invoked with
287 its "internal" name, which normally contains the prefix "__builtin". */
288
289static bool
290called_as_built_in (tree node)
291{
292 /* Note that we must use DECL_NAME, not DECL_ASSEMBLER_NAME_SET_P since
293 we want the name used to call the function, not the name it
294 will have. */
295 const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
296 return is_builtin_name (name);
297}
298
ceea063b 299/* Compute values M and N such that M divides (address of EXP - N) and such
300 that N < M. If these numbers can be determined, store M in alignp and N in
301 *BITPOSP and return true. Otherwise return false and store BITS_PER_UNIT to
302 *alignp and any bit-offset to *bitposp.
0d8f7716 303
304 Note that the address (and thus the alignment) computed here is based
305 on the address to which a symbol resolves, whereas DECL_ALIGN is based
306 on the address at which an object is actually located. These two
307 addresses are not always the same. For example, on ARM targets,
308 the address &foo of a Thumb function foo() has the lowest bit set,
3482bf13 309 whereas foo() itself starts on an even address.
698537d1 310
3482bf13 311 If ADDR_P is true we are taking the address of the memory reference EXP
312 and thus cannot rely on the access taking place. */
313
314static bool
315get_object_alignment_2 (tree exp, unsigned int *alignp,
316 unsigned HOST_WIDE_INT *bitposp, bool addr_p)
698537d1 317{
98ab9e8f 318 HOST_WIDE_INT bitsize, bitpos;
319 tree offset;
320 enum machine_mode mode;
321 int unsignedp, volatilep;
c8a2b4ff 322 unsigned int align = BITS_PER_UNIT;
ceea063b 323 bool known_alignment = false;
698537d1 324
98ab9e8f 325 /* Get the innermost object and the constant (bitpos) and possibly
326 variable (offset) offset of the access. */
327 exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
328 &mode, &unsignedp, &volatilep, true);
329
330 /* Extract alignment information from the innermost object and
331 possibly adjust bitpos and offset. */
3482bf13 332 if (TREE_CODE (exp) == FUNCTION_DECL)
0d8f7716 333 {
3482bf13 334 /* Function addresses can encode extra information besides their
335 alignment. However, if TARGET_PTRMEMFUNC_VBIT_LOCATION
336 allows the low bit to be used as a virtual bit, we know
337 that the address itself must be at least 2-byte aligned. */
338 if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn)
339 align = 2 * BITS_PER_UNIT;
0d8f7716 340 }
3482bf13 341 else if (TREE_CODE (exp) == LABEL_DECL)
342 ;
343 else if (TREE_CODE (exp) == CONST_DECL)
98ab9e8f 344 {
3482bf13 345 /* The alignment of a CONST_DECL is determined by its initializer. */
346 exp = DECL_INITIAL (exp);
98ab9e8f 347 align = TYPE_ALIGN (TREE_TYPE (exp));
348#ifdef CONSTANT_ALIGNMENT
3482bf13 349 if (CONSTANT_CLASS_P (exp))
350 align = (unsigned) CONSTANT_ALIGNMENT (exp, align);
698537d1 351#endif
3482bf13 352 known_alignment = true;
98ab9e8f 353 }
3482bf13 354 else if (DECL_P (exp))
ceea063b 355 {
3482bf13 356 align = DECL_ALIGN (exp);
ceea063b 357 known_alignment = true;
ceea063b 358 }
3482bf13 359 else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR)
ceea063b 360 {
ceea063b 361 align = TYPE_ALIGN (TREE_TYPE (exp));
362 }
3482bf13 363 else if (TREE_CODE (exp) == INDIRECT_REF
364 || TREE_CODE (exp) == MEM_REF
365 || TREE_CODE (exp) == TARGET_MEM_REF)
98ab9e8f 366 {
367 tree addr = TREE_OPERAND (exp, 0);
ceea063b 368 unsigned ptr_align;
369 unsigned HOST_WIDE_INT ptr_bitpos;
370
98ab9e8f 371 if (TREE_CODE (addr) == BIT_AND_EXPR
372 && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
373 {
374 align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))
375 & -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)));
376 align *= BITS_PER_UNIT;
377 addr = TREE_OPERAND (addr, 0);
378 }
ceea063b 379
3482bf13 380 known_alignment
381 = get_pointer_alignment_1 (addr, &ptr_align, &ptr_bitpos);
3482bf13 382 align = MAX (ptr_align, align);
383
4083990a 384 /* The alignment of the pointer operand in a TARGET_MEM_REF
385 has to take the variable offset parts into account. */
3482bf13 386 if (TREE_CODE (exp) == TARGET_MEM_REF)
153c3b50 387 {
3482bf13 388 if (TMR_INDEX (exp))
389 {
390 unsigned HOST_WIDE_INT step = 1;
391 if (TMR_STEP (exp))
392 step = TREE_INT_CST_LOW (TMR_STEP (exp));
393 align = MIN (align, (step & -step) * BITS_PER_UNIT);
394 }
395 if (TMR_INDEX2 (exp))
396 align = BITS_PER_UNIT;
397 known_alignment = false;
153c3b50 398 }
ceea063b 399
3482bf13 400 /* When EXP is an actual memory reference then we can use
401 TYPE_ALIGN of a pointer indirection to derive alignment.
402 Do so only if get_pointer_alignment_1 did not reveal absolute
4083990a 403 alignment knowledge and if using that alignment would
404 improve the situation. */
405 if (!addr_p && !known_alignment
406 && TYPE_ALIGN (TREE_TYPE (exp)) > align)
407 align = TYPE_ALIGN (TREE_TYPE (exp));
408 else
409 {
410 /* Else adjust bitpos accordingly. */
411 bitpos += ptr_bitpos;
412 if (TREE_CODE (exp) == MEM_REF
413 || TREE_CODE (exp) == TARGET_MEM_REF)
414 bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT;
415 }
98ab9e8f 416 }
3482bf13 417 else if (TREE_CODE (exp) == STRING_CST)
153c3b50 418 {
3482bf13 419 /* STRING_CST are the only constant objects we allow to be not
420 wrapped inside a CONST_DECL. */
421 align = TYPE_ALIGN (TREE_TYPE (exp));
422#ifdef CONSTANT_ALIGNMENT
423 if (CONSTANT_CLASS_P (exp))
424 align = (unsigned) CONSTANT_ALIGNMENT (exp, align);
425#endif
426 known_alignment = true;
98ab9e8f 427 }
98ab9e8f 428
429 /* If there is a non-constant offset part extract the maximum
430 alignment that can prevail. */
c8a2b4ff 431 if (offset)
98ab9e8f 432 {
c8a2b4ff 433 int trailing_zeros = tree_ctz (offset);
434 if (trailing_zeros < HOST_BITS_PER_INT)
98ab9e8f 435 {
c8a2b4ff 436 unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
437 if (inner)
438 align = MIN (align, inner);
98ab9e8f 439 }
98ab9e8f 440 }
441
3482bf13 442 *alignp = align;
443 *bitposp = bitpos & (*alignp - 1);
ceea063b 444 return known_alignment;
0c883ef3 445}
446
3482bf13 447/* For a memory reference expression EXP compute values M and N such that M
448 divides (&EXP - N) and such that N < M. If these numbers can be determined,
449 store M in alignp and N in *BITPOSP and return true. Otherwise return false
450 and store BITS_PER_UNIT to *alignp and any bit-offset to *bitposp. */
451
452bool
453get_object_alignment_1 (tree exp, unsigned int *alignp,
454 unsigned HOST_WIDE_INT *bitposp)
455{
456 return get_object_alignment_2 (exp, alignp, bitposp, false);
457}
458
957d0361 459/* Return the alignment in bits of EXP, an object. */
0c883ef3 460
461unsigned int
957d0361 462get_object_alignment (tree exp)
0c883ef3 463{
464 unsigned HOST_WIDE_INT bitpos = 0;
465 unsigned int align;
466
ceea063b 467 get_object_alignment_1 (exp, &align, &bitpos);
0c883ef3 468
98ab9e8f 469 /* align and bitpos now specify known low bits of the pointer.
470 ptr & (align - 1) == bitpos. */
471
472 if (bitpos != 0)
473 align = (bitpos & -bitpos);
957d0361 474 return align;
698537d1 475}
476
ceea063b 477/* For a pointer valued expression EXP compute values M and N such that M
478 divides (EXP - N) and such that N < M. If these numbers can be determined,
3482bf13 479 store M in alignp and N in *BITPOSP and return true. Return false if
480 the results are just a conservative approximation.
53800dbe 481
ceea063b 482 If EXP is not a pointer, false is returned too. */
53800dbe 483
ceea063b 484bool
485get_pointer_alignment_1 (tree exp, unsigned int *alignp,
486 unsigned HOST_WIDE_INT *bitposp)
53800dbe 487{
153c3b50 488 STRIP_NOPS (exp);
535e2026 489
153c3b50 490 if (TREE_CODE (exp) == ADDR_EXPR)
3482bf13 491 return get_object_alignment_2 (TREE_OPERAND (exp, 0),
492 alignp, bitposp, true);
153c3b50 493 else if (TREE_CODE (exp) == SSA_NAME
494 && POINTER_TYPE_P (TREE_TYPE (exp)))
53800dbe 495 {
ceea063b 496 unsigned int ptr_align, ptr_misalign;
153c3b50 497 struct ptr_info_def *pi = SSA_NAME_PTR_INFO (exp);
ceea063b 498
499 if (pi && get_ptr_info_alignment (pi, &ptr_align, &ptr_misalign))
500 {
501 *bitposp = ptr_misalign * BITS_PER_UNIT;
502 *alignp = ptr_align * BITS_PER_UNIT;
3482bf13 503 /* We cannot really tell whether this result is an approximation. */
ceea063b 504 return true;
505 }
506 else
69fbc3aa 507 {
508 *bitposp = 0;
ceea063b 509 *alignp = BITS_PER_UNIT;
510 return false;
69fbc3aa 511 }
53800dbe 512 }
0bb8b39a 513 else if (TREE_CODE (exp) == INTEGER_CST)
514 {
515 *alignp = BIGGEST_ALIGNMENT;
516 *bitposp = ((TREE_INT_CST_LOW (exp) * BITS_PER_UNIT)
517 & (BIGGEST_ALIGNMENT - 1));
518 return true;
519 }
153c3b50 520
69fbc3aa 521 *bitposp = 0;
ceea063b 522 *alignp = BITS_PER_UNIT;
523 return false;
53800dbe 524}
525
69fbc3aa 526/* Return the alignment in bits of EXP, a pointer valued expression.
527 The alignment returned is, by default, the alignment of the thing that
528 EXP points to. If it is not a POINTER_TYPE, 0 is returned.
529
530 Otherwise, look at the expression to see if we can do better, i.e., if the
531 expression is actually pointing at an object whose alignment is tighter. */
532
533unsigned int
534get_pointer_alignment (tree exp)
535{
536 unsigned HOST_WIDE_INT bitpos = 0;
537 unsigned int align;
ceea063b 538
539 get_pointer_alignment_1 (exp, &align, &bitpos);
69fbc3aa 540
541 /* align and bitpos now specify known low bits of the pointer.
542 ptr & (align - 1) == bitpos. */
543
544 if (bitpos != 0)
545 align = (bitpos & -bitpos);
546
547 return align;
548}
549
53800dbe 550/* Compute the length of a C string. TREE_STRING_LENGTH is not the right
551 way, because it could contain a zero byte in the middle.
552 TREE_STRING_LENGTH is the size of the character array, not the string.
553
4172d65e 554 ONLY_VALUE should be nonzero if the result is not going to be emitted
c09841f6 555 into the instruction stream and zero if it is going to be expanded.
4172d65e 556 E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
681fab1e 557 is returned, otherwise NULL, since
558 len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
559 evaluate the side-effects.
560
902de8ed 561 The value returned is of type `ssizetype'.
562
53800dbe 563 Unfortunately, string_constant can't access the values of const char
564 arrays with initializers, so neither can we do so here. */
565
4ee9c684 566tree
681fab1e 567c_strlen (tree src, int only_value)
53800dbe 568{
569 tree offset_node;
27d0c333 570 HOST_WIDE_INT offset;
571 int max;
44acf429 572 const char *ptr;
da136652 573 location_t loc;
53800dbe 574
681fab1e 575 STRIP_NOPS (src);
576 if (TREE_CODE (src) == COND_EXPR
577 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
578 {
579 tree len1, len2;
580
581 len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
582 len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
0862b7e9 583 if (tree_int_cst_equal (len1, len2))
681fab1e 584 return len1;
585 }
586
587 if (TREE_CODE (src) == COMPOUND_EXPR
588 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
589 return c_strlen (TREE_OPERAND (src, 1), only_value);
590
8637f1db 591 loc = EXPR_LOC_OR_HERE (src);
da136652 592
53800dbe 593 src = string_constant (src, &offset_node);
594 if (src == 0)
c2f47e15 595 return NULL_TREE;
902de8ed 596
83d79705 597 max = TREE_STRING_LENGTH (src) - 1;
53800dbe 598 ptr = TREE_STRING_POINTER (src);
902de8ed 599
53800dbe 600 if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
601 {
602 /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
603 compute the offset to the following null if we don't know where to
604 start searching for it. */
605 int i;
902de8ed 606
53800dbe 607 for (i = 0; i < max; i++)
608 if (ptr[i] == 0)
c2f47e15 609 return NULL_TREE;
902de8ed 610
53800dbe 611 /* We don't know the starting offset, but we do know that the string
612 has no internal zero bytes. We can assume that the offset falls
613 within the bounds of the string; otherwise, the programmer deserves
614 what he gets. Subtract the offset from the length of the string,
902de8ed 615 and return that. This would perhaps not be valid if we were dealing
616 with named arrays in addition to literal string constants. */
617
da136652 618 return size_diffop_loc (loc, size_int (max), offset_node);
53800dbe 619 }
620
621 /* We have a known offset into the string. Start searching there for
27d0c333 622 a null character if we can represent it as a single HOST_WIDE_INT. */
dabc4084 623 if (offset_node == 0)
53800dbe 624 offset = 0;
35ec552a 625 else if (! tree_fits_shwi_p (offset_node))
dabc4084 626 offset = -1;
53800dbe 627 else
fcb97e84 628 offset = tree_to_shwi (offset_node);
902de8ed 629
1f63a7d6 630 /* If the offset is known to be out of bounds, warn, and call strlen at
631 runtime. */
53800dbe 632 if (offset < 0 || offset > max)
633 {
1f63a7d6 634 /* Suppress multiple warnings for propagated constant strings. */
635 if (! TREE_NO_WARNING (src))
636 {
da136652 637 warning_at (loc, 0, "offset outside bounds of constant string");
1f63a7d6 638 TREE_NO_WARNING (src) = 1;
639 }
c2f47e15 640 return NULL_TREE;
53800dbe 641 }
902de8ed 642
53800dbe 643 /* Use strlen to search for the first zero byte. Since any strings
644 constructed with build_string will have nulls appended, we win even
645 if we get handed something like (char[4])"abcd".
646
647 Since OFFSET is our starting index into the string, no further
648 calculation is needed. */
902de8ed 649 return ssize_int (strlen (ptr + offset));
53800dbe 650}
651
83d79705 652/* Return a char pointer for a C string if it is a string constant
653 or sum of string constant and integer constant. */
654
655static const char *
aecda0d6 656c_getstr (tree src)
83d79705 657{
658 tree offset_node;
83d79705 659
660 src = string_constant (src, &offset_node);
661 if (src == 0)
662 return 0;
663
8c85fcb7 664 if (offset_node == 0)
665 return TREE_STRING_POINTER (src);
cd4547bf 666 else if (!tree_fits_uhwi_p (offset_node)
8c85fcb7 667 || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
83d79705 668 return 0;
83d79705 669
6a0712d4 670 return TREE_STRING_POINTER (src) + tree_to_uhwi (offset_node);
83d79705 671}
672
8c85fcb7 673/* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
674 GET_MODE_BITSIZE (MODE) bits from string constant STR. */
ecc318ff 675
6840589f 676static rtx
aecda0d6 677c_readstr (const char *str, enum machine_mode mode)
6840589f 678{
679 HOST_WIDE_INT c[2];
680 HOST_WIDE_INT ch;
681 unsigned int i, j;
682
64db345d 683 gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
7d3f6cc7 684
6840589f 685 c[0] = 0;
686 c[1] = 0;
687 ch = 1;
688 for (i = 0; i < GET_MODE_SIZE (mode); i++)
689 {
690 j = i;
691 if (WORDS_BIG_ENDIAN)
692 j = GET_MODE_SIZE (mode) - i - 1;
693 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
ad8f8e52 694 && GET_MODE_SIZE (mode) >= UNITS_PER_WORD)
6840589f 695 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
696 j *= BITS_PER_UNIT;
24cd46a7 697 gcc_assert (j < HOST_BITS_PER_DOUBLE_INT);
7d3f6cc7 698
6840589f 699 if (ch)
700 ch = (unsigned char) str[i];
701 c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
702 }
703 return immed_double_const (c[0], c[1], mode);
704}
705
ecc318ff 706/* Cast a target constant CST to target CHAR and if that value fits into
5206b159 707 host char type, return zero and put that value into variable pointed to by
ecc318ff 708 P. */
709
710static int
aecda0d6 711target_char_cast (tree cst, char *p)
ecc318ff 712{
713 unsigned HOST_WIDE_INT val, hostval;
714
c19686c5 715 if (TREE_CODE (cst) != INTEGER_CST
ecc318ff 716 || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
717 return 1;
718
c19686c5 719 val = TREE_INT_CST_LOW (cst);
ecc318ff 720 if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
721 val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
722
723 hostval = val;
724 if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
725 hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
726
727 if (val != hostval)
728 return 1;
729
730 *p = hostval;
731 return 0;
732}
733
4ee9c684 734/* Similar to save_expr, but assumes that arbitrary code is not executed
735 in between the multiple evaluations. In particular, we assume that a
736 non-addressable local variable will not be modified. */
737
738static tree
739builtin_save_expr (tree exp)
740{
f6c35aa4 741 if (TREE_CODE (exp) == SSA_NAME
742 || (TREE_ADDRESSABLE (exp) == 0
743 && (TREE_CODE (exp) == PARM_DECL
744 || (TREE_CODE (exp) == VAR_DECL && !TREE_STATIC (exp)))))
4ee9c684 745 return exp;
746
747 return save_expr (exp);
748}
749
53800dbe 750/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
751 times to get the address of either a higher stack frame, or a return
752 address located within it (depending on FNDECL_CODE). */
902de8ed 753
c626df3d 754static rtx
869d0ef0 755expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
53800dbe 756{
757 int i;
758
869d0ef0 759#ifdef INITIAL_FRAME_ADDRESS_RTX
760 rtx tem = INITIAL_FRAME_ADDRESS_RTX;
761#else
e3e15c50 762 rtx tem;
763
1b74fde7 764 /* For a zero count with __builtin_return_address, we don't care what
765 frame address we return, because target-specific definitions will
766 override us. Therefore frame pointer elimination is OK, and using
767 the soft frame pointer is OK.
768
fa7637bd 769 For a nonzero count, or a zero count with __builtin_frame_address,
1b74fde7 770 we require a stable offset from the current frame pointer to the
771 previous one, so we must use the hard frame pointer, and
e3e15c50 772 we must disable frame pointer elimination. */
1b74fde7 773 if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
e3e15c50 774 tem = frame_pointer_rtx;
a0c938f0 775 else
e3e15c50 776 {
777 tem = hard_frame_pointer_rtx;
778
779 /* Tell reload not to eliminate the frame pointer. */
18d50ae6 780 crtl->accesses_prior_frames = 1;
e3e15c50 781 }
869d0ef0 782#endif
783
53800dbe 784 /* Some machines need special handling before we can access
3a69c60c 785 arbitrary frames. For example, on the SPARC, we must first flush
53800dbe 786 all register windows to the stack. */
787#ifdef SETUP_FRAME_ADDRESSES
788 if (count > 0)
789 SETUP_FRAME_ADDRESSES ();
790#endif
791
3a69c60c 792 /* On the SPARC, the return address is not in the frame, it is in a
53800dbe 793 register. There is no way to access it off of the current frame
794 pointer, but it can be accessed off the previous frame pointer by
795 reading the value from the register window save area. */
796#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
797 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
798 count--;
799#endif
800
801 /* Scan back COUNT frames to the specified frame. */
802 for (i = 0; i < count; i++)
803 {
804 /* Assume the dynamic chain pointer is in the word that the
805 frame address points to, unless otherwise specified. */
806#ifdef DYNAMIC_CHAIN_ADDRESS
807 tem = DYNAMIC_CHAIN_ADDRESS (tem);
808#endif
809 tem = memory_address (Pmode, tem);
00060fc2 810 tem = gen_frame_mem (Pmode, tem);
83fc1478 811 tem = copy_to_reg (tem);
53800dbe 812 }
813
3a69c60c 814 /* For __builtin_frame_address, return what we've got. But, on
815 the SPARC for example, we may have to add a bias. */
53800dbe 816 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
3a69c60c 817#ifdef FRAME_ADDR_RTX
818 return FRAME_ADDR_RTX (tem);
819#else
53800dbe 820 return tem;
3a69c60c 821#endif
53800dbe 822
3a69c60c 823 /* For __builtin_return_address, get the return address from that frame. */
53800dbe 824#ifdef RETURN_ADDR_RTX
825 tem = RETURN_ADDR_RTX (count, tem);
826#else
827 tem = memory_address (Pmode,
29c05e22 828 plus_constant (Pmode, tem, GET_MODE_SIZE (Pmode)));
00060fc2 829 tem = gen_frame_mem (Pmode, tem);
53800dbe 830#endif
831 return tem;
832}
833
f7c44134 834/* Alias set used for setjmp buffer. */
32c2fdea 835static alias_set_type setjmp_alias_set = -1;
f7c44134 836
6b7f6858 837/* Construct the leading half of a __builtin_setjmp call. Control will
2c8a1497 838 return to RECEIVER_LABEL. This is also called directly by the SJLJ
839 exception handling code. */
53800dbe 840
6b7f6858 841void
aecda0d6 842expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
53800dbe 843{
53800dbe 844 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
53800dbe 845 rtx stack_save;
f7c44134 846 rtx mem;
53800dbe 847
f7c44134 848 if (setjmp_alias_set == -1)
849 setjmp_alias_set = new_alias_set ();
850
85d654dd 851 buf_addr = convert_memory_address (Pmode, buf_addr);
53800dbe 852
37ae8504 853 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
53800dbe 854
6b7f6858 855 /* We store the frame pointer and the address of receiver_label in
856 the buffer and use the rest of it for the stack save area, which
857 is machine-dependent. */
53800dbe 858
f7c44134 859 mem = gen_rtx_MEM (Pmode, buf_addr);
ab6ab77e 860 set_mem_alias_set (mem, setjmp_alias_set);
e3e026e8 861 emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
f7c44134 862
29c05e22 863 mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
864 GET_MODE_SIZE (Pmode))),
ab6ab77e 865 set_mem_alias_set (mem, setjmp_alias_set);
f7c44134 866
867 emit_move_insn (validize_mem (mem),
6b7f6858 868 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
53800dbe 869
870 stack_save = gen_rtx_MEM (sa_mode,
29c05e22 871 plus_constant (Pmode, buf_addr,
53800dbe 872 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 873 set_mem_alias_set (stack_save, setjmp_alias_set);
e9c97615 874 emit_stack_save (SAVE_NONLOCAL, &stack_save);
53800dbe 875
876 /* If there is further processing to do, do it. */
877#ifdef HAVE_builtin_setjmp_setup
878 if (HAVE_builtin_setjmp_setup)
879 emit_insn (gen_builtin_setjmp_setup (buf_addr));
880#endif
881
29f09705 882 /* We have a nonlocal label. */
18d50ae6 883 cfun->has_nonlocal_label = 1;
6b7f6858 884}
53800dbe 885
2c8a1497 886/* Construct the trailing part of a __builtin_setjmp call. This is
4598ade9 887 also called directly by the SJLJ exception handling code.
888 If RECEIVER_LABEL is NULL, instead contruct a nonlocal goto handler. */
6b7f6858 889
890void
aecda0d6 891expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
6b7f6858 892{
82c7907c 893 rtx chain;
894
4598ade9 895 /* Mark the FP as used when we get here, so we have to make sure it's
53800dbe 896 marked as used by this function. */
18b42941 897 emit_use (hard_frame_pointer_rtx);
53800dbe 898
899 /* Mark the static chain as clobbered here so life information
900 doesn't get messed up for it. */
82c7907c 901 chain = targetm.calls.static_chain (current_function_decl, true);
902 if (chain && REG_P (chain))
903 emit_clobber (chain);
53800dbe 904
905 /* Now put in the code to restore the frame pointer, and argument
491e04ef 906 pointer, if needed. */
53800dbe 907#ifdef HAVE_nonlocal_goto
908 if (! HAVE_nonlocal_goto)
909#endif
4598ade9 910 /* First adjust our frame pointer to its actual value. It was
911 previously set to the start of the virtual area corresponding to
912 the stacked variables when we branched here and now needs to be
913 adjusted to the actual hardware fp value.
914
915 Assignments to virtual registers are converted by
916 instantiate_virtual_regs into the corresponding assignment
917 to the underlying register (fp in this case) that makes
918 the original assignment true.
919 So the following insn will actually be decrementing fp by
920 STARTING_FRAME_OFFSET. */
921 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
53800dbe 922
5ae82d58 923#if !HARD_FRAME_POINTER_IS_ARG_POINTER
53800dbe 924 if (fixed_regs[ARG_POINTER_REGNUM])
925 {
926#ifdef ELIMINABLE_REGS
4598ade9 927 /* If the argument pointer can be eliminated in favor of the
928 frame pointer, we don't need to restore it. We assume here
929 that if such an elimination is present, it can always be used.
930 This is the case on all known machines; if we don't make this
931 assumption, we do unnecessary saving on many machines. */
53800dbe 932 size_t i;
e99c3a1d 933 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
53800dbe 934
3098b2d3 935 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
53800dbe 936 if (elim_regs[i].from == ARG_POINTER_REGNUM
937 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
938 break;
939
3098b2d3 940 if (i == ARRAY_SIZE (elim_regs))
53800dbe 941#endif
942 {
943 /* Now restore our arg pointer from the address at which it
05927e40 944 was saved in our stack frame. */
27a7a23a 945 emit_move_insn (crtl->args.internal_arg_pointer,
b079a207 946 copy_to_reg (get_arg_pointer_save_area ()));
53800dbe 947 }
948 }
949#endif
950
951#ifdef HAVE_builtin_setjmp_receiver
4598ade9 952 if (receiver_label != NULL && HAVE_builtin_setjmp_receiver)
6b7f6858 953 emit_insn (gen_builtin_setjmp_receiver (receiver_label));
53800dbe 954 else
955#endif
956#ifdef HAVE_nonlocal_goto_receiver
957 if (HAVE_nonlocal_goto_receiver)
958 emit_insn (gen_nonlocal_goto_receiver ());
959 else
960#endif
6b7f6858 961 { /* Nothing */ }
57f6bb94 962
3072d30e 963 /* We must not allow the code we just generated to be reordered by
964 scheduling. Specifically, the update of the frame pointer must
e12b44a3 965 happen immediately, not later. Similarly, we must block
966 (frame-related) register values to be used across this code. */
3072d30e 967 emit_insn (gen_blockage ());
6b7f6858 968}
53800dbe 969
53800dbe 970/* __builtin_longjmp is passed a pointer to an array of five words (not
971 all will be used on all machines). It operates similarly to the C
972 library function of the same name, but is more efficient. Much of
2c8a1497 973 the code below is copied from the handling of non-local gotos. */
53800dbe 974
c626df3d 975static void
aecda0d6 976expand_builtin_longjmp (rtx buf_addr, rtx value)
53800dbe 977{
4712c7d6 978 rtx fp, lab, stack, insn, last;
53800dbe 979 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
980
48e1416a 981 /* DRAP is needed for stack realign if longjmp is expanded to current
27a7a23a 982 function */
983 if (SUPPORTS_STACK_ALIGNMENT)
984 crtl->need_drap = true;
985
f7c44134 986 if (setjmp_alias_set == -1)
987 setjmp_alias_set = new_alias_set ();
988
85d654dd 989 buf_addr = convert_memory_address (Pmode, buf_addr);
479e4d5e 990
53800dbe 991 buf_addr = force_reg (Pmode, buf_addr);
992
82c7907c 993 /* We require that the user must pass a second argument of 1, because
994 that is what builtin_setjmp will return. */
64db345d 995 gcc_assert (value == const1_rtx);
53800dbe 996
4712c7d6 997 last = get_last_insn ();
53800dbe 998#ifdef HAVE_builtin_longjmp
999 if (HAVE_builtin_longjmp)
1000 emit_insn (gen_builtin_longjmp (buf_addr));
1001 else
1002#endif
1003 {
1004 fp = gen_rtx_MEM (Pmode, buf_addr);
29c05e22 1005 lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
53800dbe 1006 GET_MODE_SIZE (Pmode)));
1007
29c05e22 1008 stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, buf_addr,
53800dbe 1009 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 1010 set_mem_alias_set (fp, setjmp_alias_set);
1011 set_mem_alias_set (lab, setjmp_alias_set);
1012 set_mem_alias_set (stack, setjmp_alias_set);
53800dbe 1013
1014 /* Pick up FP, label, and SP from the block and jump. This code is
1015 from expand_goto in stmt.c; see there for detailed comments. */
03fd9d2c 1016#ifdef HAVE_nonlocal_goto
53800dbe 1017 if (HAVE_nonlocal_goto)
1018 /* We have to pass a value to the nonlocal_goto pattern that will
1019 get copied into the static_chain pointer, but it does not matter
1020 what that value is, because builtin_setjmp does not use it. */
28d202a8 1021 emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
53800dbe 1022 else
1023#endif
1024 {
1025 lab = copy_to_reg (lab);
1026
18b42941 1027 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
1028 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
2a871ad1 1029
53800dbe 1030 emit_move_insn (hard_frame_pointer_rtx, fp);
e9c97615 1031 emit_stack_restore (SAVE_NONLOCAL, stack);
53800dbe 1032
18b42941 1033 emit_use (hard_frame_pointer_rtx);
1034 emit_use (stack_pointer_rtx);
53800dbe 1035 emit_indirect_jump (lab);
1036 }
1037 }
615166bb 1038
1039 /* Search backwards and mark the jump insn as a non-local goto.
1040 Note that this precludes the use of __builtin_longjmp to a
1041 __builtin_setjmp target in the same function. However, we've
1042 already cautioned the user that these functions are for
1043 internal exception handling use only. */
449c0509 1044 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
1045 {
64db345d 1046 gcc_assert (insn != last);
7d3f6cc7 1047
6d7dc5b9 1048 if (JUMP_P (insn))
449c0509 1049 {
a1ddb869 1050 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
449c0509 1051 break;
1052 }
6d7dc5b9 1053 else if (CALL_P (insn))
9342ee68 1054 break;
449c0509 1055 }
53800dbe 1056}
1057
0e80b01d 1058static inline bool
1059more_const_call_expr_args_p (const const_call_expr_arg_iterator *iter)
1060{
1061 return (iter->i < iter->n);
1062}
1063
1064/* This function validates the types of a function call argument list
1065 against a specified list of tree_codes. If the last specifier is a 0,
1066 that represents an ellipses, otherwise the last specifier must be a
1067 VOID_TYPE. */
1068
1069static bool
1070validate_arglist (const_tree callexpr, ...)
1071{
1072 enum tree_code code;
1073 bool res = 0;
1074 va_list ap;
1075 const_call_expr_arg_iterator iter;
1076 const_tree arg;
1077
1078 va_start (ap, callexpr);
1079 init_const_call_expr_arg_iterator (callexpr, &iter);
1080
1081 do
1082 {
1083 code = (enum tree_code) va_arg (ap, int);
1084 switch (code)
1085 {
1086 case 0:
1087 /* This signifies an ellipses, any further arguments are all ok. */
1088 res = true;
1089 goto end;
1090 case VOID_TYPE:
1091 /* This signifies an endlink, if no arguments remain, return
1092 true, otherwise return false. */
1093 res = !more_const_call_expr_args_p (&iter);
1094 goto end;
1095 default:
1096 /* If no parameters remain or the parameter's code does not
1097 match the specified code, return false. Otherwise continue
1098 checking any remaining arguments. */
1099 arg = next_const_call_expr_arg (&iter);
1100 if (!validate_arg (arg, code))
1101 goto end;
1102 break;
1103 }
1104 }
1105 while (1);
1106
1107 /* We need gotos here since we can only have one VA_CLOSE in a
1108 function. */
1109 end: ;
1110 va_end (ap);
1111
1112 return res;
1113}
1114
4ee9c684 1115/* Expand a call to __builtin_nonlocal_goto. We're passed the target label
1116 and the address of the save area. */
1117
1118static rtx
c2f47e15 1119expand_builtin_nonlocal_goto (tree exp)
4ee9c684 1120{
1121 tree t_label, t_save_area;
1122 rtx r_label, r_save_area, r_fp, r_sp, insn;
1123
c2f47e15 1124 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4ee9c684 1125 return NULL_RTX;
1126
c2f47e15 1127 t_label = CALL_EXPR_ARG (exp, 0);
1128 t_save_area = CALL_EXPR_ARG (exp, 1);
4ee9c684 1129
8ec3c5c2 1130 r_label = expand_normal (t_label);
3dce56cc 1131 r_label = convert_memory_address (Pmode, r_label);
8ec3c5c2 1132 r_save_area = expand_normal (t_save_area);
3dce56cc 1133 r_save_area = convert_memory_address (Pmode, r_save_area);
d1ff492e 1134 /* Copy the address of the save location to a register just in case it was
1135 based on the frame pointer. */
51adbc8a 1136 r_save_area = copy_to_reg (r_save_area);
4ee9c684 1137 r_fp = gen_rtx_MEM (Pmode, r_save_area);
1138 r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
29c05e22 1139 plus_constant (Pmode, r_save_area,
1140 GET_MODE_SIZE (Pmode)));
4ee9c684 1141
18d50ae6 1142 crtl->has_nonlocal_goto = 1;
4ee9c684 1143
03fd9d2c 1144#ifdef HAVE_nonlocal_goto
4ee9c684 1145 /* ??? We no longer need to pass the static chain value, afaik. */
1146 if (HAVE_nonlocal_goto)
1147 emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
1148 else
1149#endif
1150 {
1151 r_label = copy_to_reg (r_label);
1152
18b42941 1153 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
1154 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
491e04ef 1155
d1ff492e 1156 /* Restore frame pointer for containing function. */
4ee9c684 1157 emit_move_insn (hard_frame_pointer_rtx, r_fp);
e9c97615 1158 emit_stack_restore (SAVE_NONLOCAL, r_sp);
491e04ef 1159
4ee9c684 1160 /* USE of hard_frame_pointer_rtx added for consistency;
1161 not clear if really needed. */
18b42941 1162 emit_use (hard_frame_pointer_rtx);
1163 emit_use (stack_pointer_rtx);
ad0d0af8 1164
1165 /* If the architecture is using a GP register, we must
1166 conservatively assume that the target function makes use of it.
1167 The prologue of functions with nonlocal gotos must therefore
1168 initialize the GP register to the appropriate value, and we
1169 must then make sure that this value is live at the point
1170 of the jump. (Note that this doesn't necessarily apply
1171 to targets with a nonlocal_goto pattern; they are free
1172 to implement it in their own way. Note also that this is
1173 a no-op if the GP register is a global invariant.) */
1174 if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
1175 && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
18b42941 1176 emit_use (pic_offset_table_rtx);
ad0d0af8 1177
4ee9c684 1178 emit_indirect_jump (r_label);
1179 }
491e04ef 1180
4ee9c684 1181 /* Search backwards to the jump insn and mark it as a
1182 non-local goto. */
1183 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
1184 {
6d7dc5b9 1185 if (JUMP_P (insn))
4ee9c684 1186 {
a1ddb869 1187 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
4ee9c684 1188 break;
1189 }
6d7dc5b9 1190 else if (CALL_P (insn))
4ee9c684 1191 break;
1192 }
1193
1194 return const0_rtx;
1195}
1196
843d08a9 1197/* __builtin_update_setjmp_buf is passed a pointer to an array of five words
1198 (not all will be used on all machines) that was passed to __builtin_setjmp.
1199 It updates the stack pointer in that block to correspond to the current
1200 stack pointer. */
1201
1202static void
1203expand_builtin_update_setjmp_buf (rtx buf_addr)
1204{
d1ff492e 1205 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
1206 rtx stack_save
843d08a9 1207 = gen_rtx_MEM (sa_mode,
1208 memory_address
1209 (sa_mode,
29c05e22 1210 plus_constant (Pmode, buf_addr,
1211 2 * GET_MODE_SIZE (Pmode))));
843d08a9 1212
e9c97615 1213 emit_stack_save (SAVE_NONLOCAL, &stack_save);
843d08a9 1214}
1215
5e3608d8 1216/* Expand a call to __builtin_prefetch. For a target that does not support
1217 data prefetch, evaluate the memory address argument in case it has side
1218 effects. */
1219
1220static void
c2f47e15 1221expand_builtin_prefetch (tree exp)
5e3608d8 1222{
1223 tree arg0, arg1, arg2;
c2f47e15 1224 int nargs;
5e3608d8 1225 rtx op0, op1, op2;
1226
c2f47e15 1227 if (!validate_arglist (exp, POINTER_TYPE, 0))
26a5cadb 1228 return;
1229
c2f47e15 1230 arg0 = CALL_EXPR_ARG (exp, 0);
1231
26a5cadb 1232 /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
1233 zero (read) and argument 2 (locality) defaults to 3 (high degree of
1234 locality). */
c2f47e15 1235 nargs = call_expr_nargs (exp);
1236 if (nargs > 1)
1237 arg1 = CALL_EXPR_ARG (exp, 1);
26a5cadb 1238 else
c2f47e15 1239 arg1 = integer_zero_node;
1240 if (nargs > 2)
1241 arg2 = CALL_EXPR_ARG (exp, 2);
1242 else
2512209b 1243 arg2 = integer_three_node;
5e3608d8 1244
1245 /* Argument 0 is an address. */
1246 op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
1247
1248 /* Argument 1 (read/write flag) must be a compile-time constant int. */
1249 if (TREE_CODE (arg1) != INTEGER_CST)
1250 {
07e3a3d2 1251 error ("second argument to %<__builtin_prefetch%> must be a constant");
9342ee68 1252 arg1 = integer_zero_node;
5e3608d8 1253 }
8ec3c5c2 1254 op1 = expand_normal (arg1);
5e3608d8 1255 /* Argument 1 must be either zero or one. */
1256 if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
1257 {
c3ceba8e 1258 warning (0, "invalid second argument to %<__builtin_prefetch%>;"
07e3a3d2 1259 " using zero");
5e3608d8 1260 op1 = const0_rtx;
1261 }
1262
1263 /* Argument 2 (locality) must be a compile-time constant int. */
1264 if (TREE_CODE (arg2) != INTEGER_CST)
1265 {
07e3a3d2 1266 error ("third argument to %<__builtin_prefetch%> must be a constant");
5e3608d8 1267 arg2 = integer_zero_node;
1268 }
8ec3c5c2 1269 op2 = expand_normal (arg2);
5e3608d8 1270 /* Argument 2 must be 0, 1, 2, or 3. */
1271 if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
1272 {
c3ceba8e 1273 warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
5e3608d8 1274 op2 = const0_rtx;
1275 }
1276
1277#ifdef HAVE_prefetch
1278 if (HAVE_prefetch)
1279 {
8786db1e 1280 struct expand_operand ops[3];
1281
1282 create_address_operand (&ops[0], op0);
1283 create_integer_operand (&ops[1], INTVAL (op1));
1284 create_integer_operand (&ops[2], INTVAL (op2));
1285 if (maybe_expand_insn (CODE_FOR_prefetch, 3, ops))
1286 return;
5e3608d8 1287 }
5e3608d8 1288#endif
0a534ba7 1289
f0ce3b1f 1290 /* Don't do anything with direct references to volatile memory, but
1291 generate code to handle other side effects. */
e16ceb8e 1292 if (!MEM_P (op0) && side_effects_p (op0))
f0ce3b1f 1293 emit_insn (op0);
5e3608d8 1294}
1295
f7c44134 1296/* Get a MEM rtx for expression EXP which is the address of an operand
d8ae1baa 1297 to be used in a string instruction (cmpstrsi, movmemsi, ..). LEN is
1298 the maximum length of the block of memory that might be accessed or
1299 NULL if unknown. */
f7c44134 1300
53800dbe 1301static rtx
d8ae1baa 1302get_memory_rtx (tree exp, tree len)
53800dbe 1303{
ad0a178f 1304 tree orig_exp = exp;
1305 rtx addr, mem;
ad0a178f 1306
1307 /* When EXP is not resolved SAVE_EXPR, MEM_ATTRS can be still derived
1308 from its expression, for expr->a.b only <variable>.a.b is recorded. */
1309 if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp))
1310 exp = TREE_OPERAND (exp, 0);
1311
1312 addr = expand_expr (orig_exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
1313 mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
2a631e19 1314
f7c44134 1315 /* Get an expression we can use to find the attributes to assign to MEM.
5dd3f78f 1316 First remove any nops. */
72dd6141 1317 while (CONVERT_EXPR_P (exp)
f7c44134 1318 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
1319 exp = TREE_OPERAND (exp, 0);
1320
5dd3f78f 1321 /* Build a MEM_REF representing the whole accessed area as a byte blob,
1322 (as builtin stringops may alias with anything). */
1323 exp = fold_build2 (MEM_REF,
1324 build_array_type (char_type_node,
1325 build_range_type (sizetype,
1326 size_one_node, len)),
1327 exp, build_int_cst (ptr_type_node, 0));
1328
1329 /* If the MEM_REF has no acceptable address, try to get the base object
1330 from the original address we got, and build an all-aliasing
1331 unknown-sized access to that one. */
1332 if (is_gimple_mem_ref_addr (TREE_OPERAND (exp, 0)))
1333 set_mem_attributes (mem, exp, 0);
1334 else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
1335 && (exp = get_base_address (TREE_OPERAND (TREE_OPERAND (exp, 0),
1336 0))))
eec8e941 1337 {
5dd3f78f 1338 exp = build_fold_addr_expr (exp);
1339 exp = fold_build2 (MEM_REF,
1340 build_array_type (char_type_node,
1341 build_range_type (sizetype,
1342 size_zero_node,
1343 NULL)),
1344 exp, build_int_cst (ptr_type_node, 0));
a1a25d19 1345 set_mem_attributes (mem, exp, 0);
eec8e941 1346 }
5dd3f78f 1347 set_mem_alias_set (mem, 0);
53800dbe 1348 return mem;
1349}
1350\f
1351/* Built-in functions to perform an untyped call and return. */
1352
3b9c3a16 1353#define apply_args_mode \
1354 (this_target_builtins->x_apply_args_mode)
1355#define apply_result_mode \
1356 (this_target_builtins->x_apply_result_mode)
53800dbe 1357
53800dbe 1358/* Return the size required for the block returned by __builtin_apply_args,
1359 and initialize apply_args_mode. */
1360
1361static int
aecda0d6 1362apply_args_size (void)
53800dbe 1363{
1364 static int size = -1;
58e9ce8f 1365 int align;
1366 unsigned int regno;
53800dbe 1367 enum machine_mode mode;
1368
1369 /* The values computed by this function never change. */
1370 if (size < 0)
1371 {
1372 /* The first value is the incoming arg-pointer. */
1373 size = GET_MODE_SIZE (Pmode);
1374
1375 /* The second value is the structure value address unless this is
1376 passed as an "invisible" first argument. */
6812c89e 1377 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1378 size += GET_MODE_SIZE (Pmode);
1379
1380 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1381 if (FUNCTION_ARG_REGNO_P (regno))
1382 {
4bac51c9 1383 mode = targetm.calls.get_raw_arg_mode (regno);
0862b7e9 1384
64db345d 1385 gcc_assert (mode != VOIDmode);
53800dbe 1386
1387 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1388 if (size % align != 0)
1389 size = CEIL (size, align) * align;
53800dbe 1390 size += GET_MODE_SIZE (mode);
1391 apply_args_mode[regno] = mode;
1392 }
1393 else
1394 {
1395 apply_args_mode[regno] = VOIDmode;
53800dbe 1396 }
1397 }
1398 return size;
1399}
1400
1401/* Return the size required for the block returned by __builtin_apply,
1402 and initialize apply_result_mode. */
1403
1404static int
aecda0d6 1405apply_result_size (void)
53800dbe 1406{
1407 static int size = -1;
1408 int align, regno;
1409 enum machine_mode mode;
1410
1411 /* The values computed by this function never change. */
1412 if (size < 0)
1413 {
1414 size = 0;
1415
1416 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
e1ce1485 1417 if (targetm.calls.function_value_regno_p (regno))
53800dbe 1418 {
4bac51c9 1419 mode = targetm.calls.get_raw_result_mode (regno);
0862b7e9 1420
64db345d 1421 gcc_assert (mode != VOIDmode);
53800dbe 1422
1423 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1424 if (size % align != 0)
1425 size = CEIL (size, align) * align;
1426 size += GET_MODE_SIZE (mode);
1427 apply_result_mode[regno] = mode;
1428 }
1429 else
1430 apply_result_mode[regno] = VOIDmode;
1431
1432 /* Allow targets that use untyped_call and untyped_return to override
1433 the size so that machine-specific information can be stored here. */
1434#ifdef APPLY_RESULT_SIZE
1435 size = APPLY_RESULT_SIZE;
1436#endif
1437 }
1438 return size;
1439}
1440
1441#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1442/* Create a vector describing the result block RESULT. If SAVEP is true,
1443 the result block is used to save the values; otherwise it is used to
1444 restore the values. */
1445
1446static rtx
aecda0d6 1447result_vector (int savep, rtx result)
53800dbe 1448{
1449 int regno, size, align, nelts;
1450 enum machine_mode mode;
1451 rtx reg, mem;
364c0c59 1452 rtx *savevec = XALLOCAVEC (rtx, FIRST_PSEUDO_REGISTER);
bf8e3599 1453
53800dbe 1454 size = nelts = 0;
1455 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1456 if ((mode = apply_result_mode[regno]) != VOIDmode)
1457 {
1458 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1459 if (size % align != 0)
1460 size = CEIL (size, align) * align;
1461 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
e513d163 1462 mem = adjust_address (result, mode, size);
53800dbe 1463 savevec[nelts++] = (savep
1464 ? gen_rtx_SET (VOIDmode, mem, reg)
1465 : gen_rtx_SET (VOIDmode, reg, mem));
1466 size += GET_MODE_SIZE (mode);
1467 }
1468 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1469}
1470#endif /* HAVE_untyped_call or HAVE_untyped_return */
1471
1472/* Save the state required to perform an untyped call with the same
1473 arguments as were passed to the current function. */
1474
1475static rtx
aecda0d6 1476expand_builtin_apply_args_1 (void)
53800dbe 1477{
1c7e61a7 1478 rtx registers, tem;
53800dbe 1479 int size, align, regno;
1480 enum machine_mode mode;
6812c89e 1481 rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
53800dbe 1482
1483 /* Create a block where the arg-pointer, structure value address,
1484 and argument registers can be saved. */
1485 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1486
1487 /* Walk past the arg-pointer and structure value address. */
1488 size = GET_MODE_SIZE (Pmode);
6812c89e 1489 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1490 size += GET_MODE_SIZE (Pmode);
1491
1492 /* Save each register used in calling a function to the block. */
1493 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1494 if ((mode = apply_args_mode[regno]) != VOIDmode)
1495 {
53800dbe 1496 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1497 if (size % align != 0)
1498 size = CEIL (size, align) * align;
1499
1500 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1501
e513d163 1502 emit_move_insn (adjust_address (registers, mode, size), tem);
53800dbe 1503 size += GET_MODE_SIZE (mode);
1504 }
1505
1506 /* Save the arg pointer to the block. */
27a7a23a 1507 tem = copy_to_reg (crtl->args.internal_arg_pointer);
f083a92b 1508#ifdef STACK_GROWS_DOWNWARD
1c7e61a7 1509 /* We need the pointer as the caller actually passed them to us, not
9d4b544c 1510 as we might have pretended they were passed. Make sure it's a valid
1511 operand, as emit_move_insn isn't expected to handle a PLUS. */
1512 tem
29c05e22 1513 = force_operand (plus_constant (Pmode, tem, crtl->args.pretend_args_size),
9d4b544c 1514 NULL_RTX);
1c7e61a7 1515#endif
1516 emit_move_insn (adjust_address (registers, Pmode, 0), tem);
0862b7e9 1517
53800dbe 1518 size = GET_MODE_SIZE (Pmode);
1519
1520 /* Save the structure value address unless this is passed as an
1521 "invisible" first argument. */
45550790 1522 if (struct_incoming_value)
53800dbe 1523 {
e513d163 1524 emit_move_insn (adjust_address (registers, Pmode, size),
45550790 1525 copy_to_reg (struct_incoming_value));
53800dbe 1526 size += GET_MODE_SIZE (Pmode);
1527 }
1528
1529 /* Return the address of the block. */
1530 return copy_addr_to_reg (XEXP (registers, 0));
1531}
1532
1533/* __builtin_apply_args returns block of memory allocated on
1534 the stack into which is stored the arg pointer, structure
1535 value address, static chain, and all the registers that might
1536 possibly be used in performing a function call. The code is
1537 moved to the start of the function so the incoming values are
1538 saved. */
27d0c333 1539
53800dbe 1540static rtx
aecda0d6 1541expand_builtin_apply_args (void)
53800dbe 1542{
1543 /* Don't do __builtin_apply_args more than once in a function.
1544 Save the result of the first call and reuse it. */
1545 if (apply_args_value != 0)
1546 return apply_args_value;
1547 {
1548 /* When this function is called, it means that registers must be
1549 saved on entry to this function. So we migrate the
1550 call to the first insn of this function. */
1551 rtx temp;
1552 rtx seq;
1553
1554 start_sequence ();
1555 temp = expand_builtin_apply_args_1 ();
1556 seq = get_insns ();
1557 end_sequence ();
1558
1559 apply_args_value = temp;
1560
31d3e01c 1561 /* Put the insns after the NOTE that starts the function.
1562 If this is inside a start_sequence, make the outer-level insn
53800dbe 1563 chain current, so the code is placed at the start of the
0ef1a651 1564 function. If internal_arg_pointer is a non-virtual pseudo,
1565 it needs to be placed after the function that initializes
1566 that pseudo. */
53800dbe 1567 push_topmost_sequence ();
0ef1a651 1568 if (REG_P (crtl->args.internal_arg_pointer)
1569 && REGNO (crtl->args.internal_arg_pointer) > LAST_VIRTUAL_REGISTER)
1570 emit_insn_before (seq, parm_birth_insn);
1571 else
1572 emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
53800dbe 1573 pop_topmost_sequence ();
1574 return temp;
1575 }
1576}
1577
1578/* Perform an untyped call and save the state required to perform an
1579 untyped return of whatever value was returned by the given function. */
1580
1581static rtx
aecda0d6 1582expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
53800dbe 1583{
1584 int size, align, regno;
1585 enum machine_mode mode;
2a631e19 1586 rtx incoming_args, result, reg, dest, src, call_insn;
53800dbe 1587 rtx old_stack_level = 0;
1588 rtx call_fusage = 0;
6812c89e 1589 rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
53800dbe 1590
85d654dd 1591 arguments = convert_memory_address (Pmode, arguments);
726ec87c 1592
53800dbe 1593 /* Create a block where the return registers can be saved. */
1594 result = assign_stack_local (BLKmode, apply_result_size (), -1);
1595
53800dbe 1596 /* Fetch the arg pointer from the ARGUMENTS block. */
1597 incoming_args = gen_reg_rtx (Pmode);
726ec87c 1598 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
53800dbe 1599#ifndef STACK_GROWS_DOWNWARD
ad99e708 1600 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1601 incoming_args, 0, OPTAB_LIB_WIDEN);
53800dbe 1602#endif
1603
04a46d40 1604 /* Push a new argument block and copy the arguments. Do not allow
1605 the (potential) memcpy call below to interfere with our stack
1606 manipulations. */
53800dbe 1607 do_pending_stack_adjust ();
04a46d40 1608 NO_DEFER_POP;
53800dbe 1609
2358393e 1610 /* Save the stack with nonlocal if available. */
53800dbe 1611#ifdef HAVE_save_stack_nonlocal
1612 if (HAVE_save_stack_nonlocal)
e9c97615 1613 emit_stack_save (SAVE_NONLOCAL, &old_stack_level);
53800dbe 1614 else
1615#endif
e9c97615 1616 emit_stack_save (SAVE_BLOCK, &old_stack_level);
53800dbe 1617
59647703 1618 /* Allocate a block of memory onto the stack and copy the memory
990495a7 1619 arguments to the outgoing arguments address. We can pass TRUE
1620 as the 4th argument because we just saved the stack pointer
1621 and will restore it right after the call. */
5be42b39 1622 allocate_dynamic_stack_space (argsize, 0, BIGGEST_ALIGNMENT, true);
27a7a23a 1623
1624 /* Set DRAP flag to true, even though allocate_dynamic_stack_space
1625 may have already set current_function_calls_alloca to true.
1626 current_function_calls_alloca won't be set if argsize is zero,
1627 so we have to guarantee need_drap is true here. */
1628 if (SUPPORTS_STACK_ALIGNMENT)
1629 crtl->need_drap = true;
1630
59647703 1631 dest = virtual_outgoing_args_rtx;
1632#ifndef STACK_GROWS_DOWNWARD
971ba038 1633 if (CONST_INT_P (argsize))
29c05e22 1634 dest = plus_constant (Pmode, dest, -INTVAL (argsize));
59647703 1635 else
1636 dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1637#endif
2a631e19 1638 dest = gen_rtx_MEM (BLKmode, dest);
1639 set_mem_align (dest, PARM_BOUNDARY);
1640 src = gen_rtx_MEM (BLKmode, incoming_args);
1641 set_mem_align (src, PARM_BOUNDARY);
0378dbdc 1642 emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
53800dbe 1643
1644 /* Refer to the argument block. */
1645 apply_args_size ();
1646 arguments = gen_rtx_MEM (BLKmode, arguments);
2a631e19 1647 set_mem_align (arguments, PARM_BOUNDARY);
53800dbe 1648
1649 /* Walk past the arg-pointer and structure value address. */
1650 size = GET_MODE_SIZE (Pmode);
45550790 1651 if (struct_value)
53800dbe 1652 size += GET_MODE_SIZE (Pmode);
1653
1654 /* Restore each of the registers previously saved. Make USE insns
1655 for each of these registers for use in making the call. */
1656 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1657 if ((mode = apply_args_mode[regno]) != VOIDmode)
1658 {
1659 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1660 if (size % align != 0)
1661 size = CEIL (size, align) * align;
1662 reg = gen_rtx_REG (mode, regno);
e513d163 1663 emit_move_insn (reg, adjust_address (arguments, mode, size));
53800dbe 1664 use_reg (&call_fusage, reg);
1665 size += GET_MODE_SIZE (mode);
1666 }
1667
1668 /* Restore the structure value address unless this is passed as an
1669 "invisible" first argument. */
1670 size = GET_MODE_SIZE (Pmode);
45550790 1671 if (struct_value)
53800dbe 1672 {
1673 rtx value = gen_reg_rtx (Pmode);
e513d163 1674 emit_move_insn (value, adjust_address (arguments, Pmode, size));
45550790 1675 emit_move_insn (struct_value, value);
8ad4c111 1676 if (REG_P (struct_value))
45550790 1677 use_reg (&call_fusage, struct_value);
53800dbe 1678 size += GET_MODE_SIZE (Pmode);
1679 }
1680
1681 /* All arguments and registers used for the call are set up by now! */
82c7907c 1682 function = prepare_call_address (NULL, function, NULL, &call_fusage, 0, 0);
53800dbe 1683
1684 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1685 and we don't want to load it into a register as an optimization,
1686 because prepare_call_address already did it if it should be done. */
1687 if (GET_CODE (function) != SYMBOL_REF)
1688 function = memory_address (FUNCTION_MODE, function);
1689
1690 /* Generate the actual call instruction and save the return value. */
1691#ifdef HAVE_untyped_call
1692 if (HAVE_untyped_call)
1693 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1694 result, result_vector (1, result)));
1695 else
1696#endif
1697#ifdef HAVE_call_value
1698 if (HAVE_call_value)
1699 {
1700 rtx valreg = 0;
1701
1702 /* Locate the unique return register. It is not possible to
1703 express a call that sets more than one return register using
1704 call_value; use untyped_call for that. In fact, untyped_call
1705 only needs to save the return registers in the given block. */
1706 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1707 if ((mode = apply_result_mode[regno]) != VOIDmode)
1708 {
64db345d 1709 gcc_assert (!valreg); /* HAVE_untyped_call required. */
7d3f6cc7 1710
53800dbe 1711 valreg = gen_rtx_REG (mode, regno);
1712 }
1713
2ed6c343 1714 emit_call_insn (GEN_CALL_VALUE (valreg,
53800dbe 1715 gen_rtx_MEM (FUNCTION_MODE, function),
1716 const0_rtx, NULL_RTX, const0_rtx));
1717
e513d163 1718 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
53800dbe 1719 }
1720 else
1721#endif
64db345d 1722 gcc_unreachable ();
53800dbe 1723
d5f9786f 1724 /* Find the CALL insn we just emitted, and attach the register usage
1725 information. */
1726 call_insn = last_call_insn ();
1727 add_function_usage_to (call_insn, call_fusage);
53800dbe 1728
1729 /* Restore the stack. */
1730#ifdef HAVE_save_stack_nonlocal
1731 if (HAVE_save_stack_nonlocal)
e9c97615 1732 emit_stack_restore (SAVE_NONLOCAL, old_stack_level);
53800dbe 1733 else
1734#endif
e9c97615 1735 emit_stack_restore (SAVE_BLOCK, old_stack_level);
9af5ce0c 1736 fixup_args_size_notes (call_insn, get_last_insn (), 0);
53800dbe 1737
04a46d40 1738 OK_DEFER_POP;
1739
53800dbe 1740 /* Return the address of the result block. */
85d654dd 1741 result = copy_addr_to_reg (XEXP (result, 0));
1742 return convert_memory_address (ptr_mode, result);
53800dbe 1743}
1744
1745/* Perform an untyped return. */
1746
1747static void
aecda0d6 1748expand_builtin_return (rtx result)
53800dbe 1749{
1750 int size, align, regno;
1751 enum machine_mode mode;
1752 rtx reg;
1753 rtx call_fusage = 0;
1754
85d654dd 1755 result = convert_memory_address (Pmode, result);
726ec87c 1756
53800dbe 1757 apply_result_size ();
1758 result = gen_rtx_MEM (BLKmode, result);
1759
1760#ifdef HAVE_untyped_return
1761 if (HAVE_untyped_return)
1762 {
1763 emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1764 emit_barrier ();
1765 return;
1766 }
1767#endif
1768
1769 /* Restore the return value and note that each value is used. */
1770 size = 0;
1771 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1772 if ((mode = apply_result_mode[regno]) != VOIDmode)
1773 {
1774 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1775 if (size % align != 0)
1776 size = CEIL (size, align) * align;
1777 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
e513d163 1778 emit_move_insn (reg, adjust_address (result, mode, size));
53800dbe 1779
1780 push_to_sequence (call_fusage);
18b42941 1781 emit_use (reg);
53800dbe 1782 call_fusage = get_insns ();
1783 end_sequence ();
1784 size += GET_MODE_SIZE (mode);
1785 }
1786
1787 /* Put the USE insns before the return. */
31d3e01c 1788 emit_insn (call_fusage);
53800dbe 1789
1790 /* Return whatever values was restored by jumping directly to the end
1791 of the function. */
62380d2d 1792 expand_naked_return ();
53800dbe 1793}
1794
539a3a92 1795/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
27d0c333 1796
539a3a92 1797static enum type_class
aecda0d6 1798type_to_class (tree type)
539a3a92 1799{
1800 switch (TREE_CODE (type))
1801 {
1802 case VOID_TYPE: return void_type_class;
1803 case INTEGER_TYPE: return integer_type_class;
539a3a92 1804 case ENUMERAL_TYPE: return enumeral_type_class;
1805 case BOOLEAN_TYPE: return boolean_type_class;
1806 case POINTER_TYPE: return pointer_type_class;
1807 case REFERENCE_TYPE: return reference_type_class;
1808 case OFFSET_TYPE: return offset_type_class;
1809 case REAL_TYPE: return real_type_class;
1810 case COMPLEX_TYPE: return complex_type_class;
1811 case FUNCTION_TYPE: return function_type_class;
1812 case METHOD_TYPE: return method_type_class;
1813 case RECORD_TYPE: return record_type_class;
1814 case UNION_TYPE:
1815 case QUAL_UNION_TYPE: return union_type_class;
1816 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1817 ? string_type_class : array_type_class);
539a3a92 1818 case LANG_TYPE: return lang_type_class;
1819 default: return no_type_class;
1820 }
1821}
bf8e3599 1822
c2f47e15 1823/* Expand a call EXP to __builtin_classify_type. */
27d0c333 1824
53800dbe 1825static rtx
c2f47e15 1826expand_builtin_classify_type (tree exp)
53800dbe 1827{
c2f47e15 1828 if (call_expr_nargs (exp))
1829 return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0))));
53800dbe 1830 return GEN_INT (no_type_class);
1831}
1832
07976da7 1833/* This helper macro, meant to be used in mathfn_built_in below,
1834 determines which among a set of three builtin math functions is
1835 appropriate for a given type mode. The `F' and `L' cases are
1836 automatically generated from the `double' case. */
1837#define CASE_MATHFN(BUILT_IN_MATHFN) \
1838 case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1839 fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1840 fcodel = BUILT_IN_MATHFN##L ; break;
cd2656b0 1841/* Similar to above, but appends _R after any F/L suffix. */
1842#define CASE_MATHFN_REENT(BUILT_IN_MATHFN) \
1843 case BUILT_IN_MATHFN##_R: case BUILT_IN_MATHFN##F_R: case BUILT_IN_MATHFN##L_R: \
1844 fcode = BUILT_IN_MATHFN##_R; fcodef = BUILT_IN_MATHFN##F_R ; \
1845 fcodel = BUILT_IN_MATHFN##L_R ; break;
07976da7 1846
b9a16870 1847/* Return mathematic function equivalent to FN but operating directly on TYPE,
1848 if available. If IMPLICIT is true use the implicit builtin declaration,
1849 otherwise use the explicit declaration. If we can't do the conversion,
1850 return zero. */
c319d56a 1851
1852static tree
b9a16870 1853mathfn_built_in_1 (tree type, enum built_in_function fn, bool implicit_p)
0a68165a 1854{
b9a16870 1855 enum built_in_function fcode, fcodef, fcodel, fcode2;
07976da7 1856
1857 switch (fn)
1858 {
746114e8 1859 CASE_MATHFN (BUILT_IN_ACOS)
1860 CASE_MATHFN (BUILT_IN_ACOSH)
1861 CASE_MATHFN (BUILT_IN_ASIN)
1862 CASE_MATHFN (BUILT_IN_ASINH)
07976da7 1863 CASE_MATHFN (BUILT_IN_ATAN)
746114e8 1864 CASE_MATHFN (BUILT_IN_ATAN2)
1865 CASE_MATHFN (BUILT_IN_ATANH)
1866 CASE_MATHFN (BUILT_IN_CBRT)
07976da7 1867 CASE_MATHFN (BUILT_IN_CEIL)
d735c391 1868 CASE_MATHFN (BUILT_IN_CEXPI)
746114e8 1869 CASE_MATHFN (BUILT_IN_COPYSIGN)
07976da7 1870 CASE_MATHFN (BUILT_IN_COS)
746114e8 1871 CASE_MATHFN (BUILT_IN_COSH)
1872 CASE_MATHFN (BUILT_IN_DREM)
1873 CASE_MATHFN (BUILT_IN_ERF)
1874 CASE_MATHFN (BUILT_IN_ERFC)
07976da7 1875 CASE_MATHFN (BUILT_IN_EXP)
746114e8 1876 CASE_MATHFN (BUILT_IN_EXP10)
1877 CASE_MATHFN (BUILT_IN_EXP2)
1878 CASE_MATHFN (BUILT_IN_EXPM1)
1879 CASE_MATHFN (BUILT_IN_FABS)
1880 CASE_MATHFN (BUILT_IN_FDIM)
07976da7 1881 CASE_MATHFN (BUILT_IN_FLOOR)
746114e8 1882 CASE_MATHFN (BUILT_IN_FMA)
1883 CASE_MATHFN (BUILT_IN_FMAX)
1884 CASE_MATHFN (BUILT_IN_FMIN)
1885 CASE_MATHFN (BUILT_IN_FMOD)
1886 CASE_MATHFN (BUILT_IN_FREXP)
1887 CASE_MATHFN (BUILT_IN_GAMMA)
cd2656b0 1888 CASE_MATHFN_REENT (BUILT_IN_GAMMA) /* GAMMA_R */
746114e8 1889 CASE_MATHFN (BUILT_IN_HUGE_VAL)
1890 CASE_MATHFN (BUILT_IN_HYPOT)
1891 CASE_MATHFN (BUILT_IN_ILOGB)
80ff6494 1892 CASE_MATHFN (BUILT_IN_ICEIL)
1893 CASE_MATHFN (BUILT_IN_IFLOOR)
746114e8 1894 CASE_MATHFN (BUILT_IN_INF)
80ff6494 1895 CASE_MATHFN (BUILT_IN_IRINT)
1896 CASE_MATHFN (BUILT_IN_IROUND)
69b779ea 1897 CASE_MATHFN (BUILT_IN_ISINF)
746114e8 1898 CASE_MATHFN (BUILT_IN_J0)
1899 CASE_MATHFN (BUILT_IN_J1)
1900 CASE_MATHFN (BUILT_IN_JN)
ac148751 1901 CASE_MATHFN (BUILT_IN_LCEIL)
746114e8 1902 CASE_MATHFN (BUILT_IN_LDEXP)
ad52b9b7 1903 CASE_MATHFN (BUILT_IN_LFLOOR)
746114e8 1904 CASE_MATHFN (BUILT_IN_LGAMMA)
cd2656b0 1905 CASE_MATHFN_REENT (BUILT_IN_LGAMMA) /* LGAMMA_R */
ac148751 1906 CASE_MATHFN (BUILT_IN_LLCEIL)
ad52b9b7 1907 CASE_MATHFN (BUILT_IN_LLFLOOR)
746114e8 1908 CASE_MATHFN (BUILT_IN_LLRINT)
1909 CASE_MATHFN (BUILT_IN_LLROUND)
07976da7 1910 CASE_MATHFN (BUILT_IN_LOG)
746114e8 1911 CASE_MATHFN (BUILT_IN_LOG10)
1912 CASE_MATHFN (BUILT_IN_LOG1P)
1913 CASE_MATHFN (BUILT_IN_LOG2)
1914 CASE_MATHFN (BUILT_IN_LOGB)
1915 CASE_MATHFN (BUILT_IN_LRINT)
1916 CASE_MATHFN (BUILT_IN_LROUND)
1917 CASE_MATHFN (BUILT_IN_MODF)
1918 CASE_MATHFN (BUILT_IN_NAN)
1919 CASE_MATHFN (BUILT_IN_NANS)
07976da7 1920 CASE_MATHFN (BUILT_IN_NEARBYINT)
746114e8 1921 CASE_MATHFN (BUILT_IN_NEXTAFTER)
1922 CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1923 CASE_MATHFN (BUILT_IN_POW)
757c219d 1924 CASE_MATHFN (BUILT_IN_POWI)
746114e8 1925 CASE_MATHFN (BUILT_IN_POW10)
1926 CASE_MATHFN (BUILT_IN_REMAINDER)
1927 CASE_MATHFN (BUILT_IN_REMQUO)
1928 CASE_MATHFN (BUILT_IN_RINT)
07976da7 1929 CASE_MATHFN (BUILT_IN_ROUND)
746114e8 1930 CASE_MATHFN (BUILT_IN_SCALB)
1931 CASE_MATHFN (BUILT_IN_SCALBLN)
1932 CASE_MATHFN (BUILT_IN_SCALBN)
c319d56a 1933 CASE_MATHFN (BUILT_IN_SIGNBIT)
746114e8 1934 CASE_MATHFN (BUILT_IN_SIGNIFICAND)
07976da7 1935 CASE_MATHFN (BUILT_IN_SIN)
746114e8 1936 CASE_MATHFN (BUILT_IN_SINCOS)
1937 CASE_MATHFN (BUILT_IN_SINH)
07976da7 1938 CASE_MATHFN (BUILT_IN_SQRT)
1939 CASE_MATHFN (BUILT_IN_TAN)
746114e8 1940 CASE_MATHFN (BUILT_IN_TANH)
1941 CASE_MATHFN (BUILT_IN_TGAMMA)
07976da7 1942 CASE_MATHFN (BUILT_IN_TRUNC)
746114e8 1943 CASE_MATHFN (BUILT_IN_Y0)
1944 CASE_MATHFN (BUILT_IN_Y1)
1945 CASE_MATHFN (BUILT_IN_YN)
07976da7 1946
0a68165a 1947 default:
c2f47e15 1948 return NULL_TREE;
0a68165a 1949 }
07976da7 1950
96b9f485 1951 if (TYPE_MAIN_VARIANT (type) == double_type_node)
b9a16870 1952 fcode2 = fcode;
96b9f485 1953 else if (TYPE_MAIN_VARIANT (type) == float_type_node)
b9a16870 1954 fcode2 = fcodef;
96b9f485 1955 else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
b9a16870 1956 fcode2 = fcodel;
07976da7 1957 else
c2f47e15 1958 return NULL_TREE;
b9a16870 1959
1960 if (implicit_p && !builtin_decl_implicit_p (fcode2))
1961 return NULL_TREE;
1962
1963 return builtin_decl_explicit (fcode2);
0a68165a 1964}
1965
c319d56a 1966/* Like mathfn_built_in_1(), but always use the implicit array. */
1967
1968tree
1969mathfn_built_in (tree type, enum built_in_function fn)
1970{
1971 return mathfn_built_in_1 (type, fn, /*implicit=*/ 1);
1972}
1973
0fd605a5 1974/* If errno must be maintained, expand the RTL to check if the result,
1975 TARGET, of a built-in function call, EXP, is NaN, and if so set
1976 errno to EDOM. */
1977
1978static void
aecda0d6 1979expand_errno_check (tree exp, rtx target)
0fd605a5 1980{
7f05340e 1981 rtx lab = gen_label_rtx ();
0fd605a5 1982
7f05340e 1983 /* Test the result; if it is NaN, set errno=EDOM because
1984 the argument was not in the domain. */
3fcf767f 1985 do_compare_rtx_and_jump (target, target, EQ, 0, GET_MODE (target),
79ab74cc 1986 NULL_RTX, NULL_RTX, lab,
1987 /* The jump is very likely. */
1988 REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1));
0fd605a5 1989
1990#ifdef TARGET_EDOM
7f05340e 1991 /* If this built-in doesn't throw an exception, set errno directly. */
c2f47e15 1992 if (TREE_NOTHROW (TREE_OPERAND (CALL_EXPR_FN (exp), 0)))
7f05340e 1993 {
0fd605a5 1994#ifdef GEN_ERRNO_RTX
7f05340e 1995 rtx errno_rtx = GEN_ERRNO_RTX;
0fd605a5 1996#else
7f05340e 1997 rtx errno_rtx
0fd605a5 1998 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1999#endif
d11aedc7 2000 emit_move_insn (errno_rtx,
2001 gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
0fd605a5 2002 emit_label (lab);
7f05340e 2003 return;
0fd605a5 2004 }
7f05340e 2005#endif
2006
08491912 2007 /* Make sure the library call isn't expanded as a tail call. */
2008 CALL_EXPR_TAILCALL (exp) = 0;
2009
7f05340e 2010 /* We can't set errno=EDOM directly; let the library call do it.
2011 Pop the arguments right away in case the call gets deleted. */
2012 NO_DEFER_POP;
2013 expand_call (exp, target, 0);
2014 OK_DEFER_POP;
2015 emit_label (lab);
0fd605a5 2016}
2017
6b43bae4 2018/* Expand a call to one of the builtin math functions (sqrt, exp, or log).
c2f47e15 2019 Return NULL_RTX if a normal call should be emitted rather than expanding
2020 the function in-line. EXP is the expression that is a call to the builtin
53800dbe 2021 function; if convenient, the result should be placed in TARGET.
2022 SUBTARGET may be used as the target for computing one of EXP's operands. */
27d0c333 2023
53800dbe 2024static rtx
aecda0d6 2025expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
53800dbe 2026{
bf8e3599 2027 optab builtin_optab;
1e4adcfc 2028 rtx op0, insns;
c6e6ecb1 2029 tree fndecl = get_callee_fndecl (exp);
7f05340e 2030 enum machine_mode mode;
528ee710 2031 bool errno_set = false;
d6a0a4b0 2032 bool try_widening = false;
abfea505 2033 tree arg;
53800dbe 2034
c2f47e15 2035 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2036 return NULL_RTX;
53800dbe 2037
c2f47e15 2038 arg = CALL_EXPR_ARG (exp, 0);
53800dbe 2039
2040 switch (DECL_FUNCTION_CODE (fndecl))
2041 {
4f35b1fc 2042 CASE_FLT_FN (BUILT_IN_SQRT):
7f05340e 2043 errno_set = ! tree_expr_nonnegative_p (arg);
d6a0a4b0 2044 try_widening = true;
7f05340e 2045 builtin_optab = sqrt_optab;
2046 break;
4f35b1fc 2047 CASE_FLT_FN (BUILT_IN_EXP):
528ee710 2048 errno_set = true; builtin_optab = exp_optab; break;
4f35b1fc 2049 CASE_FLT_FN (BUILT_IN_EXP10):
2050 CASE_FLT_FN (BUILT_IN_POW10):
750ef9f5 2051 errno_set = true; builtin_optab = exp10_optab; break;
4f35b1fc 2052 CASE_FLT_FN (BUILT_IN_EXP2):
750ef9f5 2053 errno_set = true; builtin_optab = exp2_optab; break;
4f35b1fc 2054 CASE_FLT_FN (BUILT_IN_EXPM1):
a6b4eed2 2055 errno_set = true; builtin_optab = expm1_optab; break;
4f35b1fc 2056 CASE_FLT_FN (BUILT_IN_LOGB):
4efbc641 2057 errno_set = true; builtin_optab = logb_optab; break;
4f35b1fc 2058 CASE_FLT_FN (BUILT_IN_LOG):
528ee710 2059 errno_set = true; builtin_optab = log_optab; break;
4f35b1fc 2060 CASE_FLT_FN (BUILT_IN_LOG10):
d3cd9bde 2061 errno_set = true; builtin_optab = log10_optab; break;
4f35b1fc 2062 CASE_FLT_FN (BUILT_IN_LOG2):
d3cd9bde 2063 errno_set = true; builtin_optab = log2_optab; break;
4f35b1fc 2064 CASE_FLT_FN (BUILT_IN_LOG1P):
f474cd93 2065 errno_set = true; builtin_optab = log1p_optab; break;
4f35b1fc 2066 CASE_FLT_FN (BUILT_IN_ASIN):
8de2f465 2067 builtin_optab = asin_optab; break;
4f35b1fc 2068 CASE_FLT_FN (BUILT_IN_ACOS):
8de2f465 2069 builtin_optab = acos_optab; break;
4f35b1fc 2070 CASE_FLT_FN (BUILT_IN_TAN):
528ee710 2071 builtin_optab = tan_optab; break;
4f35b1fc 2072 CASE_FLT_FN (BUILT_IN_ATAN):
528ee710 2073 builtin_optab = atan_optab; break;
4f35b1fc 2074 CASE_FLT_FN (BUILT_IN_FLOOR):
528ee710 2075 builtin_optab = floor_optab; break;
4f35b1fc 2076 CASE_FLT_FN (BUILT_IN_CEIL):
528ee710 2077 builtin_optab = ceil_optab; break;
4f35b1fc 2078 CASE_FLT_FN (BUILT_IN_TRUNC):
a7cc195f 2079 builtin_optab = btrunc_optab; break;
4f35b1fc 2080 CASE_FLT_FN (BUILT_IN_ROUND):
528ee710 2081 builtin_optab = round_optab; break;
4f35b1fc 2082 CASE_FLT_FN (BUILT_IN_NEARBYINT):
0ddf4ad9 2083 builtin_optab = nearbyint_optab;
2084 if (flag_trapping_math)
2085 break;
2086 /* Else fallthrough and expand as rint. */
4f35b1fc 2087 CASE_FLT_FN (BUILT_IN_RINT):
aef94a0f 2088 builtin_optab = rint_optab; break;
b3154a1f 2089 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
2090 builtin_optab = significand_optab; break;
42721db0 2091 default:
64db345d 2092 gcc_unreachable ();
53800dbe 2093 }
2094
7f05340e 2095 /* Make a suitable register to place result in. */
2096 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2097
7f05340e 2098 if (! flag_errno_math || ! HONOR_NANS (mode))
2099 errno_set = false;
2100
d6a0a4b0 2101 /* Before working hard, check whether the instruction is available, but try
2102 to widen the mode for specific operations. */
2103 if ((optab_handler (builtin_optab, mode) != CODE_FOR_nothing
2104 || (try_widening && !excess_precision_type (TREE_TYPE (exp))))
f2aca212 2105 && (!errno_set || !optimize_insn_for_size_p ()))
68e6cb9d 2106 {
de2e453e 2107 rtx result = gen_reg_rtx (mode);
7f05340e 2108
bd421108 2109 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2110 need to expand the argument again. This way, we will not perform
2111 side-effects more the once. */
abfea505 2112 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7f05340e 2113
1db6d067 2114 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
7f05340e 2115
bd421108 2116 start_sequence ();
53800dbe 2117
de2e453e 2118 /* Compute into RESULT.
2119 Set RESULT to wherever the result comes back. */
2120 result = expand_unop (mode, builtin_optab, op0, result, 0);
bd421108 2121
de2e453e 2122 if (result != 0)
bd421108 2123 {
2124 if (errno_set)
de2e453e 2125 expand_errno_check (exp, result);
bd421108 2126
2127 /* Output the entire sequence. */
2128 insns = get_insns ();
2129 end_sequence ();
2130 emit_insn (insns);
de2e453e 2131 return result;
bd421108 2132 }
2133
2134 /* If we were unable to expand via the builtin, stop the sequence
2135 (without outputting the insns) and call to the library function
2136 with the stabilized argument list. */
53800dbe 2137 end_sequence ();
53800dbe 2138 }
2139
1e5b92fa 2140 return expand_call (exp, target, target == const0_rtx);
0fd605a5 2141}
2142
2143/* Expand a call to the builtin binary math functions (pow and atan2).
c2f47e15 2144 Return NULL_RTX if a normal call should be emitted rather than expanding the
0fd605a5 2145 function in-line. EXP is the expression that is a call to the builtin
2146 function; if convenient, the result should be placed in TARGET.
2147 SUBTARGET may be used as the target for computing one of EXP's
2148 operands. */
2149
2150static rtx
aecda0d6 2151expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
0fd605a5 2152{
2153 optab builtin_optab;
de2e453e 2154 rtx op0, op1, insns, result;
4737caf2 2155 int op1_type = REAL_TYPE;
c6e6ecb1 2156 tree fndecl = get_callee_fndecl (exp);
abfea505 2157 tree arg0, arg1;
7f05340e 2158 enum machine_mode mode;
0fd605a5 2159 bool errno_set = true;
0fd605a5 2160
73a954a1 2161 switch (DECL_FUNCTION_CODE (fndecl))
2162 {
2163 CASE_FLT_FN (BUILT_IN_SCALBN):
2164 CASE_FLT_FN (BUILT_IN_SCALBLN):
2165 CASE_FLT_FN (BUILT_IN_LDEXP):
2166 op1_type = INTEGER_TYPE;
2167 default:
2168 break;
2169 }
4737caf2 2170
c2f47e15 2171 if (!validate_arglist (exp, REAL_TYPE, op1_type, VOID_TYPE))
2172 return NULL_RTX;
0fd605a5 2173
c2f47e15 2174 arg0 = CALL_EXPR_ARG (exp, 0);
2175 arg1 = CALL_EXPR_ARG (exp, 1);
0fd605a5 2176
0fd605a5 2177 switch (DECL_FUNCTION_CODE (fndecl))
2178 {
4f35b1fc 2179 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 2180 builtin_optab = pow_optab; break;
4f35b1fc 2181 CASE_FLT_FN (BUILT_IN_ATAN2):
0fd605a5 2182 builtin_optab = atan2_optab; break;
73a954a1 2183 CASE_FLT_FN (BUILT_IN_SCALB):
2184 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2185 return 0;
2186 builtin_optab = scalb_optab; break;
2187 CASE_FLT_FN (BUILT_IN_SCALBN):
2188 CASE_FLT_FN (BUILT_IN_SCALBLN):
2189 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2190 return 0;
2191 /* Fall through... */
4f35b1fc 2192 CASE_FLT_FN (BUILT_IN_LDEXP):
4737caf2 2193 builtin_optab = ldexp_optab; break;
4f35b1fc 2194 CASE_FLT_FN (BUILT_IN_FMOD):
80ed5c06 2195 builtin_optab = fmod_optab; break;
ef722005 2196 CASE_FLT_FN (BUILT_IN_REMAINDER):
4f35b1fc 2197 CASE_FLT_FN (BUILT_IN_DREM):
ef722005 2198 builtin_optab = remainder_optab; break;
0fd605a5 2199 default:
64db345d 2200 gcc_unreachable ();
0fd605a5 2201 }
2202
7f05340e 2203 /* Make a suitable register to place result in. */
2204 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2205
2206 /* Before working hard, check whether the instruction is available. */
d6bf3b14 2207 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
c2f47e15 2208 return NULL_RTX;
fc4eef90 2209
de2e453e 2210 result = gen_reg_rtx (mode);
7f05340e 2211
2212 if (! flag_errno_math || ! HONOR_NANS (mode))
2213 errno_set = false;
2214
f2aca212 2215 if (errno_set && optimize_insn_for_size_p ())
2216 return 0;
2217
4ee9c684 2218 /* Always stabilize the argument list. */
abfea505 2219 CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
2220 CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
7f05340e 2221
8ec3c5c2 2222 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2223 op1 = expand_normal (arg1);
7f05340e 2224
7f05340e 2225 start_sequence ();
2226
de2e453e 2227 /* Compute into RESULT.
2228 Set RESULT to wherever the result comes back. */
2229 result = expand_binop (mode, builtin_optab, op0, op1,
2230 result, 0, OPTAB_DIRECT);
53800dbe 2231
68e6cb9d 2232 /* If we were unable to expand via the builtin, stop the sequence
2233 (without outputting the insns) and call to the library function
2234 with the stabilized argument list. */
de2e453e 2235 if (result == 0)
0fd605a5 2236 {
2237 end_sequence ();
68e6cb9d 2238 return expand_call (exp, target, target == const0_rtx);
53800dbe 2239 }
2240
a4356fb9 2241 if (errno_set)
de2e453e 2242 expand_errno_check (exp, result);
0fd605a5 2243
53800dbe 2244 /* Output the entire sequence. */
2245 insns = get_insns ();
2246 end_sequence ();
31d3e01c 2247 emit_insn (insns);
bf8e3599 2248
de2e453e 2249 return result;
53800dbe 2250}
2251
7e0713b1 2252/* Expand a call to the builtin trinary math functions (fma).
2253 Return NULL_RTX if a normal call should be emitted rather than expanding the
2254 function in-line. EXP is the expression that is a call to the builtin
2255 function; if convenient, the result should be placed in TARGET.
2256 SUBTARGET may be used as the target for computing one of EXP's
2257 operands. */
2258
2259static rtx
2260expand_builtin_mathfn_ternary (tree exp, rtx target, rtx subtarget)
2261{
2262 optab builtin_optab;
de2e453e 2263 rtx op0, op1, op2, insns, result;
7e0713b1 2264 tree fndecl = get_callee_fndecl (exp);
2265 tree arg0, arg1, arg2;
2266 enum machine_mode mode;
2267
2268 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2269 return NULL_RTX;
2270
2271 arg0 = CALL_EXPR_ARG (exp, 0);
2272 arg1 = CALL_EXPR_ARG (exp, 1);
2273 arg2 = CALL_EXPR_ARG (exp, 2);
2274
2275 switch (DECL_FUNCTION_CODE (fndecl))
2276 {
2277 CASE_FLT_FN (BUILT_IN_FMA):
2278 builtin_optab = fma_optab; break;
2279 default:
2280 gcc_unreachable ();
2281 }
2282
2283 /* Make a suitable register to place result in. */
2284 mode = TYPE_MODE (TREE_TYPE (exp));
2285
2286 /* Before working hard, check whether the instruction is available. */
2287 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
2288 return NULL_RTX;
2289
de2e453e 2290 result = gen_reg_rtx (mode);
7e0713b1 2291
2292 /* Always stabilize the argument list. */
2293 CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
2294 CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
2295 CALL_EXPR_ARG (exp, 2) = arg2 = builtin_save_expr (arg2);
2296
2297 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2298 op1 = expand_normal (arg1);
2299 op2 = expand_normal (arg2);
2300
2301 start_sequence ();
2302
de2e453e 2303 /* Compute into RESULT.
2304 Set RESULT to wherever the result comes back. */
2305 result = expand_ternary_op (mode, builtin_optab, op0, op1, op2,
2306 result, 0);
7e0713b1 2307
2308 /* If we were unable to expand via the builtin, stop the sequence
2309 (without outputting the insns) and call to the library function
2310 with the stabilized argument list. */
de2e453e 2311 if (result == 0)
7e0713b1 2312 {
2313 end_sequence ();
2314 return expand_call (exp, target, target == const0_rtx);
2315 }
2316
2317 /* Output the entire sequence. */
2318 insns = get_insns ();
2319 end_sequence ();
2320 emit_insn (insns);
2321
de2e453e 2322 return result;
7e0713b1 2323}
2324
6b43bae4 2325/* Expand a call to the builtin sin and cos math functions.
c2f47e15 2326 Return NULL_RTX if a normal call should be emitted rather than expanding the
6b43bae4 2327 function in-line. EXP is the expression that is a call to the builtin
2328 function; if convenient, the result should be placed in TARGET.
2329 SUBTARGET may be used as the target for computing one of EXP's
2330 operands. */
2331
2332static rtx
2333expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
2334{
2335 optab builtin_optab;
7511b819 2336 rtx op0, insns;
6b43bae4 2337 tree fndecl = get_callee_fndecl (exp);
6b43bae4 2338 enum machine_mode mode;
abfea505 2339 tree arg;
6b43bae4 2340
c2f47e15 2341 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2342 return NULL_RTX;
6b43bae4 2343
c2f47e15 2344 arg = CALL_EXPR_ARG (exp, 0);
6b43bae4 2345
2346 switch (DECL_FUNCTION_CODE (fndecl))
2347 {
4f35b1fc 2348 CASE_FLT_FN (BUILT_IN_SIN):
2349 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2350 builtin_optab = sincos_optab; break;
2351 default:
64db345d 2352 gcc_unreachable ();
6b43bae4 2353 }
2354
2355 /* Make a suitable register to place result in. */
2356 mode = TYPE_MODE (TREE_TYPE (exp));
2357
6b43bae4 2358 /* Check if sincos insn is available, otherwise fallback
0bed3869 2359 to sin or cos insn. */
d6bf3b14 2360 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
6b43bae4 2361 switch (DECL_FUNCTION_CODE (fndecl))
2362 {
4f35b1fc 2363 CASE_FLT_FN (BUILT_IN_SIN):
6b43bae4 2364 builtin_optab = sin_optab; break;
4f35b1fc 2365 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2366 builtin_optab = cos_optab; break;
2367 default:
64db345d 2368 gcc_unreachable ();
6b43bae4 2369 }
6b43bae4 2370
2371 /* Before working hard, check whether the instruction is available. */
d6bf3b14 2372 if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing)
6b43bae4 2373 {
de2e453e 2374 rtx result = gen_reg_rtx (mode);
6b43bae4 2375
2376 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2377 need to expand the argument again. This way, we will not perform
2378 side-effects more the once. */
abfea505 2379 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
6b43bae4 2380
1db6d067 2381 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
6b43bae4 2382
6b43bae4 2383 start_sequence ();
2384
de2e453e 2385 /* Compute into RESULT.
2386 Set RESULT to wherever the result comes back. */
6b43bae4 2387 if (builtin_optab == sincos_optab)
2388 {
de2e453e 2389 int ok;
7d3f6cc7 2390
6b43bae4 2391 switch (DECL_FUNCTION_CODE (fndecl))
2392 {
4f35b1fc 2393 CASE_FLT_FN (BUILT_IN_SIN):
de2e453e 2394 ok = expand_twoval_unop (builtin_optab, op0, 0, result, 0);
6b43bae4 2395 break;
4f35b1fc 2396 CASE_FLT_FN (BUILT_IN_COS):
de2e453e 2397 ok = expand_twoval_unop (builtin_optab, op0, result, 0, 0);
6b43bae4 2398 break;
2399 default:
64db345d 2400 gcc_unreachable ();
6b43bae4 2401 }
de2e453e 2402 gcc_assert (ok);
6b43bae4 2403 }
2404 else
de2e453e 2405 result = expand_unop (mode, builtin_optab, op0, result, 0);
6b43bae4 2406
de2e453e 2407 if (result != 0)
6b43bae4 2408 {
6b43bae4 2409 /* Output the entire sequence. */
2410 insns = get_insns ();
2411 end_sequence ();
2412 emit_insn (insns);
de2e453e 2413 return result;
6b43bae4 2414 }
2415
2416 /* If we were unable to expand via the builtin, stop the sequence
2417 (without outputting the insns) and call to the library function
2418 with the stabilized argument list. */
2419 end_sequence ();
2420 }
2421
de2e453e 2422 return expand_call (exp, target, target == const0_rtx);
6b43bae4 2423}
2424
a65c4d64 2425/* Given an interclass math builtin decl FNDECL and it's argument ARG
2426 return an RTL instruction code that implements the functionality.
2427 If that isn't possible or available return CODE_FOR_nothing. */
a67a90e5 2428
a65c4d64 2429static enum insn_code
2430interclass_mathfn_icode (tree arg, tree fndecl)
a67a90e5 2431{
a65c4d64 2432 bool errno_set = false;
6cdd383a 2433 optab builtin_optab = unknown_optab;
a67a90e5 2434 enum machine_mode mode;
a67a90e5 2435
2436 switch (DECL_FUNCTION_CODE (fndecl))
2437 {
2438 CASE_FLT_FN (BUILT_IN_ILOGB):
2439 errno_set = true; builtin_optab = ilogb_optab; break;
69b779ea 2440 CASE_FLT_FN (BUILT_IN_ISINF):
2441 builtin_optab = isinf_optab; break;
8a1a9cb7 2442 case BUILT_IN_ISNORMAL:
cde061c1 2443 case BUILT_IN_ISFINITE:
2444 CASE_FLT_FN (BUILT_IN_FINITE):
a65c4d64 2445 case BUILT_IN_FINITED32:
2446 case BUILT_IN_FINITED64:
2447 case BUILT_IN_FINITED128:
2448 case BUILT_IN_ISINFD32:
2449 case BUILT_IN_ISINFD64:
2450 case BUILT_IN_ISINFD128:
cde061c1 2451 /* These builtins have no optabs (yet). */
2452 break;
a67a90e5 2453 default:
2454 gcc_unreachable ();
2455 }
2456
2457 /* There's no easy way to detect the case we need to set EDOM. */
2458 if (flag_errno_math && errno_set)
a65c4d64 2459 return CODE_FOR_nothing;
a67a90e5 2460
2461 /* Optab mode depends on the mode of the input argument. */
2462 mode = TYPE_MODE (TREE_TYPE (arg));
2463
cde061c1 2464 if (builtin_optab)
d6bf3b14 2465 return optab_handler (builtin_optab, mode);
a65c4d64 2466 return CODE_FOR_nothing;
2467}
2468
2469/* Expand a call to one of the builtin math functions that operate on
2470 floating point argument and output an integer result (ilogb, isinf,
2471 isnan, etc).
2472 Return 0 if a normal call should be emitted rather than expanding the
2473 function in-line. EXP is the expression that is a call to the builtin
f97eea22 2474 function; if convenient, the result should be placed in TARGET. */
a65c4d64 2475
2476static rtx
f97eea22 2477expand_builtin_interclass_mathfn (tree exp, rtx target)
a65c4d64 2478{
2479 enum insn_code icode = CODE_FOR_nothing;
2480 rtx op0;
2481 tree fndecl = get_callee_fndecl (exp);
2482 enum machine_mode mode;
2483 tree arg;
2484
2485 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2486 return NULL_RTX;
2487
2488 arg = CALL_EXPR_ARG (exp, 0);
2489 icode = interclass_mathfn_icode (arg, fndecl);
2490 mode = TYPE_MODE (TREE_TYPE (arg));
2491
a67a90e5 2492 if (icode != CODE_FOR_nothing)
2493 {
8786db1e 2494 struct expand_operand ops[1];
4e2a2fb4 2495 rtx last = get_last_insn ();
2496 tree orig_arg = arg;
a67a90e5 2497
2498 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2499 need to expand the argument again. This way, we will not perform
2500 side-effects more the once. */
abfea505 2501 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
a67a90e5 2502
f97eea22 2503 op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
a67a90e5 2504
2505 if (mode != GET_MODE (op0))
2506 op0 = convert_to_mode (mode, op0, 0);
2507
8786db1e 2508 create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
2509 if (maybe_legitimize_operands (icode, 0, 1, ops)
2510 && maybe_emit_unop_insn (icode, ops[0].value, op0, UNKNOWN))
2511 return ops[0].value;
2512
4e2a2fb4 2513 delete_insns_since (last);
2514 CALL_EXPR_ARG (exp, 0) = orig_arg;
a67a90e5 2515 }
2516
a65c4d64 2517 return NULL_RTX;
a67a90e5 2518}
2519
c3147c1a 2520/* Expand a call to the builtin sincos math function.
c2f47e15 2521 Return NULL_RTX if a normal call should be emitted rather than expanding the
c3147c1a 2522 function in-line. EXP is the expression that is a call to the builtin
2523 function. */
2524
2525static rtx
2526expand_builtin_sincos (tree exp)
2527{
2528 rtx op0, op1, op2, target1, target2;
c3147c1a 2529 enum machine_mode mode;
2530 tree arg, sinp, cosp;
2531 int result;
389dd41b 2532 location_t loc = EXPR_LOCATION (exp);
be5575b2 2533 tree alias_type, alias_off;
c3147c1a 2534
c2f47e15 2535 if (!validate_arglist (exp, REAL_TYPE,
2536 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2537 return NULL_RTX;
c3147c1a 2538
c2f47e15 2539 arg = CALL_EXPR_ARG (exp, 0);
2540 sinp = CALL_EXPR_ARG (exp, 1);
2541 cosp = CALL_EXPR_ARG (exp, 2);
c3147c1a 2542
2543 /* Make a suitable register to place result in. */
2544 mode = TYPE_MODE (TREE_TYPE (arg));
2545
2546 /* Check if sincos insn is available, otherwise emit the call. */
d6bf3b14 2547 if (optab_handler (sincos_optab, mode) == CODE_FOR_nothing)
c3147c1a 2548 return NULL_RTX;
2549
2550 target1 = gen_reg_rtx (mode);
2551 target2 = gen_reg_rtx (mode);
2552
8ec3c5c2 2553 op0 = expand_normal (arg);
be5575b2 2554 alias_type = build_pointer_type_for_mode (TREE_TYPE (arg), ptr_mode, true);
2555 alias_off = build_int_cst (alias_type, 0);
2556 op1 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
2557 sinp, alias_off));
2558 op2 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
2559 cosp, alias_off));
c3147c1a 2560
2561 /* Compute into target1 and target2.
2562 Set TARGET to wherever the result comes back. */
2563 result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
2564 gcc_assert (result);
2565
2566 /* Move target1 and target2 to the memory locations indicated
2567 by op1 and op2. */
2568 emit_move_insn (op1, target1);
2569 emit_move_insn (op2, target2);
2570
2571 return const0_rtx;
2572}
2573
d735c391 2574/* Expand a call to the internal cexpi builtin to the sincos math function.
2575 EXP is the expression that is a call to the builtin function; if convenient,
f97eea22 2576 the result should be placed in TARGET. */
d735c391 2577
2578static rtx
f97eea22 2579expand_builtin_cexpi (tree exp, rtx target)
d735c391 2580{
2581 tree fndecl = get_callee_fndecl (exp);
d735c391 2582 tree arg, type;
c2f47e15 2583 enum machine_mode mode;
d735c391 2584 rtx op0, op1, op2;
389dd41b 2585 location_t loc = EXPR_LOCATION (exp);
d735c391 2586
c2f47e15 2587 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2588 return NULL_RTX;
d735c391 2589
c2f47e15 2590 arg = CALL_EXPR_ARG (exp, 0);
d735c391 2591 type = TREE_TYPE (arg);
2592 mode = TYPE_MODE (TREE_TYPE (arg));
2593
2594 /* Try expanding via a sincos optab, fall back to emitting a libcall
18b8d8ae 2595 to sincos or cexp. We are sure we have sincos or cexp because cexpi
2596 is only generated from sincos, cexp or if we have either of them. */
d6bf3b14 2597 if (optab_handler (sincos_optab, mode) != CODE_FOR_nothing)
d735c391 2598 {
2599 op1 = gen_reg_rtx (mode);
2600 op2 = gen_reg_rtx (mode);
2601
f97eea22 2602 op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
d735c391 2603
2604 /* Compute into op1 and op2. */
2605 expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
2606 }
30f690e0 2607 else if (targetm.libc_has_function (function_sincos))
d735c391 2608 {
c2f47e15 2609 tree call, fn = NULL_TREE;
d735c391 2610 tree top1, top2;
2611 rtx op1a, op2a;
2612
2613 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
b9a16870 2614 fn = builtin_decl_explicit (BUILT_IN_SINCOSF);
d735c391 2615 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
b9a16870 2616 fn = builtin_decl_explicit (BUILT_IN_SINCOS);
d735c391 2617 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
b9a16870 2618 fn = builtin_decl_explicit (BUILT_IN_SINCOSL);
c2f47e15 2619 else
2620 gcc_unreachable ();
48e1416a 2621
0ab48139 2622 op1 = assign_temp (TREE_TYPE (arg), 1, 1);
2623 op2 = assign_temp (TREE_TYPE (arg), 1, 1);
99182918 2624 op1a = copy_addr_to_reg (XEXP (op1, 0));
2625 op2a = copy_addr_to_reg (XEXP (op2, 0));
d735c391 2626 top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
2627 top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
2628
d735c391 2629 /* Make sure not to fold the sincos call again. */
2630 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
c2f47e15 2631 expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
2632 call, 3, arg, top1, top2));
d735c391 2633 }
18b8d8ae 2634 else
2635 {
0ecbc158 2636 tree call, fn = NULL_TREE, narg;
18b8d8ae 2637 tree ctype = build_complex_type (type);
2638
0ecbc158 2639 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
b9a16870 2640 fn = builtin_decl_explicit (BUILT_IN_CEXPF);
0ecbc158 2641 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
b9a16870 2642 fn = builtin_decl_explicit (BUILT_IN_CEXP);
0ecbc158 2643 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
b9a16870 2644 fn = builtin_decl_explicit (BUILT_IN_CEXPL);
c2f47e15 2645 else
2646 gcc_unreachable ();
fc0dfa6e 2647
2648 /* If we don't have a decl for cexp create one. This is the
2649 friendliest fallback if the user calls __builtin_cexpi
2650 without full target C99 function support. */
2651 if (fn == NULL_TREE)
2652 {
2653 tree fntype;
2654 const char *name = NULL;
2655
2656 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2657 name = "cexpf";
2658 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2659 name = "cexp";
2660 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2661 name = "cexpl";
2662
2663 fntype = build_function_type_list (ctype, ctype, NULL_TREE);
2664 fn = build_fn_decl (name, fntype);
2665 }
2666
389dd41b 2667 narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype,
18b8d8ae 2668 build_real (type, dconst0), arg);
2669
2670 /* Make sure not to fold the cexp call again. */
2671 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
48e1416a 2672 return expand_expr (build_call_nary (ctype, call, 1, narg),
1db6d067 2673 target, VOIDmode, EXPAND_NORMAL);
18b8d8ae 2674 }
d735c391 2675
2676 /* Now build the proper return type. */
2677 return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
2678 make_tree (TREE_TYPE (arg), op2),
2679 make_tree (TREE_TYPE (arg), op1)),
1db6d067 2680 target, VOIDmode, EXPAND_NORMAL);
d735c391 2681}
2682
a65c4d64 2683/* Conveniently construct a function call expression. FNDECL names the
2684 function to be called, N is the number of arguments, and the "..."
2685 parameters are the argument expressions. Unlike build_call_exr
2686 this doesn't fold the call, hence it will always return a CALL_EXPR. */
2687
2688static tree
2689build_call_nofold_loc (location_t loc, tree fndecl, int n, ...)
2690{
2691 va_list ap;
2692 tree fntype = TREE_TYPE (fndecl);
2693 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
2694
2695 va_start (ap, n);
2696 fn = build_call_valist (TREE_TYPE (fntype), fn, n, ap);
2697 va_end (ap);
2698 SET_EXPR_LOCATION (fn, loc);
2699 return fn;
2700}
a65c4d64 2701
7d3afc77 2702/* Expand a call to one of the builtin rounding functions gcc defines
2703 as an extension (lfloor and lceil). As these are gcc extensions we
2704 do not need to worry about setting errno to EDOM.
ad52b9b7 2705 If expanding via optab fails, lower expression to (int)(floor(x)).
2706 EXP is the expression that is a call to the builtin function;
ff1b14e4 2707 if convenient, the result should be placed in TARGET. */
ad52b9b7 2708
2709static rtx
ff1b14e4 2710expand_builtin_int_roundingfn (tree exp, rtx target)
ad52b9b7 2711{
9c42dd28 2712 convert_optab builtin_optab;
ad52b9b7 2713 rtx op0, insns, tmp;
2714 tree fndecl = get_callee_fndecl (exp);
ad52b9b7 2715 enum built_in_function fallback_fn;
2716 tree fallback_fndecl;
2717 enum machine_mode mode;
4de0924f 2718 tree arg;
ad52b9b7 2719
c2f47e15 2720 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
ad52b9b7 2721 gcc_unreachable ();
2722
c2f47e15 2723 arg = CALL_EXPR_ARG (exp, 0);
ad52b9b7 2724
2725 switch (DECL_FUNCTION_CODE (fndecl))
2726 {
80ff6494 2727 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 2728 CASE_FLT_FN (BUILT_IN_LCEIL):
2729 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 2730 builtin_optab = lceil_optab;
2731 fallback_fn = BUILT_IN_CEIL;
2732 break;
2733
80ff6494 2734 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 2735 CASE_FLT_FN (BUILT_IN_LFLOOR):
2736 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 2737 builtin_optab = lfloor_optab;
2738 fallback_fn = BUILT_IN_FLOOR;
2739 break;
2740
2741 default:
2742 gcc_unreachable ();
2743 }
2744
2745 /* Make a suitable register to place result in. */
2746 mode = TYPE_MODE (TREE_TYPE (exp));
2747
9c42dd28 2748 target = gen_reg_rtx (mode);
ad52b9b7 2749
9c42dd28 2750 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2751 need to expand the argument again. This way, we will not perform
2752 side-effects more the once. */
abfea505 2753 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
ad52b9b7 2754
ff1b14e4 2755 op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
ad52b9b7 2756
9c42dd28 2757 start_sequence ();
ad52b9b7 2758
9c42dd28 2759 /* Compute into TARGET. */
2760 if (expand_sfix_optab (target, op0, builtin_optab))
2761 {
2762 /* Output the entire sequence. */
2763 insns = get_insns ();
ad52b9b7 2764 end_sequence ();
9c42dd28 2765 emit_insn (insns);
2766 return target;
ad52b9b7 2767 }
2768
9c42dd28 2769 /* If we were unable to expand via the builtin, stop the sequence
2770 (without outputting the insns). */
2771 end_sequence ();
2772
ad52b9b7 2773 /* Fall back to floating point rounding optab. */
2774 fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
fc0dfa6e 2775
2776 /* For non-C99 targets we may end up without a fallback fndecl here
2777 if the user called __builtin_lfloor directly. In this case emit
2778 a call to the floor/ceil variants nevertheless. This should result
2779 in the best user experience for not full C99 targets. */
2780 if (fallback_fndecl == NULL_TREE)
2781 {
2782 tree fntype;
2783 const char *name = NULL;
2784
2785 switch (DECL_FUNCTION_CODE (fndecl))
2786 {
80ff6494 2787 case BUILT_IN_ICEIL:
fc0dfa6e 2788 case BUILT_IN_LCEIL:
2789 case BUILT_IN_LLCEIL:
2790 name = "ceil";
2791 break;
80ff6494 2792 case BUILT_IN_ICEILF:
fc0dfa6e 2793 case BUILT_IN_LCEILF:
2794 case BUILT_IN_LLCEILF:
2795 name = "ceilf";
2796 break;
80ff6494 2797 case BUILT_IN_ICEILL:
fc0dfa6e 2798 case BUILT_IN_LCEILL:
2799 case BUILT_IN_LLCEILL:
2800 name = "ceill";
2801 break;
80ff6494 2802 case BUILT_IN_IFLOOR:
fc0dfa6e 2803 case BUILT_IN_LFLOOR:
2804 case BUILT_IN_LLFLOOR:
2805 name = "floor";
2806 break;
80ff6494 2807 case BUILT_IN_IFLOORF:
fc0dfa6e 2808 case BUILT_IN_LFLOORF:
2809 case BUILT_IN_LLFLOORF:
2810 name = "floorf";
2811 break;
80ff6494 2812 case BUILT_IN_IFLOORL:
fc0dfa6e 2813 case BUILT_IN_LFLOORL:
2814 case BUILT_IN_LLFLOORL:
2815 name = "floorl";
2816 break;
2817 default:
2818 gcc_unreachable ();
2819 }
2820
2821 fntype = build_function_type_list (TREE_TYPE (arg),
2822 TREE_TYPE (arg), NULL_TREE);
2823 fallback_fndecl = build_fn_decl (name, fntype);
2824 }
2825
0568e9c1 2826 exp = build_call_nofold_loc (EXPR_LOCATION (exp), fallback_fndecl, 1, arg);
ad52b9b7 2827
d4c690af 2828 tmp = expand_normal (exp);
933eb13a 2829 tmp = maybe_emit_group_store (tmp, TREE_TYPE (exp));
ad52b9b7 2830
2831 /* Truncate the result of floating point optab to integer
2832 via expand_fix (). */
2833 target = gen_reg_rtx (mode);
2834 expand_fix (target, tmp, 0);
2835
2836 return target;
2837}
2838
7d3afc77 2839/* Expand a call to one of the builtin math functions doing integer
2840 conversion (lrint).
2841 Return 0 if a normal call should be emitted rather than expanding the
2842 function in-line. EXP is the expression that is a call to the builtin
ff1b14e4 2843 function; if convenient, the result should be placed in TARGET. */
7d3afc77 2844
2845static rtx
ff1b14e4 2846expand_builtin_int_roundingfn_2 (tree exp, rtx target)
7d3afc77 2847{
5f51ee59 2848 convert_optab builtin_optab;
7d3afc77 2849 rtx op0, insns;
2850 tree fndecl = get_callee_fndecl (exp);
4de0924f 2851 tree arg;
c2f47e15 2852 enum machine_mode mode;
e951f9a4 2853 enum built_in_function fallback_fn = BUILT_IN_NONE;
7d3afc77 2854
c2f47e15 2855 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2856 gcc_unreachable ();
48e1416a 2857
c2f47e15 2858 arg = CALL_EXPR_ARG (exp, 0);
7d3afc77 2859
2860 switch (DECL_FUNCTION_CODE (fndecl))
2861 {
80ff6494 2862 CASE_FLT_FN (BUILT_IN_IRINT):
e951f9a4 2863 fallback_fn = BUILT_IN_LRINT;
2864 /* FALLTHRU */
7d3afc77 2865 CASE_FLT_FN (BUILT_IN_LRINT):
2866 CASE_FLT_FN (BUILT_IN_LLRINT):
e951f9a4 2867 builtin_optab = lrint_optab;
2868 break;
80ff6494 2869
2870 CASE_FLT_FN (BUILT_IN_IROUND):
e951f9a4 2871 fallback_fn = BUILT_IN_LROUND;
2872 /* FALLTHRU */
ef2f1a10 2873 CASE_FLT_FN (BUILT_IN_LROUND):
2874 CASE_FLT_FN (BUILT_IN_LLROUND):
e951f9a4 2875 builtin_optab = lround_optab;
2876 break;
80ff6494 2877
7d3afc77 2878 default:
2879 gcc_unreachable ();
2880 }
2881
e951f9a4 2882 /* There's no easy way to detect the case we need to set EDOM. */
2883 if (flag_errno_math && fallback_fn == BUILT_IN_NONE)
2884 return NULL_RTX;
2885
7d3afc77 2886 /* Make a suitable register to place result in. */
2887 mode = TYPE_MODE (TREE_TYPE (exp));
2888
e951f9a4 2889 /* There's no easy way to detect the case we need to set EDOM. */
2890 if (!flag_errno_math)
2891 {
de2e453e 2892 rtx result = gen_reg_rtx (mode);
7d3afc77 2893
e951f9a4 2894 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2895 need to expand the argument again. This way, we will not perform
2896 side-effects more the once. */
2897 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7d3afc77 2898
e951f9a4 2899 op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
7d3afc77 2900
e951f9a4 2901 start_sequence ();
7d3afc77 2902
de2e453e 2903 if (expand_sfix_optab (result, op0, builtin_optab))
e951f9a4 2904 {
2905 /* Output the entire sequence. */
2906 insns = get_insns ();
2907 end_sequence ();
2908 emit_insn (insns);
de2e453e 2909 return result;
e951f9a4 2910 }
2911
2912 /* If we were unable to expand via the builtin, stop the sequence
2913 (without outputting the insns) and call to the library function
2914 with the stabilized argument list. */
7d3afc77 2915 end_sequence ();
2916 }
2917
e951f9a4 2918 if (fallback_fn != BUILT_IN_NONE)
2919 {
2920 /* Fall back to rounding to long int. Use implicit_p 0 - for non-C99
2921 targets, (int) round (x) should never be transformed into
2922 BUILT_IN_IROUND and if __builtin_iround is called directly, emit
2923 a call to lround in the hope that the target provides at least some
2924 C99 functions. This should result in the best user experience for
2925 not full C99 targets. */
2926 tree fallback_fndecl = mathfn_built_in_1 (TREE_TYPE (arg),
2927 fallback_fn, 0);
2928
2929 exp = build_call_nofold_loc (EXPR_LOCATION (exp),
2930 fallback_fndecl, 1, arg);
2931
2932 target = expand_call (exp, NULL_RTX, target == const0_rtx);
933eb13a 2933 target = maybe_emit_group_store (target, TREE_TYPE (exp));
e951f9a4 2934 return convert_to_mode (mode, target, 0);
2935 }
5f51ee59 2936
de2e453e 2937 return expand_call (exp, target, target == const0_rtx);
7d3afc77 2938}
2939
c2f47e15 2940/* Expand a call to the powi built-in mathematical function. Return NULL_RTX if
757c219d 2941 a normal call should be emitted rather than expanding the function
2942 in-line. EXP is the expression that is a call to the builtin
2943 function; if convenient, the result should be placed in TARGET. */
2944
2945static rtx
f97eea22 2946expand_builtin_powi (tree exp, rtx target)
757c219d 2947{
757c219d 2948 tree arg0, arg1;
2949 rtx op0, op1;
2950 enum machine_mode mode;
d0405f40 2951 enum machine_mode mode2;
757c219d 2952
c2f47e15 2953 if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
2954 return NULL_RTX;
757c219d 2955
c2f47e15 2956 arg0 = CALL_EXPR_ARG (exp, 0);
2957 arg1 = CALL_EXPR_ARG (exp, 1);
757c219d 2958 mode = TYPE_MODE (TREE_TYPE (exp));
2959
757c219d 2960 /* Emit a libcall to libgcc. */
2961
c2f47e15 2962 /* Mode of the 2nd argument must match that of an int. */
d0405f40 2963 mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
2964
757c219d 2965 if (target == NULL_RTX)
2966 target = gen_reg_rtx (mode);
2967
f97eea22 2968 op0 = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
757c219d 2969 if (GET_MODE (op0) != mode)
2970 op0 = convert_to_mode (mode, op0, 0);
1db6d067 2971 op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
d0405f40 2972 if (GET_MODE (op1) != mode2)
2973 op1 = convert_to_mode (mode2, op1, 0);
757c219d 2974
f36b9f69 2975 target = emit_library_call_value (optab_libfunc (powi_optab, mode),
2dd6f9ed 2976 target, LCT_CONST, mode, 2,
d0405f40 2977 op0, mode, op1, mode2);
757c219d 2978
2979 return target;
2980}
2981
48e1416a 2982/* Expand expression EXP which is a call to the strlen builtin. Return
c2f47e15 2983 NULL_RTX if we failed the caller should emit a normal call, otherwise
aed0bd19 2984 try to get the result in TARGET, if convenient. */
f7c44134 2985
53800dbe 2986static rtx
c2f47e15 2987expand_builtin_strlen (tree exp, rtx target,
aecda0d6 2988 enum machine_mode target_mode)
53800dbe 2989{
c2f47e15 2990 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2991 return NULL_RTX;
53800dbe 2992 else
2993 {
8786db1e 2994 struct expand_operand ops[4];
911c0150 2995 rtx pat;
c2f47e15 2996 tree len;
2997 tree src = CALL_EXPR_ARG (exp, 0);
8786db1e 2998 rtx src_reg, before_strlen;
2999 enum machine_mode insn_mode = target_mode;
ef2c4a29 3000 enum insn_code icode = CODE_FOR_nothing;
153c3b50 3001 unsigned int align;
6248e345 3002
3003 /* If the length can be computed at compile-time, return it. */
681fab1e 3004 len = c_strlen (src, 0);
6248e345 3005 if (len)
80cd7a5e 3006 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
6248e345 3007
681fab1e 3008 /* If the length can be computed at compile-time and is constant
3009 integer, but there are side-effects in src, evaluate
3010 src for side-effects, then return len.
3011 E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
3012 can be optimized into: i++; x = 3; */
3013 len = c_strlen (src, 1);
3014 if (len && TREE_CODE (len) == INTEGER_CST)
3015 {
3016 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
3017 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
3018 }
3019
957d0361 3020 align = get_pointer_alignment (src) / BITS_PER_UNIT;
53800dbe 3021
53800dbe 3022 /* If SRC is not a pointer type, don't do this operation inline. */
3023 if (align == 0)
c2f47e15 3024 return NULL_RTX;
53800dbe 3025
911c0150 3026 /* Bail out if we can't compute strlen in the right mode. */
53800dbe 3027 while (insn_mode != VOIDmode)
3028 {
d6bf3b14 3029 icode = optab_handler (strlen_optab, insn_mode);
53800dbe 3030 if (icode != CODE_FOR_nothing)
c28ae87f 3031 break;
53800dbe 3032
3033 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
3034 }
3035 if (insn_mode == VOIDmode)
c2f47e15 3036 return NULL_RTX;
53800dbe 3037
911c0150 3038 /* Make a place to hold the source address. We will not expand
3039 the actual source until we are sure that the expansion will
3040 not fail -- there are trees that cannot be expanded twice. */
3041 src_reg = gen_reg_rtx (Pmode);
53800dbe 3042
911c0150 3043 /* Mark the beginning of the strlen sequence so we can emit the
3044 source operand later. */
f0ce3b1f 3045 before_strlen = get_last_insn ();
53800dbe 3046
8786db1e 3047 create_output_operand (&ops[0], target, insn_mode);
3048 create_fixed_operand (&ops[1], gen_rtx_MEM (BLKmode, src_reg));
3049 create_integer_operand (&ops[2], 0);
3050 create_integer_operand (&ops[3], align);
3051 if (!maybe_expand_insn (icode, 4, ops))
c2f47e15 3052 return NULL_RTX;
911c0150 3053
3054 /* Now that we are assured of success, expand the source. */
3055 start_sequence ();
499eee58 3056 pat = expand_expr (src, src_reg, Pmode, EXPAND_NORMAL);
911c0150 3057 if (pat != src_reg)
499eee58 3058 {
3059#ifdef POINTERS_EXTEND_UNSIGNED
3060 if (GET_MODE (pat) != Pmode)
3061 pat = convert_to_mode (Pmode, pat,
3062 POINTERS_EXTEND_UNSIGNED);
3063#endif
3064 emit_move_insn (src_reg, pat);
3065 }
31d3e01c 3066 pat = get_insns ();
911c0150 3067 end_sequence ();
bceb0d1f 3068
3069 if (before_strlen)
3070 emit_insn_after (pat, before_strlen);
3071 else
3072 emit_insn_before (pat, get_insns ());
53800dbe 3073
3074 /* Return the value in the proper mode for this function. */
8786db1e 3075 if (GET_MODE (ops[0].value) == target_mode)
3076 target = ops[0].value;
53800dbe 3077 else if (target != 0)
8786db1e 3078 convert_move (target, ops[0].value, 0);
53800dbe 3079 else
8786db1e 3080 target = convert_to_mode (target_mode, ops[0].value, 0);
911c0150 3081
3082 return target;
53800dbe 3083 }
3084}
3085
6840589f 3086/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3087 bytes from constant string DATA + OFFSET and return it as target
3088 constant. */
3089
3090static rtx
aecda0d6 3091builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
3092 enum machine_mode mode)
6840589f 3093{
3094 const char *str = (const char *) data;
3095
64db345d 3096 gcc_assert (offset >= 0
3097 && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
3098 <= strlen (str) + 1));
6840589f 3099
3100 return c_readstr (str + offset, mode);
3101}
3102
36d63243 3103/* LEN specify length of the block of memcpy/memset operation.
9db0f34d 3104 Figure out its range and put it into MIN_SIZE/MAX_SIZE.
3105 In some cases we can make very likely guess on max size, then we
3106 set it into PROBABLE_MAX_SIZE. */
36d63243 3107
3108static void
3109determine_block_size (tree len, rtx len_rtx,
3110 unsigned HOST_WIDE_INT *min_size,
9db0f34d 3111 unsigned HOST_WIDE_INT *max_size,
3112 unsigned HOST_WIDE_INT *probable_max_size)
36d63243 3113{
3114 if (CONST_INT_P (len_rtx))
3115 {
3116 *min_size = *max_size = UINTVAL (len_rtx);
3117 return;
3118 }
3119 else
3120 {
3121 double_int min, max;
9db0f34d 3122 enum value_range_type range_type = VR_UNDEFINED;
3123
3124 /* Determine bounds from the type. */
3125 if (tree_fits_uhwi_p (TYPE_MIN_VALUE (TREE_TYPE (len))))
3126 *min_size = tree_to_uhwi (TYPE_MIN_VALUE (TREE_TYPE (len)));
3127 else
3128 *min_size = 0;
3129 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (TREE_TYPE (len))))
3130 *probable_max_size = *max_size = tree_to_uhwi (TYPE_MAX_VALUE (TREE_TYPE (len)));
3131 else
3132 *probable_max_size = *max_size = GET_MODE_MASK (GET_MODE (len_rtx));
3133
3134 if (TREE_CODE (len) == SSA_NAME)
3135 range_type = get_range_info (len, &min, &max);
3136 if (range_type == VR_RANGE)
36d63243 3137 {
9db0f34d 3138 if (min.fits_uhwi () && *min_size < min.to_uhwi ())
36d63243 3139 *min_size = min.to_uhwi ();
9db0f34d 3140 if (max.fits_uhwi () && *max_size > max.to_uhwi ())
3141 *probable_max_size = *max_size = max.to_uhwi ();
36d63243 3142 }
9db0f34d 3143 else if (range_type == VR_ANTI_RANGE)
36d63243 3144 {
9db0f34d 3145 /* Anti range 0...N lets us to determine minmal size to N+1. */
3146 if (min.is_zero ())
3147 {
3148 if ((max + double_int_one).fits_uhwi ())
3149 *min_size = (max + double_int_one).to_uhwi ();
3150 }
3151 /* Code like
3152
3153 int n;
3154 if (n < 100)
3155 memcpy (a,b, n)
3156
3157 Produce anti range allowing negative values of N. We still
3158 can use the information and make a guess that N is not negative.
3159 */
3160 else if (!max.ule (double_int_one.lshift (30))
3161 && min.fits_uhwi ())
3162 *probable_max_size = min.to_uhwi () - 1;
36d63243 3163 }
3164 }
3165 gcc_checking_assert (*max_size <=
3166 (unsigned HOST_WIDE_INT)
3167 GET_MODE_MASK (GET_MODE (len_rtx)));
3168}
3169
c2f47e15 3170/* Expand a call EXP to the memcpy builtin.
3171 Return NULL_RTX if we failed, the caller should emit a normal call,
3b824fa6 3172 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3173 mode MODE if that's convenient). */
c2f47e15 3174
53800dbe 3175static rtx
a65c4d64 3176expand_builtin_memcpy (tree exp, rtx target)
53800dbe 3177{
c2f47e15 3178 if (!validate_arglist (exp,
3179 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3180 return NULL_RTX;
53800dbe 3181 else
3182 {
c2f47e15 3183 tree dest = CALL_EXPR_ARG (exp, 0);
3184 tree src = CALL_EXPR_ARG (exp, 1);
3185 tree len = CALL_EXPR_ARG (exp, 2);
6840589f 3186 const char *src_str;
957d0361 3187 unsigned int src_align = get_pointer_alignment (src);
3188 unsigned int dest_align = get_pointer_alignment (dest);
53800dbe 3189 rtx dest_mem, src_mem, dest_addr, len_rtx;
162719b3 3190 HOST_WIDE_INT expected_size = -1;
3191 unsigned int expected_align = 0;
36d63243 3192 unsigned HOST_WIDE_INT min_size;
3193 unsigned HOST_WIDE_INT max_size;
9db0f34d 3194 unsigned HOST_WIDE_INT probable_max_size;
5a0de151 3195
6f428e8b 3196 /* If DEST is not a pointer type, call the normal function. */
3197 if (dest_align == 0)
c2f47e15 3198 return NULL_RTX;
6f428e8b 3199
6f428e8b 3200 /* If either SRC is not a pointer type, don't do this
a0c938f0 3201 operation in-line. */
6f428e8b 3202 if (src_align == 0)
c2f47e15 3203 return NULL_RTX;
48e1416a 3204
8cee8dc0 3205 if (currently_expanding_gimple_stmt)
3206 stringop_block_profile (currently_expanding_gimple_stmt,
3207 &expected_align, &expected_size);
75a70cf9 3208
162719b3 3209 if (expected_align < dest_align)
3210 expected_align = dest_align;
d8ae1baa 3211 dest_mem = get_memory_rtx (dest, len);
2a631e19 3212 set_mem_align (dest_mem, dest_align);
8ec3c5c2 3213 len_rtx = expand_normal (len);
9db0f34d 3214 determine_block_size (len, len_rtx, &min_size, &max_size,
3215 &probable_max_size);
6840589f 3216 src_str = c_getstr (src);
3217
3218 /* If SRC is a string constant and block move would be done
3219 by pieces, we can avoid loading the string from memory
3220 and only stored the computed constants. */
3221 if (src_str
971ba038 3222 && CONST_INT_P (len_rtx)
6840589f 3223 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3224 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3225 CONST_CAST (char *, src_str),
3226 dest_align, false))
6840589f 3227 {
9fe0e1b8 3228 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3229 builtin_memcpy_read_str,
364c0c59 3230 CONST_CAST (char *, src_str),
3231 dest_align, false, 0);
a65c4d64 3232 dest_mem = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3233 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3234 return dest_mem;
6840589f 3235 }
3236
d8ae1baa 3237 src_mem = get_memory_rtx (src, len);
2a631e19 3238 set_mem_align (src_mem, src_align);
53800dbe 3239
53800dbe 3240 /* Copy word part most expediently. */
162719b3 3241 dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
3242 CALL_EXPR_TAILCALL (exp)
3243 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
36d63243 3244 expected_align, expected_size,
9db0f34d 3245 min_size, max_size, probable_max_size);
53800dbe 3246
3247 if (dest_addr == 0)
e5716f7e 3248 {
a65c4d64 3249 dest_addr = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3250 dest_addr = convert_memory_address (ptr_mode, dest_addr);
e5716f7e 3251 }
9fe0e1b8 3252 return dest_addr;
53800dbe 3253 }
3254}
3255
c2f47e15 3256/* Expand a call EXP to the mempcpy builtin.
3257 Return NULL_RTX if we failed; the caller should emit a normal call,
647661c6 3258 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3259 mode MODE if that's convenient). If ENDP is 0 return the
3260 destination pointer, if ENDP is 1 return the end pointer ala
3261 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3262 stpcpy. */
647661c6 3263
3264static rtx
c8b17b2e 3265expand_builtin_mempcpy (tree exp, rtx target, enum machine_mode mode)
647661c6 3266{
c2f47e15 3267 if (!validate_arglist (exp,
3268 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3269 return NULL_RTX;
3270 else
3271 {
3272 tree dest = CALL_EXPR_ARG (exp, 0);
3273 tree src = CALL_EXPR_ARG (exp, 1);
3274 tree len = CALL_EXPR_ARG (exp, 2);
3275 return expand_builtin_mempcpy_args (dest, src, len,
c2f47e15 3276 target, mode, /*endp=*/ 1);
3277 }
3278}
3279
3280/* Helper function to do the actual work for expand_builtin_mempcpy. The
3281 arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out
3282 so that this can also be called without constructing an actual CALL_EXPR.
a65c4d64 3283 The other arguments and return value are the same as for
3284 expand_builtin_mempcpy. */
c2f47e15 3285
3286static rtx
a65c4d64 3287expand_builtin_mempcpy_args (tree dest, tree src, tree len,
c2f47e15 3288 rtx target, enum machine_mode mode, int endp)
3289{
3290 /* If return value is ignored, transform mempcpy into memcpy. */
b9a16870 3291 if (target == const0_rtx && builtin_decl_implicit_p (BUILT_IN_MEMCPY))
9fe0e1b8 3292 {
b9a16870 3293 tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
0568e9c1 3294 tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3,
3295 dest, src, len);
c8b17b2e 3296 return expand_expr (result, target, mode, EXPAND_NORMAL);
9fe0e1b8 3297 }
647661c6 3298 else
3299 {
9fe0e1b8 3300 const char *src_str;
957d0361 3301 unsigned int src_align = get_pointer_alignment (src);
3302 unsigned int dest_align = get_pointer_alignment (dest);
9fe0e1b8 3303 rtx dest_mem, src_mem, len_rtx;
a0c938f0 3304
7da1412b 3305 /* If either SRC or DEST is not a pointer type, don't do this
a0c938f0 3306 operation in-line. */
7da1412b 3307 if (dest_align == 0 || src_align == 0)
c2f47e15 3308 return NULL_RTX;
9fe0e1b8 3309
6217c238 3310 /* If LEN is not constant, call the normal function. */
cd4547bf 3311 if (! tree_fits_uhwi_p (len))
c2f47e15 3312 return NULL_RTX;
0862b7e9 3313
8ec3c5c2 3314 len_rtx = expand_normal (len);
9fe0e1b8 3315 src_str = c_getstr (src);
647661c6 3316
9fe0e1b8 3317 /* If SRC is a string constant and block move would be done
3318 by pieces, we can avoid loading the string from memory
3319 and only stored the computed constants. */
3320 if (src_str
971ba038 3321 && CONST_INT_P (len_rtx)
9fe0e1b8 3322 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3323 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3324 CONST_CAST (char *, src_str),
3325 dest_align, false))
9fe0e1b8 3326 {
d8ae1baa 3327 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3328 set_mem_align (dest_mem, dest_align);
3329 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3330 builtin_memcpy_read_str,
364c0c59 3331 CONST_CAST (char *, src_str),
3332 dest_align, false, endp);
9fe0e1b8 3333 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3334 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3335 return dest_mem;
647661c6 3336 }
3337
971ba038 3338 if (CONST_INT_P (len_rtx)
9fe0e1b8 3339 && can_move_by_pieces (INTVAL (len_rtx),
3340 MIN (dest_align, src_align)))
3341 {
d8ae1baa 3342 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3343 set_mem_align (dest_mem, dest_align);
d8ae1baa 3344 src_mem = get_memory_rtx (src, len);
9fe0e1b8 3345 set_mem_align (src_mem, src_align);
3346 dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
3347 MIN (dest_align, src_align), endp);
3348 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3349 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3350 return dest_mem;
3351 }
3352
c2f47e15 3353 return NULL_RTX;
647661c6 3354 }
3355}
3356
727c62dd 3357#ifndef HAVE_movstr
3358# define HAVE_movstr 0
3359# define CODE_FOR_movstr CODE_FOR_nothing
3360#endif
3361
c2f47e15 3362/* Expand into a movstr instruction, if one is available. Return NULL_RTX if
727c62dd 3363 we failed, the caller should emit a normal call, otherwise try to
3364 get the result in TARGET, if convenient. If ENDP is 0 return the
3365 destination pointer, if ENDP is 1 return the end pointer ala
3366 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3367 stpcpy. */
3368
3369static rtx
3370expand_movstr (tree dest, tree src, rtx target, int endp)
3371{
8786db1e 3372 struct expand_operand ops[3];
727c62dd 3373 rtx dest_mem;
3374 rtx src_mem;
727c62dd 3375
3376 if (!HAVE_movstr)
c2f47e15 3377 return NULL_RTX;
727c62dd 3378
d8ae1baa 3379 dest_mem = get_memory_rtx (dest, NULL);
3380 src_mem = get_memory_rtx (src, NULL);
727c62dd 3381 if (!endp)
3382 {
3383 target = force_reg (Pmode, XEXP (dest_mem, 0));
3384 dest_mem = replace_equiv_address (dest_mem, target);
727c62dd 3385 }
3386
8786db1e 3387 create_output_operand (&ops[0], endp ? target : NULL_RTX, Pmode);
3388 create_fixed_operand (&ops[1], dest_mem);
3389 create_fixed_operand (&ops[2], src_mem);
3390 expand_insn (CODE_FOR_movstr, 3, ops);
727c62dd 3391
8786db1e 3392 if (endp && target != const0_rtx)
c5aba89c 3393 {
8786db1e 3394 target = ops[0].value;
3395 /* movstr is supposed to set end to the address of the NUL
3396 terminator. If the caller requested a mempcpy-like return value,
3397 adjust it. */
3398 if (endp == 1)
3399 {
29c05e22 3400 rtx tem = plus_constant (GET_MODE (target),
3401 gen_lowpart (GET_MODE (target), target), 1);
8786db1e 3402 emit_move_insn (target, force_operand (tem, NULL_RTX));
3403 }
c5aba89c 3404 }
727c62dd 3405 return target;
3406}
3407
48e1416a 3408/* Expand expression EXP, which is a call to the strcpy builtin. Return
3409 NULL_RTX if we failed the caller should emit a normal call, otherwise
c2f47e15 3410 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3411 convenient). */
902de8ed 3412
53800dbe 3413static rtx
a65c4d64 3414expand_builtin_strcpy (tree exp, rtx target)
53800dbe 3415{
c2f47e15 3416 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3417 {
3418 tree dest = CALL_EXPR_ARG (exp, 0);
3419 tree src = CALL_EXPR_ARG (exp, 1);
a65c4d64 3420 return expand_builtin_strcpy_args (dest, src, target);
c2f47e15 3421 }
3422 return NULL_RTX;
3423}
3424
3425/* Helper function to do the actual work for expand_builtin_strcpy. The
3426 arguments to the builtin_strcpy call DEST and SRC are broken out
3427 so that this can also be called without constructing an actual CALL_EXPR.
3428 The other arguments and return value are the same as for
3429 expand_builtin_strcpy. */
3430
3431static rtx
a65c4d64 3432expand_builtin_strcpy_args (tree dest, tree src, rtx target)
c2f47e15 3433{
c2f47e15 3434 return expand_movstr (dest, src, target, /*endp=*/0);
53800dbe 3435}
3436
c2f47e15 3437/* Expand a call EXP to the stpcpy builtin.
3438 Return NULL_RTX if we failed the caller should emit a normal call,
3b824fa6 3439 otherwise try to get the result in TARGET, if convenient (and in
3440 mode MODE if that's convenient). */
3441
3442static rtx
dc369150 3443expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
3b824fa6 3444{
c2f47e15 3445 tree dst, src;
389dd41b 3446 location_t loc = EXPR_LOCATION (exp);
c2f47e15 3447
3448 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3449 return NULL_RTX;
3450
3451 dst = CALL_EXPR_ARG (exp, 0);
3452 src = CALL_EXPR_ARG (exp, 1);
3453
727c62dd 3454 /* If return value is ignored, transform stpcpy into strcpy. */
b9a16870 3455 if (target == const0_rtx && builtin_decl_implicit (BUILT_IN_STRCPY))
978836e5 3456 {
b9a16870 3457 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
0568e9c1 3458 tree result = build_call_nofold_loc (loc, fn, 2, dst, src);
c8b17b2e 3459 return expand_expr (result, target, mode, EXPAND_NORMAL);
978836e5 3460 }
3b824fa6 3461 else
3462 {
c2f47e15 3463 tree len, lenp1;
727c62dd 3464 rtx ret;
647661c6 3465
9fe0e1b8 3466 /* Ensure we get an actual string whose length can be evaluated at
a0c938f0 3467 compile-time, not an expression containing a string. This is
3468 because the latter will potentially produce pessimized code
3469 when used to produce the return value. */
681fab1e 3470 if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
c2f47e15 3471 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3472
389dd41b 3473 lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
a65c4d64 3474 ret = expand_builtin_mempcpy_args (dst, src, lenp1,
c2f47e15 3475 target, mode, /*endp=*/2);
727c62dd 3476
3477 if (ret)
3478 return ret;
3479
3480 if (TREE_CODE (len) == INTEGER_CST)
3481 {
8ec3c5c2 3482 rtx len_rtx = expand_normal (len);
727c62dd 3483
971ba038 3484 if (CONST_INT_P (len_rtx))
727c62dd 3485 {
a65c4d64 3486 ret = expand_builtin_strcpy_args (dst, src, target);
727c62dd 3487
3488 if (ret)
3489 {
3490 if (! target)
7ac87324 3491 {
3492 if (mode != VOIDmode)
3493 target = gen_reg_rtx (mode);
3494 else
3495 target = gen_reg_rtx (GET_MODE (ret));
3496 }
727c62dd 3497 if (GET_MODE (target) != GET_MODE (ret))
3498 ret = gen_lowpart (GET_MODE (target), ret);
3499
29c05e22 3500 ret = plus_constant (GET_MODE (ret), ret, INTVAL (len_rtx));
c5aba89c 3501 ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
64db345d 3502 gcc_assert (ret);
727c62dd 3503
3504 return target;
3505 }
3506 }
3507 }
3508
c2f47e15 3509 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3510 }
3511}
3512
6840589f 3513/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3514 bytes from constant string DATA + OFFSET and return it as target
3515 constant. */
3516
09879952 3517rtx
aecda0d6 3518builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
3519 enum machine_mode mode)
6840589f 3520{
3521 const char *str = (const char *) data;
3522
3523 if ((unsigned HOST_WIDE_INT) offset > strlen (str))
3524 return const0_rtx;
3525
3526 return c_readstr (str + offset, mode);
3527}
3528
48e1416a 3529/* Expand expression EXP, which is a call to the strncpy builtin. Return
c2f47e15 3530 NULL_RTX if we failed the caller should emit a normal call. */
ed09096d 3531
3532static rtx
a65c4d64 3533expand_builtin_strncpy (tree exp, rtx target)
ed09096d 3534{
389dd41b 3535 location_t loc = EXPR_LOCATION (exp);
c2f47e15 3536
3537 if (validate_arglist (exp,
3538 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
ed09096d 3539 {
c2f47e15 3540 tree dest = CALL_EXPR_ARG (exp, 0);
3541 tree src = CALL_EXPR_ARG (exp, 1);
3542 tree len = CALL_EXPR_ARG (exp, 2);
3543 tree slen = c_strlen (src, 1);
6840589f 3544
8ff6a5cd 3545 /* We must be passed a constant len and src parameter. */
cd4547bf 3546 if (!tree_fits_uhwi_p (len) || !slen || !tree_fits_uhwi_p (slen))
c2f47e15 3547 return NULL_RTX;
ed09096d 3548
389dd41b 3549 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
ed09096d 3550
3551 /* We're required to pad with trailing zeros if the requested
a0c938f0 3552 len is greater than strlen(s2)+1. In that case try to
6840589f 3553 use store_by_pieces, if it fails, punt. */
ed09096d 3554 if (tree_int_cst_lt (slen, len))
6840589f 3555 {
957d0361 3556 unsigned int dest_align = get_pointer_alignment (dest);
c2f47e15 3557 const char *p = c_getstr (src);
6840589f 3558 rtx dest_mem;
3559
cd4547bf 3560 if (!p || dest_align == 0 || !tree_fits_uhwi_p (len)
6a0712d4 3561 || !can_store_by_pieces (tree_to_uhwi (len),
6840589f 3562 builtin_strncpy_read_str,
364c0c59 3563 CONST_CAST (char *, p),
3564 dest_align, false))
c2f47e15 3565 return NULL_RTX;
6840589f 3566
d8ae1baa 3567 dest_mem = get_memory_rtx (dest, len);
6a0712d4 3568 store_by_pieces (dest_mem, tree_to_uhwi (len),
6840589f 3569 builtin_strncpy_read_str,
364c0c59 3570 CONST_CAST (char *, p), dest_align, false, 0);
a65c4d64 3571 dest_mem = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3572 dest_mem = convert_memory_address (ptr_mode, dest_mem);
e5716f7e 3573 return dest_mem;
6840589f 3574 }
ed09096d 3575 }
c2f47e15 3576 return NULL_RTX;
ed09096d 3577}
3578
ecc318ff 3579/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3580 bytes from constant string DATA + OFFSET and return it as target
3581 constant. */
3582
f656b751 3583rtx
aecda0d6 3584builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3585 enum machine_mode mode)
ecc318ff 3586{
3587 const char *c = (const char *) data;
364c0c59 3588 char *p = XALLOCAVEC (char, GET_MODE_SIZE (mode));
ecc318ff 3589
3590 memset (p, *c, GET_MODE_SIZE (mode));
3591
3592 return c_readstr (p, mode);
3593}
3594
a7ec6974 3595/* Callback routine for store_by_pieces. Return the RTL of a register
3596 containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
3597 char value given in the RTL register data. For example, if mode is
3598 4 bytes wide, return the RTL for 0x01010101*data. */
3599
3600static rtx
aecda0d6 3601builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3602 enum machine_mode mode)
a7ec6974 3603{
3604 rtx target, coeff;
3605 size_t size;
3606 char *p;
3607
3608 size = GET_MODE_SIZE (mode);
f0ce3b1f 3609 if (size == 1)
3610 return (rtx) data;
a7ec6974 3611
364c0c59 3612 p = XALLOCAVEC (char, size);
a7ec6974 3613 memset (p, 1, size);
3614 coeff = c_readstr (p, mode);
3615
f0ce3b1f 3616 target = convert_to_mode (mode, (rtx) data, 1);
a7ec6974 3617 target = expand_mult (mode, target, coeff, NULL_RTX, 1);
3618 return force_reg (mode, target);
3619}
3620
48e1416a 3621/* Expand expression EXP, which is a call to the memset builtin. Return
3622 NULL_RTX if we failed the caller should emit a normal call, otherwise
c2f47e15 3623 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3624 convenient). */
902de8ed 3625
53800dbe 3626static rtx
c2f47e15 3627expand_builtin_memset (tree exp, rtx target, enum machine_mode mode)
53800dbe 3628{
c2f47e15 3629 if (!validate_arglist (exp,
3630 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
3631 return NULL_RTX;
53800dbe 3632 else
3633 {
c2f47e15 3634 tree dest = CALL_EXPR_ARG (exp, 0);
3635 tree val = CALL_EXPR_ARG (exp, 1);
3636 tree len = CALL_EXPR_ARG (exp, 2);
3637 return expand_builtin_memset_args (dest, val, len, target, mode, exp);
3638 }
3639}
53800dbe 3640
c2f47e15 3641/* Helper function to do the actual work for expand_builtin_memset. The
3642 arguments to the builtin_memset call DEST, VAL, and LEN are broken out
3643 so that this can also be called without constructing an actual CALL_EXPR.
3644 The other arguments and return value are the same as for
3645 expand_builtin_memset. */
6b961939 3646
c2f47e15 3647static rtx
3648expand_builtin_memset_args (tree dest, tree val, tree len,
3649 rtx target, enum machine_mode mode, tree orig_exp)
3650{
3651 tree fndecl, fn;
3652 enum built_in_function fcode;
03a5dda9 3653 enum machine_mode val_mode;
c2f47e15 3654 char c;
3655 unsigned int dest_align;
3656 rtx dest_mem, dest_addr, len_rtx;
3657 HOST_WIDE_INT expected_size = -1;
3658 unsigned int expected_align = 0;
36d63243 3659 unsigned HOST_WIDE_INT min_size;
3660 unsigned HOST_WIDE_INT max_size;
9db0f34d 3661 unsigned HOST_WIDE_INT probable_max_size;
53800dbe 3662
957d0361 3663 dest_align = get_pointer_alignment (dest);
162719b3 3664
c2f47e15 3665 /* If DEST is not a pointer type, don't do this operation in-line. */
3666 if (dest_align == 0)
3667 return NULL_RTX;
6f428e8b 3668
8cee8dc0 3669 if (currently_expanding_gimple_stmt)
3670 stringop_block_profile (currently_expanding_gimple_stmt,
3671 &expected_align, &expected_size);
75a70cf9 3672
c2f47e15 3673 if (expected_align < dest_align)
3674 expected_align = dest_align;
6b961939 3675
c2f47e15 3676 /* If the LEN parameter is zero, return DEST. */
3677 if (integer_zerop (len))
3678 {
3679 /* Evaluate and ignore VAL in case it has side-effects. */
3680 expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
3681 return expand_expr (dest, target, mode, EXPAND_NORMAL);
3682 }
7a3e5564 3683
c2f47e15 3684 /* Stabilize the arguments in case we fail. */
3685 dest = builtin_save_expr (dest);
3686 val = builtin_save_expr (val);
3687 len = builtin_save_expr (len);
a7ec6974 3688
c2f47e15 3689 len_rtx = expand_normal (len);
9db0f34d 3690 determine_block_size (len, len_rtx, &min_size, &max_size,
3691 &probable_max_size);
c2f47e15 3692 dest_mem = get_memory_rtx (dest, len);
03a5dda9 3693 val_mode = TYPE_MODE (unsigned_char_type_node);
a7ec6974 3694
c2f47e15 3695 if (TREE_CODE (val) != INTEGER_CST)
3696 {
3697 rtx val_rtx;
a7ec6974 3698
c2f47e15 3699 val_rtx = expand_normal (val);
03a5dda9 3700 val_rtx = convert_to_mode (val_mode, val_rtx, 0);
53800dbe 3701
c2f47e15 3702 /* Assume that we can memset by pieces if we can store
3703 * the coefficients by pieces (in the required modes).
3704 * We can't pass builtin_memset_gen_str as that emits RTL. */
3705 c = 1;
cd4547bf 3706 if (tree_fits_uhwi_p (len)
6a0712d4 3707 && can_store_by_pieces (tree_to_uhwi (len),
4b297e2e 3708 builtin_memset_read_str, &c, dest_align,
3709 true))
c2f47e15 3710 {
03a5dda9 3711 val_rtx = force_reg (val_mode, val_rtx);
6a0712d4 3712 store_by_pieces (dest_mem, tree_to_uhwi (len),
4b297e2e 3713 builtin_memset_gen_str, val_rtx, dest_align,
3714 true, 0);
c2f47e15 3715 }
3716 else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
3717 dest_align, expected_align,
9db0f34d 3718 expected_size, min_size, max_size,
3719 probable_max_size))
6b961939 3720 goto do_libcall;
48e1416a 3721
c2f47e15 3722 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3723 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3724 return dest_mem;
3725 }
53800dbe 3726
c2f47e15 3727 if (target_char_cast (val, &c))
3728 goto do_libcall;
ecc318ff 3729
c2f47e15 3730 if (c)
3731 {
cd4547bf 3732 if (tree_fits_uhwi_p (len)
6a0712d4 3733 && can_store_by_pieces (tree_to_uhwi (len),
4b297e2e 3734 builtin_memset_read_str, &c, dest_align,
3735 true))
6a0712d4 3736 store_by_pieces (dest_mem, tree_to_uhwi (len),
4b297e2e 3737 builtin_memset_read_str, &c, dest_align, true, 0);
03a5dda9 3738 else if (!set_storage_via_setmem (dest_mem, len_rtx,
3739 gen_int_mode (c, val_mode),
c2f47e15 3740 dest_align, expected_align,
9db0f34d 3741 expected_size, min_size, max_size,
3742 probable_max_size))
c2f47e15 3743 goto do_libcall;
48e1416a 3744
c2f47e15 3745 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3746 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3747 return dest_mem;
3748 }
ecc318ff 3749
c2f47e15 3750 set_mem_align (dest_mem, dest_align);
3751 dest_addr = clear_storage_hints (dest_mem, len_rtx,
3752 CALL_EXPR_TAILCALL (orig_exp)
3753 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
36d63243 3754 expected_align, expected_size,
9db0f34d 3755 min_size, max_size,
3756 probable_max_size);
53800dbe 3757
c2f47e15 3758 if (dest_addr == 0)
3759 {
3760 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3761 dest_addr = convert_memory_address (ptr_mode, dest_addr);
3762 }
53800dbe 3763
c2f47e15 3764 return dest_addr;
6b961939 3765
c2f47e15 3766 do_libcall:
3767 fndecl = get_callee_fndecl (orig_exp);
3768 fcode = DECL_FUNCTION_CODE (fndecl);
3769 if (fcode == BUILT_IN_MEMSET)
0568e9c1 3770 fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 3,
3771 dest, val, len);
c2f47e15 3772 else if (fcode == BUILT_IN_BZERO)
0568e9c1 3773 fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 2,
3774 dest, len);
c2f47e15 3775 else
3776 gcc_unreachable ();
a65c4d64 3777 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
3778 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
c2f47e15 3779 return expand_call (fn, target, target == const0_rtx);
53800dbe 3780}
3781
48e1416a 3782/* Expand expression EXP, which is a call to the bzero builtin. Return
c2f47e15 3783 NULL_RTX if we failed the caller should emit a normal call. */
27d0c333 3784
ffc83088 3785static rtx
0b25db21 3786expand_builtin_bzero (tree exp)
ffc83088 3787{
c2f47e15 3788 tree dest, size;
389dd41b 3789 location_t loc = EXPR_LOCATION (exp);
ffc83088 3790
c2f47e15 3791 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
7369e7ba 3792 return NULL_RTX;
ffc83088 3793
c2f47e15 3794 dest = CALL_EXPR_ARG (exp, 0);
3795 size = CALL_EXPR_ARG (exp, 1);
bf8e3599 3796
7369e7ba 3797 /* New argument list transforming bzero(ptr x, int y) to
6f428e8b 3798 memset(ptr x, int 0, size_t y). This is done this way
3799 so that if it isn't expanded inline, we fallback to
3800 calling bzero instead of memset. */
bf8e3599 3801
c2f47e15 3802 return expand_builtin_memset_args (dest, integer_zero_node,
a0553bff 3803 fold_convert_loc (loc,
3804 size_type_node, size),
c2f47e15 3805 const0_rtx, VOIDmode, exp);
ffc83088 3806}
3807
7a3f89b5 3808/* Expand expression EXP, which is a call to the memcmp built-in function.
bd021c1c 3809 Return NULL_RTX if we failed and the caller should emit a normal call,
3810 otherwise try to get the result in TARGET, if convenient (and in mode
3811 MODE, if that's convenient). */
27d0c333 3812
53800dbe 3813static rtx
a65c4d64 3814expand_builtin_memcmp (tree exp, ATTRIBUTE_UNUSED rtx target,
3815 ATTRIBUTE_UNUSED enum machine_mode mode)
53800dbe 3816{
a65c4d64 3817 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
389dd41b 3818
c2f47e15 3819 if (!validate_arglist (exp,
3820 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3821 return NULL_RTX;
6f428e8b 3822
bd021c1c 3823 /* Note: The cmpstrnsi pattern, if it exists, is not suitable for
3824 implementing memcmp because it will stop if it encounters two
3825 zero bytes. */
3826#if defined HAVE_cmpmemsi
53800dbe 3827 {
0cd832f0 3828 rtx arg1_rtx, arg2_rtx, arg3_rtx;
53800dbe 3829 rtx result;
0cd832f0 3830 rtx insn;
c2f47e15 3831 tree arg1 = CALL_EXPR_ARG (exp, 0);
3832 tree arg2 = CALL_EXPR_ARG (exp, 1);
3833 tree len = CALL_EXPR_ARG (exp, 2);
53800dbe 3834
957d0361 3835 unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
3836 unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
b428c0a5 3837 enum machine_mode insn_mode;
3838
b428c0a5 3839 if (HAVE_cmpmemsi)
3840 insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
3841 else
c2f47e15 3842 return NULL_RTX;
53800dbe 3843
3844 /* If we don't have POINTER_TYPE, call the function. */
3845 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 3846 return NULL_RTX;
53800dbe 3847
3848 /* Make a place to write the result of the instruction. */
3849 result = target;
3850 if (! (result != 0
8ad4c111 3851 && REG_P (result) && GET_MODE (result) == insn_mode
53800dbe 3852 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3853 result = gen_reg_rtx (insn_mode);
3854
d8ae1baa 3855 arg1_rtx = get_memory_rtx (arg1, len);
3856 arg2_rtx = get_memory_rtx (arg2, len);
389dd41b 3857 arg3_rtx = expand_normal (fold_convert_loc (loc, sizetype, len));
83f88f8e 3858
3859 /* Set MEM_SIZE as appropriate. */
971ba038 3860 if (CONST_INT_P (arg3_rtx))
83f88f8e 3861 {
5b2a69fa 3862 set_mem_size (arg1_rtx, INTVAL (arg3_rtx));
3863 set_mem_size (arg2_rtx, INTVAL (arg3_rtx));
83f88f8e 3864 }
3865
b428c0a5 3866 if (HAVE_cmpmemsi)
3867 insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3868 GEN_INT (MIN (arg1_align, arg2_align)));
0cd832f0 3869 else
64db345d 3870 gcc_unreachable ();
0cd832f0 3871
3872 if (insn)
3873 emit_insn (insn);
3874 else
2dd6f9ed 3875 emit_library_call_value (memcmp_libfunc, result, LCT_PURE,
0cd832f0 3876 TYPE_MODE (integer_type_node), 3,
3877 XEXP (arg1_rtx, 0), Pmode,
3878 XEXP (arg2_rtx, 0), Pmode,
3879 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
78a8ed03 3880 TYPE_UNSIGNED (sizetype)),
0cd832f0 3881 TYPE_MODE (sizetype));
53800dbe 3882
3883 /* Return the value in the proper mode for this function. */
3884 mode = TYPE_MODE (TREE_TYPE (exp));
3885 if (GET_MODE (result) == mode)
3886 return result;
3887 else if (target != 0)
3888 {
3889 convert_move (target, result, 0);
3890 return target;
3891 }
3892 else
3893 return convert_to_mode (mode, result, 0);
3894 }
bd021c1c 3895#endif /* HAVE_cmpmemsi. */
53800dbe 3896
c2f47e15 3897 return NULL_RTX;
6f428e8b 3898}
3899
c2f47e15 3900/* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX
53800dbe 3901 if we failed the caller should emit a normal call, otherwise try to get
3902 the result in TARGET, if convenient. */
902de8ed 3903
53800dbe 3904static rtx
a65c4d64 3905expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
53800dbe 3906{
c2f47e15 3907 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3908 return NULL_RTX;
bf8e3599 3909
6ac5504b 3910#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
6b531606 3911 if (direct_optab_handler (cmpstr_optab, SImode) != CODE_FOR_nothing
3912 || direct_optab_handler (cmpstrn_optab, SImode) != CODE_FOR_nothing)
6ac5504b 3913 {
3914 rtx arg1_rtx, arg2_rtx;
3915 rtx result, insn = NULL_RTX;
3916 tree fndecl, fn;
c2f47e15 3917 tree arg1 = CALL_EXPR_ARG (exp, 0);
3918 tree arg2 = CALL_EXPR_ARG (exp, 1);
a0c938f0 3919
957d0361 3920 unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
3921 unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
6ac5504b 3922
3923 /* If we don't have POINTER_TYPE, call the function. */
3924 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 3925 return NULL_RTX;
7a3f89b5 3926
6ac5504b 3927 /* Stabilize the arguments in case gen_cmpstr(n)si fail. */
3928 arg1 = builtin_save_expr (arg1);
3929 arg2 = builtin_save_expr (arg2);
7a3f89b5 3930
d8ae1baa 3931 arg1_rtx = get_memory_rtx (arg1, NULL);
3932 arg2_rtx = get_memory_rtx (arg2, NULL);
53800dbe 3933
6ac5504b 3934#ifdef HAVE_cmpstrsi
3935 /* Try to call cmpstrsi. */
3936 if (HAVE_cmpstrsi)
3937 {
a0c938f0 3938 enum machine_mode insn_mode
6ac5504b 3939 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3940
3941 /* Make a place to write the result of the instruction. */
3942 result = target;
3943 if (! (result != 0
3944 && REG_P (result) && GET_MODE (result) == insn_mode
3945 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3946 result = gen_reg_rtx (insn_mode);
3947
3948 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
3949 GEN_INT (MIN (arg1_align, arg2_align)));
3950 }
3951#endif
03fd9d2c 3952#ifdef HAVE_cmpstrnsi
6ac5504b 3953 /* Try to determine at least one length and call cmpstrnsi. */
a0c938f0 3954 if (!insn && HAVE_cmpstrnsi)
6ac5504b 3955 {
3956 tree len;
3957 rtx arg3_rtx;
3958
a0c938f0 3959 enum machine_mode insn_mode
6ac5504b 3960 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
3961 tree len1 = c_strlen (arg1, 1);
3962 tree len2 = c_strlen (arg2, 1);
3963
3964 if (len1)
3965 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3966 if (len2)
3967 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3968
3969 /* If we don't have a constant length for the first, use the length
3970 of the second, if we know it. We don't require a constant for
3971 this case; some cost analysis could be done if both are available
3972 but neither is constant. For now, assume they're equally cheap,
3973 unless one has side effects. If both strings have constant lengths,
3974 use the smaller. */
3975
3976 if (!len1)
3977 len = len2;
3978 else if (!len2)
3979 len = len1;
3980 else if (TREE_SIDE_EFFECTS (len1))
3981 len = len2;
3982 else if (TREE_SIDE_EFFECTS (len2))
3983 len = len1;
3984 else if (TREE_CODE (len1) != INTEGER_CST)
3985 len = len2;
3986 else if (TREE_CODE (len2) != INTEGER_CST)
3987 len = len1;
3988 else if (tree_int_cst_lt (len1, len2))
3989 len = len1;
3990 else
3991 len = len2;
3992
3993 /* If both arguments have side effects, we cannot optimize. */
3994 if (!len || TREE_SIDE_EFFECTS (len))
6b961939 3995 goto do_libcall;
53800dbe 3996
8ec3c5c2 3997 arg3_rtx = expand_normal (len);
902de8ed 3998
6ac5504b 3999 /* Make a place to write the result of the instruction. */
4000 result = target;
4001 if (! (result != 0
4002 && REG_P (result) && GET_MODE (result) == insn_mode
4003 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4004 result = gen_reg_rtx (insn_mode);
53800dbe 4005
6ac5504b 4006 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4007 GEN_INT (MIN (arg1_align, arg2_align)));
4008 }
4009#endif
3f8aefe2 4010
6ac5504b 4011 if (insn)
4012 {
a65c4d64 4013 enum machine_mode mode;
6ac5504b 4014 emit_insn (insn);
3f8aefe2 4015
6ac5504b 4016 /* Return the value in the proper mode for this function. */
4017 mode = TYPE_MODE (TREE_TYPE (exp));
4018 if (GET_MODE (result) == mode)
4019 return result;
4020 if (target == 0)
4021 return convert_to_mode (mode, result, 0);
4022 convert_move (target, result, 0);
4023 return target;
4024 }
902de8ed 4025
6ac5504b 4026 /* Expand the library call ourselves using a stabilized argument
4027 list to avoid re-evaluating the function's arguments twice. */
2694880e 4028#ifdef HAVE_cmpstrnsi
6b961939 4029 do_libcall:
2694880e 4030#endif
6ac5504b 4031 fndecl = get_callee_fndecl (exp);
0568e9c1 4032 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2);
a65c4d64 4033 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
4034 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
6ac5504b 4035 return expand_call (fn, target, target == const0_rtx);
4036 }
7a3f89b5 4037#endif
c2f47e15 4038 return NULL_RTX;
83d79705 4039}
53800dbe 4040
48e1416a 4041/* Expand expression EXP, which is a call to the strncmp builtin. Return
c2f47e15 4042 NULL_RTX if we failed the caller should emit a normal call, otherwise try to get
ed09096d 4043 the result in TARGET, if convenient. */
27d0c333 4044
ed09096d 4045static rtx
a65c4d64 4046expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
4047 ATTRIBUTE_UNUSED enum machine_mode mode)
ed09096d 4048{
a65c4d64 4049 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
389dd41b 4050
c2f47e15 4051 if (!validate_arglist (exp,
4052 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4053 return NULL_RTX;
ed09096d 4054
6e34e617 4055 /* If c_strlen can determine an expression for one of the string
6ac5504b 4056 lengths, and it doesn't have side effects, then emit cmpstrnsi
7a3f89b5 4057 using length MIN(strlen(string)+1, arg3). */
6ac5504b 4058#ifdef HAVE_cmpstrnsi
4059 if (HAVE_cmpstrnsi)
7a3f89b5 4060 {
4061 tree len, len1, len2;
4062 rtx arg1_rtx, arg2_rtx, arg3_rtx;
4063 rtx result, insn;
0b25db21 4064 tree fndecl, fn;
c2f47e15 4065 tree arg1 = CALL_EXPR_ARG (exp, 0);
4066 tree arg2 = CALL_EXPR_ARG (exp, 1);
4067 tree arg3 = CALL_EXPR_ARG (exp, 2);
6f428e8b 4068
957d0361 4069 unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
4070 unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
7a3f89b5 4071 enum machine_mode insn_mode
6ac5504b 4072 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
bf8e3599 4073
681fab1e 4074 len1 = c_strlen (arg1, 1);
4075 len2 = c_strlen (arg2, 1);
7a3f89b5 4076
4077 if (len1)
389dd41b 4078 len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1);
7a3f89b5 4079 if (len2)
389dd41b 4080 len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2);
7a3f89b5 4081
4082 /* If we don't have a constant length for the first, use the length
4083 of the second, if we know it. We don't require a constant for
4084 this case; some cost analysis could be done if both are available
4085 but neither is constant. For now, assume they're equally cheap,
4086 unless one has side effects. If both strings have constant lengths,
4087 use the smaller. */
4088
4089 if (!len1)
4090 len = len2;
4091 else if (!len2)
4092 len = len1;
4093 else if (TREE_SIDE_EFFECTS (len1))
4094 len = len2;
4095 else if (TREE_SIDE_EFFECTS (len2))
4096 len = len1;
4097 else if (TREE_CODE (len1) != INTEGER_CST)
4098 len = len2;
4099 else if (TREE_CODE (len2) != INTEGER_CST)
4100 len = len1;
4101 else if (tree_int_cst_lt (len1, len2))
4102 len = len1;
4103 else
4104 len = len2;
6e34e617 4105
7a3f89b5 4106 /* If both arguments have side effects, we cannot optimize. */
4107 if (!len || TREE_SIDE_EFFECTS (len))
c2f47e15 4108 return NULL_RTX;
bf8e3599 4109
7a3f89b5 4110 /* The actual new length parameter is MIN(len,arg3). */
389dd41b 4111 len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len,
4112 fold_convert_loc (loc, TREE_TYPE (len), arg3));
7a3f89b5 4113
4114 /* If we don't have POINTER_TYPE, call the function. */
4115 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 4116 return NULL_RTX;
7a3f89b5 4117
4118 /* Make a place to write the result of the instruction. */
4119 result = target;
4120 if (! (result != 0
8ad4c111 4121 && REG_P (result) && GET_MODE (result) == insn_mode
7a3f89b5 4122 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
4123 result = gen_reg_rtx (insn_mode);
4124
a65c4d64 4125 /* Stabilize the arguments in case gen_cmpstrnsi fails. */
4126 arg1 = builtin_save_expr (arg1);
4127 arg2 = builtin_save_expr (arg2);
4128 len = builtin_save_expr (len);
27d0c333 4129
a65c4d64 4130 arg1_rtx = get_memory_rtx (arg1, len);
4131 arg2_rtx = get_memory_rtx (arg2, len);
4132 arg3_rtx = expand_normal (len);
4133 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
4134 GEN_INT (MIN (arg1_align, arg2_align)));
4135 if (insn)
4136 {
4137 emit_insn (insn);
49f0327b 4138
a65c4d64 4139 /* Return the value in the proper mode for this function. */
4140 mode = TYPE_MODE (TREE_TYPE (exp));
4141 if (GET_MODE (result) == mode)
4142 return result;
4143 if (target == 0)
4144 return convert_to_mode (mode, result, 0);
4145 convert_move (target, result, 0);
4146 return target;
4147 }
27d0c333 4148
a65c4d64 4149 /* Expand the library call ourselves using a stabilized argument
4150 list to avoid re-evaluating the function's arguments twice. */
4151 fndecl = get_callee_fndecl (exp);
0568e9c1 4152 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 3,
4153 arg1, arg2, len);
a65c4d64 4154 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
4155 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4156 return expand_call (fn, target, target == const0_rtx);
4157 }
4158#endif
c2f47e15 4159 return NULL_RTX;
49f0327b 4160}
4161
a66c9326 4162/* Expand a call to __builtin_saveregs, generating the result in TARGET,
4163 if that's convenient. */
902de8ed 4164
a66c9326 4165rtx
aecda0d6 4166expand_builtin_saveregs (void)
53800dbe 4167{
a66c9326 4168 rtx val, seq;
53800dbe 4169
4170 /* Don't do __builtin_saveregs more than once in a function.
4171 Save the result of the first call and reuse it. */
4172 if (saveregs_value != 0)
4173 return saveregs_value;
53800dbe 4174
a66c9326 4175 /* When this function is called, it means that registers must be
4176 saved on entry to this function. So we migrate the call to the
4177 first insn of this function. */
4178
4179 start_sequence ();
53800dbe 4180
a66c9326 4181 /* Do whatever the machine needs done in this case. */
45550790 4182 val = targetm.calls.expand_builtin_saveregs ();
53800dbe 4183
a66c9326 4184 seq = get_insns ();
4185 end_sequence ();
53800dbe 4186
a66c9326 4187 saveregs_value = val;
53800dbe 4188
31d3e01c 4189 /* Put the insns after the NOTE that starts the function. If this
4190 is inside a start_sequence, make the outer-level insn chain current, so
a66c9326 4191 the code is placed at the start of the function. */
4192 push_topmost_sequence ();
0ec80471 4193 emit_insn_after (seq, entry_of_function ());
a66c9326 4194 pop_topmost_sequence ();
4195
4196 return val;
53800dbe 4197}
4198
79012a9d 4199/* Expand a call to __builtin_next_arg. */
27d0c333 4200
53800dbe 4201static rtx
79012a9d 4202expand_builtin_next_arg (void)
53800dbe 4203{
79012a9d 4204 /* Checking arguments is already done in fold_builtin_next_arg
4205 that must be called before this function. */
940ddc5c 4206 return expand_binop (ptr_mode, add_optab,
abe32cce 4207 crtl->args.internal_arg_pointer,
4208 crtl->args.arg_offset_rtx,
53800dbe 4209 NULL_RTX, 0, OPTAB_LIB_WIDEN);
4210}
4211
a66c9326 4212/* Make it easier for the backends by protecting the valist argument
4213 from multiple evaluations. */
4214
4215static tree
389dd41b 4216stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
a66c9326 4217{
5f57a8b1 4218 tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
4219
182cf5a9 4220 /* The current way of determining the type of valist is completely
4221 bogus. We should have the information on the va builtin instead. */
4222 if (!vatype)
4223 vatype = targetm.fn_abi_va_list (cfun->decl);
5f57a8b1 4224
4225 if (TREE_CODE (vatype) == ARRAY_TYPE)
a66c9326 4226 {
2d47cc32 4227 if (TREE_SIDE_EFFECTS (valist))
4228 valist = save_expr (valist);
11a61dea 4229
2d47cc32 4230 /* For this case, the backends will be expecting a pointer to
5f57a8b1 4231 vatype, but it's possible we've actually been given an array
4232 (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)).
2d47cc32 4233 So fix it. */
4234 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
8a15c04a 4235 {
5f57a8b1 4236 tree p1 = build_pointer_type (TREE_TYPE (vatype));
389dd41b 4237 valist = build_fold_addr_expr_with_type_loc (loc, valist, p1);
8a15c04a 4238 }
a66c9326 4239 }
11a61dea 4240 else
a66c9326 4241 {
182cf5a9 4242 tree pt = build_pointer_type (vatype);
11a61dea 4243
2d47cc32 4244 if (! needs_lvalue)
4245 {
11a61dea 4246 if (! TREE_SIDE_EFFECTS (valist))
4247 return valist;
bf8e3599 4248
389dd41b 4249 valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist);
a66c9326 4250 TREE_SIDE_EFFECTS (valist) = 1;
a66c9326 4251 }
2d47cc32 4252
11a61dea 4253 if (TREE_SIDE_EFFECTS (valist))
2d47cc32 4254 valist = save_expr (valist);
182cf5a9 4255 valist = fold_build2_loc (loc, MEM_REF,
4256 vatype, valist, build_int_cst (pt, 0));
a66c9326 4257 }
4258
4259 return valist;
4260}
4261
2e15d750 4262/* The "standard" definition of va_list is void*. */
4263
4264tree
4265std_build_builtin_va_list (void)
4266{
4267 return ptr_type_node;
4268}
4269
5f57a8b1 4270/* The "standard" abi va_list is va_list_type_node. */
4271
4272tree
4273std_fn_abi_va_list (tree fndecl ATTRIBUTE_UNUSED)
4274{
4275 return va_list_type_node;
4276}
4277
4278/* The "standard" type of va_list is va_list_type_node. */
4279
4280tree
4281std_canonical_va_list_type (tree type)
4282{
4283 tree wtype, htype;
4284
4285 if (INDIRECT_REF_P (type))
4286 type = TREE_TYPE (type);
9af5ce0c 4287 else if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE (type)))
5f57a8b1 4288 type = TREE_TYPE (type);
5f57a8b1 4289 wtype = va_list_type_node;
4290 htype = type;
7b36f9ab 4291 /* Treat structure va_list types. */
4292 if (TREE_CODE (wtype) == RECORD_TYPE && POINTER_TYPE_P (htype))
4293 htype = TREE_TYPE (htype);
4294 else if (TREE_CODE (wtype) == ARRAY_TYPE)
5f57a8b1 4295 {
4296 /* If va_list is an array type, the argument may have decayed
4297 to a pointer type, e.g. by being passed to another function.
4298 In that case, unwrap both types so that we can compare the
4299 underlying records. */
4300 if (TREE_CODE (htype) == ARRAY_TYPE
4301 || POINTER_TYPE_P (htype))
4302 {
4303 wtype = TREE_TYPE (wtype);
4304 htype = TREE_TYPE (htype);
4305 }
4306 }
4307 if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype))
4308 return va_list_type_node;
4309
4310 return NULL_TREE;
4311}
4312
a66c9326 4313/* The "standard" implementation of va_start: just assign `nextarg' to
4314 the variable. */
27d0c333 4315
a66c9326 4316void
aecda0d6 4317std_expand_builtin_va_start (tree valist, rtx nextarg)
a66c9326 4318{
f03c17bc 4319 rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
4320 convert_move (va_r, nextarg, 0);
a66c9326 4321}
4322
c2f47e15 4323/* Expand EXP, a call to __builtin_va_start. */
27d0c333 4324
a66c9326 4325static rtx
c2f47e15 4326expand_builtin_va_start (tree exp)
a66c9326 4327{
4328 rtx nextarg;
c2f47e15 4329 tree valist;
389dd41b 4330 location_t loc = EXPR_LOCATION (exp);
a66c9326 4331
c2f47e15 4332 if (call_expr_nargs (exp) < 2)
cb166087 4333 {
389dd41b 4334 error_at (loc, "too few arguments to function %<va_start%>");
cb166087 4335 return const0_rtx;
4336 }
a66c9326 4337
c2f47e15 4338 if (fold_builtin_next_arg (exp, true))
79012a9d 4339 return const0_rtx;
7c2f0500 4340
79012a9d 4341 nextarg = expand_builtin_next_arg ();
389dd41b 4342 valist = stabilize_va_list_loc (loc, CALL_EXPR_ARG (exp, 0), 1);
a66c9326 4343
8a58ed0a 4344 if (targetm.expand_builtin_va_start)
4345 targetm.expand_builtin_va_start (valist, nextarg);
4346 else
4347 std_expand_builtin_va_start (valist, nextarg);
a66c9326 4348
4349 return const0_rtx;
4350}
4351
c2f47e15 4352/* Expand EXP, a call to __builtin_va_end. */
f7c44134 4353
a66c9326 4354static rtx
c2f47e15 4355expand_builtin_va_end (tree exp)
a66c9326 4356{
c2f47e15 4357 tree valist = CALL_EXPR_ARG (exp, 0);
8a15c04a 4358
8a15c04a 4359 /* Evaluate for side effects, if needed. I hate macros that don't
4360 do that. */
4361 if (TREE_SIDE_EFFECTS (valist))
4362 expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
a66c9326 4363
4364 return const0_rtx;
4365}
4366
c2f47e15 4367/* Expand EXP, a call to __builtin_va_copy. We do this as a
a66c9326 4368 builtin rather than just as an assignment in stdarg.h because of the
4369 nastiness of array-type va_list types. */
f7c44134 4370
a66c9326 4371static rtx
c2f47e15 4372expand_builtin_va_copy (tree exp)
a66c9326 4373{
4374 tree dst, src, t;
389dd41b 4375 location_t loc = EXPR_LOCATION (exp);
a66c9326 4376
c2f47e15 4377 dst = CALL_EXPR_ARG (exp, 0);
4378 src = CALL_EXPR_ARG (exp, 1);
a66c9326 4379
389dd41b 4380 dst = stabilize_va_list_loc (loc, dst, 1);
4381 src = stabilize_va_list_loc (loc, src, 0);
a66c9326 4382
5f57a8b1 4383 gcc_assert (cfun != NULL && cfun->decl != NULL_TREE);
4384
4385 if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE)
a66c9326 4386 {
5f57a8b1 4387 t = build2 (MODIFY_EXPR, targetm.fn_abi_va_list (cfun->decl), dst, src);
a66c9326 4388 TREE_SIDE_EFFECTS (t) = 1;
4389 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4390 }
4391 else
4392 {
11a61dea 4393 rtx dstb, srcb, size;
4394
4395 /* Evaluate to pointers. */
4396 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
4397 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
5f57a8b1 4398 size = expand_expr (TYPE_SIZE_UNIT (targetm.fn_abi_va_list (cfun->decl)),
4399 NULL_RTX, VOIDmode, EXPAND_NORMAL);
11a61dea 4400
85d654dd 4401 dstb = convert_memory_address (Pmode, dstb);
4402 srcb = convert_memory_address (Pmode, srcb);
726ec87c 4403
11a61dea 4404 /* "Dereference" to BLKmode memories. */
4405 dstb = gen_rtx_MEM (BLKmode, dstb);
ab6ab77e 4406 set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
5f57a8b1 4407 set_mem_align (dstb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 4408 srcb = gen_rtx_MEM (BLKmode, srcb);
ab6ab77e 4409 set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
5f57a8b1 4410 set_mem_align (srcb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 4411
4412 /* Copy. */
0378dbdc 4413 emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
a66c9326 4414 }
4415
4416 return const0_rtx;
4417}
4418
53800dbe 4419/* Expand a call to one of the builtin functions __builtin_frame_address or
4420 __builtin_return_address. */
27d0c333 4421
53800dbe 4422static rtx
c2f47e15 4423expand_builtin_frame_address (tree fndecl, tree exp)
53800dbe 4424{
53800dbe 4425 /* The argument must be a nonnegative integer constant.
4426 It counts the number of frames to scan up the stack.
4427 The value is the return address saved in that frame. */
c2f47e15 4428 if (call_expr_nargs (exp) == 0)
53800dbe 4429 /* Warning about missing arg was already issued. */
4430 return const0_rtx;
cd4547bf 4431 else if (! tree_fits_uhwi_p (CALL_EXPR_ARG (exp, 0)))
53800dbe 4432 {
4433 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
07e3a3d2 4434 error ("invalid argument to %<__builtin_frame_address%>");
53800dbe 4435 else
07e3a3d2 4436 error ("invalid argument to %<__builtin_return_address%>");
53800dbe 4437 return const0_rtx;
4438 }
4439 else
4440 {
27d0c333 4441 rtx tem
4442 = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
6a0712d4 4443 tree_to_uhwi (CALL_EXPR_ARG (exp, 0)));
53800dbe 4444
4445 /* Some ports cannot access arbitrary stack frames. */
4446 if (tem == NULL)
4447 {
4448 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
c3ceba8e 4449 warning (0, "unsupported argument to %<__builtin_frame_address%>");
53800dbe 4450 else
c3ceba8e 4451 warning (0, "unsupported argument to %<__builtin_return_address%>");
53800dbe 4452 return const0_rtx;
4453 }
4454
4455 /* For __builtin_frame_address, return what we've got. */
4456 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4457 return tem;
4458
8ad4c111 4459 if (!REG_P (tem)
53800dbe 4460 && ! CONSTANT_P (tem))
99182918 4461 tem = copy_addr_to_reg (tem);
53800dbe 4462 return tem;
4463 }
4464}
4465
990495a7 4466/* Expand EXP, a call to the alloca builtin. Return NULL_RTX if we
5be42b39 4467 failed and the caller should emit a normal call. CANNOT_ACCUMULATE
4468 is the same as for allocate_dynamic_stack_space. */
15c6cf6b 4469
53800dbe 4470static rtx
5be42b39 4471expand_builtin_alloca (tree exp, bool cannot_accumulate)
53800dbe 4472{
4473 rtx op0;
15c6cf6b 4474 rtx result;
581bf1c2 4475 bool valid_arglist;
4476 unsigned int align;
4477 bool alloca_with_align = (DECL_FUNCTION_CODE (get_callee_fndecl (exp))
4478 == BUILT_IN_ALLOCA_WITH_ALIGN);
53800dbe 4479
581bf1c2 4480 valid_arglist
4481 = (alloca_with_align
4482 ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
4483 : validate_arglist (exp, INTEGER_TYPE, VOID_TYPE));
4484
4485 if (!valid_arglist)
c2f47e15 4486 return NULL_RTX;
53800dbe 4487
4488 /* Compute the argument. */
c2f47e15 4489 op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
53800dbe 4490
581bf1c2 4491 /* Compute the alignment. */
4492 align = (alloca_with_align
4493 ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1))
4494 : BIGGEST_ALIGNMENT);
4495
53800dbe 4496 /* Allocate the desired space. */
581bf1c2 4497 result = allocate_dynamic_stack_space (op0, 0, align, cannot_accumulate);
85d654dd 4498 result = convert_memory_address (ptr_mode, result);
15c6cf6b 4499
4500 return result;
53800dbe 4501}
4502
74bdbe96 4503/* Expand a call to bswap builtin in EXP.
4504 Return NULL_RTX if a normal call should be emitted rather than expanding the
4505 function in-line. If convenient, the result should be placed in TARGET.
4506 SUBTARGET may be used as the target for computing one of EXP's operands. */
42791117 4507
4508static rtx
74bdbe96 4509expand_builtin_bswap (enum machine_mode target_mode, tree exp, rtx target,
4510 rtx subtarget)
42791117 4511{
42791117 4512 tree arg;
4513 rtx op0;
4514
c2f47e15 4515 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4516 return NULL_RTX;
42791117 4517
c2f47e15 4518 arg = CALL_EXPR_ARG (exp, 0);
74bdbe96 4519 op0 = expand_expr (arg,
4520 subtarget && GET_MODE (subtarget) == target_mode
4521 ? subtarget : NULL_RTX,
4522 target_mode, EXPAND_NORMAL);
4523 if (GET_MODE (op0) != target_mode)
4524 op0 = convert_to_mode (target_mode, op0, 1);
42791117 4525
74bdbe96 4526 target = expand_unop (target_mode, bswap_optab, op0, target, 1);
42791117 4527
4528 gcc_assert (target);
4529
74bdbe96 4530 return convert_to_mode (target_mode, target, 1);
42791117 4531}
4532
c2f47e15 4533/* Expand a call to a unary builtin in EXP.
4534 Return NULL_RTX if a normal call should be emitted rather than expanding the
53800dbe 4535 function in-line. If convenient, the result should be placed in TARGET.
4536 SUBTARGET may be used as the target for computing one of EXP's operands. */
15c6cf6b 4537
53800dbe 4538static rtx
c2f47e15 4539expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target,
aecda0d6 4540 rtx subtarget, optab op_optab)
53800dbe 4541{
4542 rtx op0;
c2f47e15 4543
4544 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4545 return NULL_RTX;
53800dbe 4546
4547 /* Compute the argument. */
f97eea22 4548 op0 = expand_expr (CALL_EXPR_ARG (exp, 0),
4549 (subtarget
4550 && (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0)))
4551 == GET_MODE (subtarget))) ? subtarget : NULL_RTX,
1db6d067 4552 VOIDmode, EXPAND_NORMAL);
6a08d0ab 4553 /* Compute op, into TARGET if possible.
53800dbe 4554 Set TARGET to wherever the result comes back. */
c2f47e15 4555 target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
6aaa1f9e 4556 op_optab, op0, target, op_optab != clrsb_optab);
64db345d 4557 gcc_assert (target);
7d3f6cc7 4558
efb070c8 4559 return convert_to_mode (target_mode, target, 0);
53800dbe 4560}
89cfe6e5 4561
48e1416a 4562/* Expand a call to __builtin_expect. We just return our argument
5a74f77e 4563 as the builtin_expect semantic should've been already executed by
4564 tree branch prediction pass. */
89cfe6e5 4565
4566static rtx
c2f47e15 4567expand_builtin_expect (tree exp, rtx target)
89cfe6e5 4568{
1e4adcfc 4569 tree arg;
89cfe6e5 4570
c2f47e15 4571 if (call_expr_nargs (exp) < 2)
89cfe6e5 4572 return const0_rtx;
c2f47e15 4573 arg = CALL_EXPR_ARG (exp, 0);
89cfe6e5 4574
c2f47e15 4575 target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5a74f77e 4576 /* When guessing was done, the hints should be already stripped away. */
07311427 4577 gcc_assert (!flag_guess_branch_prob
852f689e 4578 || optimize == 0 || seen_error ());
89cfe6e5 4579 return target;
4580}
689df48e 4581
fca0886c 4582/* Expand a call to __builtin_assume_aligned. We just return our first
4583 argument as the builtin_assume_aligned semantic should've been already
4584 executed by CCP. */
4585
4586static rtx
4587expand_builtin_assume_aligned (tree exp, rtx target)
4588{
4589 if (call_expr_nargs (exp) < 2)
4590 return const0_rtx;
4591 target = expand_expr (CALL_EXPR_ARG (exp, 0), target, VOIDmode,
4592 EXPAND_NORMAL);
4593 gcc_assert (!TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 1))
4594 && (call_expr_nargs (exp) < 3
4595 || !TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 2))));
4596 return target;
4597}
4598
c22de3f0 4599void
aecda0d6 4600expand_builtin_trap (void)
a0ef1725 4601{
4602#ifdef HAVE_trap
4603 if (HAVE_trap)
f73960eb 4604 {
4605 rtx insn = emit_insn (gen_trap ());
4606 /* For trap insns when not accumulating outgoing args force
4607 REG_ARGS_SIZE note to prevent crossjumping of calls with
4608 different args sizes. */
4609 if (!ACCUMULATE_OUTGOING_ARGS)
4610 add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (stack_pointer_delta));
4611 }
a0ef1725 4612 else
4613#endif
4614 emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
4615 emit_barrier ();
4616}
78a74442 4617
d2b48f0c 4618/* Expand a call to __builtin_unreachable. We do nothing except emit
4619 a barrier saying that control flow will not pass here.
4620
4621 It is the responsibility of the program being compiled to ensure
4622 that control flow does never reach __builtin_unreachable. */
4623static void
4624expand_builtin_unreachable (void)
4625{
4626 emit_barrier ();
4627}
4628
c2f47e15 4629/* Expand EXP, a call to fabs, fabsf or fabsl.
4630 Return NULL_RTX if a normal call should be emitted rather than expanding
78a74442 4631 the function inline. If convenient, the result should be placed
4632 in TARGET. SUBTARGET may be used as the target for computing
4633 the operand. */
4634
4635static rtx
c2f47e15 4636expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
78a74442 4637{
4638 enum machine_mode mode;
4639 tree arg;
4640 rtx op0;
4641
c2f47e15 4642 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
4643 return NULL_RTX;
78a74442 4644
c2f47e15 4645 arg = CALL_EXPR_ARG (exp, 0);
c7f617c2 4646 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
78a74442 4647 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 4648 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
78a74442 4649 return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
4650}
4651
c2f47e15 4652/* Expand EXP, a call to copysign, copysignf, or copysignl.
270436f3 4653 Return NULL is a normal call should be emitted rather than expanding the
4654 function inline. If convenient, the result should be placed in TARGET.
4655 SUBTARGET may be used as the target for computing the operand. */
4656
4657static rtx
c2f47e15 4658expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
270436f3 4659{
4660 rtx op0, op1;
4661 tree arg;
4662
c2f47e15 4663 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
4664 return NULL_RTX;
270436f3 4665
c2f47e15 4666 arg = CALL_EXPR_ARG (exp, 0);
8ec3c5c2 4667 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
270436f3 4668
c2f47e15 4669 arg = CALL_EXPR_ARG (exp, 1);
8ec3c5c2 4670 op1 = expand_normal (arg);
270436f3 4671
4672 return expand_copysign (op0, op1, target);
4673}
4674
19bf118a 4675/* Create a new constant string literal and return a char* pointer to it.
4676 The STRING_CST value is the LEN characters at STR. */
1e8e9920 4677tree
19bf118a 4678build_string_literal (int len, const char *str)
4679{
4680 tree t, elem, index, type;
4681
4682 t = build_string (len, str);
4683 elem = build_type_variant (char_type_node, 1, 0);
40238f64 4684 index = build_index_type (size_int (len - 1));
19bf118a 4685 type = build_array_type (elem, index);
4686 TREE_TYPE (t) = type;
4687 TREE_CONSTANT (t) = 1;
4688 TREE_READONLY (t) = 1;
4689 TREE_STATIC (t) = 1;
4690
19bf118a 4691 type = build_pointer_type (elem);
40238f64 4692 t = build1 (ADDR_EXPR, type,
4693 build4 (ARRAY_REF, elem,
4694 t, integer_zero_node, NULL_TREE, NULL_TREE));
19bf118a 4695 return t;
4696}
4697
ac8fb6db 4698/* Expand a call to __builtin___clear_cache. */
4699
4700static rtx
4701expand_builtin___clear_cache (tree exp ATTRIBUTE_UNUSED)
4702{
4703#ifndef HAVE_clear_cache
4704#ifdef CLEAR_INSN_CACHE
4705 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
4706 does something. Just do the default expansion to a call to
4707 __clear_cache(). */
4708 return NULL_RTX;
4709#else
4710 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
4711 does nothing. There is no need to call it. Do nothing. */
4712 return const0_rtx;
4713#endif /* CLEAR_INSN_CACHE */
4714#else
4715 /* We have a "clear_cache" insn, and it will handle everything. */
4716 tree begin, end;
4717 rtx begin_rtx, end_rtx;
ac8fb6db 4718
4719 /* We must not expand to a library call. If we did, any
4720 fallback library function in libgcc that might contain a call to
4721 __builtin___clear_cache() would recurse infinitely. */
4722 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4723 {
4724 error ("both arguments to %<__builtin___clear_cache%> must be pointers");
4725 return const0_rtx;
4726 }
4727
4728 if (HAVE_clear_cache)
4729 {
8786db1e 4730 struct expand_operand ops[2];
ac8fb6db 4731
4732 begin = CALL_EXPR_ARG (exp, 0);
4733 begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
ac8fb6db 4734
4735 end = CALL_EXPR_ARG (exp, 1);
4736 end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
ac8fb6db 4737
8786db1e 4738 create_address_operand (&ops[0], begin_rtx);
4739 create_address_operand (&ops[1], end_rtx);
4740 if (maybe_expand_insn (CODE_FOR_clear_cache, 2, ops))
4741 return const0_rtx;
ac8fb6db 4742 }
4743 return const0_rtx;
4744#endif /* HAVE_clear_cache */
4745}
4746
4ee9c684 4747/* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
4748
4749static rtx
4750round_trampoline_addr (rtx tramp)
4751{
4752 rtx temp, addend, mask;
4753
4754 /* If we don't need too much alignment, we'll have been guaranteed
4755 proper alignment by get_trampoline_type. */
4756 if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
4757 return tramp;
4758
4759 /* Round address up to desired boundary. */
4760 temp = gen_reg_rtx (Pmode);
0359f9f5 4761 addend = gen_int_mode (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1, Pmode);
4762 mask = gen_int_mode (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT, Pmode);
4ee9c684 4763
4764 temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
4765 temp, 0, OPTAB_LIB_WIDEN);
4766 tramp = expand_simple_binop (Pmode, AND, temp, mask,
4767 temp, 0, OPTAB_LIB_WIDEN);
4768
4769 return tramp;
4770}
4771
4772static rtx
c307f106 4773expand_builtin_init_trampoline (tree exp, bool onstack)
4ee9c684 4774{
4775 tree t_tramp, t_func, t_chain;
82c7907c 4776 rtx m_tramp, r_tramp, r_chain, tmp;
4ee9c684 4777
c2f47e15 4778 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
4ee9c684 4779 POINTER_TYPE, VOID_TYPE))
4780 return NULL_RTX;
4781
c2f47e15 4782 t_tramp = CALL_EXPR_ARG (exp, 0);
4783 t_func = CALL_EXPR_ARG (exp, 1);
4784 t_chain = CALL_EXPR_ARG (exp, 2);
4ee9c684 4785
8ec3c5c2 4786 r_tramp = expand_normal (t_tramp);
82c7907c 4787 m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
4788 MEM_NOTRAP_P (m_tramp) = 1;
4789
c307f106 4790 /* If ONSTACK, the TRAMP argument should be the address of a field
4791 within the local function's FRAME decl. Either way, let's see if
4792 we can fill in the MEM_ATTRs for this memory. */
82c7907c 4793 if (TREE_CODE (t_tramp) == ADDR_EXPR)
f4146cb8 4794 set_mem_attributes (m_tramp, TREE_OPERAND (t_tramp, 0), true);
82c7907c 4795
c307f106 4796 /* Creator of a heap trampoline is responsible for making sure the
4797 address is aligned to at least STACK_BOUNDARY. Normally malloc
4798 will ensure this anyhow. */
82c7907c 4799 tmp = round_trampoline_addr (r_tramp);
4800 if (tmp != r_tramp)
4801 {
4802 m_tramp = change_address (m_tramp, BLKmode, tmp);
4803 set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
5b2a69fa 4804 set_mem_size (m_tramp, TRAMPOLINE_SIZE);
82c7907c 4805 }
4806
4807 /* The FUNC argument should be the address of the nested function.
4808 Extract the actual function decl to pass to the hook. */
4809 gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
4810 t_func = TREE_OPERAND (t_func, 0);
4811 gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
4812
8ec3c5c2 4813 r_chain = expand_normal (t_chain);
4ee9c684 4814
4815 /* Generate insns to initialize the trampoline. */
82c7907c 4816 targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
4ee9c684 4817
c307f106 4818 if (onstack)
4819 {
4820 trampolines_created = 1;
8bc8a8f4 4821
c307f106 4822 warning_at (DECL_SOURCE_LOCATION (t_func), OPT_Wtrampolines,
4823 "trampoline generated for nested function %qD", t_func);
4824 }
8bc8a8f4 4825
4ee9c684 4826 return const0_rtx;
4827}
4828
4829static rtx
c2f47e15 4830expand_builtin_adjust_trampoline (tree exp)
4ee9c684 4831{
4832 rtx tramp;
4833
c2f47e15 4834 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
4ee9c684 4835 return NULL_RTX;
4836
c2f47e15 4837 tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
4ee9c684 4838 tramp = round_trampoline_addr (tramp);
82c7907c 4839 if (targetm.calls.trampoline_adjust_address)
4840 tramp = targetm.calls.trampoline_adjust_address (tramp);
4ee9c684 4841
4842 return tramp;
4843}
4844
93f564d6 4845/* Expand the call EXP to the built-in signbit, signbitf or signbitl
4846 function. The function first checks whether the back end provides
4847 an insn to implement signbit for the respective mode. If not, it
4848 checks whether the floating point format of the value is such that
4849 the sign bit can be extracted. If that is not the case, the
4850 function returns NULL_RTX to indicate that a normal call should be
4851 emitted rather than expanding the function in-line. EXP is the
4852 expression that is a call to the builtin function; if convenient,
4853 the result should be placed in TARGET. */
27f261ef 4854static rtx
4855expand_builtin_signbit (tree exp, rtx target)
4856{
4857 const struct real_format *fmt;
4858 enum machine_mode fmode, imode, rmode;
c2f47e15 4859 tree arg;
ca4f1f5b 4860 int word, bitpos;
27eda240 4861 enum insn_code icode;
27f261ef 4862 rtx temp;
389dd41b 4863 location_t loc = EXPR_LOCATION (exp);
27f261ef 4864
c2f47e15 4865 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
4866 return NULL_RTX;
27f261ef 4867
c2f47e15 4868 arg = CALL_EXPR_ARG (exp, 0);
27f261ef 4869 fmode = TYPE_MODE (TREE_TYPE (arg));
4870 rmode = TYPE_MODE (TREE_TYPE (exp));
4871 fmt = REAL_MODE_FORMAT (fmode);
4872
93f564d6 4873 arg = builtin_save_expr (arg);
4874
4875 /* Expand the argument yielding a RTX expression. */
4876 temp = expand_normal (arg);
4877
4878 /* Check if the back end provides an insn that handles signbit for the
4879 argument's mode. */
d6bf3b14 4880 icode = optab_handler (signbit_optab, fmode);
27eda240 4881 if (icode != CODE_FOR_nothing)
93f564d6 4882 {
4e2a2fb4 4883 rtx last = get_last_insn ();
93f564d6 4884 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
4e2a2fb4 4885 if (maybe_emit_unop_insn (icode, target, temp, UNKNOWN))
4886 return target;
4887 delete_insns_since (last);
93f564d6 4888 }
4889
27f261ef 4890 /* For floating point formats without a sign bit, implement signbit
4891 as "ARG < 0.0". */
8d564692 4892 bitpos = fmt->signbit_ro;
ca4f1f5b 4893 if (bitpos < 0)
27f261ef 4894 {
4895 /* But we can't do this if the format supports signed zero. */
4896 if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
c2f47e15 4897 return NULL_RTX;
27f261ef 4898
389dd41b 4899 arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
49d00087 4900 build_real (TREE_TYPE (arg), dconst0));
27f261ef 4901 return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
4902 }
4903
ca4f1f5b 4904 if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
27f261ef 4905 {
ca4f1f5b 4906 imode = int_mode_for_mode (fmode);
4907 if (imode == BLKmode)
c2f47e15 4908 return NULL_RTX;
ca4f1f5b 4909 temp = gen_lowpart (imode, temp);
24fd4260 4910 }
4911 else
4912 {
ca4f1f5b 4913 imode = word_mode;
4914 /* Handle targets with different FP word orders. */
4915 if (FLOAT_WORDS_BIG_ENDIAN)
a0c938f0 4916 word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
ca4f1f5b 4917 else
a0c938f0 4918 word = bitpos / BITS_PER_WORD;
ca4f1f5b 4919 temp = operand_subword_force (temp, word, fmode);
4920 bitpos = bitpos % BITS_PER_WORD;
4921 }
4922
44b0f1d0 4923 /* Force the intermediate word_mode (or narrower) result into a
4924 register. This avoids attempting to create paradoxical SUBREGs
4925 of floating point modes below. */
4926 temp = force_reg (imode, temp);
4927
ca4f1f5b 4928 /* If the bitpos is within the "result mode" lowpart, the operation
4929 can be implement with a single bitwise AND. Otherwise, we need
4930 a right shift and an AND. */
4931
4932 if (bitpos < GET_MODE_BITSIZE (rmode))
4933 {
cf8f0e63 4934 double_int mask = double_int_zero.set_bit (bitpos);
27f261ef 4935
4a46f016 4936 if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
ca4f1f5b 4937 temp = gen_lowpart (rmode, temp);
24fd4260 4938 temp = expand_binop (rmode, and_optab, temp,
3e052aec 4939 immed_double_int_const (mask, rmode),
ca4f1f5b 4940 NULL_RTX, 1, OPTAB_LIB_WIDEN);
27f261ef 4941 }
ca4f1f5b 4942 else
4943 {
4944 /* Perform a logical right shift to place the signbit in the least
a0c938f0 4945 significant bit, then truncate the result to the desired mode
ca4f1f5b 4946 and mask just this bit. */
f5ff0b21 4947 temp = expand_shift (RSHIFT_EXPR, imode, temp, bitpos, NULL_RTX, 1);
ca4f1f5b 4948 temp = gen_lowpart (rmode, temp);
4949 temp = expand_binop (rmode, and_optab, temp, const1_rtx,
4950 NULL_RTX, 1, OPTAB_LIB_WIDEN);
4951 }
4952
27f261ef 4953 return temp;
4954}
73673831 4955
4956/* Expand fork or exec calls. TARGET is the desired target of the
c2f47e15 4957 call. EXP is the call. FN is the
73673831 4958 identificator of the actual function. IGNORE is nonzero if the
4959 value is to be ignored. */
4960
4961static rtx
c2f47e15 4962expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
73673831 4963{
4964 tree id, decl;
4965 tree call;
4966
4967 /* If we are not profiling, just call the function. */
4968 if (!profile_arc_flag)
4969 return NULL_RTX;
4970
4971 /* Otherwise call the wrapper. This should be equivalent for the rest of
4972 compiler, so the code does not diverge, and the wrapper may run the
9c9bad97 4973 code necessary for keeping the profiling sane. */
73673831 4974
4975 switch (DECL_FUNCTION_CODE (fn))
4976 {
4977 case BUILT_IN_FORK:
4978 id = get_identifier ("__gcov_fork");
4979 break;
4980
4981 case BUILT_IN_EXECL:
4982 id = get_identifier ("__gcov_execl");
4983 break;
4984
4985 case BUILT_IN_EXECV:
4986 id = get_identifier ("__gcov_execv");
4987 break;
4988
4989 case BUILT_IN_EXECLP:
4990 id = get_identifier ("__gcov_execlp");
4991 break;
4992
4993 case BUILT_IN_EXECLE:
4994 id = get_identifier ("__gcov_execle");
4995 break;
4996
4997 case BUILT_IN_EXECVP:
4998 id = get_identifier ("__gcov_execvp");
4999 break;
5000
5001 case BUILT_IN_EXECVE:
5002 id = get_identifier ("__gcov_execve");
5003 break;
5004
5005 default:
64db345d 5006 gcc_unreachable ();
73673831 5007 }
5008
e60a6f7b 5009 decl = build_decl (DECL_SOURCE_LOCATION (fn),
5010 FUNCTION_DECL, id, TREE_TYPE (fn));
73673831 5011 DECL_EXTERNAL (decl) = 1;
5012 TREE_PUBLIC (decl) = 1;
5013 DECL_ARTIFICIAL (decl) = 1;
5014 TREE_NOTHROW (decl) = 1;
e82d310b 5015 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
5016 DECL_VISIBILITY_SPECIFIED (decl) = 1;
389dd41b 5017 call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0);
73673831 5018 return expand_call (call, target, ignore);
c2f47e15 5019 }
48e1416a 5020
b6a5fc45 5021
5022\f
3e272de8 5023/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
5024 the pointer in these functions is void*, the tree optimizers may remove
5025 casts. The mode computed in expand_builtin isn't reliable either, due
5026 to __sync_bool_compare_and_swap.
5027
5028 FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
5029 group of builtins. This gives us log2 of the mode size. */
5030
5031static inline enum machine_mode
5032get_builtin_sync_mode (int fcode_diff)
5033{
ad3a13b5 5034 /* The size is not negotiable, so ask not to get BLKmode in return
5035 if the target indicates that a smaller size would be better. */
5036 return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
3e272de8 5037}
5038
041e0215 5039/* Expand the memory expression LOC and return the appropriate memory operand
5040 for the builtin_sync operations. */
5041
5042static rtx
5043get_builtin_sync_mem (tree loc, enum machine_mode mode)
5044{
5045 rtx addr, mem;
5046
7f4d56ad 5047 addr = expand_expr (loc, NULL_RTX, ptr_mode, EXPAND_SUM);
5048 addr = convert_memory_address (Pmode, addr);
041e0215 5049
5050 /* Note that we explicitly do not want any alias information for this
5051 memory, so that we kill all other live memories. Otherwise we don't
5052 satisfy the full barrier semantics of the intrinsic. */
5053 mem = validize_mem (gen_rtx_MEM (mode, addr));
5054
153c3b50 5055 /* The alignment needs to be at least according to that of the mode. */
5056 set_mem_align (mem, MAX (GET_MODE_ALIGNMENT (mode),
957d0361 5057 get_pointer_alignment (loc)));
c94cfd1c 5058 set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
041e0215 5059 MEM_VOLATILE_P (mem) = 1;
5060
5061 return mem;
5062}
5063
1cd6e20d 5064/* Make sure an argument is in the right mode.
5065 EXP is the tree argument.
5066 MODE is the mode it should be in. */
5067
5068static rtx
5069expand_expr_force_mode (tree exp, enum machine_mode mode)
5070{
5071 rtx val;
5072 enum machine_mode old_mode;
5073
5074 val = expand_expr (exp, NULL_RTX, mode, EXPAND_NORMAL);
5075 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5076 of CONST_INTs, where we know the old_mode only from the call argument. */
5077
5078 old_mode = GET_MODE (val);
5079 if (old_mode == VOIDmode)
5080 old_mode = TYPE_MODE (TREE_TYPE (exp));
5081 val = convert_modes (mode, old_mode, val, 1);
5082 return val;
5083}
5084
5085
b6a5fc45 5086/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
c2f47e15 5087 EXP is the CALL_EXPR. CODE is the rtx code
b6a5fc45 5088 that corresponds to the arithmetic or logical operation from the name;
5089 an exception here is that NOT actually means NAND. TARGET is an optional
5090 place for us to store the results; AFTER is true if this is the
1cd6e20d 5091 fetch_and_xxx form. */
b6a5fc45 5092
5093static rtx
c2f47e15 5094expand_builtin_sync_operation (enum machine_mode mode, tree exp,
3e272de8 5095 enum rtx_code code, bool after,
1cd6e20d 5096 rtx target)
b6a5fc45 5097{
041e0215 5098 rtx val, mem;
e60a6f7b 5099 location_t loc = EXPR_LOCATION (exp);
b6a5fc45 5100
cf73e559 5101 if (code == NOT && warn_sync_nand)
5102 {
5103 tree fndecl = get_callee_fndecl (exp);
5104 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
5105
5106 static bool warned_f_a_n, warned_n_a_f;
5107
5108 switch (fcode)
5109 {
2797f13a 5110 case BUILT_IN_SYNC_FETCH_AND_NAND_1:
5111 case BUILT_IN_SYNC_FETCH_AND_NAND_2:
5112 case BUILT_IN_SYNC_FETCH_AND_NAND_4:
5113 case BUILT_IN_SYNC_FETCH_AND_NAND_8:
5114 case BUILT_IN_SYNC_FETCH_AND_NAND_16:
cf73e559 5115 if (warned_f_a_n)
5116 break;
5117
b9a16870 5118 fndecl = builtin_decl_implicit (BUILT_IN_SYNC_FETCH_AND_NAND_N);
e60a6f7b 5119 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
cf73e559 5120 warned_f_a_n = true;
5121 break;
5122
2797f13a 5123 case BUILT_IN_SYNC_NAND_AND_FETCH_1:
5124 case BUILT_IN_SYNC_NAND_AND_FETCH_2:
5125 case BUILT_IN_SYNC_NAND_AND_FETCH_4:
5126 case BUILT_IN_SYNC_NAND_AND_FETCH_8:
5127 case BUILT_IN_SYNC_NAND_AND_FETCH_16:
cf73e559 5128 if (warned_n_a_f)
5129 break;
5130
b9a16870 5131 fndecl = builtin_decl_implicit (BUILT_IN_SYNC_NAND_AND_FETCH_N);
e60a6f7b 5132 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
cf73e559 5133 warned_n_a_f = true;
5134 break;
5135
5136 default:
5137 gcc_unreachable ();
5138 }
5139 }
5140
b6a5fc45 5141 /* Expand the operands. */
c2f47e15 5142 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1cd6e20d 5143 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
b6a5fc45 5144
1cd6e20d 5145 return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SEQ_CST,
5146 after);
b6a5fc45 5147}
5148
5149/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
c2f47e15 5150 intrinsics. EXP is the CALL_EXPR. IS_BOOL is
b6a5fc45 5151 true if this is the boolean form. TARGET is a place for us to store the
5152 results; this is NOT optional if IS_BOOL is true. */
5153
5154static rtx
c2f47e15 5155expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
3e272de8 5156 bool is_bool, rtx target)
b6a5fc45 5157{
041e0215 5158 rtx old_val, new_val, mem;
ba885f6a 5159 rtx *pbool, *poval;
b6a5fc45 5160
5161 /* Expand the operands. */
c2f47e15 5162 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1cd6e20d 5163 old_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5164 new_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
b6a5fc45 5165
ba885f6a 5166 pbool = poval = NULL;
5167 if (target != const0_rtx)
5168 {
5169 if (is_bool)
5170 pbool = &target;
5171 else
5172 poval = &target;
5173 }
5174 if (!expand_atomic_compare_and_swap (pbool, poval, mem, old_val, new_val,
5175 false, MEMMODEL_SEQ_CST,
5176 MEMMODEL_SEQ_CST))
1cd6e20d 5177 return NULL_RTX;
c2f47e15 5178
1cd6e20d 5179 return target;
b6a5fc45 5180}
5181
5182/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
5183 general form is actually an atomic exchange, and some targets only
5184 support a reduced form with the second argument being a constant 1.
48e1416a 5185 EXP is the CALL_EXPR; TARGET is an optional place for us to store
c2f47e15 5186 the results. */
b6a5fc45 5187
5188static rtx
2797f13a 5189expand_builtin_sync_lock_test_and_set (enum machine_mode mode, tree exp,
1cd6e20d 5190 rtx target)
b6a5fc45 5191{
041e0215 5192 rtx val, mem;
b6a5fc45 5193
5194 /* Expand the operands. */
c2f47e15 5195 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1cd6e20d 5196 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5197
7821cde1 5198 return expand_sync_lock_test_and_set (target, mem, val);
1cd6e20d 5199}
5200
5201/* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */
5202
5203static void
5204expand_builtin_sync_lock_release (enum machine_mode mode, tree exp)
5205{
5206 rtx mem;
5207
5208 /* Expand the operands. */
5209 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5210
8808bf16 5211 expand_atomic_store (mem, const0_rtx, MEMMODEL_RELEASE, true);
1cd6e20d 5212}
5213
5214/* Given an integer representing an ``enum memmodel'', verify its
5215 correctness and return the memory model enum. */
5216
5217static enum memmodel
5218get_memmodel (tree exp)
5219{
5220 rtx op;
7f738025 5221 unsigned HOST_WIDE_INT val;
1cd6e20d 5222
5223 /* If the parameter is not a constant, it's a run time value so we'll just
5224 convert it to MEMMODEL_SEQ_CST to avoid annoying runtime checking. */
5225 if (TREE_CODE (exp) != INTEGER_CST)
5226 return MEMMODEL_SEQ_CST;
5227
5228 op = expand_normal (exp);
7f738025 5229
5230 val = INTVAL (op);
5231 if (targetm.memmodel_check)
5232 val = targetm.memmodel_check (val);
5233 else if (val & ~MEMMODEL_MASK)
5234 {
5235 warning (OPT_Winvalid_memory_model,
5236 "Unknown architecture specifier in memory model to builtin.");
5237 return MEMMODEL_SEQ_CST;
5238 }
5239
9af5ce0c 5240 if ((INTVAL (op) & MEMMODEL_MASK) >= MEMMODEL_LAST)
1cd6e20d 5241 {
5242 warning (OPT_Winvalid_memory_model,
5243 "invalid memory model argument to builtin");
5244 return MEMMODEL_SEQ_CST;
5245 }
7f738025 5246
5247 return (enum memmodel) val;
1cd6e20d 5248}
5249
5250/* Expand the __atomic_exchange intrinsic:
5251 TYPE __atomic_exchange (TYPE *object, TYPE desired, enum memmodel)
5252 EXP is the CALL_EXPR.
5253 TARGET is an optional place for us to store the results. */
5254
5255static rtx
5256expand_builtin_atomic_exchange (enum machine_mode mode, tree exp, rtx target)
5257{
5258 rtx val, mem;
5259 enum memmodel model;
5260
5261 model = get_memmodel (CALL_EXPR_ARG (exp, 2));
7f738025 5262 if ((model & MEMMODEL_MASK) == MEMMODEL_CONSUME)
1cd6e20d 5263 {
5264 error ("invalid memory model for %<__atomic_exchange%>");
5265 return NULL_RTX;
5266 }
5267
5268 if (!flag_inline_atomics)
5269 return NULL_RTX;
5270
5271 /* Expand the operands. */
5272 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5273 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5274
7821cde1 5275 return expand_atomic_exchange (target, mem, val, model);
1cd6e20d 5276}
5277
5278/* Expand the __atomic_compare_exchange intrinsic:
5279 bool __atomic_compare_exchange (TYPE *object, TYPE *expect,
5280 TYPE desired, BOOL weak,
5281 enum memmodel success,
5282 enum memmodel failure)
5283 EXP is the CALL_EXPR.
5284 TARGET is an optional place for us to store the results. */
5285
5286static rtx
5287expand_builtin_atomic_compare_exchange (enum machine_mode mode, tree exp,
5288 rtx target)
5289{
5290 rtx expect, desired, mem, oldval;
5291 enum memmodel success, failure;
5292 tree weak;
5293 bool is_weak;
5294
5295 success = get_memmodel (CALL_EXPR_ARG (exp, 4));
5296 failure = get_memmodel (CALL_EXPR_ARG (exp, 5));
5297
7f738025 5298 if ((failure & MEMMODEL_MASK) == MEMMODEL_RELEASE
5299 || (failure & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
1cd6e20d 5300 {
5301 error ("invalid failure memory model for %<__atomic_compare_exchange%>");
5302 return NULL_RTX;
5303 }
5304
5305 if (failure > success)
5306 {
5307 error ("failure memory model cannot be stronger than success "
5308 "memory model for %<__atomic_compare_exchange%>");
5309 return NULL_RTX;
5310 }
5311
5312 if (!flag_inline_atomics)
5313 return NULL_RTX;
5314
5315 /* Expand the operands. */
5316 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5317
5318 expect = expand_normal (CALL_EXPR_ARG (exp, 1));
5319 expect = convert_memory_address (Pmode, expect);
c401b131 5320 expect = gen_rtx_MEM (mode, expect);
1cd6e20d 5321 desired = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
5322
5323 weak = CALL_EXPR_ARG (exp, 3);
5324 is_weak = false;
fcb97e84 5325 if (tree_fits_shwi_p (weak) && tree_to_shwi (weak) != 0)
1cd6e20d 5326 is_weak = true;
5327
c401b131 5328 oldval = expect;
ba885f6a 5329 if (!expand_atomic_compare_and_swap ((target == const0_rtx ? NULL : &target),
5330 &oldval, mem, oldval, desired,
5331 is_weak, success, failure))
1cd6e20d 5332 return NULL_RTX;
5333
c401b131 5334 if (oldval != expect)
5335 emit_move_insn (expect, oldval);
5336
1cd6e20d 5337 return target;
5338}
5339
5340/* Expand the __atomic_load intrinsic:
5341 TYPE __atomic_load (TYPE *object, enum memmodel)
5342 EXP is the CALL_EXPR.
5343 TARGET is an optional place for us to store the results. */
5344
5345static rtx
5346expand_builtin_atomic_load (enum machine_mode mode, tree exp, rtx target)
5347{
5348 rtx mem;
5349 enum memmodel model;
5350
5351 model = get_memmodel (CALL_EXPR_ARG (exp, 1));
7f738025 5352 if ((model & MEMMODEL_MASK) == MEMMODEL_RELEASE
5353 || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
1cd6e20d 5354 {
5355 error ("invalid memory model for %<__atomic_load%>");
5356 return NULL_RTX;
5357 }
5358
5359 if (!flag_inline_atomics)
5360 return NULL_RTX;
5361
5362 /* Expand the operand. */
5363 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5364
5365 return expand_atomic_load (target, mem, model);
5366}
5367
5368
5369/* Expand the __atomic_store intrinsic:
5370 void __atomic_store (TYPE *object, TYPE desired, enum memmodel)
5371 EXP is the CALL_EXPR.
5372 TARGET is an optional place for us to store the results. */
5373
5374static rtx
5375expand_builtin_atomic_store (enum machine_mode mode, tree exp)
5376{
5377 rtx mem, val;
5378 enum memmodel model;
5379
5380 model = get_memmodel (CALL_EXPR_ARG (exp, 2));
7f738025 5381 if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED
5382 && (model & MEMMODEL_MASK) != MEMMODEL_SEQ_CST
5383 && (model & MEMMODEL_MASK) != MEMMODEL_RELEASE)
1cd6e20d 5384 {
5385 error ("invalid memory model for %<__atomic_store%>");
5386 return NULL_RTX;
5387 }
5388
5389 if (!flag_inline_atomics)
5390 return NULL_RTX;
5391
5392 /* Expand the operands. */
5393 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5394 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5395
8808bf16 5396 return expand_atomic_store (mem, val, model, false);
1cd6e20d 5397}
5398
5399/* Expand the __atomic_fetch_XXX intrinsic:
5400 TYPE __atomic_fetch_XXX (TYPE *object, TYPE val, enum memmodel)
5401 EXP is the CALL_EXPR.
5402 TARGET is an optional place for us to store the results.
5403 CODE is the operation, PLUS, MINUS, ADD, XOR, or IOR.
5404 FETCH_AFTER is true if returning the result of the operation.
5405 FETCH_AFTER is false if returning the value before the operation.
5406 IGNORE is true if the result is not used.
5407 EXT_CALL is the correct builtin for an external call if this cannot be
5408 resolved to an instruction sequence. */
5409
5410static rtx
5411expand_builtin_atomic_fetch_op (enum machine_mode mode, tree exp, rtx target,
5412 enum rtx_code code, bool fetch_after,
5413 bool ignore, enum built_in_function ext_call)
5414{
5415 rtx val, mem, ret;
5416 enum memmodel model;
5417 tree fndecl;
5418 tree addr;
5419
5420 model = get_memmodel (CALL_EXPR_ARG (exp, 2));
5421
5422 /* Expand the operands. */
5423 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5424 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5425
5426 /* Only try generating instructions if inlining is turned on. */
5427 if (flag_inline_atomics)
5428 {
5429 ret = expand_atomic_fetch_op (target, mem, val, code, model, fetch_after);
5430 if (ret)
5431 return ret;
5432 }
5433
5434 /* Return if a different routine isn't needed for the library call. */
5435 if (ext_call == BUILT_IN_NONE)
5436 return NULL_RTX;
5437
5438 /* Change the call to the specified function. */
5439 fndecl = get_callee_fndecl (exp);
5440 addr = CALL_EXPR_FN (exp);
5441 STRIP_NOPS (addr);
5442
5443 gcc_assert (TREE_OPERAND (addr, 0) == fndecl);
9af5ce0c 5444 TREE_OPERAND (addr, 0) = builtin_decl_explicit (ext_call);
1cd6e20d 5445
5446 /* Expand the call here so we can emit trailing code. */
5447 ret = expand_call (exp, target, ignore);
5448
5449 /* Replace the original function just in case it matters. */
5450 TREE_OPERAND (addr, 0) = fndecl;
5451
5452 /* Then issue the arithmetic correction to return the right result. */
5453 if (!ignore)
c449f851 5454 {
5455 if (code == NOT)
5456 {
5457 ret = expand_simple_binop (mode, AND, ret, val, NULL_RTX, true,
5458 OPTAB_LIB_WIDEN);
5459 ret = expand_simple_unop (mode, NOT, ret, target, true);
5460 }
5461 else
5462 ret = expand_simple_binop (mode, code, ret, val, target, true,
5463 OPTAB_LIB_WIDEN);
5464 }
1cd6e20d 5465 return ret;
5466}
5467
10b744a3 5468
7821cde1 5469#ifndef HAVE_atomic_clear
5470# define HAVE_atomic_clear 0
5471# define gen_atomic_clear(x,y) (gcc_unreachable (), NULL_RTX)
5472#endif
5473
10b744a3 5474/* Expand an atomic clear operation.
5475 void _atomic_clear (BOOL *obj, enum memmodel)
5476 EXP is the call expression. */
5477
5478static rtx
5479expand_builtin_atomic_clear (tree exp)
5480{
5481 enum machine_mode mode;
5482 rtx mem, ret;
5483 enum memmodel model;
5484
5485 mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0);
5486 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5487 model = get_memmodel (CALL_EXPR_ARG (exp, 1));
5488
7f738025 5489 if ((model & MEMMODEL_MASK) == MEMMODEL_ACQUIRE
5490 || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
10b744a3 5491 {
5492 error ("invalid memory model for %<__atomic_store%>");
5493 return const0_rtx;
5494 }
5495
7821cde1 5496 if (HAVE_atomic_clear)
5497 {
5498 emit_insn (gen_atomic_clear (mem, model));
5499 return const0_rtx;
5500 }
5501
10b744a3 5502 /* Try issuing an __atomic_store, and allow fallback to __sync_lock_release.
5503 Failing that, a store is issued by __atomic_store. The only way this can
5504 fail is if the bool type is larger than a word size. Unlikely, but
5505 handle it anyway for completeness. Assume a single threaded model since
5506 there is no atomic support in this case, and no barriers are required. */
5507 ret = expand_atomic_store (mem, const0_rtx, model, true);
5508 if (!ret)
5509 emit_move_insn (mem, const0_rtx);
5510 return const0_rtx;
5511}
5512
5513/* Expand an atomic test_and_set operation.
5514 bool _atomic_test_and_set (BOOL *obj, enum memmodel)
5515 EXP is the call expression. */
5516
5517static rtx
7821cde1 5518expand_builtin_atomic_test_and_set (tree exp, rtx target)
10b744a3 5519{
7821cde1 5520 rtx mem;
10b744a3 5521 enum memmodel model;
5522 enum machine_mode mode;
5523
5524 mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0);
5525 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5526 model = get_memmodel (CALL_EXPR_ARG (exp, 1));
5527
7821cde1 5528 return expand_atomic_test_and_set (target, mem, model);
10b744a3 5529}
5530
5531
1cd6e20d 5532/* Return true if (optional) argument ARG1 of size ARG0 is always lock free on
5533 this architecture. If ARG1 is NULL, use typical alignment for size ARG0. */
5534
5535static tree
5536fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
5537{
5538 int size;
5539 enum machine_mode mode;
5540 unsigned int mode_align, type_align;
5541
5542 if (TREE_CODE (arg0) != INTEGER_CST)
5543 return NULL_TREE;
b6a5fc45 5544
1cd6e20d 5545 size = INTVAL (expand_normal (arg0)) * BITS_PER_UNIT;
5546 mode = mode_for_size (size, MODE_INT, 0);
5547 mode_align = GET_MODE_ALIGNMENT (mode);
5548
5549 if (TREE_CODE (arg1) == INTEGER_CST && INTVAL (expand_normal (arg1)) == 0)
5550 type_align = mode_align;
5551 else
5552 {
5553 tree ttype = TREE_TYPE (arg1);
5554
5555 /* This function is usually invoked and folded immediately by the front
5556 end before anything else has a chance to look at it. The pointer
5557 parameter at this point is usually cast to a void *, so check for that
5558 and look past the cast. */
5559 if (TREE_CODE (arg1) == NOP_EXPR && POINTER_TYPE_P (ttype)
5560 && VOID_TYPE_P (TREE_TYPE (ttype)))
5561 arg1 = TREE_OPERAND (arg1, 0);
5562
5563 ttype = TREE_TYPE (arg1);
5564 gcc_assert (POINTER_TYPE_P (ttype));
5565
5566 /* Get the underlying type of the object. */
5567 ttype = TREE_TYPE (ttype);
5568 type_align = TYPE_ALIGN (ttype);
5569 }
5570
5571 /* If the object has smaller alignment, the the lock free routines cannot
5572 be used. */
5573 if (type_align < mode_align)
06308d2a 5574 return boolean_false_node;
1cd6e20d 5575
5576 /* Check if a compare_and_swap pattern exists for the mode which represents
5577 the required size. The pattern is not allowed to fail, so the existence
5578 of the pattern indicates support is present. */
29139cdc 5579 if (can_compare_and_swap_p (mode, true))
06308d2a 5580 return boolean_true_node;
1cd6e20d 5581 else
06308d2a 5582 return boolean_false_node;
1cd6e20d 5583}
5584
5585/* Return true if the parameters to call EXP represent an object which will
5586 always generate lock free instructions. The first argument represents the
5587 size of the object, and the second parameter is a pointer to the object
5588 itself. If NULL is passed for the object, then the result is based on
5589 typical alignment for an object of the specified size. Otherwise return
5590 false. */
5591
5592static rtx
5593expand_builtin_atomic_always_lock_free (tree exp)
5594{
5595 tree size;
5596 tree arg0 = CALL_EXPR_ARG (exp, 0);
5597 tree arg1 = CALL_EXPR_ARG (exp, 1);
5598
5599 if (TREE_CODE (arg0) != INTEGER_CST)
5600 {
5601 error ("non-constant argument 1 to __atomic_always_lock_free");
5602 return const0_rtx;
5603 }
5604
5605 size = fold_builtin_atomic_always_lock_free (arg0, arg1);
06308d2a 5606 if (size == boolean_true_node)
1cd6e20d 5607 return const1_rtx;
5608 return const0_rtx;
5609}
5610
5611/* Return a one or zero if it can be determined that object ARG1 of size ARG
5612 is lock free on this architecture. */
5613
5614static tree
5615fold_builtin_atomic_is_lock_free (tree arg0, tree arg1)
5616{
5617 if (!flag_inline_atomics)
5618 return NULL_TREE;
5619
5620 /* If it isn't always lock free, don't generate a result. */
06308d2a 5621 if (fold_builtin_atomic_always_lock_free (arg0, arg1) == boolean_true_node)
5622 return boolean_true_node;
1cd6e20d 5623
5624 return NULL_TREE;
5625}
5626
5627/* Return true if the parameters to call EXP represent an object which will
5628 always generate lock free instructions. The first argument represents the
5629 size of the object, and the second parameter is a pointer to the object
5630 itself. If NULL is passed for the object, then the result is based on
5631 typical alignment for an object of the specified size. Otherwise return
5632 NULL*/
5633
5634static rtx
5635expand_builtin_atomic_is_lock_free (tree exp)
5636{
5637 tree size;
5638 tree arg0 = CALL_EXPR_ARG (exp, 0);
5639 tree arg1 = CALL_EXPR_ARG (exp, 1);
5640
5641 if (!INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
5642 {
5643 error ("non-integer argument 1 to __atomic_is_lock_free");
5644 return NULL_RTX;
5645 }
5646
5647 if (!flag_inline_atomics)
5648 return NULL_RTX;
5649
5650 /* If the value is known at compile time, return the RTX for it. */
5651 size = fold_builtin_atomic_is_lock_free (arg0, arg1);
06308d2a 5652 if (size == boolean_true_node)
1cd6e20d 5653 return const1_rtx;
5654
5655 return NULL_RTX;
5656}
5657
1cd6e20d 5658/* Expand the __atomic_thread_fence intrinsic:
5659 void __atomic_thread_fence (enum memmodel)
5660 EXP is the CALL_EXPR. */
5661
5662static void
5663expand_builtin_atomic_thread_fence (tree exp)
5664{
fe54c06b 5665 enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
5666 expand_mem_thread_fence (model);
1cd6e20d 5667}
5668
5669/* Expand the __atomic_signal_fence intrinsic:
5670 void __atomic_signal_fence (enum memmodel)
5671 EXP is the CALL_EXPR. */
5672
5673static void
5674expand_builtin_atomic_signal_fence (tree exp)
5675{
fe54c06b 5676 enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
5677 expand_mem_signal_fence (model);
b6a5fc45 5678}
5679
5680/* Expand the __sync_synchronize intrinsic. */
5681
5682static void
2797f13a 5683expand_builtin_sync_synchronize (void)
b6a5fc45 5684{
fe54c06b 5685 expand_mem_thread_fence (MEMMODEL_SEQ_CST);
b6a5fc45 5686}
5687
badaa04c 5688static rtx
5689expand_builtin_thread_pointer (tree exp, rtx target)
5690{
5691 enum insn_code icode;
5692 if (!validate_arglist (exp, VOID_TYPE))
5693 return const0_rtx;
5694 icode = direct_optab_handler (get_thread_pointer_optab, Pmode);
5695 if (icode != CODE_FOR_nothing)
5696 {
5697 struct expand_operand op;
5698 if (!REG_P (target) || GET_MODE (target) != Pmode)
5699 target = gen_reg_rtx (Pmode);
5700 create_output_operand (&op, target, Pmode);
5701 expand_insn (icode, 1, &op);
5702 return target;
5703 }
5704 error ("__builtin_thread_pointer is not supported on this target");
5705 return const0_rtx;
5706}
5707
5708static void
5709expand_builtin_set_thread_pointer (tree exp)
5710{
5711 enum insn_code icode;
5712 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
5713 return;
5714 icode = direct_optab_handler (set_thread_pointer_optab, Pmode);
5715 if (icode != CODE_FOR_nothing)
5716 {
5717 struct expand_operand op;
5718 rtx val = expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX,
5719 Pmode, EXPAND_NORMAL);
6f343c10 5720 create_input_operand (&op, val, Pmode);
badaa04c 5721 expand_insn (icode, 1, &op);
5722 return;
5723 }
5724 error ("__builtin_set_thread_pointer is not supported on this target");
5725}
5726
53800dbe 5727\f
0e80b01d 5728/* Emit code to restore the current value of stack. */
5729
5730static void
5731expand_stack_restore (tree var)
5732{
5733 rtx prev, sa = expand_normal (var);
5734
5735 sa = convert_memory_address (Pmode, sa);
5736
5737 prev = get_last_insn ();
5738 emit_stack_restore (SAVE_BLOCK, sa);
5739 fixup_args_size_notes (prev, get_last_insn (), 0);
5740}
5741
5742
5743/* Emit code to save the current value of stack. */
5744
5745static rtx
5746expand_stack_save (void)
5747{
5748 rtx ret = NULL_RTX;
5749
5750 do_pending_stack_adjust ();
5751 emit_stack_save (SAVE_BLOCK, &ret);
5752 return ret;
5753}
5754
53800dbe 5755/* Expand an expression EXP that calls a built-in function,
5756 with result going to TARGET if that's convenient
5757 (and in mode MODE if that's convenient).
5758 SUBTARGET may be used as the target for computing one of EXP's operands.
5759 IGNORE is nonzero if the value is to be ignored. */
5760
5761rtx
aecda0d6 5762expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
5763 int ignore)
53800dbe 5764{
c6e6ecb1 5765 tree fndecl = get_callee_fndecl (exp);
53800dbe 5766 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
efb070c8 5767 enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
67fa4078 5768 int flags;
53800dbe 5769
8305149e 5770 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
883b2e73 5771 return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
bf8e3599 5772
53800dbe 5773 /* When not optimizing, generate calls to library functions for a certain
5774 set of builtins. */
cd9ff771 5775 if (!optimize
b6a5fc45 5776 && !called_as_built_in (fndecl)
73037a1e 5777 && fcode != BUILT_IN_FORK
5778 && fcode != BUILT_IN_EXECL
5779 && fcode != BUILT_IN_EXECV
5780 && fcode != BUILT_IN_EXECLP
5781 && fcode != BUILT_IN_EXECLE
5782 && fcode != BUILT_IN_EXECVP
5783 && fcode != BUILT_IN_EXECVE
2c281b15 5784 && fcode != BUILT_IN_ALLOCA
581bf1c2 5785 && fcode != BUILT_IN_ALLOCA_WITH_ALIGN
9b76d759 5786 && fcode != BUILT_IN_FREE
5787 && fcode != BUILT_IN_CHKP_SET_PTR_BOUNDS
5788 && fcode != BUILT_IN_CHKP_INIT_PTR_BOUNDS
5789 && fcode != BUILT_IN_CHKP_NULL_PTR_BOUNDS
5790 && fcode != BUILT_IN_CHKP_COPY_PTR_BOUNDS
5791 && fcode != BUILT_IN_CHKP_NARROW_PTR_BOUNDS
5792 && fcode != BUILT_IN_CHKP_STORE_PTR_BOUNDS
5793 && fcode != BUILT_IN_CHKP_CHECK_PTR_LBOUNDS
5794 && fcode != BUILT_IN_CHKP_CHECK_PTR_UBOUNDS
5795 && fcode != BUILT_IN_CHKP_CHECK_PTR_BOUNDS
5796 && fcode != BUILT_IN_CHKP_GET_PTR_LBOUND
5797 && fcode != BUILT_IN_CHKP_GET_PTR_UBOUND)
cd9ff771 5798 return expand_call (exp, target, ignore);
53800dbe 5799
8d6d7930 5800 /* The built-in function expanders test for target == const0_rtx
5801 to determine whether the function's result will be ignored. */
5802 if (ignore)
5803 target = const0_rtx;
5804
5805 /* If the result of a pure or const built-in function is ignored, and
5806 none of its arguments are volatile, we can avoid expanding the
5807 built-in call and just evaluate the arguments for side-effects. */
5808 if (target == const0_rtx
67fa4078 5809 && ((flags = flags_from_decl_or_type (fndecl)) & (ECF_CONST | ECF_PURE))
5810 && !(flags & ECF_LOOPING_CONST_OR_PURE))
8d6d7930 5811 {
5812 bool volatilep = false;
5813 tree arg;
c2f47e15 5814 call_expr_arg_iterator iter;
8d6d7930 5815
c2f47e15 5816 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5817 if (TREE_THIS_VOLATILE (arg))
8d6d7930 5818 {
5819 volatilep = true;
5820 break;
5821 }
5822
5823 if (! volatilep)
5824 {
c2f47e15 5825 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5826 expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
8d6d7930 5827 return const0_rtx;
5828 }
5829 }
5830
53800dbe 5831 switch (fcode)
5832 {
4f35b1fc 5833 CASE_FLT_FN (BUILT_IN_FABS):
8aa32773 5834 case BUILT_IN_FABSD32:
5835 case BUILT_IN_FABSD64:
5836 case BUILT_IN_FABSD128:
c2f47e15 5837 target = expand_builtin_fabs (exp, target, subtarget);
78a74442 5838 if (target)
a0c938f0 5839 return target;
78a74442 5840 break;
5841
4f35b1fc 5842 CASE_FLT_FN (BUILT_IN_COPYSIGN):
c2f47e15 5843 target = expand_builtin_copysign (exp, target, subtarget);
270436f3 5844 if (target)
5845 return target;
5846 break;
5847
7d3f6cc7 5848 /* Just do a normal library call if we were unable to fold
5849 the values. */
4f35b1fc 5850 CASE_FLT_FN (BUILT_IN_CABS):
78a74442 5851 break;
53800dbe 5852
4f35b1fc 5853 CASE_FLT_FN (BUILT_IN_EXP):
5854 CASE_FLT_FN (BUILT_IN_EXP10):
5855 CASE_FLT_FN (BUILT_IN_POW10):
5856 CASE_FLT_FN (BUILT_IN_EXP2):
5857 CASE_FLT_FN (BUILT_IN_EXPM1):
5858 CASE_FLT_FN (BUILT_IN_LOGB):
4f35b1fc 5859 CASE_FLT_FN (BUILT_IN_LOG):
5860 CASE_FLT_FN (BUILT_IN_LOG10):
5861 CASE_FLT_FN (BUILT_IN_LOG2):
5862 CASE_FLT_FN (BUILT_IN_LOG1P):
5863 CASE_FLT_FN (BUILT_IN_TAN):
5864 CASE_FLT_FN (BUILT_IN_ASIN):
5865 CASE_FLT_FN (BUILT_IN_ACOS):
5866 CASE_FLT_FN (BUILT_IN_ATAN):
b3154a1f 5867 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
7f3be425 5868 /* Treat these like sqrt only if unsafe math optimizations are allowed,
5869 because of possible accuracy problems. */
5870 if (! flag_unsafe_math_optimizations)
53800dbe 5871 break;
4f35b1fc 5872 CASE_FLT_FN (BUILT_IN_SQRT):
5873 CASE_FLT_FN (BUILT_IN_FLOOR):
5874 CASE_FLT_FN (BUILT_IN_CEIL):
5875 CASE_FLT_FN (BUILT_IN_TRUNC):
5876 CASE_FLT_FN (BUILT_IN_ROUND):
5877 CASE_FLT_FN (BUILT_IN_NEARBYINT):
5878 CASE_FLT_FN (BUILT_IN_RINT):
53800dbe 5879 target = expand_builtin_mathfn (exp, target, subtarget);
5880 if (target)
5881 return target;
5882 break;
5883
7e0713b1 5884 CASE_FLT_FN (BUILT_IN_FMA):
5885 target = expand_builtin_mathfn_ternary (exp, target, subtarget);
5886 if (target)
5887 return target;
5888 break;
5889
a67a90e5 5890 CASE_FLT_FN (BUILT_IN_ILOGB):
5891 if (! flag_unsafe_math_optimizations)
5892 break;
69b779ea 5893 CASE_FLT_FN (BUILT_IN_ISINF):
cde061c1 5894 CASE_FLT_FN (BUILT_IN_FINITE):
5895 case BUILT_IN_ISFINITE:
8a1a9cb7 5896 case BUILT_IN_ISNORMAL:
f97eea22 5897 target = expand_builtin_interclass_mathfn (exp, target);
a67a90e5 5898 if (target)
5899 return target;
5900 break;
5901
80ff6494 5902 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 5903 CASE_FLT_FN (BUILT_IN_LCEIL):
5904 CASE_FLT_FN (BUILT_IN_LLCEIL):
5905 CASE_FLT_FN (BUILT_IN_LFLOOR):
80ff6494 5906 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 5907 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ff1b14e4 5908 target = expand_builtin_int_roundingfn (exp, target);
ad52b9b7 5909 if (target)
5910 return target;
5911 break;
5912
80ff6494 5913 CASE_FLT_FN (BUILT_IN_IRINT):
7d3afc77 5914 CASE_FLT_FN (BUILT_IN_LRINT):
5915 CASE_FLT_FN (BUILT_IN_LLRINT):
80ff6494 5916 CASE_FLT_FN (BUILT_IN_IROUND):
ef2f1a10 5917 CASE_FLT_FN (BUILT_IN_LROUND):
5918 CASE_FLT_FN (BUILT_IN_LLROUND):
ff1b14e4 5919 target = expand_builtin_int_roundingfn_2 (exp, target);
7d3afc77 5920 if (target)
5921 return target;
5922 break;
5923
4f35b1fc 5924 CASE_FLT_FN (BUILT_IN_POWI):
f97eea22 5925 target = expand_builtin_powi (exp, target);
757c219d 5926 if (target)
5927 return target;
5928 break;
5929
4f35b1fc 5930 CASE_FLT_FN (BUILT_IN_ATAN2):
5931 CASE_FLT_FN (BUILT_IN_LDEXP):
73a954a1 5932 CASE_FLT_FN (BUILT_IN_SCALB):
5933 CASE_FLT_FN (BUILT_IN_SCALBN):
5934 CASE_FLT_FN (BUILT_IN_SCALBLN):
0fd605a5 5935 if (! flag_unsafe_math_optimizations)
5936 break;
ef722005 5937
5938 CASE_FLT_FN (BUILT_IN_FMOD):
5939 CASE_FLT_FN (BUILT_IN_REMAINDER):
5940 CASE_FLT_FN (BUILT_IN_DREM):
0810ff17 5941 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 5942 target = expand_builtin_mathfn_2 (exp, target, subtarget);
5943 if (target)
5944 return target;
5945 break;
5946
d735c391 5947 CASE_FLT_FN (BUILT_IN_CEXPI):
f97eea22 5948 target = expand_builtin_cexpi (exp, target);
d735c391 5949 gcc_assert (target);
5950 return target;
5951
4f35b1fc 5952 CASE_FLT_FN (BUILT_IN_SIN):
5953 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 5954 if (! flag_unsafe_math_optimizations)
5955 break;
5956 target = expand_builtin_mathfn_3 (exp, target, subtarget);
5957 if (target)
5958 return target;
5959 break;
5960
c3147c1a 5961 CASE_FLT_FN (BUILT_IN_SINCOS):
5962 if (! flag_unsafe_math_optimizations)
5963 break;
5964 target = expand_builtin_sincos (exp);
5965 if (target)
5966 return target;
5967 break;
5968
53800dbe 5969 case BUILT_IN_APPLY_ARGS:
5970 return expand_builtin_apply_args ();
5971
5972 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
5973 FUNCTION with a copy of the parameters described by
5974 ARGUMENTS, and ARGSIZE. It returns a block of memory
5975 allocated on the stack into which is stored all the registers
5976 that might possibly be used for returning the result of a
5977 function. ARGUMENTS is the value returned by
5978 __builtin_apply_args. ARGSIZE is the number of bytes of
5979 arguments that must be copied. ??? How should this value be
5980 computed? We'll also need a safe worst case value for varargs
5981 functions. */
5982 case BUILT_IN_APPLY:
c2f47e15 5983 if (!validate_arglist (exp, POINTER_TYPE,
0eb671f7 5984 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
c2f47e15 5985 && !validate_arglist (exp, REFERENCE_TYPE,
0eb671f7 5986 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 5987 return const0_rtx;
5988 else
5989 {
53800dbe 5990 rtx ops[3];
5991
c2f47e15 5992 ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
5993 ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
5994 ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
53800dbe 5995
5996 return expand_builtin_apply (ops[0], ops[1], ops[2]);
5997 }
5998
5999 /* __builtin_return (RESULT) causes the function to return the
6000 value described by RESULT. RESULT is address of the block of
6001 memory returned by __builtin_apply. */
6002 case BUILT_IN_RETURN:
c2f47e15 6003 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
6004 expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
53800dbe 6005 return const0_rtx;
6006
6007 case BUILT_IN_SAVEREGS:
a66c9326 6008 return expand_builtin_saveregs ();
53800dbe 6009
48dc2227 6010 case BUILT_IN_VA_ARG_PACK:
6011 /* All valid uses of __builtin_va_arg_pack () are removed during
6012 inlining. */
b8c23db3 6013 error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
48dc2227 6014 return const0_rtx;
6015
4e1d7ea4 6016 case BUILT_IN_VA_ARG_PACK_LEN:
6017 /* All valid uses of __builtin_va_arg_pack_len () are removed during
6018 inlining. */
b8c23db3 6019 error ("%Kinvalid use of %<__builtin_va_arg_pack_len ()%>", exp);
4e1d7ea4 6020 return const0_rtx;
6021
53800dbe 6022 /* Return the address of the first anonymous stack arg. */
6023 case BUILT_IN_NEXT_ARG:
c2f47e15 6024 if (fold_builtin_next_arg (exp, false))
a0c938f0 6025 return const0_rtx;
79012a9d 6026 return expand_builtin_next_arg ();
53800dbe 6027
ac8fb6db 6028 case BUILT_IN_CLEAR_CACHE:
6029 target = expand_builtin___clear_cache (exp);
6030 if (target)
6031 return target;
6032 break;
6033
53800dbe 6034 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 6035 return expand_builtin_classify_type (exp);
53800dbe 6036
6037 case BUILT_IN_CONSTANT_P:
4ee9c684 6038 return const0_rtx;
53800dbe 6039
6040 case BUILT_IN_FRAME_ADDRESS:
6041 case BUILT_IN_RETURN_ADDRESS:
c2f47e15 6042 return expand_builtin_frame_address (fndecl, exp);
53800dbe 6043
6044 /* Returns the address of the area where the structure is returned.
6045 0 otherwise. */
6046 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
c2f47e15 6047 if (call_expr_nargs (exp) != 0
9342ee68 6048 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
e16ceb8e 6049 || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
9342ee68 6050 return const0_rtx;
53800dbe 6051 else
9342ee68 6052 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
53800dbe 6053
6054 case BUILT_IN_ALLOCA:
581bf1c2 6055 case BUILT_IN_ALLOCA_WITH_ALIGN:
990495a7 6056 /* If the allocation stems from the declaration of a variable-sized
6057 object, it cannot accumulate. */
a882d754 6058 target = expand_builtin_alloca (exp, CALL_ALLOCA_FOR_VAR_P (exp));
53800dbe 6059 if (target)
6060 return target;
6061 break;
6062
4ee9c684 6063 case BUILT_IN_STACK_SAVE:
6064 return expand_stack_save ();
6065
6066 case BUILT_IN_STACK_RESTORE:
c2f47e15 6067 expand_stack_restore (CALL_EXPR_ARG (exp, 0));
4ee9c684 6068 return const0_rtx;
6069
74bdbe96 6070 case BUILT_IN_BSWAP16:
42791117 6071 case BUILT_IN_BSWAP32:
6072 case BUILT_IN_BSWAP64:
74bdbe96 6073 target = expand_builtin_bswap (target_mode, exp, target, subtarget);
42791117 6074 if (target)
6075 return target;
6076 break;
6077
4f35b1fc 6078 CASE_INT_FN (BUILT_IN_FFS):
c2f47e15 6079 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6080 subtarget, ffs_optab);
6a08d0ab 6081 if (target)
6082 return target;
6083 break;
6084
4f35b1fc 6085 CASE_INT_FN (BUILT_IN_CLZ):
c2f47e15 6086 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6087 subtarget, clz_optab);
6a08d0ab 6088 if (target)
6089 return target;
6090 break;
6091
4f35b1fc 6092 CASE_INT_FN (BUILT_IN_CTZ):
c2f47e15 6093 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6094 subtarget, ctz_optab);
6a08d0ab 6095 if (target)
6096 return target;
6097 break;
6098
d8492bd3 6099 CASE_INT_FN (BUILT_IN_CLRSB):
d8492bd3 6100 target = expand_builtin_unop (target_mode, exp, target,
6101 subtarget, clrsb_optab);
6102 if (target)
6103 return target;
6104 break;
6105
4f35b1fc 6106 CASE_INT_FN (BUILT_IN_POPCOUNT):
c2f47e15 6107 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6108 subtarget, popcount_optab);
6a08d0ab 6109 if (target)
6110 return target;
6111 break;
6112
4f35b1fc 6113 CASE_INT_FN (BUILT_IN_PARITY):
c2f47e15 6114 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6115 subtarget, parity_optab);
53800dbe 6116 if (target)
6117 return target;
6118 break;
6119
6120 case BUILT_IN_STRLEN:
c2f47e15 6121 target = expand_builtin_strlen (exp, target, target_mode);
53800dbe 6122 if (target)
6123 return target;
6124 break;
6125
6126 case BUILT_IN_STRCPY:
a65c4d64 6127 target = expand_builtin_strcpy (exp, target);
53800dbe 6128 if (target)
6129 return target;
6130 break;
bf8e3599 6131
ed09096d 6132 case BUILT_IN_STRNCPY:
a65c4d64 6133 target = expand_builtin_strncpy (exp, target);
ed09096d 6134 if (target)
6135 return target;
6136 break;
bf8e3599 6137
3b824fa6 6138 case BUILT_IN_STPCPY:
dc369150 6139 target = expand_builtin_stpcpy (exp, target, mode);
3b824fa6 6140 if (target)
6141 return target;
6142 break;
6143
53800dbe 6144 case BUILT_IN_MEMCPY:
a65c4d64 6145 target = expand_builtin_memcpy (exp, target);
3b824fa6 6146 if (target)
6147 return target;
6148 break;
6149
6150 case BUILT_IN_MEMPCPY:
c2f47e15 6151 target = expand_builtin_mempcpy (exp, target, mode);
53800dbe 6152 if (target)
6153 return target;
6154 break;
6155
6156 case BUILT_IN_MEMSET:
c2f47e15 6157 target = expand_builtin_memset (exp, target, mode);
53800dbe 6158 if (target)
6159 return target;
6160 break;
6161
ffc83088 6162 case BUILT_IN_BZERO:
0b25db21 6163 target = expand_builtin_bzero (exp);
ffc83088 6164 if (target)
6165 return target;
6166 break;
6167
53800dbe 6168 case BUILT_IN_STRCMP:
a65c4d64 6169 target = expand_builtin_strcmp (exp, target);
53800dbe 6170 if (target)
6171 return target;
6172 break;
6173
ed09096d 6174 case BUILT_IN_STRNCMP:
6175 target = expand_builtin_strncmp (exp, target, mode);
6176 if (target)
6177 return target;
6178 break;
6179
071f1696 6180 case BUILT_IN_BCMP:
53800dbe 6181 case BUILT_IN_MEMCMP:
c2f47e15 6182 target = expand_builtin_memcmp (exp, target, mode);
53800dbe 6183 if (target)
6184 return target;
6185 break;
53800dbe 6186
6187 case BUILT_IN_SETJMP:
2c8a1497 6188 /* This should have been lowered to the builtins below. */
6189 gcc_unreachable ();
6190
6191 case BUILT_IN_SETJMP_SETUP:
6192 /* __builtin_setjmp_setup is passed a pointer to an array of five words
6193 and the receiver label. */
c2f47e15 6194 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2c8a1497 6195 {
c2f47e15 6196 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
2c8a1497 6197 VOIDmode, EXPAND_NORMAL);
c2f47e15 6198 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
2c8a1497 6199 rtx label_r = label_rtx (label);
6200
6201 /* This is copied from the handling of non-local gotos. */
6202 expand_builtin_setjmp_setup (buf_addr, label_r);
6203 nonlocal_goto_handler_labels
6204 = gen_rtx_EXPR_LIST (VOIDmode, label_r,
6205 nonlocal_goto_handler_labels);
6206 /* ??? Do not let expand_label treat us as such since we would
6207 not want to be both on the list of non-local labels and on
6208 the list of forced labels. */
6209 FORCED_LABEL (label) = 0;
6210 return const0_rtx;
6211 }
6212 break;
6213
6214 case BUILT_IN_SETJMP_DISPATCHER:
6215 /* __builtin_setjmp_dispatcher is passed the dispatcher label. */
c2f47e15 6216 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6217 {
c2f47e15 6218 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6219 rtx label_r = label_rtx (label);
6220
6221 /* Remove the dispatcher label from the list of non-local labels
6222 since the receiver labels have been added to it above. */
6223 remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels);
6224 return const0_rtx;
6225 }
6226 break;
6227
6228 case BUILT_IN_SETJMP_RECEIVER:
6229 /* __builtin_setjmp_receiver is passed the receiver label. */
c2f47e15 6230 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6231 {
c2f47e15 6232 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6233 rtx label_r = label_rtx (label);
6234
6235 expand_builtin_setjmp_receiver (label_r);
6236 return const0_rtx;
6237 }
6b7f6858 6238 break;
53800dbe 6239
6240 /* __builtin_longjmp is passed a pointer to an array of five words.
6241 It's similar to the C library longjmp function but works with
6242 __builtin_setjmp above. */
6243 case BUILT_IN_LONGJMP:
c2f47e15 6244 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 6245 {
c2f47e15 6246 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
8ec3c5c2 6247 VOIDmode, EXPAND_NORMAL);
c2f47e15 6248 rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
53800dbe 6249
6250 if (value != const1_rtx)
6251 {
1e5fcbe2 6252 error ("%<__builtin_longjmp%> second argument must be 1");
53800dbe 6253 return const0_rtx;
6254 }
6255
6256 expand_builtin_longjmp (buf_addr, value);
6257 return const0_rtx;
6258 }
2c8a1497 6259 break;
53800dbe 6260
4ee9c684 6261 case BUILT_IN_NONLOCAL_GOTO:
c2f47e15 6262 target = expand_builtin_nonlocal_goto (exp);
4ee9c684 6263 if (target)
6264 return target;
6265 break;
6266
843d08a9 6267 /* This updates the setjmp buffer that is its argument with the value
6268 of the current stack pointer. */
6269 case BUILT_IN_UPDATE_SETJMP_BUF:
c2f47e15 6270 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
843d08a9 6271 {
6272 rtx buf_addr
c2f47e15 6273 = expand_normal (CALL_EXPR_ARG (exp, 0));
843d08a9 6274
6275 expand_builtin_update_setjmp_buf (buf_addr);
6276 return const0_rtx;
6277 }
6278 break;
6279
53800dbe 6280 case BUILT_IN_TRAP:
a0ef1725 6281 expand_builtin_trap ();
53800dbe 6282 return const0_rtx;
6283
d2b48f0c 6284 case BUILT_IN_UNREACHABLE:
6285 expand_builtin_unreachable ();
6286 return const0_rtx;
6287
4f35b1fc 6288 CASE_FLT_FN (BUILT_IN_SIGNBIT):
004e23c4 6289 case BUILT_IN_SIGNBITD32:
6290 case BUILT_IN_SIGNBITD64:
6291 case BUILT_IN_SIGNBITD128:
27f261ef 6292 target = expand_builtin_signbit (exp, target);
6293 if (target)
6294 return target;
6295 break;
6296
53800dbe 6297 /* Various hooks for the DWARF 2 __throw routine. */
6298 case BUILT_IN_UNWIND_INIT:
6299 expand_builtin_unwind_init ();
6300 return const0_rtx;
6301 case BUILT_IN_DWARF_CFA:
6302 return virtual_cfa_rtx;
6303#ifdef DWARF2_UNWIND_INFO
f8f023a5 6304 case BUILT_IN_DWARF_SP_COLUMN:
6305 return expand_builtin_dwarf_sp_column ();
695e919b 6306 case BUILT_IN_INIT_DWARF_REG_SIZES:
c2f47e15 6307 expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
695e919b 6308 return const0_rtx;
53800dbe 6309#endif
6310 case BUILT_IN_FROB_RETURN_ADDR:
c2f47e15 6311 return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6312 case BUILT_IN_EXTRACT_RETURN_ADDR:
c2f47e15 6313 return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6314 case BUILT_IN_EH_RETURN:
c2f47e15 6315 expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
6316 CALL_EXPR_ARG (exp, 1));
53800dbe 6317 return const0_rtx;
df4b504c 6318#ifdef EH_RETURN_DATA_REGNO
6319 case BUILT_IN_EH_RETURN_DATA_REGNO:
c2f47e15 6320 return expand_builtin_eh_return_data_regno (exp);
df4b504c 6321#endif
26093bf4 6322 case BUILT_IN_EXTEND_POINTER:
c2f47e15 6323 return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
e38def9c 6324 case BUILT_IN_EH_POINTER:
6325 return expand_builtin_eh_pointer (exp);
6326 case BUILT_IN_EH_FILTER:
6327 return expand_builtin_eh_filter (exp);
6328 case BUILT_IN_EH_COPY_VALUES:
6329 return expand_builtin_eh_copy_values (exp);
26093bf4 6330
7ccc713a 6331 case BUILT_IN_VA_START:
c2f47e15 6332 return expand_builtin_va_start (exp);
a66c9326 6333 case BUILT_IN_VA_END:
c2f47e15 6334 return expand_builtin_va_end (exp);
a66c9326 6335 case BUILT_IN_VA_COPY:
c2f47e15 6336 return expand_builtin_va_copy (exp);
89cfe6e5 6337 case BUILT_IN_EXPECT:
c2f47e15 6338 return expand_builtin_expect (exp, target);
fca0886c 6339 case BUILT_IN_ASSUME_ALIGNED:
6340 return expand_builtin_assume_aligned (exp, target);
5e3608d8 6341 case BUILT_IN_PREFETCH:
c2f47e15 6342 expand_builtin_prefetch (exp);
5e3608d8 6343 return const0_rtx;
6344
4ee9c684 6345 case BUILT_IN_INIT_TRAMPOLINE:
c307f106 6346 return expand_builtin_init_trampoline (exp, true);
6347 case BUILT_IN_INIT_HEAP_TRAMPOLINE:
6348 return expand_builtin_init_trampoline (exp, false);
4ee9c684 6349 case BUILT_IN_ADJUST_TRAMPOLINE:
c2f47e15 6350 return expand_builtin_adjust_trampoline (exp);
4ee9c684 6351
73673831 6352 case BUILT_IN_FORK:
6353 case BUILT_IN_EXECL:
6354 case BUILT_IN_EXECV:
6355 case BUILT_IN_EXECLP:
6356 case BUILT_IN_EXECLE:
6357 case BUILT_IN_EXECVP:
6358 case BUILT_IN_EXECVE:
c2f47e15 6359 target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
73673831 6360 if (target)
6361 return target;
6362 break;
53800dbe 6363
2797f13a 6364 case BUILT_IN_SYNC_FETCH_AND_ADD_1:
6365 case BUILT_IN_SYNC_FETCH_AND_ADD_2:
6366 case BUILT_IN_SYNC_FETCH_AND_ADD_4:
6367 case BUILT_IN_SYNC_FETCH_AND_ADD_8:
6368 case BUILT_IN_SYNC_FETCH_AND_ADD_16:
6369 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_ADD_1);
1cd6e20d 6370 target = expand_builtin_sync_operation (mode, exp, PLUS, false, target);
b6a5fc45 6371 if (target)
6372 return target;
6373 break;
6374
2797f13a 6375 case BUILT_IN_SYNC_FETCH_AND_SUB_1:
6376 case BUILT_IN_SYNC_FETCH_AND_SUB_2:
6377 case BUILT_IN_SYNC_FETCH_AND_SUB_4:
6378 case BUILT_IN_SYNC_FETCH_AND_SUB_8:
6379 case BUILT_IN_SYNC_FETCH_AND_SUB_16:
6380 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_SUB_1);
1cd6e20d 6381 target = expand_builtin_sync_operation (mode, exp, MINUS, false, target);
b6a5fc45 6382 if (target)
6383 return target;
6384 break;
6385
2797f13a 6386 case BUILT_IN_SYNC_FETCH_AND_OR_1:
6387 case BUILT_IN_SYNC_FETCH_AND_OR_2:
6388 case BUILT_IN_SYNC_FETCH_AND_OR_4:
6389 case BUILT_IN_SYNC_FETCH_AND_OR_8:
6390 case BUILT_IN_SYNC_FETCH_AND_OR_16:
6391 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_OR_1);
1cd6e20d 6392 target = expand_builtin_sync_operation (mode, exp, IOR, false, target);
b6a5fc45 6393 if (target)
6394 return target;
6395 break;
6396
2797f13a 6397 case BUILT_IN_SYNC_FETCH_AND_AND_1:
6398 case BUILT_IN_SYNC_FETCH_AND_AND_2:
6399 case BUILT_IN_SYNC_FETCH_AND_AND_4:
6400 case BUILT_IN_SYNC_FETCH_AND_AND_8:
6401 case BUILT_IN_SYNC_FETCH_AND_AND_16:
6402 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_AND_1);
1cd6e20d 6403 target = expand_builtin_sync_operation (mode, exp, AND, false, target);
b6a5fc45 6404 if (target)
6405 return target;
6406 break;
6407
2797f13a 6408 case BUILT_IN_SYNC_FETCH_AND_XOR_1:
6409 case BUILT_IN_SYNC_FETCH_AND_XOR_2:
6410 case BUILT_IN_SYNC_FETCH_AND_XOR_4:
6411 case BUILT_IN_SYNC_FETCH_AND_XOR_8:
6412 case BUILT_IN_SYNC_FETCH_AND_XOR_16:
6413 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_XOR_1);
1cd6e20d 6414 target = expand_builtin_sync_operation (mode, exp, XOR, false, target);
b6a5fc45 6415 if (target)
6416 return target;
6417 break;
6418
2797f13a 6419 case BUILT_IN_SYNC_FETCH_AND_NAND_1:
6420 case BUILT_IN_SYNC_FETCH_AND_NAND_2:
6421 case BUILT_IN_SYNC_FETCH_AND_NAND_4:
6422 case BUILT_IN_SYNC_FETCH_AND_NAND_8:
6423 case BUILT_IN_SYNC_FETCH_AND_NAND_16:
6424 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_NAND_1);
1cd6e20d 6425 target = expand_builtin_sync_operation (mode, exp, NOT, false, target);
b6a5fc45 6426 if (target)
6427 return target;
6428 break;
6429
2797f13a 6430 case BUILT_IN_SYNC_ADD_AND_FETCH_1:
6431 case BUILT_IN_SYNC_ADD_AND_FETCH_2:
6432 case BUILT_IN_SYNC_ADD_AND_FETCH_4:
6433 case BUILT_IN_SYNC_ADD_AND_FETCH_8:
6434 case BUILT_IN_SYNC_ADD_AND_FETCH_16:
6435 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_ADD_AND_FETCH_1);
1cd6e20d 6436 target = expand_builtin_sync_operation (mode, exp, PLUS, true, target);
b6a5fc45 6437 if (target)
6438 return target;
6439 break;
6440
2797f13a 6441 case BUILT_IN_SYNC_SUB_AND_FETCH_1:
6442 case BUILT_IN_SYNC_SUB_AND_FETCH_2:
6443 case BUILT_IN_SYNC_SUB_AND_FETCH_4:
6444 case BUILT_IN_SYNC_SUB_AND_FETCH_8:
6445 case BUILT_IN_SYNC_SUB_AND_FETCH_16:
6446 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_SUB_AND_FETCH_1);
1cd6e20d 6447 target = expand_builtin_sync_operation (mode, exp, MINUS, true, target);
b6a5fc45 6448 if (target)
6449 return target;
6450 break;
6451
2797f13a 6452 case BUILT_IN_SYNC_OR_AND_FETCH_1:
6453 case BUILT_IN_SYNC_OR_AND_FETCH_2:
6454 case BUILT_IN_SYNC_OR_AND_FETCH_4:
6455 case BUILT_IN_SYNC_OR_AND_FETCH_8:
6456 case BUILT_IN_SYNC_OR_AND_FETCH_16:
6457 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_OR_AND_FETCH_1);
1cd6e20d 6458 target = expand_builtin_sync_operation (mode, exp, IOR, true, target);
b6a5fc45 6459 if (target)
6460 return target;
6461 break;
6462
2797f13a 6463 case BUILT_IN_SYNC_AND_AND_FETCH_1:
6464 case BUILT_IN_SYNC_AND_AND_FETCH_2:
6465 case BUILT_IN_SYNC_AND_AND_FETCH_4:
6466 case BUILT_IN_SYNC_AND_AND_FETCH_8:
6467 case BUILT_IN_SYNC_AND_AND_FETCH_16:
6468 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_AND_AND_FETCH_1);
1cd6e20d 6469 target = expand_builtin_sync_operation (mode, exp, AND, true, target);
b6a5fc45 6470 if (target)
6471 return target;
6472 break;
6473
2797f13a 6474 case BUILT_IN_SYNC_XOR_AND_FETCH_1:
6475 case BUILT_IN_SYNC_XOR_AND_FETCH_2:
6476 case BUILT_IN_SYNC_XOR_AND_FETCH_4:
6477 case BUILT_IN_SYNC_XOR_AND_FETCH_8:
6478 case BUILT_IN_SYNC_XOR_AND_FETCH_16:
6479 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_XOR_AND_FETCH_1);
1cd6e20d 6480 target = expand_builtin_sync_operation (mode, exp, XOR, true, target);
b6a5fc45 6481 if (target)
6482 return target;
6483 break;
6484
2797f13a 6485 case BUILT_IN_SYNC_NAND_AND_FETCH_1:
6486 case BUILT_IN_SYNC_NAND_AND_FETCH_2:
6487 case BUILT_IN_SYNC_NAND_AND_FETCH_4:
6488 case BUILT_IN_SYNC_NAND_AND_FETCH_8:
6489 case BUILT_IN_SYNC_NAND_AND_FETCH_16:
6490 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_NAND_AND_FETCH_1);
1cd6e20d 6491 target = expand_builtin_sync_operation (mode, exp, NOT, true, target);
b6a5fc45 6492 if (target)
6493 return target;
6494 break;
6495
2797f13a 6496 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
6497 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
6498 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
6499 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
6500 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16:
a601d32a 6501 if (mode == VOIDmode)
6502 mode = TYPE_MODE (boolean_type_node);
b6a5fc45 6503 if (!target || !register_operand (target, mode))
6504 target = gen_reg_rtx (mode);
3e272de8 6505
2797f13a 6506 mode = get_builtin_sync_mode
6507 (fcode - BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1);
c2f47e15 6508 target = expand_builtin_compare_and_swap (mode, exp, true, target);
b6a5fc45 6509 if (target)
6510 return target;
6511 break;
6512
2797f13a 6513 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
6514 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
6515 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
6516 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
6517 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
6518 mode = get_builtin_sync_mode
6519 (fcode - BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1);
c2f47e15 6520 target = expand_builtin_compare_and_swap (mode, exp, false, target);
b6a5fc45 6521 if (target)
6522 return target;
6523 break;
6524
2797f13a 6525 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
6526 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
6527 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
6528 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
6529 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16:
6530 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_TEST_AND_SET_1);
6531 target = expand_builtin_sync_lock_test_and_set (mode, exp, target);
b6a5fc45 6532 if (target)
6533 return target;
6534 break;
6535
2797f13a 6536 case BUILT_IN_SYNC_LOCK_RELEASE_1:
6537 case BUILT_IN_SYNC_LOCK_RELEASE_2:
6538 case BUILT_IN_SYNC_LOCK_RELEASE_4:
6539 case BUILT_IN_SYNC_LOCK_RELEASE_8:
6540 case BUILT_IN_SYNC_LOCK_RELEASE_16:
6541 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_RELEASE_1);
6542 expand_builtin_sync_lock_release (mode, exp);
b6a5fc45 6543 return const0_rtx;
6544
2797f13a 6545 case BUILT_IN_SYNC_SYNCHRONIZE:
6546 expand_builtin_sync_synchronize ();
b6a5fc45 6547 return const0_rtx;
6548
1cd6e20d 6549 case BUILT_IN_ATOMIC_EXCHANGE_1:
6550 case BUILT_IN_ATOMIC_EXCHANGE_2:
6551 case BUILT_IN_ATOMIC_EXCHANGE_4:
6552 case BUILT_IN_ATOMIC_EXCHANGE_8:
6553 case BUILT_IN_ATOMIC_EXCHANGE_16:
6554 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_EXCHANGE_1);
6555 target = expand_builtin_atomic_exchange (mode, exp, target);
6556 if (target)
6557 return target;
6558 break;
6559
6560 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1:
6561 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2:
6562 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4:
6563 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8:
6564 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
2c201ad1 6565 {
6566 unsigned int nargs, z;
f1f41a6c 6567 vec<tree, va_gc> *vec;
2c201ad1 6568
6569 mode =
6570 get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1);
6571 target = expand_builtin_atomic_compare_exchange (mode, exp, target);
6572 if (target)
6573 return target;
6574
6575 /* If this is turned into an external library call, the weak parameter
6576 must be dropped to match the expected parameter list. */
6577 nargs = call_expr_nargs (exp);
f1f41a6c 6578 vec_alloc (vec, nargs - 1);
2c201ad1 6579 for (z = 0; z < 3; z++)
f1f41a6c 6580 vec->quick_push (CALL_EXPR_ARG (exp, z));
2c201ad1 6581 /* Skip the boolean weak parameter. */
6582 for (z = 4; z < 6; z++)
f1f41a6c 6583 vec->quick_push (CALL_EXPR_ARG (exp, z));
2c201ad1 6584 exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), vec);
6585 break;
6586 }
1cd6e20d 6587
6588 case BUILT_IN_ATOMIC_LOAD_1:
6589 case BUILT_IN_ATOMIC_LOAD_2:
6590 case BUILT_IN_ATOMIC_LOAD_4:
6591 case BUILT_IN_ATOMIC_LOAD_8:
6592 case BUILT_IN_ATOMIC_LOAD_16:
6593 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_LOAD_1);
6594 target = expand_builtin_atomic_load (mode, exp, target);
6595 if (target)
6596 return target;
6597 break;
6598
6599 case BUILT_IN_ATOMIC_STORE_1:
6600 case BUILT_IN_ATOMIC_STORE_2:
6601 case BUILT_IN_ATOMIC_STORE_4:
6602 case BUILT_IN_ATOMIC_STORE_8:
6603 case BUILT_IN_ATOMIC_STORE_16:
6604 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_STORE_1);
6605 target = expand_builtin_atomic_store (mode, exp);
6606 if (target)
6607 return const0_rtx;
6608 break;
6609
6610 case BUILT_IN_ATOMIC_ADD_FETCH_1:
6611 case BUILT_IN_ATOMIC_ADD_FETCH_2:
6612 case BUILT_IN_ATOMIC_ADD_FETCH_4:
6613 case BUILT_IN_ATOMIC_ADD_FETCH_8:
6614 case BUILT_IN_ATOMIC_ADD_FETCH_16:
6615 {
6616 enum built_in_function lib;
6617 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1);
6618 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_ADD_1 +
6619 (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1));
6620 target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, true,
6621 ignore, lib);
6622 if (target)
6623 return target;
6624 break;
6625 }
6626 case BUILT_IN_ATOMIC_SUB_FETCH_1:
6627 case BUILT_IN_ATOMIC_SUB_FETCH_2:
6628 case BUILT_IN_ATOMIC_SUB_FETCH_4:
6629 case BUILT_IN_ATOMIC_SUB_FETCH_8:
6630 case BUILT_IN_ATOMIC_SUB_FETCH_16:
6631 {
6632 enum built_in_function lib;
6633 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1);
6634 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_SUB_1 +
6635 (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1));
6636 target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, true,
6637 ignore, lib);
6638 if (target)
6639 return target;
6640 break;
6641 }
6642 case BUILT_IN_ATOMIC_AND_FETCH_1:
6643 case BUILT_IN_ATOMIC_AND_FETCH_2:
6644 case BUILT_IN_ATOMIC_AND_FETCH_4:
6645 case BUILT_IN_ATOMIC_AND_FETCH_8:
6646 case BUILT_IN_ATOMIC_AND_FETCH_16:
6647 {
6648 enum built_in_function lib;
6649 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_AND_FETCH_1);
6650 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_AND_1 +
6651 (fcode - BUILT_IN_ATOMIC_AND_FETCH_1));
6652 target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, true,
6653 ignore, lib);
6654 if (target)
6655 return target;
6656 break;
6657 }
6658 case BUILT_IN_ATOMIC_NAND_FETCH_1:
6659 case BUILT_IN_ATOMIC_NAND_FETCH_2:
6660 case BUILT_IN_ATOMIC_NAND_FETCH_4:
6661 case BUILT_IN_ATOMIC_NAND_FETCH_8:
6662 case BUILT_IN_ATOMIC_NAND_FETCH_16:
6663 {
6664 enum built_in_function lib;
6665 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1);
6666 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_NAND_1 +
6667 (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1));
6668 target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, true,
6669 ignore, lib);
6670 if (target)
6671 return target;
6672 break;
6673 }
6674 case BUILT_IN_ATOMIC_XOR_FETCH_1:
6675 case BUILT_IN_ATOMIC_XOR_FETCH_2:
6676 case BUILT_IN_ATOMIC_XOR_FETCH_4:
6677 case BUILT_IN_ATOMIC_XOR_FETCH_8:
6678 case BUILT_IN_ATOMIC_XOR_FETCH_16:
6679 {
6680 enum built_in_function lib;
6681 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1);
6682 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_XOR_1 +
6683 (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1));
6684 target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, true,
6685 ignore, lib);
6686 if (target)
6687 return target;
6688 break;
6689 }
6690 case BUILT_IN_ATOMIC_OR_FETCH_1:
6691 case BUILT_IN_ATOMIC_OR_FETCH_2:
6692 case BUILT_IN_ATOMIC_OR_FETCH_4:
6693 case BUILT_IN_ATOMIC_OR_FETCH_8:
6694 case BUILT_IN_ATOMIC_OR_FETCH_16:
6695 {
6696 enum built_in_function lib;
6697 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_OR_FETCH_1);
6698 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_OR_1 +
6699 (fcode - BUILT_IN_ATOMIC_OR_FETCH_1));
6700 target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, true,
6701 ignore, lib);
6702 if (target)
6703 return target;
6704 break;
6705 }
6706 case BUILT_IN_ATOMIC_FETCH_ADD_1:
6707 case BUILT_IN_ATOMIC_FETCH_ADD_2:
6708 case BUILT_IN_ATOMIC_FETCH_ADD_4:
6709 case BUILT_IN_ATOMIC_FETCH_ADD_8:
6710 case BUILT_IN_ATOMIC_FETCH_ADD_16:
6711 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_ADD_1);
6712 target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, false,
6713 ignore, BUILT_IN_NONE);
6714 if (target)
6715 return target;
6716 break;
6717
6718 case BUILT_IN_ATOMIC_FETCH_SUB_1:
6719 case BUILT_IN_ATOMIC_FETCH_SUB_2:
6720 case BUILT_IN_ATOMIC_FETCH_SUB_4:
6721 case BUILT_IN_ATOMIC_FETCH_SUB_8:
6722 case BUILT_IN_ATOMIC_FETCH_SUB_16:
6723 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_SUB_1);
6724 target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, false,
6725 ignore, BUILT_IN_NONE);
6726 if (target)
6727 return target;
6728 break;
6729
6730 case BUILT_IN_ATOMIC_FETCH_AND_1:
6731 case BUILT_IN_ATOMIC_FETCH_AND_2:
6732 case BUILT_IN_ATOMIC_FETCH_AND_4:
6733 case BUILT_IN_ATOMIC_FETCH_AND_8:
6734 case BUILT_IN_ATOMIC_FETCH_AND_16:
6735 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_AND_1);
6736 target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, false,
6737 ignore, BUILT_IN_NONE);
6738 if (target)
6739 return target;
6740 break;
6741
6742 case BUILT_IN_ATOMIC_FETCH_NAND_1:
6743 case BUILT_IN_ATOMIC_FETCH_NAND_2:
6744 case BUILT_IN_ATOMIC_FETCH_NAND_4:
6745 case BUILT_IN_ATOMIC_FETCH_NAND_8:
6746 case BUILT_IN_ATOMIC_FETCH_NAND_16:
6747 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_NAND_1);
6748 target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, false,
6749 ignore, BUILT_IN_NONE);
6750 if (target)
6751 return target;
6752 break;
6753
6754 case BUILT_IN_ATOMIC_FETCH_XOR_1:
6755 case BUILT_IN_ATOMIC_FETCH_XOR_2:
6756 case BUILT_IN_ATOMIC_FETCH_XOR_4:
6757 case BUILT_IN_ATOMIC_FETCH_XOR_8:
6758 case BUILT_IN_ATOMIC_FETCH_XOR_16:
6759 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_XOR_1);
6760 target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, false,
6761 ignore, BUILT_IN_NONE);
6762 if (target)
6763 return target;
6764 break;
6765
6766 case BUILT_IN_ATOMIC_FETCH_OR_1:
6767 case BUILT_IN_ATOMIC_FETCH_OR_2:
6768 case BUILT_IN_ATOMIC_FETCH_OR_4:
6769 case BUILT_IN_ATOMIC_FETCH_OR_8:
6770 case BUILT_IN_ATOMIC_FETCH_OR_16:
6771 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_OR_1);
6772 target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, false,
6773 ignore, BUILT_IN_NONE);
6774 if (target)
6775 return target;
6776 break;
10b744a3 6777
6778 case BUILT_IN_ATOMIC_TEST_AND_SET:
7821cde1 6779 return expand_builtin_atomic_test_and_set (exp, target);
10b744a3 6780
6781 case BUILT_IN_ATOMIC_CLEAR:
6782 return expand_builtin_atomic_clear (exp);
1cd6e20d 6783
6784 case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
6785 return expand_builtin_atomic_always_lock_free (exp);
6786
6787 case BUILT_IN_ATOMIC_IS_LOCK_FREE:
6788 target = expand_builtin_atomic_is_lock_free (exp);
6789 if (target)
6790 return target;
6791 break;
6792
6793 case BUILT_IN_ATOMIC_THREAD_FENCE:
6794 expand_builtin_atomic_thread_fence (exp);
6795 return const0_rtx;
6796
6797 case BUILT_IN_ATOMIC_SIGNAL_FENCE:
6798 expand_builtin_atomic_signal_fence (exp);
6799 return const0_rtx;
6800
0a39fd54 6801 case BUILT_IN_OBJECT_SIZE:
6802 return expand_builtin_object_size (exp);
6803
6804 case BUILT_IN_MEMCPY_CHK:
6805 case BUILT_IN_MEMPCPY_CHK:
6806 case BUILT_IN_MEMMOVE_CHK:
6807 case BUILT_IN_MEMSET_CHK:
6808 target = expand_builtin_memory_chk (exp, target, mode, fcode);
6809 if (target)
6810 return target;
6811 break;
6812
6813 case BUILT_IN_STRCPY_CHK:
6814 case BUILT_IN_STPCPY_CHK:
6815 case BUILT_IN_STRNCPY_CHK:
1063acde 6816 case BUILT_IN_STPNCPY_CHK:
0a39fd54 6817 case BUILT_IN_STRCAT_CHK:
b356dfef 6818 case BUILT_IN_STRNCAT_CHK:
0a39fd54 6819 case BUILT_IN_SNPRINTF_CHK:
6820 case BUILT_IN_VSNPRINTF_CHK:
6821 maybe_emit_chk_warning (exp, fcode);
6822 break;
6823
6824 case BUILT_IN_SPRINTF_CHK:
6825 case BUILT_IN_VSPRINTF_CHK:
6826 maybe_emit_sprintf_chk_warning (exp, fcode);
6827 break;
6828
2c281b15 6829 case BUILT_IN_FREE:
f74ea1c2 6830 if (warn_free_nonheap_object)
6831 maybe_emit_free_warning (exp);
2c281b15 6832 break;
6833
badaa04c 6834 case BUILT_IN_THREAD_POINTER:
6835 return expand_builtin_thread_pointer (exp, target);
6836
6837 case BUILT_IN_SET_THREAD_POINTER:
6838 expand_builtin_set_thread_pointer (exp);
6839 return const0_rtx;
6840
d037099f 6841 case BUILT_IN_CILK_DETACH:
6842 expand_builtin_cilk_detach (exp);
6843 return const0_rtx;
6844
6845 case BUILT_IN_CILK_POP_FRAME:
6846 expand_builtin_cilk_pop_frame (exp);
6847 return const0_rtx;
6848
9b76d759 6849 case BUILT_IN_CHKP_INIT_PTR_BOUNDS:
6850 case BUILT_IN_CHKP_NULL_PTR_BOUNDS:
6851 case BUILT_IN_CHKP_COPY_PTR_BOUNDS:
6852 return expand_normal (CALL_EXPR_ARG (exp, 0));
6853
6854 case BUILT_IN_CHKP_CHECK_PTR_LBOUNDS:
6855 case BUILT_IN_CHKP_CHECK_PTR_UBOUNDS:
6856 case BUILT_IN_CHKP_CHECK_PTR_BOUNDS:
6857 case BUILT_IN_CHKP_SET_PTR_BOUNDS:
6858 case BUILT_IN_CHKP_NARROW_PTR_BOUNDS:
6859 case BUILT_IN_CHKP_STORE_PTR_BOUNDS:
6860 case BUILT_IN_CHKP_GET_PTR_LBOUND:
6861 case BUILT_IN_CHKP_GET_PTR_UBOUND:
6862 /* We allow user CHKP builtins if Pointer Bounds
6863 Checker is off. */
6864 if (!flag_check_pointer_bounds)
6865 {
6866 if (fcode == BUILT_IN_CHKP_SET_PTR_BOUNDS
6867 || fcode == BUILT_IN_CHKP_NARROW_PTR_BOUNDS)
6868 return expand_normal (CALL_EXPR_ARG (exp, 0));
6869 else if (fcode == BUILT_IN_CHKP_GET_PTR_LBOUND)
6870 return expand_normal (size_zero_node);
6871 else if (fcode == BUILT_IN_CHKP_GET_PTR_UBOUND)
6872 return expand_normal (size_int (-1));
6873 else
6874 return const0_rtx;
6875 }
6876 /* FALLTHROUGH */
6877
6878 case BUILT_IN_CHKP_BNDMK:
6879 case BUILT_IN_CHKP_BNDSTX:
6880 case BUILT_IN_CHKP_BNDCL:
6881 case BUILT_IN_CHKP_BNDCU:
6882 case BUILT_IN_CHKP_BNDLDX:
6883 case BUILT_IN_CHKP_BNDRET:
6884 case BUILT_IN_CHKP_INTERSECT:
6885 case BUILT_IN_CHKP_ARG_BND:
6886 case BUILT_IN_CHKP_NARROW:
6887 case BUILT_IN_CHKP_EXTRACT_LOWER:
6888 case BUILT_IN_CHKP_EXTRACT_UPPER:
6889 /* Software implementation of pointers checker is NYI.
6890 Target support is required. */
6891 error ("Your target platform does not support -fcheck-pointers");
6892 break;
6893
92482ee0 6894 default: /* just do library call, if unknown builtin */
146c1b4f 6895 break;
53800dbe 6896 }
6897
6898 /* The switch statement above can drop through to cause the function
6899 to be called normally. */
6900 return expand_call (exp, target, ignore);
6901}
650e4c94 6902
805e22b2 6903/* Determine whether a tree node represents a call to a built-in
52203a9d 6904 function. If the tree T is a call to a built-in function with
6905 the right number of arguments of the appropriate types, return
6906 the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
6907 Otherwise the return value is END_BUILTINS. */
aecda0d6 6908
805e22b2 6909enum built_in_function
b7bf20db 6910builtin_mathfn_code (const_tree t)
805e22b2 6911{
b7bf20db 6912 const_tree fndecl, arg, parmlist;
6913 const_tree argtype, parmtype;
6914 const_call_expr_arg_iterator iter;
805e22b2 6915
6916 if (TREE_CODE (t) != CALL_EXPR
c2f47e15 6917 || TREE_CODE (CALL_EXPR_FN (t)) != ADDR_EXPR)
805e22b2 6918 return END_BUILTINS;
6919
c6e6ecb1 6920 fndecl = get_callee_fndecl (t);
6921 if (fndecl == NULL_TREE
52203a9d 6922 || TREE_CODE (fndecl) != FUNCTION_DECL
805e22b2 6923 || ! DECL_BUILT_IN (fndecl)
6924 || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
6925 return END_BUILTINS;
6926
52203a9d 6927 parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
b7bf20db 6928 init_const_call_expr_arg_iterator (t, &iter);
52203a9d 6929 for (; parmlist; parmlist = TREE_CHAIN (parmlist))
e9f80ff5 6930 {
52203a9d 6931 /* If a function doesn't take a variable number of arguments,
6932 the last element in the list will have type `void'. */
6933 parmtype = TREE_VALUE (parmlist);
6934 if (VOID_TYPE_P (parmtype))
6935 {
b7bf20db 6936 if (more_const_call_expr_args_p (&iter))
52203a9d 6937 return END_BUILTINS;
6938 return DECL_FUNCTION_CODE (fndecl);
6939 }
6940
b7bf20db 6941 if (! more_const_call_expr_args_p (&iter))
e9f80ff5 6942 return END_BUILTINS;
48e1416a 6943
b7bf20db 6944 arg = next_const_call_expr_arg (&iter);
c2f47e15 6945 argtype = TREE_TYPE (arg);
52203a9d 6946
6947 if (SCALAR_FLOAT_TYPE_P (parmtype))
6948 {
6949 if (! SCALAR_FLOAT_TYPE_P (argtype))
6950 return END_BUILTINS;
6951 }
6952 else if (COMPLEX_FLOAT_TYPE_P (parmtype))
6953 {
6954 if (! COMPLEX_FLOAT_TYPE_P (argtype))
6955 return END_BUILTINS;
6956 }
6957 else if (POINTER_TYPE_P (parmtype))
6958 {
6959 if (! POINTER_TYPE_P (argtype))
6960 return END_BUILTINS;
6961 }
6962 else if (INTEGRAL_TYPE_P (parmtype))
6963 {
6964 if (! INTEGRAL_TYPE_P (argtype))
6965 return END_BUILTINS;
6966 }
6967 else
e9f80ff5 6968 return END_BUILTINS;
e9f80ff5 6969 }
6970
52203a9d 6971 /* Variable-length argument list. */
805e22b2 6972 return DECL_FUNCTION_CODE (fndecl);
6973}
6974
c2f47e15 6975/* Fold a call to __builtin_constant_p, if we know its argument ARG will
6976 evaluate to a constant. */
650e4c94 6977
6978static tree
c2f47e15 6979fold_builtin_constant_p (tree arg)
650e4c94 6980{
650e4c94 6981 /* We return 1 for a numeric type that's known to be a constant
6982 value at compile-time or for an aggregate type that's a
6983 literal constant. */
c2f47e15 6984 STRIP_NOPS (arg);
650e4c94 6985
6986 /* If we know this is a constant, emit the constant of one. */
c2f47e15 6987 if (CONSTANT_CLASS_P (arg)
6988 || (TREE_CODE (arg) == CONSTRUCTOR
6989 && TREE_CONSTANT (arg)))
650e4c94 6990 return integer_one_node;
c2f47e15 6991 if (TREE_CODE (arg) == ADDR_EXPR)
adcfa3a3 6992 {
c2f47e15 6993 tree op = TREE_OPERAND (arg, 0);
adcfa3a3 6994 if (TREE_CODE (op) == STRING_CST
6995 || (TREE_CODE (op) == ARRAY_REF
6996 && integer_zerop (TREE_OPERAND (op, 1))
6997 && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
6998 return integer_one_node;
6999 }
650e4c94 7000
1fb4300c 7001 /* If this expression has side effects, show we don't know it to be a
7002 constant. Likewise if it's a pointer or aggregate type since in
7003 those case we only want literals, since those are only optimized
f97c71a1 7004 when generating RTL, not later.
7005 And finally, if we are compiling an initializer, not code, we
7006 need to return a definite result now; there's not going to be any
7007 more optimization done. */
c2f47e15 7008 if (TREE_SIDE_EFFECTS (arg)
7009 || AGGREGATE_TYPE_P (TREE_TYPE (arg))
7010 || POINTER_TYPE_P (TREE_TYPE (arg))
47be647d 7011 || cfun == 0
0b049e15 7012 || folding_initializer
7013 || force_folding_builtin_constant_p)
650e4c94 7014 return integer_zero_node;
7015
c2f47e15 7016 return NULL_TREE;
650e4c94 7017}
7018
76f5a783 7019/* Create builtin_expect with PRED and EXPECTED as its arguments and
7020 return it as a truthvalue. */
4ee9c684 7021
7022static tree
389dd41b 7023build_builtin_expect_predicate (location_t loc, tree pred, tree expected)
4ee9c684 7024{
76f5a783 7025 tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
4ee9c684 7026
b9a16870 7027 fn = builtin_decl_explicit (BUILT_IN_EXPECT);
76f5a783 7028 arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
7029 ret_type = TREE_TYPE (TREE_TYPE (fn));
7030 pred_type = TREE_VALUE (arg_types);
7031 expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
7032
389dd41b 7033 pred = fold_convert_loc (loc, pred_type, pred);
7034 expected = fold_convert_loc (loc, expected_type, expected);
7035 call_expr = build_call_expr_loc (loc, fn, 2, pred, expected);
76f5a783 7036
7037 return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
7038 build_int_cst (ret_type, 0));
7039}
7040
7041/* Fold a call to builtin_expect with arguments ARG0 and ARG1. Return
7042 NULL_TREE if no simplification is possible. */
7043
7044static tree
389dd41b 7045fold_builtin_expect (location_t loc, tree arg0, tree arg1)
76f5a783 7046{
083bada9 7047 tree inner, fndecl, inner_arg0;
76f5a783 7048 enum tree_code code;
7049
083bada9 7050 /* Distribute the expected value over short-circuiting operators.
7051 See through the cast from truthvalue_type_node to long. */
7052 inner_arg0 = arg0;
7053 while (TREE_CODE (inner_arg0) == NOP_EXPR
7054 && INTEGRAL_TYPE_P (TREE_TYPE (inner_arg0))
7055 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner_arg0, 0))))
7056 inner_arg0 = TREE_OPERAND (inner_arg0, 0);
7057
76f5a783 7058 /* If this is a builtin_expect within a builtin_expect keep the
7059 inner one. See through a comparison against a constant. It
7060 might have been added to create a thruthvalue. */
083bada9 7061 inner = inner_arg0;
7062
76f5a783 7063 if (COMPARISON_CLASS_P (inner)
7064 && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST)
7065 inner = TREE_OPERAND (inner, 0);
7066
7067 if (TREE_CODE (inner) == CALL_EXPR
7068 && (fndecl = get_callee_fndecl (inner))
7069 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
7070 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT)
7071 return arg0;
7072
083bada9 7073 inner = inner_arg0;
76f5a783 7074 code = TREE_CODE (inner);
7075 if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
7076 {
7077 tree op0 = TREE_OPERAND (inner, 0);
7078 tree op1 = TREE_OPERAND (inner, 1);
7079
389dd41b 7080 op0 = build_builtin_expect_predicate (loc, op0, arg1);
7081 op1 = build_builtin_expect_predicate (loc, op1, arg1);
76f5a783 7082 inner = build2 (code, TREE_TYPE (inner), op0, op1);
7083
389dd41b 7084 return fold_convert_loc (loc, TREE_TYPE (arg0), inner);
76f5a783 7085 }
7086
7087 /* If the argument isn't invariant then there's nothing else we can do. */
083bada9 7088 if (!TREE_CONSTANT (inner_arg0))
c2f47e15 7089 return NULL_TREE;
4ee9c684 7090
76f5a783 7091 /* If we expect that a comparison against the argument will fold to
7092 a constant return the constant. In practice, this means a true
7093 constant or the address of a non-weak symbol. */
083bada9 7094 inner = inner_arg0;
4ee9c684 7095 STRIP_NOPS (inner);
7096 if (TREE_CODE (inner) == ADDR_EXPR)
7097 {
7098 do
7099 {
7100 inner = TREE_OPERAND (inner, 0);
7101 }
7102 while (TREE_CODE (inner) == COMPONENT_REF
7103 || TREE_CODE (inner) == ARRAY_REF);
062b4460 7104 if ((TREE_CODE (inner) == VAR_DECL
7105 || TREE_CODE (inner) == FUNCTION_DECL)
7106 && DECL_WEAK (inner))
c2f47e15 7107 return NULL_TREE;
4ee9c684 7108 }
7109
76f5a783 7110 /* Otherwise, ARG0 already has the proper type for the return value. */
7111 return arg0;
4ee9c684 7112}
7113
c2f47e15 7114/* Fold a call to __builtin_classify_type with argument ARG. */
27d0c333 7115
539a3a92 7116static tree
c2f47e15 7117fold_builtin_classify_type (tree arg)
539a3a92 7118{
c2f47e15 7119 if (arg == 0)
7002a1c8 7120 return build_int_cst (integer_type_node, no_type_class);
539a3a92 7121
7002a1c8 7122 return build_int_cst (integer_type_node, type_to_class (TREE_TYPE (arg)));
539a3a92 7123}
7124
c2f47e15 7125/* Fold a call to __builtin_strlen with argument ARG. */
e6e27594 7126
7127static tree
c7cbde74 7128fold_builtin_strlen (location_t loc, tree type, tree arg)
e6e27594 7129{
c2f47e15 7130 if (!validate_arg (arg, POINTER_TYPE))
e6e27594 7131 return NULL_TREE;
7132 else
7133 {
c2f47e15 7134 tree len = c_strlen (arg, 0);
e6e27594 7135
7136 if (len)
c7cbde74 7137 return fold_convert_loc (loc, type, len);
e6e27594 7138
7139 return NULL_TREE;
7140 }
7141}
7142
92c43e3c 7143/* Fold a call to __builtin_inf or __builtin_huge_val. */
7144
7145static tree
389dd41b 7146fold_builtin_inf (location_t loc, tree type, int warn)
92c43e3c 7147{
aa870c1b 7148 REAL_VALUE_TYPE real;
7149
40f4dbd5 7150 /* __builtin_inff is intended to be usable to define INFINITY on all
7151 targets. If an infinity is not available, INFINITY expands "to a
7152 positive constant of type float that overflows at translation
7153 time", footnote "In this case, using INFINITY will violate the
7154 constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
7155 Thus we pedwarn to ensure this constraint violation is
7156 diagnosed. */
92c43e3c 7157 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
389dd41b 7158 pedwarn (loc, 0, "target format does not support infinity");
92c43e3c 7159
aa870c1b 7160 real_inf (&real);
7161 return build_real (type, real);
92c43e3c 7162}
7163
c2f47e15 7164/* Fold a call to __builtin_nan or __builtin_nans with argument ARG. */
b0db7939 7165
7166static tree
c2f47e15 7167fold_builtin_nan (tree arg, tree type, int quiet)
b0db7939 7168{
7169 REAL_VALUE_TYPE real;
7170 const char *str;
7171
c2f47e15 7172 if (!validate_arg (arg, POINTER_TYPE))
7173 return NULL_TREE;
7174 str = c_getstr (arg);
b0db7939 7175 if (!str)
c2f47e15 7176 return NULL_TREE;
b0db7939 7177
7178 if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
c2f47e15 7179 return NULL_TREE;
b0db7939 7180
7181 return build_real (type, real);
7182}
7183
277f8dd2 7184/* Return true if the floating point expression T has an integer value.
7185 We also allow +Inf, -Inf and NaN to be considered integer values. */
7186
7187static bool
7188integer_valued_real_p (tree t)
7189{
7190 switch (TREE_CODE (t))
7191 {
7192 case FLOAT_EXPR:
7193 return true;
7194
7195 case ABS_EXPR:
7196 case SAVE_EXPR:
277f8dd2 7197 return integer_valued_real_p (TREE_OPERAND (t, 0));
7198
7199 case COMPOUND_EXPR:
41076ef6 7200 case MODIFY_EXPR:
277f8dd2 7201 case BIND_EXPR:
75a70cf9 7202 return integer_valued_real_p (TREE_OPERAND (t, 1));
277f8dd2 7203
7204 case PLUS_EXPR:
7205 case MINUS_EXPR:
7206 case MULT_EXPR:
7207 case MIN_EXPR:
7208 case MAX_EXPR:
7209 return integer_valued_real_p (TREE_OPERAND (t, 0))
7210 && integer_valued_real_p (TREE_OPERAND (t, 1));
7211
7212 case COND_EXPR:
7213 return integer_valued_real_p (TREE_OPERAND (t, 1))
7214 && integer_valued_real_p (TREE_OPERAND (t, 2));
7215
7216 case REAL_CST:
0570334c 7217 return real_isinteger (TREE_REAL_CST_PTR (t), TYPE_MODE (TREE_TYPE (t)));
277f8dd2 7218
7219 case NOP_EXPR:
7220 {
7221 tree type = TREE_TYPE (TREE_OPERAND (t, 0));
7222 if (TREE_CODE (type) == INTEGER_TYPE)
7223 return true;
7224 if (TREE_CODE (type) == REAL_TYPE)
7225 return integer_valued_real_p (TREE_OPERAND (t, 0));
7226 break;
7227 }
7228
7229 case CALL_EXPR:
7230 switch (builtin_mathfn_code (t))
7231 {
4f35b1fc 7232 CASE_FLT_FN (BUILT_IN_CEIL):
7233 CASE_FLT_FN (BUILT_IN_FLOOR):
7234 CASE_FLT_FN (BUILT_IN_NEARBYINT):
7235 CASE_FLT_FN (BUILT_IN_RINT):
7236 CASE_FLT_FN (BUILT_IN_ROUND):
7237 CASE_FLT_FN (BUILT_IN_TRUNC):
277f8dd2 7238 return true;
7239
d4a43a03 7240 CASE_FLT_FN (BUILT_IN_FMIN):
7241 CASE_FLT_FN (BUILT_IN_FMAX):
c2f47e15 7242 return integer_valued_real_p (CALL_EXPR_ARG (t, 0))
7243 && integer_valued_real_p (CALL_EXPR_ARG (t, 1));
d4a43a03 7244
277f8dd2 7245 default:
7246 break;
7247 }
7248 break;
7249
7250 default:
7251 break;
7252 }
7253 return false;
7254}
7255
c2f47e15 7256/* FNDECL is assumed to be a builtin where truncation can be propagated
6528f4f4 7257 across (for instance floor((double)f) == (double)floorf (f).
c2f47e15 7258 Do the transformation for a call with argument ARG. */
277f8dd2 7259
6528f4f4 7260static tree
389dd41b 7261fold_trunc_transparent_mathfn (location_t loc, tree fndecl, tree arg)
6528f4f4 7262{
6528f4f4 7263 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
277f8dd2 7264
c2f47e15 7265 if (!validate_arg (arg, REAL_TYPE))
7266 return NULL_TREE;
6528f4f4 7267
277f8dd2 7268 /* Integer rounding functions are idempotent. */
7269 if (fcode == builtin_mathfn_code (arg))
7270 return arg;
7271
7272 /* If argument is already integer valued, and we don't need to worry
7273 about setting errno, there's no need to perform rounding. */
7274 if (! flag_errno_math && integer_valued_real_p (arg))
7275 return arg;
7276
7277 if (optimize)
6528f4f4 7278 {
277f8dd2 7279 tree arg0 = strip_float_extensions (arg);
2426241c 7280 tree ftype = TREE_TYPE (TREE_TYPE (fndecl));
6528f4f4 7281 tree newtype = TREE_TYPE (arg0);
7282 tree decl;
7283
7284 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7285 && (decl = mathfn_built_in (newtype, fcode)))
389dd41b 7286 return fold_convert_loc (loc, ftype,
7287 build_call_expr_loc (loc, decl, 1,
7288 fold_convert_loc (loc,
7289 newtype,
7290 arg0)));
6528f4f4 7291 }
c2f47e15 7292 return NULL_TREE;
6528f4f4 7293}
7294
c2f47e15 7295/* FNDECL is assumed to be builtin which can narrow the FP type of
7296 the argument, for instance lround((double)f) -> lroundf (f).
7297 Do the transformation for a call with argument ARG. */
9ed65c7f 7298
7299static tree
389dd41b 7300fold_fixed_mathfn (location_t loc, tree fndecl, tree arg)
9ed65c7f 7301{
9ed65c7f 7302 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9ed65c7f 7303
c2f47e15 7304 if (!validate_arg (arg, REAL_TYPE))
7305 return NULL_TREE;
9ed65c7f 7306
7307 /* If argument is already integer valued, and we don't need to worry
7308 about setting errno, there's no need to perform rounding. */
7309 if (! flag_errno_math && integer_valued_real_p (arg))
389dd41b 7310 return fold_build1_loc (loc, FIX_TRUNC_EXPR,
7311 TREE_TYPE (TREE_TYPE (fndecl)), arg);
9ed65c7f 7312
7313 if (optimize)
7314 {
7315 tree ftype = TREE_TYPE (arg);
7316 tree arg0 = strip_float_extensions (arg);
7317 tree newtype = TREE_TYPE (arg0);
7318 tree decl;
7319
7320 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7321 && (decl = mathfn_built_in (newtype, fcode)))
389dd41b 7322 return build_call_expr_loc (loc, decl, 1,
7323 fold_convert_loc (loc, newtype, arg0));
9ed65c7f 7324 }
73a0da56 7325
80ff6494 7326 /* Canonicalize iround (x) to lround (x) on ILP32 targets where
7327 sizeof (int) == sizeof (long). */
7328 if (TYPE_PRECISION (integer_type_node)
7329 == TYPE_PRECISION (long_integer_type_node))
7330 {
7331 tree newfn = NULL_TREE;
7332 switch (fcode)
7333 {
7334 CASE_FLT_FN (BUILT_IN_ICEIL):
7335 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
7336 break;
7337
7338 CASE_FLT_FN (BUILT_IN_IFLOOR):
7339 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
7340 break;
7341
7342 CASE_FLT_FN (BUILT_IN_IROUND):
7343 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
7344 break;
7345
7346 CASE_FLT_FN (BUILT_IN_IRINT):
7347 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
7348 break;
7349
7350 default:
7351 break;
7352 }
7353
7354 if (newfn)
7355 {
7356 tree newcall = build_call_expr_loc (loc, newfn, 1, arg);
7357 return fold_convert_loc (loc,
7358 TREE_TYPE (TREE_TYPE (fndecl)), newcall);
7359 }
7360 }
7361
73a0da56 7362 /* Canonicalize llround (x) to lround (x) on LP64 targets where
7363 sizeof (long long) == sizeof (long). */
7364 if (TYPE_PRECISION (long_long_integer_type_node)
7365 == TYPE_PRECISION (long_integer_type_node))
7366 {
7367 tree newfn = NULL_TREE;
7368 switch (fcode)
7369 {
7370 CASE_FLT_FN (BUILT_IN_LLCEIL):
7371 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
7372 break;
7373
7374 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7375 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
7376 break;
7377
7378 CASE_FLT_FN (BUILT_IN_LLROUND):
7379 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
7380 break;
7381
7382 CASE_FLT_FN (BUILT_IN_LLRINT):
7383 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
7384 break;
7385
7386 default:
7387 break;
7388 }
7389
7390 if (newfn)
7391 {
389dd41b 7392 tree newcall = build_call_expr_loc (loc, newfn, 1, arg);
7393 return fold_convert_loc (loc,
7394 TREE_TYPE (TREE_TYPE (fndecl)), newcall);
73a0da56 7395 }
7396 }
7397
c2f47e15 7398 return NULL_TREE;
9ed65c7f 7399}
7400
c2f47e15 7401/* Fold call to builtin cabs, cabsf or cabsl with argument ARG. TYPE is the
7402 return type. Return NULL_TREE if no simplification can be made. */
c63f4ad3 7403
7404static tree
389dd41b 7405fold_builtin_cabs (location_t loc, tree arg, tree type, tree fndecl)
c63f4ad3 7406{
c2f47e15 7407 tree res;
c63f4ad3 7408
b0ce8887 7409 if (!validate_arg (arg, COMPLEX_TYPE)
c63f4ad3 7410 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
7411 return NULL_TREE;
7412
b4725390 7413 /* Calculate the result when the argument is a constant. */
7414 if (TREE_CODE (arg) == COMPLEX_CST
7415 && (res = do_mpfr_arg2 (TREE_REALPART (arg), TREE_IMAGPART (arg),
7416 type, mpfr_hypot)))
7417 return res;
48e1416a 7418
1af0d139 7419 if (TREE_CODE (arg) == COMPLEX_EXPR)
7420 {
7421 tree real = TREE_OPERAND (arg, 0);
7422 tree imag = TREE_OPERAND (arg, 1);
48e1416a 7423
1af0d139 7424 /* If either part is zero, cabs is fabs of the other. */
7425 if (real_zerop (real))
389dd41b 7426 return fold_build1_loc (loc, ABS_EXPR, type, imag);
1af0d139 7427 if (real_zerop (imag))
389dd41b 7428 return fold_build1_loc (loc, ABS_EXPR, type, real);
1af0d139 7429
7430 /* cabs(x+xi) -> fabs(x)*sqrt(2). */
7431 if (flag_unsafe_math_optimizations
7432 && operand_equal_p (real, imag, OEP_PURE_SAME))
7433 {
2e7ca27b 7434 const REAL_VALUE_TYPE sqrt2_trunc
7910b2fb 7435 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
1af0d139 7436 STRIP_NOPS (real);
389dd41b 7437 return fold_build2_loc (loc, MULT_EXPR, type,
7438 fold_build1_loc (loc, ABS_EXPR, type, real),
2e7ca27b 7439 build_real (type, sqrt2_trunc));
1af0d139 7440 }
7441 }
c63f4ad3 7442
749891b2 7443 /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */
7444 if (TREE_CODE (arg) == NEGATE_EXPR
7445 || TREE_CODE (arg) == CONJ_EXPR)
389dd41b 7446 return build_call_expr_loc (loc, fndecl, 1, TREE_OPERAND (arg, 0));
749891b2 7447
7d3f6cc7 7448 /* Don't do this when optimizing for size. */
7449 if (flag_unsafe_math_optimizations
0bfd8d5c 7450 && optimize && optimize_function_for_speed_p (cfun))
c63f4ad3 7451 {
0da0dbfa 7452 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
c63f4ad3 7453
7454 if (sqrtfn != NULL_TREE)
7455 {
c2f47e15 7456 tree rpart, ipart, result;
c63f4ad3 7457
4ee9c684 7458 arg = builtin_save_expr (arg);
29a6518e 7459
389dd41b 7460 rpart = fold_build1_loc (loc, REALPART_EXPR, type, arg);
7461 ipart = fold_build1_loc (loc, IMAGPART_EXPR, type, arg);
c63f4ad3 7462
4ee9c684 7463 rpart = builtin_save_expr (rpart);
7464 ipart = builtin_save_expr (ipart);
c63f4ad3 7465
389dd41b 7466 result = fold_build2_loc (loc, PLUS_EXPR, type,
7467 fold_build2_loc (loc, MULT_EXPR, type,
49d00087 7468 rpart, rpart),
389dd41b 7469 fold_build2_loc (loc, MULT_EXPR, type,
49d00087 7470 ipart, ipart));
c63f4ad3 7471
389dd41b 7472 return build_call_expr_loc (loc, sqrtfn, 1, result);
c63f4ad3 7473 }
7474 }
7475
7476 return NULL_TREE;
7477}
7478
c2373fdb 7479/* Build a complex (inf +- 0i) for the result of cproj. TYPE is the
7480 complex tree type of the result. If NEG is true, the imaginary
7481 zero is negative. */
7482
7483static tree
7484build_complex_cproj (tree type, bool neg)
7485{
7486 REAL_VALUE_TYPE rinf, rzero = dconst0;
7487
7488 real_inf (&rinf);
7489 rzero.sign = neg;
7490 return build_complex (type, build_real (TREE_TYPE (type), rinf),
7491 build_real (TREE_TYPE (type), rzero));
7492}
7493
7494/* Fold call to builtin cproj, cprojf or cprojl with argument ARG. TYPE is the
7495 return type. Return NULL_TREE if no simplification can be made. */
7496
7497static tree
7498fold_builtin_cproj (location_t loc, tree arg, tree type)
7499{
7500 if (!validate_arg (arg, COMPLEX_TYPE)
7501 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
7502 return NULL_TREE;
7503
7504 /* If there are no infinities, return arg. */
7505 if (! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (type))))
7506 return non_lvalue_loc (loc, arg);
7507
7508 /* Calculate the result when the argument is a constant. */
7509 if (TREE_CODE (arg) == COMPLEX_CST)
7510 {
7511 const REAL_VALUE_TYPE *real = TREE_REAL_CST_PTR (TREE_REALPART (arg));
7512 const REAL_VALUE_TYPE *imag = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
7513
7514 if (real_isinf (real) || real_isinf (imag))
7515 return build_complex_cproj (type, imag->sign);
7516 else
7517 return arg;
7518 }
b4c7e601 7519 else if (TREE_CODE (arg) == COMPLEX_EXPR)
7520 {
7521 tree real = TREE_OPERAND (arg, 0);
7522 tree imag = TREE_OPERAND (arg, 1);
7523
7524 STRIP_NOPS (real);
7525 STRIP_NOPS (imag);
7526
7527 /* If the real part is inf and the imag part is known to be
7528 nonnegative, return (inf + 0i). Remember side-effects are
7529 possible in the imag part. */
7530 if (TREE_CODE (real) == REAL_CST
7531 && real_isinf (TREE_REAL_CST_PTR (real))
7532 && tree_expr_nonnegative_p (imag))
7533 return omit_one_operand_loc (loc, type,
7534 build_complex_cproj (type, false),
7535 arg);
7536
7537 /* If the imag part is inf, return (inf+I*copysign(0,imag)).
7538 Remember side-effects are possible in the real part. */
7539 if (TREE_CODE (imag) == REAL_CST
7540 && real_isinf (TREE_REAL_CST_PTR (imag)))
7541 return
7542 omit_one_operand_loc (loc, type,
7543 build_complex_cproj (type, TREE_REAL_CST_PTR
7544 (imag)->sign), arg);
7545 }
c2373fdb 7546
7547 return NULL_TREE;
7548}
7549
c2f47e15 7550/* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG.
7551 Return NULL_TREE if no simplification can be made. */
e6e27594 7552
7553static tree
389dd41b 7554fold_builtin_sqrt (location_t loc, tree arg, tree type)
e6e27594 7555{
7556
7557 enum built_in_function fcode;
b4e8ab0c 7558 tree res;
c2f47e15 7559
7560 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7561 return NULL_TREE;
7562
b4e8ab0c 7563 /* Calculate the result when the argument is a constant. */
7564 if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
7565 return res;
48e1416a 7566
e6e27594 7567 /* Optimize sqrt(expN(x)) = expN(x*0.5). */
7568 fcode = builtin_mathfn_code (arg);
7569 if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
7570 {
c2f47e15 7571 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
389dd41b 7572 arg = fold_build2_loc (loc, MULT_EXPR, type,
c2f47e15 7573 CALL_EXPR_ARG (arg, 0),
49d00087 7574 build_real (type, dconsthalf));
389dd41b 7575 return build_call_expr_loc (loc, expfn, 1, arg);
e6e27594 7576 }
7577
7578 /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */
7579 if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
7580 {
7581 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7582
7583 if (powfn)
7584 {
c2f47e15 7585 tree arg0 = CALL_EXPR_ARG (arg, 0);
e6e27594 7586 tree tree_root;
7587 /* The inner root was either sqrt or cbrt. */
57510da6 7588 /* This was a conditional expression but it triggered a bug
18381619 7589 in Sun C 5.5. */
ce6cd837 7590 REAL_VALUE_TYPE dconstroot;
7591 if (BUILTIN_SQRT_P (fcode))
7592 dconstroot = dconsthalf;
7593 else
7594 dconstroot = dconst_third ();
e6e27594 7595
7596 /* Adjust for the outer root. */
7597 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7598 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7599 tree_root = build_real (type, dconstroot);
389dd41b 7600 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
e6e27594 7601 }
7602 }
7603
bc33117f 7604 /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
e6e27594 7605 if (flag_unsafe_math_optimizations
7606 && (fcode == BUILT_IN_POW
7607 || fcode == BUILT_IN_POWF
7608 || fcode == BUILT_IN_POWL))
7609 {
c2f47e15 7610 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
7611 tree arg0 = CALL_EXPR_ARG (arg, 0);
7612 tree arg1 = CALL_EXPR_ARG (arg, 1);
bc33117f 7613 tree narg1;
7614 if (!tree_expr_nonnegative_p (arg0))
7615 arg0 = build1 (ABS_EXPR, type, arg0);
389dd41b 7616 narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 7617 build_real (type, dconsthalf));
389dd41b 7618 return build_call_expr_loc (loc, powfn, 2, arg0, narg1);
e6e27594 7619 }
7620
7621 return NULL_TREE;
7622}
7623
c2f47e15 7624/* Fold a builtin function call to cbrt, cbrtf, or cbrtl with argument ARG.
7625 Return NULL_TREE if no simplification can be made. */
7626
e6e27594 7627static tree
389dd41b 7628fold_builtin_cbrt (location_t loc, tree arg, tree type)
e6e27594 7629{
e6e27594 7630 const enum built_in_function fcode = builtin_mathfn_code (arg);
29f4cd78 7631 tree res;
e6e27594 7632
c2f47e15 7633 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7634 return NULL_TREE;
7635
29f4cd78 7636 /* Calculate the result when the argument is a constant. */
7637 if ((res = do_mpfr_arg1 (arg, type, mpfr_cbrt, NULL, NULL, 0)))
7638 return res;
e6e27594 7639
cdfeb715 7640 if (flag_unsafe_math_optimizations)
e6e27594 7641 {
cdfeb715 7642 /* Optimize cbrt(expN(x)) -> expN(x/3). */
7643 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 7644 {
c2f47e15 7645 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7646 const REAL_VALUE_TYPE third_trunc =
7910b2fb 7647 real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 7648 arg = fold_build2_loc (loc, MULT_EXPR, type,
c2f47e15 7649 CALL_EXPR_ARG (arg, 0),
49d00087 7650 build_real (type, third_trunc));
389dd41b 7651 return build_call_expr_loc (loc, expfn, 1, arg);
cdfeb715 7652 }
e6e27594 7653
cdfeb715 7654 /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */
7655 if (BUILTIN_SQRT_P (fcode))
a0c938f0 7656 {
cdfeb715 7657 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
e6e27594 7658
cdfeb715 7659 if (powfn)
7660 {
c2f47e15 7661 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7662 tree tree_root;
7910b2fb 7663 REAL_VALUE_TYPE dconstroot = dconst_third ();
cdfeb715 7664
7665 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7666 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7667 tree_root = build_real (type, dconstroot);
389dd41b 7668 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
cdfeb715 7669 }
e6e27594 7670 }
7671
cdfeb715 7672 /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */
7673 if (BUILTIN_CBRT_P (fcode))
a0c938f0 7674 {
c2f47e15 7675 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7676 if (tree_expr_nonnegative_p (arg0))
7677 {
7678 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7679
7680 if (powfn)
a0c938f0 7681 {
cdfeb715 7682 tree tree_root;
7683 REAL_VALUE_TYPE dconstroot;
a0c938f0 7684
3fa759a9 7685 real_arithmetic (&dconstroot, MULT_EXPR,
7910b2fb 7686 dconst_third_ptr (), dconst_third_ptr ());
cdfeb715 7687 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7688 tree_root = build_real (type, dconstroot);
389dd41b 7689 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
cdfeb715 7690 }
7691 }
7692 }
a0c938f0 7693
cdfeb715 7694 /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */
48e1416a 7695 if (fcode == BUILT_IN_POW
c2f47e15 7696 || fcode == BUILT_IN_POWF
cdfeb715 7697 || fcode == BUILT_IN_POWL)
a0c938f0 7698 {
c2f47e15 7699 tree arg00 = CALL_EXPR_ARG (arg, 0);
7700 tree arg01 = CALL_EXPR_ARG (arg, 1);
cdfeb715 7701 if (tree_expr_nonnegative_p (arg00))
7702 {
c2f47e15 7703 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7704 const REAL_VALUE_TYPE dconstroot
7910b2fb 7705 = real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 7706 tree narg01 = fold_build2_loc (loc, MULT_EXPR, type, arg01,
49d00087 7707 build_real (type, dconstroot));
389dd41b 7708 return build_call_expr_loc (loc, powfn, 2, arg00, narg01);
cdfeb715 7709 }
7710 }
e6e27594 7711 }
7712 return NULL_TREE;
7713}
7714
c2f47e15 7715/* Fold function call to builtin cos, cosf, or cosl with argument ARG.
7716 TYPE is the type of the return value. Return NULL_TREE if no
7717 simplification can be made. */
7718
e6e27594 7719static tree
389dd41b 7720fold_builtin_cos (location_t loc,
7721 tree arg, tree type, tree fndecl)
e6e27594 7722{
e6ab33d8 7723 tree res, narg;
e6e27594 7724
c2f47e15 7725 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7726 return NULL_TREE;
7727
bffb7645 7728 /* Calculate the result when the argument is a constant. */
728bac60 7729 if ((res = do_mpfr_arg1 (arg, type, mpfr_cos, NULL, NULL, 0)))
bffb7645 7730 return res;
48e1416a 7731
e6e27594 7732 /* Optimize cos(-x) into cos (x). */
e6ab33d8 7733 if ((narg = fold_strip_sign_ops (arg)))
389dd41b 7734 return build_call_expr_loc (loc, fndecl, 1, narg);
e6e27594 7735
7736 return NULL_TREE;
7737}
7738
c2f47e15 7739/* Fold function call to builtin cosh, coshf, or coshl with argument ARG.
7740 Return NULL_TREE if no simplification can be made. */
7741
cacdc1af 7742static tree
389dd41b 7743fold_builtin_cosh (location_t loc, tree arg, tree type, tree fndecl)
cacdc1af 7744{
c2f47e15 7745 if (validate_arg (arg, REAL_TYPE))
cacdc1af 7746 {
cacdc1af 7747 tree res, narg;
7748
7749 /* Calculate the result when the argument is a constant. */
7750 if ((res = do_mpfr_arg1 (arg, type, mpfr_cosh, NULL, NULL, 0)))
7751 return res;
48e1416a 7752
cacdc1af 7753 /* Optimize cosh(-x) into cosh (x). */
7754 if ((narg = fold_strip_sign_ops (arg)))
389dd41b 7755 return build_call_expr_loc (loc, fndecl, 1, narg);
cacdc1af 7756 }
48e1416a 7757
cacdc1af 7758 return NULL_TREE;
7759}
7760
239d491a 7761/* Fold function call to builtin ccos (or ccosh if HYPER is TRUE) with
7762 argument ARG. TYPE is the type of the return value. Return
7763 NULL_TREE if no simplification can be made. */
7764
7765static tree
965d0f29 7766fold_builtin_ccos (location_t loc, tree arg, tree type, tree fndecl,
7767 bool hyper)
239d491a 7768{
7769 if (validate_arg (arg, COMPLEX_TYPE)
7770 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
7771 {
7772 tree tmp;
7773
239d491a 7774 /* Calculate the result when the argument is a constant. */
7775 if ((tmp = do_mpc_arg1 (arg, type, (hyper ? mpc_cosh : mpc_cos))))
7776 return tmp;
48e1416a 7777
239d491a 7778 /* Optimize fn(-x) into fn(x). */
7779 if ((tmp = fold_strip_sign_ops (arg)))
389dd41b 7780 return build_call_expr_loc (loc, fndecl, 1, tmp);
239d491a 7781 }
7782
7783 return NULL_TREE;
7784}
7785
c2f47e15 7786/* Fold function call to builtin tan, tanf, or tanl with argument ARG.
7787 Return NULL_TREE if no simplification can be made. */
7788
e6e27594 7789static tree
c2f47e15 7790fold_builtin_tan (tree arg, tree type)
e6e27594 7791{
7792 enum built_in_function fcode;
29f4cd78 7793 tree res;
e6e27594 7794
c2f47e15 7795 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7796 return NULL_TREE;
7797
bffb7645 7798 /* Calculate the result when the argument is a constant. */
728bac60 7799 if ((res = do_mpfr_arg1 (arg, type, mpfr_tan, NULL, NULL, 0)))
bffb7645 7800 return res;
48e1416a 7801
e6e27594 7802 /* Optimize tan(atan(x)) = x. */
7803 fcode = builtin_mathfn_code (arg);
7804 if (flag_unsafe_math_optimizations
7805 && (fcode == BUILT_IN_ATAN
7806 || fcode == BUILT_IN_ATANF
7807 || fcode == BUILT_IN_ATANL))
c2f47e15 7808 return CALL_EXPR_ARG (arg, 0);
e6e27594 7809
7810 return NULL_TREE;
7811}
7812
d735c391 7813/* Fold function call to builtin sincos, sincosf, or sincosl. Return
7814 NULL_TREE if no simplification can be made. */
7815
7816static tree
389dd41b 7817fold_builtin_sincos (location_t loc,
7818 tree arg0, tree arg1, tree arg2)
d735c391 7819{
c2f47e15 7820 tree type;
d735c391 7821 tree res, fn, call;
7822
c2f47e15 7823 if (!validate_arg (arg0, REAL_TYPE)
7824 || !validate_arg (arg1, POINTER_TYPE)
7825 || !validate_arg (arg2, POINTER_TYPE))
d735c391 7826 return NULL_TREE;
7827
d735c391 7828 type = TREE_TYPE (arg0);
d735c391 7829
7830 /* Calculate the result when the argument is a constant. */
7831 if ((res = do_mpfr_sincos (arg0, arg1, arg2)))
7832 return res;
7833
7834 /* Canonicalize sincos to cexpi. */
30f690e0 7835 if (!targetm.libc_has_function (function_c99_math_complex))
2a6b4c77 7836 return NULL_TREE;
d735c391 7837 fn = mathfn_built_in (type, BUILT_IN_CEXPI);
7838 if (!fn)
7839 return NULL_TREE;
7840
389dd41b 7841 call = build_call_expr_loc (loc, fn, 1, arg0);
d735c391 7842 call = builtin_save_expr (call);
7843
a75b1c71 7844 return build2 (COMPOUND_EXPR, void_type_node,
d735c391 7845 build2 (MODIFY_EXPR, void_type_node,
389dd41b 7846 build_fold_indirect_ref_loc (loc, arg1),
d735c391 7847 build1 (IMAGPART_EXPR, type, call)),
7848 build2 (MODIFY_EXPR, void_type_node,
389dd41b 7849 build_fold_indirect_ref_loc (loc, arg2),
d735c391 7850 build1 (REALPART_EXPR, type, call)));
7851}
7852
c5bb2c4b 7853/* Fold function call to builtin cexp, cexpf, or cexpl. Return
7854 NULL_TREE if no simplification can be made. */
7855
7856static tree
389dd41b 7857fold_builtin_cexp (location_t loc, tree arg0, tree type)
c5bb2c4b 7858{
c2f47e15 7859 tree rtype;
c5bb2c4b 7860 tree realp, imagp, ifn;
239d491a 7861 tree res;
c5bb2c4b 7862
239d491a 7863 if (!validate_arg (arg0, COMPLEX_TYPE)
b0ce8887 7864 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) != REAL_TYPE)
c5bb2c4b 7865 return NULL_TREE;
7866
239d491a 7867 /* Calculate the result when the argument is a constant. */
7868 if ((res = do_mpc_arg1 (arg0, type, mpc_exp)))
7869 return res;
48e1416a 7870
c5bb2c4b 7871 rtype = TREE_TYPE (TREE_TYPE (arg0));
7872
7873 /* In case we can figure out the real part of arg0 and it is constant zero
7874 fold to cexpi. */
30f690e0 7875 if (!targetm.libc_has_function (function_c99_math_complex))
2a6b4c77 7876 return NULL_TREE;
c5bb2c4b 7877 ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI);
7878 if (!ifn)
7879 return NULL_TREE;
7880
389dd41b 7881 if ((realp = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0))
c5bb2c4b 7882 && real_zerop (realp))
7883 {
389dd41b 7884 tree narg = fold_build1_loc (loc, IMAGPART_EXPR, rtype, arg0);
7885 return build_call_expr_loc (loc, ifn, 1, narg);
c5bb2c4b 7886 }
7887
7888 /* In case we can easily decompose real and imaginary parts split cexp
7889 to exp (r) * cexpi (i). */
7890 if (flag_unsafe_math_optimizations
7891 && realp)
7892 {
7893 tree rfn, rcall, icall;
7894
7895 rfn = mathfn_built_in (rtype, BUILT_IN_EXP);
7896 if (!rfn)
7897 return NULL_TREE;
7898
389dd41b 7899 imagp = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
c5bb2c4b 7900 if (!imagp)
7901 return NULL_TREE;
7902
389dd41b 7903 icall = build_call_expr_loc (loc, ifn, 1, imagp);
c5bb2c4b 7904 icall = builtin_save_expr (icall);
389dd41b 7905 rcall = build_call_expr_loc (loc, rfn, 1, realp);
c5bb2c4b 7906 rcall = builtin_save_expr (rcall);
389dd41b 7907 return fold_build2_loc (loc, COMPLEX_EXPR, type,
7908 fold_build2_loc (loc, MULT_EXPR, rtype,
71bf42bb 7909 rcall,
389dd41b 7910 fold_build1_loc (loc, REALPART_EXPR,
7911 rtype, icall)),
7912 fold_build2_loc (loc, MULT_EXPR, rtype,
71bf42bb 7913 rcall,
389dd41b 7914 fold_build1_loc (loc, IMAGPART_EXPR,
7915 rtype, icall)));
c5bb2c4b 7916 }
7917
7918 return NULL_TREE;
7919}
7920
c2f47e15 7921/* Fold function call to builtin trunc, truncf or truncl with argument ARG.
7922 Return NULL_TREE if no simplification can be made. */
277f8dd2 7923
7924static tree
389dd41b 7925fold_builtin_trunc (location_t loc, tree fndecl, tree arg)
277f8dd2 7926{
c2f47e15 7927 if (!validate_arg (arg, REAL_TYPE))
7928 return NULL_TREE;
277f8dd2 7929
7930 /* Optimize trunc of constant value. */
f96bd2bf 7931 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7932 {
7933 REAL_VALUE_TYPE r, x;
2426241c 7934 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7935
7936 x = TREE_REAL_CST (arg);
7937 real_trunc (&r, TYPE_MODE (type), &x);
7938 return build_real (type, r);
7939 }
7940
389dd41b 7941 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7942}
7943
c2f47e15 7944/* Fold function call to builtin floor, floorf or floorl with argument ARG.
7945 Return NULL_TREE if no simplification can be made. */
277f8dd2 7946
7947static tree
389dd41b 7948fold_builtin_floor (location_t loc, tree fndecl, tree arg)
277f8dd2 7949{
c2f47e15 7950 if (!validate_arg (arg, REAL_TYPE))
7951 return NULL_TREE;
277f8dd2 7952
7953 /* Optimize floor of constant value. */
f96bd2bf 7954 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7955 {
7956 REAL_VALUE_TYPE x;
7957
7958 x = TREE_REAL_CST (arg);
7959 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7960 {
2426241c 7961 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7962 REAL_VALUE_TYPE r;
7963
7964 real_floor (&r, TYPE_MODE (type), &x);
7965 return build_real (type, r);
7966 }
7967 }
7968
acc2b92e 7969 /* Fold floor (x) where x is nonnegative to trunc (x). */
7970 if (tree_expr_nonnegative_p (arg))
30fe8286 7971 {
7972 tree truncfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_TRUNC);
7973 if (truncfn)
389dd41b 7974 return build_call_expr_loc (loc, truncfn, 1, arg);
30fe8286 7975 }
acc2b92e 7976
389dd41b 7977 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7978}
7979
c2f47e15 7980/* Fold function call to builtin ceil, ceilf or ceill with argument ARG.
7981 Return NULL_TREE if no simplification can be made. */
277f8dd2 7982
7983static tree
389dd41b 7984fold_builtin_ceil (location_t loc, tree fndecl, tree arg)
277f8dd2 7985{
c2f47e15 7986 if (!validate_arg (arg, REAL_TYPE))
7987 return NULL_TREE;
277f8dd2 7988
7989 /* Optimize ceil of constant value. */
f96bd2bf 7990 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7991 {
7992 REAL_VALUE_TYPE x;
7993
7994 x = TREE_REAL_CST (arg);
7995 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7996 {
2426241c 7997 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7998 REAL_VALUE_TYPE r;
7999
8000 real_ceil (&r, TYPE_MODE (type), &x);
8001 return build_real (type, r);
8002 }
8003 }
8004
389dd41b 8005 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 8006}
8007
c2f47e15 8008/* Fold function call to builtin round, roundf or roundl with argument ARG.
8009 Return NULL_TREE if no simplification can be made. */
89ab3887 8010
8011static tree
389dd41b 8012fold_builtin_round (location_t loc, tree fndecl, tree arg)
89ab3887 8013{
c2f47e15 8014 if (!validate_arg (arg, REAL_TYPE))
8015 return NULL_TREE;
89ab3887 8016
34f17811 8017 /* Optimize round of constant value. */
f96bd2bf 8018 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
89ab3887 8019 {
8020 REAL_VALUE_TYPE x;
8021
8022 x = TREE_REAL_CST (arg);
8023 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
8024 {
2426241c 8025 tree type = TREE_TYPE (TREE_TYPE (fndecl));
89ab3887 8026 REAL_VALUE_TYPE r;
8027
8028 real_round (&r, TYPE_MODE (type), &x);
8029 return build_real (type, r);
8030 }
8031 }
8032
389dd41b 8033 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
89ab3887 8034}
8035
34f17811 8036/* Fold function call to builtin lround, lroundf or lroundl (or the
c2f47e15 8037 corresponding long long versions) and other rounding functions. ARG
8038 is the argument to the call. Return NULL_TREE if no simplification
8039 can be made. */
34f17811 8040
8041static tree
389dd41b 8042fold_builtin_int_roundingfn (location_t loc, tree fndecl, tree arg)
34f17811 8043{
c2f47e15 8044 if (!validate_arg (arg, REAL_TYPE))
8045 return NULL_TREE;
34f17811 8046
8047 /* Optimize lround of constant value. */
f96bd2bf 8048 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
34f17811 8049 {
8050 const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
8051
776a7bab 8052 if (real_isfinite (&x))
34f17811 8053 {
2426241c 8054 tree itype = TREE_TYPE (TREE_TYPE (fndecl));
ca9b061d 8055 tree ftype = TREE_TYPE (arg);
a6caa15f 8056 double_int val;
34f17811 8057 REAL_VALUE_TYPE r;
8058
ad52b9b7 8059 switch (DECL_FUNCTION_CODE (fndecl))
8060 {
80ff6494 8061 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 8062 CASE_FLT_FN (BUILT_IN_LFLOOR):
8063 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 8064 real_floor (&r, TYPE_MODE (ftype), &x);
8065 break;
8066
80ff6494 8067 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 8068 CASE_FLT_FN (BUILT_IN_LCEIL):
8069 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 8070 real_ceil (&r, TYPE_MODE (ftype), &x);
8071 break;
8072
80ff6494 8073 CASE_FLT_FN (BUILT_IN_IROUND):
4f35b1fc 8074 CASE_FLT_FN (BUILT_IN_LROUND):
8075 CASE_FLT_FN (BUILT_IN_LLROUND):
ad52b9b7 8076 real_round (&r, TYPE_MODE (ftype), &x);
8077 break;
8078
8079 default:
8080 gcc_unreachable ();
8081 }
8082
a6caa15f 8083 real_to_integer2 ((HOST_WIDE_INT *)&val.low, &val.high, &r);
8084 if (double_int_fits_to_tree_p (itype, val))
8085 return double_int_to_tree (itype, val);
34f17811 8086 }
8087 }
8088
acc2b92e 8089 switch (DECL_FUNCTION_CODE (fndecl))
8090 {
8091 CASE_FLT_FN (BUILT_IN_LFLOOR):
8092 CASE_FLT_FN (BUILT_IN_LLFLOOR):
8093 /* Fold lfloor (x) where x is nonnegative to FIX_TRUNC (x). */
8094 if (tree_expr_nonnegative_p (arg))
389dd41b 8095 return fold_build1_loc (loc, FIX_TRUNC_EXPR,
8096 TREE_TYPE (TREE_TYPE (fndecl)), arg);
acc2b92e 8097 break;
8098 default:;
8099 }
8100
389dd41b 8101 return fold_fixed_mathfn (loc, fndecl, arg);
34f17811 8102}
8103
70fb4c07 8104/* Fold function call to builtin ffs, clz, ctz, popcount and parity
c2f47e15 8105 and their long and long long variants (i.e. ffsl and ffsll). ARG is
8106 the argument to the call. Return NULL_TREE if no simplification can
8107 be made. */
70fb4c07 8108
8109static tree
c2f47e15 8110fold_builtin_bitop (tree fndecl, tree arg)
70fb4c07 8111{
c2f47e15 8112 if (!validate_arg (arg, INTEGER_TYPE))
70fb4c07 8113 return NULL_TREE;
8114
8115 /* Optimize for constant argument. */
f96bd2bf 8116 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
70fb4c07 8117 {
8118 HOST_WIDE_INT hi, width, result;
8119 unsigned HOST_WIDE_INT lo;
7c446c95 8120 tree type;
70fb4c07 8121
8122 type = TREE_TYPE (arg);
8123 width = TYPE_PRECISION (type);
8124 lo = TREE_INT_CST_LOW (arg);
8125
8126 /* Clear all the bits that are beyond the type's precision. */
8127 if (width > HOST_BITS_PER_WIDE_INT)
8128 {
8129 hi = TREE_INT_CST_HIGH (arg);
24cd46a7 8130 if (width < HOST_BITS_PER_DOUBLE_INT)
561f0ec8 8131 hi &= ~(HOST_WIDE_INT_M1U << (width - HOST_BITS_PER_WIDE_INT));
70fb4c07 8132 }
8133 else
8134 {
8135 hi = 0;
8136 if (width < HOST_BITS_PER_WIDE_INT)
561f0ec8 8137 lo &= ~(HOST_WIDE_INT_M1U << width);
70fb4c07 8138 }
8139
8140 switch (DECL_FUNCTION_CODE (fndecl))
8141 {
4f35b1fc 8142 CASE_INT_FN (BUILT_IN_FFS):
70fb4c07 8143 if (lo != 0)
7e8d812e 8144 result = ffs_hwi (lo);
70fb4c07 8145 else if (hi != 0)
7e8d812e 8146 result = HOST_BITS_PER_WIDE_INT + ffs_hwi (hi);
70fb4c07 8147 else
8148 result = 0;
8149 break;
8150
4f35b1fc 8151 CASE_INT_FN (BUILT_IN_CLZ):
70fb4c07 8152 if (hi != 0)
8153 result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
8154 else if (lo != 0)
8155 result = width - floor_log2 (lo) - 1;
8156 else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
8157 result = width;
8158 break;
8159
4f35b1fc 8160 CASE_INT_FN (BUILT_IN_CTZ):
70fb4c07 8161 if (lo != 0)
7e8d812e 8162 result = ctz_hwi (lo);
70fb4c07 8163 else if (hi != 0)
7e8d812e 8164 result = HOST_BITS_PER_WIDE_INT + ctz_hwi (hi);
70fb4c07 8165 else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
8166 result = width;
8167 break;
8168
6aaa1f9e 8169 CASE_INT_FN (BUILT_IN_CLRSB):
64b5be08 8170 if (width > 2 * HOST_BITS_PER_WIDE_INT)
8171 return NULL_TREE;
6aaa1f9e 8172 if (width > HOST_BITS_PER_WIDE_INT
8173 && (hi & ((unsigned HOST_WIDE_INT) 1
8174 << (width - HOST_BITS_PER_WIDE_INT - 1))) != 0)
8175 {
561f0ec8 8176 hi = ~hi & ~(HOST_WIDE_INT_M1U
6aaa1f9e 8177 << (width - HOST_BITS_PER_WIDE_INT - 1));
8178 lo = ~lo;
8179 }
8180 else if (width <= HOST_BITS_PER_WIDE_INT
8181 && (lo & ((unsigned HOST_WIDE_INT) 1 << (width - 1))) != 0)
561f0ec8 8182 lo = ~lo & ~(HOST_WIDE_INT_M1U << (width - 1));
6aaa1f9e 8183 if (hi != 0)
8184 result = width - floor_log2 (hi) - 2 - HOST_BITS_PER_WIDE_INT;
8185 else if (lo != 0)
8186 result = width - floor_log2 (lo) - 2;
8187 else
8188 result = width - 1;
8189 break;
8190
4f35b1fc 8191 CASE_INT_FN (BUILT_IN_POPCOUNT):
70fb4c07 8192 result = 0;
8193 while (lo)
8194 result++, lo &= lo - 1;
8195 while (hi)
7e8d812e 8196 result++, hi &= (unsigned HOST_WIDE_INT) hi - 1;
70fb4c07 8197 break;
8198
4f35b1fc 8199 CASE_INT_FN (BUILT_IN_PARITY):
70fb4c07 8200 result = 0;
8201 while (lo)
8202 result++, lo &= lo - 1;
8203 while (hi)
7e8d812e 8204 result++, hi &= (unsigned HOST_WIDE_INT) hi - 1;
70fb4c07 8205 result &= 1;
8206 break;
8207
8208 default:
64db345d 8209 gcc_unreachable ();
70fb4c07 8210 }
8211
2426241c 8212 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
70fb4c07 8213 }
8214
8215 return NULL_TREE;
8216}
8217
74bdbe96 8218/* Fold function call to builtin_bswap and the short, long and long long
42791117 8219 variants. Return NULL_TREE if no simplification can be made. */
8220static tree
c2f47e15 8221fold_builtin_bswap (tree fndecl, tree arg)
42791117 8222{
c2f47e15 8223 if (! validate_arg (arg, INTEGER_TYPE))
8224 return NULL_TREE;
42791117 8225
8226 /* Optimize constant value. */
f96bd2bf 8227 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
42791117 8228 {
8229 HOST_WIDE_INT hi, width, r_hi = 0;
8230 unsigned HOST_WIDE_INT lo, r_lo = 0;
74bdbe96 8231 tree type = TREE_TYPE (TREE_TYPE (fndecl));
42791117 8232
42791117 8233 width = TYPE_PRECISION (type);
8234 lo = TREE_INT_CST_LOW (arg);
8235 hi = TREE_INT_CST_HIGH (arg);
8236
8237 switch (DECL_FUNCTION_CODE (fndecl))
8238 {
74bdbe96 8239 case BUILT_IN_BSWAP16:
42791117 8240 case BUILT_IN_BSWAP32:
8241 case BUILT_IN_BSWAP64:
8242 {
8243 int s;
8244
8245 for (s = 0; s < width; s += 8)
8246 {
8247 int d = width - s - 8;
8248 unsigned HOST_WIDE_INT byte;
8249
8250 if (s < HOST_BITS_PER_WIDE_INT)
8251 byte = (lo >> s) & 0xff;
8252 else
8253 byte = (hi >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff;
8254
8255 if (d < HOST_BITS_PER_WIDE_INT)
8256 r_lo |= byte << d;
8257 else
8258 r_hi |= byte << (d - HOST_BITS_PER_WIDE_INT);
8259 }
8260 }
8261
8262 break;
8263
8264 default:
8265 gcc_unreachable ();
8266 }
8267
8268 if (width < HOST_BITS_PER_WIDE_INT)
74bdbe96 8269 return build_int_cst (type, r_lo);
42791117 8270 else
74bdbe96 8271 return build_int_cst_wide (type, r_lo, r_hi);
42791117 8272 }
8273
8274 return NULL_TREE;
8275}
c2f47e15 8276
8918c507 8277/* A subroutine of fold_builtin to fold the various logarithmic
29f4cd78 8278 functions. Return NULL_TREE if no simplification can me made.
8279 FUNC is the corresponding MPFR logarithm function. */
8918c507 8280
8281static tree
389dd41b 8282fold_builtin_logarithm (location_t loc, tree fndecl, tree arg,
29f4cd78 8283 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8284{
c2f47e15 8285 if (validate_arg (arg, REAL_TYPE))
8918c507 8286 {
8918c507 8287 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8288 tree res;
8918c507 8289 const enum built_in_function fcode = builtin_mathfn_code (arg);
0862b7e9 8290
29f4cd78 8291 /* Calculate the result when the argument is a constant. */
8292 if ((res = do_mpfr_arg1 (arg, type, func, &dconst0, NULL, false)))
8293 return res;
8294
8918c507 8295 /* Special case, optimize logN(expN(x)) = x. */
8296 if (flag_unsafe_math_optimizations
29f4cd78 8297 && ((func == mpfr_log
8918c507 8298 && (fcode == BUILT_IN_EXP
8299 || fcode == BUILT_IN_EXPF
8300 || fcode == BUILT_IN_EXPL))
29f4cd78 8301 || (func == mpfr_log2
8918c507 8302 && (fcode == BUILT_IN_EXP2
8303 || fcode == BUILT_IN_EXP2F
8304 || fcode == BUILT_IN_EXP2L))
29f4cd78 8305 || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode)))))
389dd41b 8306 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
8918c507 8307
ca273d4a 8308 /* Optimize logN(func()) for various exponential functions. We
a0c938f0 8309 want to determine the value "x" and the power "exponent" in
8310 order to transform logN(x**exponent) into exponent*logN(x). */
8918c507 8311 if (flag_unsafe_math_optimizations)
a0c938f0 8312 {
8918c507 8313 tree exponent = 0, x = 0;
0862b7e9 8314
8918c507 8315 switch (fcode)
8316 {
4f35b1fc 8317 CASE_FLT_FN (BUILT_IN_EXP):
8918c507 8318 /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
48e1416a 8319 x = build_real (type, real_value_truncate (TYPE_MODE (type),
7910b2fb 8320 dconst_e ()));
c2f47e15 8321 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8322 break;
4f35b1fc 8323 CASE_FLT_FN (BUILT_IN_EXP2):
8918c507 8324 /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */
8325 x = build_real (type, dconst2);
c2f47e15 8326 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8327 break;
4f35b1fc 8328 CASE_FLT_FN (BUILT_IN_EXP10):
8329 CASE_FLT_FN (BUILT_IN_POW10):
8918c507 8330 /* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */
3fa759a9 8331 {
8332 REAL_VALUE_TYPE dconst10;
8333 real_from_integer (&dconst10, VOIDmode, 10, 0, 0);
8334 x = build_real (type, dconst10);
8335 }
c2f47e15 8336 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8337 break;
4f35b1fc 8338 CASE_FLT_FN (BUILT_IN_SQRT):
8918c507 8339 /* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */
c2f47e15 8340 x = CALL_EXPR_ARG (arg, 0);
8918c507 8341 exponent = build_real (type, dconsthalf);
8342 break;
4f35b1fc 8343 CASE_FLT_FN (BUILT_IN_CBRT):
8918c507 8344 /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */
c2f47e15 8345 x = CALL_EXPR_ARG (arg, 0);
8918c507 8346 exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
7910b2fb 8347 dconst_third ()));
8918c507 8348 break;
4f35b1fc 8349 CASE_FLT_FN (BUILT_IN_POW):
8918c507 8350 /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x). */
c2f47e15 8351 x = CALL_EXPR_ARG (arg, 0);
8352 exponent = CALL_EXPR_ARG (arg, 1);
8918c507 8353 break;
8354 default:
8355 break;
8356 }
8357
8358 /* Now perform the optimization. */
8359 if (x && exponent)
8360 {
389dd41b 8361 tree logfn = build_call_expr_loc (loc, fndecl, 1, x);
8362 return fold_build2_loc (loc, MULT_EXPR, type, exponent, logfn);
8918c507 8363 }
8364 }
8365 }
8366
c2f47e15 8367 return NULL_TREE;
8918c507 8368}
0862b7e9 8369
f0c477f2 8370/* Fold a builtin function call to hypot, hypotf, or hypotl. Return
8371 NULL_TREE if no simplification can be made. */
8372
8373static tree
389dd41b 8374fold_builtin_hypot (location_t loc, tree fndecl,
8375 tree arg0, tree arg1, tree type)
f0c477f2 8376{
e6ab33d8 8377 tree res, narg0, narg1;
f0c477f2 8378
c2f47e15 8379 if (!validate_arg (arg0, REAL_TYPE)
8380 || !validate_arg (arg1, REAL_TYPE))
f0c477f2 8381 return NULL_TREE;
8382
8383 /* Calculate the result when the argument is a constant. */
8384 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot)))
8385 return res;
48e1416a 8386
6c95f21c 8387 /* If either argument to hypot has a negate or abs, strip that off.
8388 E.g. hypot(-x,fabs(y)) -> hypot(x,y). */
e6ab33d8 8389 narg0 = fold_strip_sign_ops (arg0);
8390 narg1 = fold_strip_sign_ops (arg1);
8391 if (narg0 || narg1)
8392 {
48e1416a 8393 return build_call_expr_loc (loc, fndecl, 2, narg0 ? narg0 : arg0,
c2f47e15 8394 narg1 ? narg1 : arg1);
6c95f21c 8395 }
48e1416a 8396
f0c477f2 8397 /* If either argument is zero, hypot is fabs of the other. */
8398 if (real_zerop (arg0))
389dd41b 8399 return fold_build1_loc (loc, ABS_EXPR, type, arg1);
f0c477f2 8400 else if (real_zerop (arg1))
389dd41b 8401 return fold_build1_loc (loc, ABS_EXPR, type, arg0);
48e1416a 8402
6c95f21c 8403 /* hypot(x,x) -> fabs(x)*sqrt(2). */
8404 if (flag_unsafe_math_optimizations
8405 && operand_equal_p (arg0, arg1, OEP_PURE_SAME))
f0c477f2 8406 {
2e7ca27b 8407 const REAL_VALUE_TYPE sqrt2_trunc
7910b2fb 8408 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
389dd41b 8409 return fold_build2_loc (loc, MULT_EXPR, type,
8410 fold_build1_loc (loc, ABS_EXPR, type, arg0),
2e7ca27b 8411 build_real (type, sqrt2_trunc));
f0c477f2 8412 }
8413
f0c477f2 8414 return NULL_TREE;
8415}
8416
8417
e6e27594 8418/* Fold a builtin function call to pow, powf, or powl. Return
8419 NULL_TREE if no simplification can be made. */
8420static tree
389dd41b 8421fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
e6e27594 8422{
f0c477f2 8423 tree res;
e6e27594 8424
c2f47e15 8425 if (!validate_arg (arg0, REAL_TYPE)
8426 || !validate_arg (arg1, REAL_TYPE))
e6e27594 8427 return NULL_TREE;
8428
f0c477f2 8429 /* Calculate the result when the argument is a constant. */
8430 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_pow)))
8431 return res;
8432
e6e27594 8433 /* Optimize pow(1.0,y) = 1.0. */
8434 if (real_onep (arg0))
389dd41b 8435 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
e6e27594 8436
8437 if (TREE_CODE (arg1) == REAL_CST
f96bd2bf 8438 && !TREE_OVERFLOW (arg1))
e6e27594 8439 {
198d9bbe 8440 REAL_VALUE_TYPE cint;
e6e27594 8441 REAL_VALUE_TYPE c;
198d9bbe 8442 HOST_WIDE_INT n;
8443
e6e27594 8444 c = TREE_REAL_CST (arg1);
8445
8446 /* Optimize pow(x,0.0) = 1.0. */
8447 if (REAL_VALUES_EQUAL (c, dconst0))
389dd41b 8448 return omit_one_operand_loc (loc, type, build_real (type, dconst1),
e6e27594 8449 arg0);
8450
8451 /* Optimize pow(x,1.0) = x. */
8452 if (REAL_VALUES_EQUAL (c, dconst1))
8453 return arg0;
8454
8455 /* Optimize pow(x,-1.0) = 1.0/x. */
8456 if (REAL_VALUES_EQUAL (c, dconstm1))
389dd41b 8457 return fold_build2_loc (loc, RDIV_EXPR, type,
49d00087 8458 build_real (type, dconst1), arg0);
e6e27594 8459
8460 /* Optimize pow(x,0.5) = sqrt(x). */
8461 if (flag_unsafe_math_optimizations
8462 && REAL_VALUES_EQUAL (c, dconsthalf))
8463 {
8464 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
8465
8466 if (sqrtfn != NULL_TREE)
389dd41b 8467 return build_call_expr_loc (loc, sqrtfn, 1, arg0);
e6e27594 8468 }
8469
feb5b3eb 8470 /* Optimize pow(x,1.0/3.0) = cbrt(x). */
8471 if (flag_unsafe_math_optimizations)
8472 {
8473 const REAL_VALUE_TYPE dconstroot
7910b2fb 8474 = real_value_truncate (TYPE_MODE (type), dconst_third ());
feb5b3eb 8475
8476 if (REAL_VALUES_EQUAL (c, dconstroot))
8477 {
8478 tree cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT);
8479 if (cbrtfn != NULL_TREE)
389dd41b 8480 return build_call_expr_loc (loc, cbrtfn, 1, arg0);
feb5b3eb 8481 }
8482 }
8483
198d9bbe 8484 /* Check for an integer exponent. */
8485 n = real_to_integer (&c);
8486 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
8487 if (real_identical (&c, &cint))
e6e27594 8488 {
a2b30b48 8489 /* Attempt to evaluate pow at compile-time, unless this should
8490 raise an exception. */
198d9bbe 8491 if (TREE_CODE (arg0) == REAL_CST
a2b30b48 8492 && !TREE_OVERFLOW (arg0)
8493 && (n > 0
8494 || (!flag_trapping_math && !flag_errno_math)
8495 || !REAL_VALUES_EQUAL (TREE_REAL_CST (arg0), dconst0)))
e6e27594 8496 {
8497 REAL_VALUE_TYPE x;
8498 bool inexact;
8499
8500 x = TREE_REAL_CST (arg0);
8501 inexact = real_powi (&x, TYPE_MODE (type), &x, n);
8502 if (flag_unsafe_math_optimizations || !inexact)
8503 return build_real (type, x);
8504 }
198d9bbe 8505
8506 /* Strip sign ops from even integer powers. */
8507 if ((n & 1) == 0 && flag_unsafe_math_optimizations)
8508 {
8509 tree narg0 = fold_strip_sign_ops (arg0);
8510 if (narg0)
389dd41b 8511 return build_call_expr_loc (loc, fndecl, 2, narg0, arg1);
198d9bbe 8512 }
e6e27594 8513 }
8514 }
8515
cdfeb715 8516 if (flag_unsafe_math_optimizations)
e6e27594 8517 {
cdfeb715 8518 const enum built_in_function fcode = builtin_mathfn_code (arg0);
e6e27594 8519
cdfeb715 8520 /* Optimize pow(expN(x),y) = expN(x*y). */
8521 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 8522 {
c2f47e15 8523 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
8524 tree arg = CALL_EXPR_ARG (arg0, 0);
389dd41b 8525 arg = fold_build2_loc (loc, MULT_EXPR, type, arg, arg1);
8526 return build_call_expr_loc (loc, expfn, 1, arg);
cdfeb715 8527 }
e6e27594 8528
cdfeb715 8529 /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
8530 if (BUILTIN_SQRT_P (fcode))
a0c938f0 8531 {
c2f47e15 8532 tree narg0 = CALL_EXPR_ARG (arg0, 0);
389dd41b 8533 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 8534 build_real (type, dconsthalf));
389dd41b 8535 return build_call_expr_loc (loc, fndecl, 2, narg0, narg1);
cdfeb715 8536 }
8537
8538 /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */
8539 if (BUILTIN_CBRT_P (fcode))
a0c938f0 8540 {
c2f47e15 8541 tree arg = CALL_EXPR_ARG (arg0, 0);
cdfeb715 8542 if (tree_expr_nonnegative_p (arg))
8543 {
8544 const REAL_VALUE_TYPE dconstroot
7910b2fb 8545 = real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 8546 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 8547 build_real (type, dconstroot));
389dd41b 8548 return build_call_expr_loc (loc, fndecl, 2, arg, narg1);
cdfeb715 8549 }
8550 }
a0c938f0 8551
49e436b5 8552 /* Optimize pow(pow(x,y),z) = pow(x,y*z) iff x is nonnegative. */
c2f47e15 8553 if (fcode == BUILT_IN_POW
8554 || fcode == BUILT_IN_POWF
8555 || fcode == BUILT_IN_POWL)
a0c938f0 8556 {
c2f47e15 8557 tree arg00 = CALL_EXPR_ARG (arg0, 0);
49e436b5 8558 if (tree_expr_nonnegative_p (arg00))
8559 {
8560 tree arg01 = CALL_EXPR_ARG (arg0, 1);
8561 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg01, arg1);
8562 return build_call_expr_loc (loc, fndecl, 2, arg00, narg1);
8563 }
cdfeb715 8564 }
e6e27594 8565 }
cdfeb715 8566
e6e27594 8567 return NULL_TREE;
8568}
8569
c2f47e15 8570/* Fold a builtin function call to powi, powif, or powil with argument ARG.
8571 Return NULL_TREE if no simplification can be made. */
b4d0c20c 8572static tree
389dd41b 8573fold_builtin_powi (location_t loc, tree fndecl ATTRIBUTE_UNUSED,
c2f47e15 8574 tree arg0, tree arg1, tree type)
b4d0c20c 8575{
c2f47e15 8576 if (!validate_arg (arg0, REAL_TYPE)
8577 || !validate_arg (arg1, INTEGER_TYPE))
b4d0c20c 8578 return NULL_TREE;
8579
8580 /* Optimize pow(1.0,y) = 1.0. */
8581 if (real_onep (arg0))
389dd41b 8582 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
b4d0c20c 8583
35ec552a 8584 if (tree_fits_shwi_p (arg1))
b4d0c20c 8585 {
8586 HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
8587
8588 /* Evaluate powi at compile-time. */
8589 if (TREE_CODE (arg0) == REAL_CST
f96bd2bf 8590 && !TREE_OVERFLOW (arg0))
b4d0c20c 8591 {
8592 REAL_VALUE_TYPE x;
8593 x = TREE_REAL_CST (arg0);
8594 real_powi (&x, TYPE_MODE (type), &x, c);
8595 return build_real (type, x);
8596 }
8597
8598 /* Optimize pow(x,0) = 1.0. */
8599 if (c == 0)
389dd41b 8600 return omit_one_operand_loc (loc, type, build_real (type, dconst1),
b4d0c20c 8601 arg0);
8602
8603 /* Optimize pow(x,1) = x. */
8604 if (c == 1)
8605 return arg0;
8606
8607 /* Optimize pow(x,-1) = 1.0/x. */
8608 if (c == -1)
389dd41b 8609 return fold_build2_loc (loc, RDIV_EXPR, type,
49d00087 8610 build_real (type, dconst1), arg0);
b4d0c20c 8611 }
8612
8613 return NULL_TREE;
8614}
8615
8918c507 8616/* A subroutine of fold_builtin to fold the various exponent
c2f47e15 8617 functions. Return NULL_TREE if no simplification can be made.
debf9994 8618 FUNC is the corresponding MPFR exponent function. */
8918c507 8619
8620static tree
389dd41b 8621fold_builtin_exponent (location_t loc, tree fndecl, tree arg,
debf9994 8622 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8623{
c2f47e15 8624 if (validate_arg (arg, REAL_TYPE))
8918c507 8625 {
8918c507 8626 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8627 tree res;
48e1416a 8628
debf9994 8629 /* Calculate the result when the argument is a constant. */
728bac60 8630 if ((res = do_mpfr_arg1 (arg, type, func, NULL, NULL, 0)))
debf9994 8631 return res;
8918c507 8632
8633 /* Optimize expN(logN(x)) = x. */
8634 if (flag_unsafe_math_optimizations)
a0c938f0 8635 {
8918c507 8636 const enum built_in_function fcode = builtin_mathfn_code (arg);
8637
debf9994 8638 if ((func == mpfr_exp
8918c507 8639 && (fcode == BUILT_IN_LOG
8640 || fcode == BUILT_IN_LOGF
8641 || fcode == BUILT_IN_LOGL))
debf9994 8642 || (func == mpfr_exp2
8918c507 8643 && (fcode == BUILT_IN_LOG2
8644 || fcode == BUILT_IN_LOG2F
8645 || fcode == BUILT_IN_LOG2L))
debf9994 8646 || (func == mpfr_exp10
8918c507 8647 && (fcode == BUILT_IN_LOG10
8648 || fcode == BUILT_IN_LOG10F
8649 || fcode == BUILT_IN_LOG10L)))
389dd41b 8650 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
8918c507 8651 }
8652 }
8653
c2f47e15 8654 return NULL_TREE;
8918c507 8655}
8656
e973ffcc 8657/* Return true if VAR is a VAR_DECL or a component thereof. */
8658
8659static bool
8660var_decl_component_p (tree var)
8661{
8662 tree inner = var;
8663 while (handled_component_p (inner))
8664 inner = TREE_OPERAND (inner, 0);
8665 return SSA_VAR_P (inner);
8666}
8667
4f46f2b9 8668/* Fold function call to builtin memset. Return
9c8a1629 8669 NULL_TREE if no simplification can be made. */
8670
8671static tree
389dd41b 8672fold_builtin_memset (location_t loc, tree dest, tree c, tree len,
8673 tree type, bool ignore)
9c8a1629 8674{
45bb3afb 8675 tree var, ret, etype;
4f46f2b9 8676 unsigned HOST_WIDE_INT length, cval;
9c8a1629 8677
c2f47e15 8678 if (! validate_arg (dest, POINTER_TYPE)
8679 || ! validate_arg (c, INTEGER_TYPE)
8680 || ! validate_arg (len, INTEGER_TYPE))
8681 return NULL_TREE;
9c8a1629 8682
cd4547bf 8683 if (! tree_fits_uhwi_p (len))
c2f47e15 8684 return NULL_TREE;
4f46f2b9 8685
9c8a1629 8686 /* If the LEN parameter is zero, return DEST. */
8687 if (integer_zerop (len))
389dd41b 8688 return omit_one_operand_loc (loc, type, dest, c);
9c8a1629 8689
d5d2f74a 8690 if (TREE_CODE (c) != INTEGER_CST || TREE_SIDE_EFFECTS (dest))
c2f47e15 8691 return NULL_TREE;
9c8a1629 8692
4f46f2b9 8693 var = dest;
8694 STRIP_NOPS (var);
8695 if (TREE_CODE (var) != ADDR_EXPR)
c2f47e15 8696 return NULL_TREE;
4f46f2b9 8697
8698 var = TREE_OPERAND (var, 0);
8699 if (TREE_THIS_VOLATILE (var))
c2f47e15 8700 return NULL_TREE;
4f46f2b9 8701
45bb3afb 8702 etype = TREE_TYPE (var);
8703 if (TREE_CODE (etype) == ARRAY_TYPE)
8704 etype = TREE_TYPE (etype);
8705
8706 if (!INTEGRAL_TYPE_P (etype)
8707 && !POINTER_TYPE_P (etype))
c2f47e15 8708 return NULL_TREE;
4f46f2b9 8709
e973ffcc 8710 if (! var_decl_component_p (var))
c2f47e15 8711 return NULL_TREE;
e973ffcc 8712
6a0712d4 8713 length = tree_to_uhwi (len);
45bb3afb 8714 if (GET_MODE_SIZE (TYPE_MODE (etype)) != length
957d0361 8715 || get_pointer_alignment (dest) / BITS_PER_UNIT < length)
c2f47e15 8716 return NULL_TREE;
4f46f2b9 8717
8718 if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT)
c2f47e15 8719 return NULL_TREE;
4f46f2b9 8720
8721 if (integer_zerop (c))
8722 cval = 0;
8723 else
8724 {
8725 if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64)
c2f47e15 8726 return NULL_TREE;
4f46f2b9 8727
d5d2f74a 8728 cval = TREE_INT_CST_LOW (c);
4f46f2b9 8729 cval &= 0xff;
8730 cval |= cval << 8;
8731 cval |= cval << 16;
8732 cval |= (cval << 31) << 1;
8733 }
8734
45bb3afb 8735 ret = build_int_cst_type (etype, cval);
389dd41b 8736 var = build_fold_indirect_ref_loc (loc,
8737 fold_convert_loc (loc,
8738 build_pointer_type (etype),
8739 dest));
45bb3afb 8740 ret = build2 (MODIFY_EXPR, etype, var, ret);
4f46f2b9 8741 if (ignore)
8742 return ret;
8743
389dd41b 8744 return omit_one_operand_loc (loc, type, dest, ret);
9c8a1629 8745}
8746
4f46f2b9 8747/* Fold function call to builtin memset. Return
9c8a1629 8748 NULL_TREE if no simplification can be made. */
8749
8750static tree
389dd41b 8751fold_builtin_bzero (location_t loc, tree dest, tree size, bool ignore)
9c8a1629 8752{
c2f47e15 8753 if (! validate_arg (dest, POINTER_TYPE)
8754 || ! validate_arg (size, INTEGER_TYPE))
8755 return NULL_TREE;
9c8a1629 8756
4f46f2b9 8757 if (!ignore)
c2f47e15 8758 return NULL_TREE;
a0c938f0 8759
4f46f2b9 8760 /* New argument list transforming bzero(ptr x, int y) to
8761 memset(ptr x, int 0, size_t y). This is done this way
8762 so that if it isn't expanded inline, we fallback to
8763 calling bzero instead of memset. */
8764
389dd41b 8765 return fold_builtin_memset (loc, dest, integer_zero_node,
a0553bff 8766 fold_convert_loc (loc, size_type_node, size),
c2f47e15 8767 void_type_node, ignore);
9c8a1629 8768}
8769
4f46f2b9 8770/* Fold function call to builtin mem{{,p}cpy,move}. Return
8771 NULL_TREE if no simplification can be made.
8772 If ENDP is 0, return DEST (like memcpy).
8773 If ENDP is 1, return DEST+LEN (like mempcpy).
8774 If ENDP is 2, return DEST+LEN-1 (like stpcpy).
8775 If ENDP is 3, return DEST, additionally *SRC and *DEST may overlap
8776 (memmove). */
9c8a1629 8777
8778static tree
389dd41b 8779fold_builtin_memory_op (location_t loc, tree dest, tree src,
8780 tree len, tree type, bool ignore, int endp)
9c8a1629 8781{
c2f47e15 8782 tree destvar, srcvar, expr;
9c8a1629 8783
c2f47e15 8784 if (! validate_arg (dest, POINTER_TYPE)
8785 || ! validate_arg (src, POINTER_TYPE)
8786 || ! validate_arg (len, INTEGER_TYPE))
8787 return NULL_TREE;
9c8a1629 8788
8789 /* If the LEN parameter is zero, return DEST. */
8790 if (integer_zerop (len))
389dd41b 8791 return omit_one_operand_loc (loc, type, dest, src);
9c8a1629 8792
4f46f2b9 8793 /* If SRC and DEST are the same (and not volatile), return
8794 DEST{,+LEN,+LEN-1}. */
9c8a1629 8795 if (operand_equal_p (src, dest, 0))
4f46f2b9 8796 expr = len;
8797 else
8798 {
5a84fdd6 8799 tree srctype, desttype;
153c3b50 8800 unsigned int src_align, dest_align;
182cf5a9 8801 tree off0;
5383fb56 8802
3b1757a2 8803 if (endp == 3)
8804 {
957d0361 8805 src_align = get_pointer_alignment (src);
8806 dest_align = get_pointer_alignment (dest);
5a84fdd6 8807
48e1416a 8808 /* Both DEST and SRC must be pointer types.
3b1757a2 8809 ??? This is what old code did. Is the testing for pointer types
8810 really mandatory?
8811
8812 If either SRC is readonly or length is 1, we can use memcpy. */
3f95c690 8813 if (!dest_align || !src_align)
8814 return NULL_TREE;
8815 if (readonly_data_expr (src)
cd4547bf 8816 || (tree_fits_uhwi_p (len)
3f95c690 8817 && (MIN (src_align, dest_align) / BITS_PER_UNIT
aa59f000 8818 >= tree_to_uhwi (len))))
3b1757a2 8819 {
b9a16870 8820 tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
3b1757a2 8821 if (!fn)
c2f47e15 8822 return NULL_TREE;
389dd41b 8823 return build_call_expr_loc (loc, fn, 3, dest, src, len);
3b1757a2 8824 }
3f95c690 8825
8826 /* If *src and *dest can't overlap, optimize into memcpy as well. */
182cf5a9 8827 if (TREE_CODE (src) == ADDR_EXPR
8828 && TREE_CODE (dest) == ADDR_EXPR)
3f95c690 8829 {
f85fb819 8830 tree src_base, dest_base, fn;
8831 HOST_WIDE_INT src_offset = 0, dest_offset = 0;
8832 HOST_WIDE_INT size = -1;
8833 HOST_WIDE_INT maxsize = -1;
8834
182cf5a9 8835 srcvar = TREE_OPERAND (src, 0);
8836 src_base = get_ref_base_and_extent (srcvar, &src_offset,
8837 &size, &maxsize);
8838 destvar = TREE_OPERAND (dest, 0);
8839 dest_base = get_ref_base_and_extent (destvar, &dest_offset,
8840 &size, &maxsize);
cd4547bf 8841 if (tree_fits_uhwi_p (len))
6a0712d4 8842 maxsize = tree_to_uhwi (len);
f85fb819 8843 else
8844 maxsize = -1;
182cf5a9 8845 src_offset /= BITS_PER_UNIT;
8846 dest_offset /= BITS_PER_UNIT;
f85fb819 8847 if (SSA_VAR_P (src_base)
8848 && SSA_VAR_P (dest_base))
8849 {
8850 if (operand_equal_p (src_base, dest_base, 0)
8851 && ranges_overlap_p (src_offset, maxsize,
8852 dest_offset, maxsize))
8853 return NULL_TREE;
8854 }
182cf5a9 8855 else if (TREE_CODE (src_base) == MEM_REF
8856 && TREE_CODE (dest_base) == MEM_REF)
f85fb819 8857 {
182cf5a9 8858 double_int off;
f85fb819 8859 if (! operand_equal_p (TREE_OPERAND (src_base, 0),
182cf5a9 8860 TREE_OPERAND (dest_base, 0), 0))
8861 return NULL_TREE;
cf8f0e63 8862 off = mem_ref_offset (src_base) +
8863 double_int::from_shwi (src_offset);
8864 if (!off.fits_shwi ())
182cf5a9 8865 return NULL_TREE;
8866 src_offset = off.low;
cf8f0e63 8867 off = mem_ref_offset (dest_base) +
8868 double_int::from_shwi (dest_offset);
8869 if (!off.fits_shwi ())
182cf5a9 8870 return NULL_TREE;
8871 dest_offset = off.low;
8872 if (ranges_overlap_p (src_offset, maxsize,
8873 dest_offset, maxsize))
f85fb819 8874 return NULL_TREE;
8875 }
8876 else
8877 return NULL_TREE;
8878
b9a16870 8879 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
3f95c690 8880 if (!fn)
8881 return NULL_TREE;
389dd41b 8882 return build_call_expr_loc (loc, fn, 3, dest, src, len);
3f95c690 8883 }
c4222b63 8884
8885 /* If the destination and source do not alias optimize into
8886 memcpy as well. */
8887 if ((is_gimple_min_invariant (dest)
8888 || TREE_CODE (dest) == SSA_NAME)
8889 && (is_gimple_min_invariant (src)
8890 || TREE_CODE (src) == SSA_NAME))
8891 {
8892 ao_ref destr, srcr;
8893 ao_ref_init_from_ptr_and_size (&destr, dest, len);
8894 ao_ref_init_from_ptr_and_size (&srcr, src, len);
8895 if (!refs_may_alias_p_1 (&destr, &srcr, false))
8896 {
8897 tree fn;
b9a16870 8898 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
c4222b63 8899 if (!fn)
8900 return NULL_TREE;
8901 return build_call_expr_loc (loc, fn, 3, dest, src, len);
8902 }
8903 }
8904
c2f47e15 8905 return NULL_TREE;
3b1757a2 8906 }
4f46f2b9 8907
35ec552a 8908 if (!tree_fits_shwi_p (len))
c2f47e15 8909 return NULL_TREE;
5a84fdd6 8910 /* FIXME:
8911 This logic lose for arguments like (type *)malloc (sizeof (type)),
8912 since we strip the casts of up to VOID return value from malloc.
8913 Perhaps we ought to inherit type from non-VOID argument here? */
8914 STRIP_NOPS (src);
8915 STRIP_NOPS (dest);
e07c7898 8916 if (!POINTER_TYPE_P (TREE_TYPE (src))
8917 || !POINTER_TYPE_P (TREE_TYPE (dest)))
8918 return NULL_TREE;
45bb3afb 8919 /* As we fold (void *)(p + CST) to (void *)p + CST undo this here. */
8920 if (TREE_CODE (src) == POINTER_PLUS_EXPR)
8921 {
8922 tree tem = TREE_OPERAND (src, 0);
8923 STRIP_NOPS (tem);
8924 if (tem != TREE_OPERAND (src, 0))
8925 src = build1 (NOP_EXPR, TREE_TYPE (tem), src);
8926 }
8927 if (TREE_CODE (dest) == POINTER_PLUS_EXPR)
8928 {
8929 tree tem = TREE_OPERAND (dest, 0);
8930 STRIP_NOPS (tem);
8931 if (tem != TREE_OPERAND (dest, 0))
8932 dest = build1 (NOP_EXPR, TREE_TYPE (tem), dest);
8933 }
5a84fdd6 8934 srctype = TREE_TYPE (TREE_TYPE (src));
e07c7898 8935 if (TREE_CODE (srctype) == ARRAY_TYPE
97d4c6a6 8936 && !tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
45bb3afb 8937 {
8938 srctype = TREE_TYPE (srctype);
8939 STRIP_NOPS (src);
8940 src = build1 (NOP_EXPR, build_pointer_type (srctype), src);
8941 }
5a84fdd6 8942 desttype = TREE_TYPE (TREE_TYPE (dest));
e07c7898 8943 if (TREE_CODE (desttype) == ARRAY_TYPE
97d4c6a6 8944 && !tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
45bb3afb 8945 {
8946 desttype = TREE_TYPE (desttype);
8947 STRIP_NOPS (dest);
8948 dest = build1 (NOP_EXPR, build_pointer_type (desttype), dest);
8949 }
e07c7898 8950 if (TREE_ADDRESSABLE (srctype)
8951 || TREE_ADDRESSABLE (desttype))
c2f47e15 8952 return NULL_TREE;
4f46f2b9 8953
957d0361 8954 src_align = get_pointer_alignment (src);
8955 dest_align = get_pointer_alignment (dest);
153c3b50 8956 if (dest_align < TYPE_ALIGN (desttype)
8957 || src_align < TYPE_ALIGN (srctype))
c2f47e15 8958 return NULL_TREE;
e973ffcc 8959
5a84fdd6 8960 if (!ignore)
8961 dest = builtin_save_expr (dest);
4f46f2b9 8962
182cf5a9 8963 /* Build accesses at offset zero with a ref-all character type. */
8964 off0 = build_int_cst (build_pointer_type_for_mode (char_type_node,
8965 ptr_mode, true), 0);
4f46f2b9 8966
182cf5a9 8967 destvar = dest;
8968 STRIP_NOPS (destvar);
8969 if (TREE_CODE (destvar) == ADDR_EXPR
8970 && var_decl_component_p (TREE_OPERAND (destvar, 0))
8971 && tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
8972 destvar = fold_build2 (MEM_REF, desttype, destvar, off0);
8973 else
8974 destvar = NULL_TREE;
8975
8976 srcvar = src;
8977 STRIP_NOPS (srcvar);
8978 if (TREE_CODE (srcvar) == ADDR_EXPR
8979 && var_decl_component_p (TREE_OPERAND (srcvar, 0))
5b99ff01 8980 && tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
8981 {
8982 if (!destvar
8983 || src_align >= TYPE_ALIGN (desttype))
8984 srcvar = fold_build2 (MEM_REF, destvar ? desttype : srctype,
8985 srcvar, off0);
8986 else if (!STRICT_ALIGNMENT)
8987 {
8988 srctype = build_aligned_type (TYPE_MAIN_VARIANT (desttype),
8989 src_align);
8990 srcvar = fold_build2 (MEM_REF, srctype, srcvar, off0);
8991 }
8992 else
8993 srcvar = NULL_TREE;
8994 }
182cf5a9 8995 else
8996 srcvar = NULL_TREE;
5383fb56 8997
8998 if (srcvar == NULL_TREE && destvar == NULL_TREE)
c2f47e15 8999 return NULL_TREE;
4f46f2b9 9000
5383fb56 9001 if (srcvar == NULL_TREE)
9002 {
182cf5a9 9003 STRIP_NOPS (src);
5b99ff01 9004 if (src_align >= TYPE_ALIGN (desttype))
9005 srcvar = fold_build2 (MEM_REF, desttype, src, off0);
9006 else
9007 {
9008 if (STRICT_ALIGNMENT)
9009 return NULL_TREE;
9010 srctype = build_aligned_type (TYPE_MAIN_VARIANT (desttype),
9011 src_align);
9012 srcvar = fold_build2 (MEM_REF, srctype, src, off0);
9013 }
5383fb56 9014 }
9015 else if (destvar == NULL_TREE)
9016 {
182cf5a9 9017 STRIP_NOPS (dest);
5b99ff01 9018 if (dest_align >= TYPE_ALIGN (srctype))
9019 destvar = fold_build2 (MEM_REF, srctype, dest, off0);
9020 else
9021 {
9022 if (STRICT_ALIGNMENT)
9023 return NULL_TREE;
9024 desttype = build_aligned_type (TYPE_MAIN_VARIANT (srctype),
9025 dest_align);
9026 destvar = fold_build2 (MEM_REF, desttype, dest, off0);
9027 }
5383fb56 9028 }
9029
182cf5a9 9030 expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, srcvar);
4f46f2b9 9031 }
9032
9033 if (ignore)
9034 return expr;
9035
9036 if (endp == 0 || endp == 3)
389dd41b 9037 return omit_one_operand_loc (loc, type, dest, expr);
4f46f2b9 9038
9039 if (expr == len)
c2f47e15 9040 expr = NULL_TREE;
4f46f2b9 9041
9042 if (endp == 2)
389dd41b 9043 len = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (len), len,
4f46f2b9 9044 ssize_int (1));
9045
2cc66f2a 9046 dest = fold_build_pointer_plus_loc (loc, dest, len);
389dd41b 9047 dest = fold_convert_loc (loc, type, dest);
4f46f2b9 9048 if (expr)
389dd41b 9049 dest = omit_one_operand_loc (loc, type, dest, expr);
4f46f2b9 9050 return dest;
9051}
9052
c2f47e15 9053/* Fold function call to builtin strcpy with arguments DEST and SRC.
9054 If LEN is not NULL, it represents the length of the string to be
9055 copied. Return NULL_TREE if no simplification can be made. */
9c8a1629 9056
f0613857 9057tree
389dd41b 9058fold_builtin_strcpy (location_t loc, tree fndecl, tree dest, tree src, tree len)
9c8a1629 9059{
c2f47e15 9060 tree fn;
9c8a1629 9061
c2f47e15 9062 if (!validate_arg (dest, POINTER_TYPE)
9063 || !validate_arg (src, POINTER_TYPE))
9064 return NULL_TREE;
9c8a1629 9065
9066 /* If SRC and DEST are the same (and not volatile), return DEST. */
9067 if (operand_equal_p (src, dest, 0))
389dd41b 9068 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
9c8a1629 9069
0bfd8d5c 9070 if (optimize_function_for_size_p (cfun))
c2f47e15 9071 return NULL_TREE;
f0613857 9072
b9a16870 9073 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
f0613857 9074 if (!fn)
c2f47e15 9075 return NULL_TREE;
f0613857 9076
9077 if (!len)
9078 {
9079 len = c_strlen (src, 1);
9080 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 9081 return NULL_TREE;
f0613857 9082 }
9083
bd6dcc04 9084 len = fold_convert_loc (loc, size_type_node, len);
9085 len = size_binop_loc (loc, PLUS_EXPR, len, build_int_cst (size_type_node, 1));
389dd41b 9086 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
9087 build_call_expr_loc (loc, fn, 3, dest, src, len));
9c8a1629 9088}
9089
a65c4d64 9090/* Fold function call to builtin stpcpy with arguments DEST and SRC.
9091 Return NULL_TREE if no simplification can be made. */
9092
9093static tree
9094fold_builtin_stpcpy (location_t loc, tree fndecl, tree dest, tree src)
9095{
9096 tree fn, len, lenp1, call, type;
9097
9098 if (!validate_arg (dest, POINTER_TYPE)
9099 || !validate_arg (src, POINTER_TYPE))
9100 return NULL_TREE;
9101
9102 len = c_strlen (src, 1);
9103 if (!len
9104 || TREE_CODE (len) != INTEGER_CST)
9105 return NULL_TREE;
9106
9107 if (optimize_function_for_size_p (cfun)
9108 /* If length is zero it's small enough. */
9109 && !integer_zerop (len))
9110 return NULL_TREE;
9111
b9a16870 9112 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
a65c4d64 9113 if (!fn)
9114 return NULL_TREE;
9115
bd6dcc04 9116 lenp1 = size_binop_loc (loc, PLUS_EXPR,
9117 fold_convert_loc (loc, size_type_node, len),
9118 build_int_cst (size_type_node, 1));
a65c4d64 9119 /* We use dest twice in building our expression. Save it from
9120 multiple expansions. */
9121 dest = builtin_save_expr (dest);
9122 call = build_call_expr_loc (loc, fn, 3, dest, src, lenp1);
9123
9124 type = TREE_TYPE (TREE_TYPE (fndecl));
2cc66f2a 9125 dest = fold_build_pointer_plus_loc (loc, dest, len);
a65c4d64 9126 dest = fold_convert_loc (loc, type, dest);
9127 dest = omit_one_operand_loc (loc, type, dest, call);
9128 return dest;
9129}
9130
c2f47e15 9131/* Fold function call to builtin strncpy with arguments DEST, SRC, and LEN.
9132 If SLEN is not NULL, it represents the length of the source string.
9133 Return NULL_TREE if no simplification can be made. */
9c8a1629 9134
f0613857 9135tree
389dd41b 9136fold_builtin_strncpy (location_t loc, tree fndecl, tree dest,
9137 tree src, tree len, tree slen)
9c8a1629 9138{
c2f47e15 9139 tree fn;
9c8a1629 9140
c2f47e15 9141 if (!validate_arg (dest, POINTER_TYPE)
9142 || !validate_arg (src, POINTER_TYPE)
9143 || !validate_arg (len, INTEGER_TYPE))
9144 return NULL_TREE;
9c8a1629 9145
9146 /* If the LEN parameter is zero, return DEST. */
9147 if (integer_zerop (len))
389dd41b 9148 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
9c8a1629 9149
19226313 9150 /* We can't compare slen with len as constants below if len is not a
9151 constant. */
9152 if (len == 0 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 9153 return NULL_TREE;
19226313 9154
f0613857 9155 if (!slen)
9156 slen = c_strlen (src, 1);
9157
9158 /* Now, we must be passed a constant src ptr parameter. */
9159 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
c2f47e15 9160 return NULL_TREE;
f0613857 9161
389dd41b 9162 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
f0613857 9163
9164 /* We do not support simplification of this case, though we do
9165 support it when expanding trees into RTL. */
9166 /* FIXME: generate a call to __builtin_memset. */
9167 if (tree_int_cst_lt (slen, len))
c2f47e15 9168 return NULL_TREE;
f0613857 9169
9170 /* OK transform into builtin memcpy. */
b9a16870 9171 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
f0613857 9172 if (!fn)
c2f47e15 9173 return NULL_TREE;
bd6dcc04 9174
9175 len = fold_convert_loc (loc, size_type_node, len);
389dd41b 9176 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
9177 build_call_expr_loc (loc, fn, 3, dest, src, len));
9c8a1629 9178}
9179
7959b13b 9180/* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the
9181 arguments to the call, and TYPE is its return type.
9182 Return NULL_TREE if no simplification can be made. */
9183
9184static tree
389dd41b 9185fold_builtin_memchr (location_t loc, tree arg1, tree arg2, tree len, tree type)
7959b13b 9186{
9187 if (!validate_arg (arg1, POINTER_TYPE)
9188 || !validate_arg (arg2, INTEGER_TYPE)
9189 || !validate_arg (len, INTEGER_TYPE))
9190 return NULL_TREE;
9191 else
9192 {
9193 const char *p1;
9194
9195 if (TREE_CODE (arg2) != INTEGER_CST
cd4547bf 9196 || !tree_fits_uhwi_p (len))
7959b13b 9197 return NULL_TREE;
9198
9199 p1 = c_getstr (arg1);
9200 if (p1 && compare_tree_int (len, strlen (p1) + 1) <= 0)
9201 {
9202 char c;
9203 const char *r;
9204 tree tem;
9205
9206 if (target_char_cast (arg2, &c))
9207 return NULL_TREE;
9208
6a0712d4 9209 r = (const char *) memchr (p1, c, tree_to_uhwi (len));
7959b13b 9210
9211 if (r == NULL)
9212 return build_int_cst (TREE_TYPE (arg1), 0);
9213
2cc66f2a 9214 tem = fold_build_pointer_plus_hwi_loc (loc, arg1, r - p1);
389dd41b 9215 return fold_convert_loc (loc, type, tem);
7959b13b 9216 }
9217 return NULL_TREE;
9218 }
9219}
9220
c2f47e15 9221/* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
9222 Return NULL_TREE if no simplification can be made. */
9c8a1629 9223
9224static tree
389dd41b 9225fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
9c8a1629 9226{
c4fef134 9227 const char *p1, *p2;
9c8a1629 9228
c2f47e15 9229 if (!validate_arg (arg1, POINTER_TYPE)
9230 || !validate_arg (arg2, POINTER_TYPE)
9231 || !validate_arg (len, INTEGER_TYPE))
9232 return NULL_TREE;
9c8a1629 9233
9234 /* If the LEN parameter is zero, return zero. */
9235 if (integer_zerop (len))
389dd41b 9236 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
c4fef134 9237 arg1, arg2);
9c8a1629 9238
9239 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9240 if (operand_equal_p (arg1, arg2, 0))
389dd41b 9241 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
c4fef134 9242
9243 p1 = c_getstr (arg1);
9244 p2 = c_getstr (arg2);
9245
9246 /* If all arguments are constant, and the value of len is not greater
9247 than the lengths of arg1 and arg2, evaluate at compile-time. */
cd4547bf 9248 if (tree_fits_uhwi_p (len) && p1 && p2
c4fef134 9249 && compare_tree_int (len, strlen (p1) + 1) <= 0
9250 && compare_tree_int (len, strlen (p2) + 1) <= 0)
9251 {
6a0712d4 9252 const int r = memcmp (p1, p2, tree_to_uhwi (len));
c4fef134 9253
9254 if (r > 0)
9255 return integer_one_node;
9256 else if (r < 0)
9257 return integer_minus_one_node;
9258 else
9259 return integer_zero_node;
9260 }
9261
9262 /* If len parameter is one, return an expression corresponding to
9263 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
6a0712d4 9264 if (tree_fits_uhwi_p (len) && tree_to_uhwi (len) == 1)
c4fef134 9265 {
9266 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9267 tree cst_uchar_ptr_node
9268 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9269
389dd41b 9270 tree ind1
9271 = fold_convert_loc (loc, integer_type_node,
9272 build1 (INDIRECT_REF, cst_uchar_node,
9273 fold_convert_loc (loc,
9274 cst_uchar_ptr_node,
c4fef134 9275 arg1)));
389dd41b 9276 tree ind2
9277 = fold_convert_loc (loc, integer_type_node,
9278 build1 (INDIRECT_REF, cst_uchar_node,
9279 fold_convert_loc (loc,
9280 cst_uchar_ptr_node,
c4fef134 9281 arg2)));
389dd41b 9282 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
c4fef134 9283 }
9c8a1629 9284
c2f47e15 9285 return NULL_TREE;
9c8a1629 9286}
9287
c2f47e15 9288/* Fold function call to builtin strcmp with arguments ARG1 and ARG2.
9289 Return NULL_TREE if no simplification can be made. */
9c8a1629 9290
9291static tree
389dd41b 9292fold_builtin_strcmp (location_t loc, tree arg1, tree arg2)
9c8a1629 9293{
9c8a1629 9294 const char *p1, *p2;
9295
c2f47e15 9296 if (!validate_arg (arg1, POINTER_TYPE)
9297 || !validate_arg (arg2, POINTER_TYPE))
9298 return NULL_TREE;
9c8a1629 9299
9300 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9301 if (operand_equal_p (arg1, arg2, 0))
c4fef134 9302 return integer_zero_node;
9c8a1629 9303
9304 p1 = c_getstr (arg1);
9305 p2 = c_getstr (arg2);
9306
9307 if (p1 && p2)
9308 {
9c8a1629 9309 const int i = strcmp (p1, p2);
9310 if (i < 0)
c4fef134 9311 return integer_minus_one_node;
9c8a1629 9312 else if (i > 0)
c4fef134 9313 return integer_one_node;
9c8a1629 9314 else
c4fef134 9315 return integer_zero_node;
9316 }
9317
9318 /* If the second arg is "", return *(const unsigned char*)arg1. */
9319 if (p2 && *p2 == '\0')
9320 {
9321 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9322 tree cst_uchar_ptr_node
9323 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9324
389dd41b 9325 return fold_convert_loc (loc, integer_type_node,
9326 build1 (INDIRECT_REF, cst_uchar_node,
9327 fold_convert_loc (loc,
9328 cst_uchar_ptr_node,
9329 arg1)));
c4fef134 9330 }
9331
9332 /* If the first arg is "", return -*(const unsigned char*)arg2. */
9333 if (p1 && *p1 == '\0')
9334 {
9335 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9336 tree cst_uchar_ptr_node
9337 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9338
389dd41b 9339 tree temp
9340 = fold_convert_loc (loc, integer_type_node,
9341 build1 (INDIRECT_REF, cst_uchar_node,
9342 fold_convert_loc (loc,
9343 cst_uchar_ptr_node,
c4fef134 9344 arg2)));
389dd41b 9345 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp);
9c8a1629 9346 }
9347
c2f47e15 9348 return NULL_TREE;
9c8a1629 9349}
9350
c2f47e15 9351/* Fold function call to builtin strncmp with arguments ARG1, ARG2, and LEN.
9352 Return NULL_TREE if no simplification can be made. */
9c8a1629 9353
9354static tree
389dd41b 9355fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len)
9c8a1629 9356{
9c8a1629 9357 const char *p1, *p2;
9358
c2f47e15 9359 if (!validate_arg (arg1, POINTER_TYPE)
9360 || !validate_arg (arg2, POINTER_TYPE)
9361 || !validate_arg (len, INTEGER_TYPE))
9362 return NULL_TREE;
9c8a1629 9363
9364 /* If the LEN parameter is zero, return zero. */
9365 if (integer_zerop (len))
389dd41b 9366 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
c4fef134 9367 arg1, arg2);
9c8a1629 9368
9369 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9370 if (operand_equal_p (arg1, arg2, 0))
389dd41b 9371 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
9c8a1629 9372
9373 p1 = c_getstr (arg1);
9374 p2 = c_getstr (arg2);
9375
cd4547bf 9376 if (tree_fits_uhwi_p (len) && p1 && p2)
9c8a1629 9377 {
6a0712d4 9378 const int i = strncmp (p1, p2, tree_to_uhwi (len));
c4fef134 9379 if (i > 0)
9380 return integer_one_node;
9381 else if (i < 0)
9382 return integer_minus_one_node;
9c8a1629 9383 else
c4fef134 9384 return integer_zero_node;
9385 }
9386
9387 /* If the second arg is "", and the length is greater than zero,
9388 return *(const unsigned char*)arg1. */
9389 if (p2 && *p2 == '\0'
9390 && TREE_CODE (len) == INTEGER_CST
9391 && tree_int_cst_sgn (len) == 1)
9392 {
9393 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9394 tree cst_uchar_ptr_node
9395 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9396
389dd41b 9397 return fold_convert_loc (loc, integer_type_node,
9398 build1 (INDIRECT_REF, cst_uchar_node,
9399 fold_convert_loc (loc,
9400 cst_uchar_ptr_node,
9401 arg1)));
c4fef134 9402 }
9403
9404 /* If the first arg is "", and the length is greater than zero,
9405 return -*(const unsigned char*)arg2. */
9406 if (p1 && *p1 == '\0'
9407 && TREE_CODE (len) == INTEGER_CST
9408 && tree_int_cst_sgn (len) == 1)
9409 {
9410 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9411 tree cst_uchar_ptr_node
9412 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9413
389dd41b 9414 tree temp = fold_convert_loc (loc, integer_type_node,
9415 build1 (INDIRECT_REF, cst_uchar_node,
9416 fold_convert_loc (loc,
9417 cst_uchar_ptr_node,
9418 arg2)));
9419 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp);
c4fef134 9420 }
9421
9422 /* If len parameter is one, return an expression corresponding to
9423 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
6a0712d4 9424 if (tree_fits_uhwi_p (len) && tree_to_uhwi (len) == 1)
c4fef134 9425 {
9426 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9427 tree cst_uchar_ptr_node
9428 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9429
389dd41b 9430 tree ind1 = fold_convert_loc (loc, integer_type_node,
9431 build1 (INDIRECT_REF, cst_uchar_node,
9432 fold_convert_loc (loc,
9433 cst_uchar_ptr_node,
9434 arg1)));
9435 tree ind2 = fold_convert_loc (loc, integer_type_node,
9436 build1 (INDIRECT_REF, cst_uchar_node,
9437 fold_convert_loc (loc,
9438 cst_uchar_ptr_node,
9439 arg2)));
9440 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
9c8a1629 9441 }
9442
c2f47e15 9443 return NULL_TREE;
9c8a1629 9444}
9445
c2f47e15 9446/* Fold function call to builtin signbit, signbitf or signbitl with argument
9447 ARG. Return NULL_TREE if no simplification can be made. */
27f261ef 9448
9449static tree
389dd41b 9450fold_builtin_signbit (location_t loc, tree arg, tree type)
27f261ef 9451{
c2f47e15 9452 if (!validate_arg (arg, REAL_TYPE))
27f261ef 9453 return NULL_TREE;
9454
27f261ef 9455 /* If ARG is a compile-time constant, determine the result. */
9456 if (TREE_CODE (arg) == REAL_CST
f96bd2bf 9457 && !TREE_OVERFLOW (arg))
27f261ef 9458 {
9459 REAL_VALUE_TYPE c;
9460
9461 c = TREE_REAL_CST (arg);
385f3f36 9462 return (REAL_VALUE_NEGATIVE (c)
9463 ? build_one_cst (type)
9464 : build_zero_cst (type));
27f261ef 9465 }
9466
9467 /* If ARG is non-negative, the result is always zero. */
9468 if (tree_expr_nonnegative_p (arg))
389dd41b 9469 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
27f261ef 9470
9471 /* If ARG's format doesn't have signed zeros, return "arg < 0.0". */
9472 if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
de67cbb8 9473 return fold_convert (type,
9474 fold_build2_loc (loc, LT_EXPR, boolean_type_node, arg,
9475 build_real (TREE_TYPE (arg), dconst0)));
27f261ef 9476
9477 return NULL_TREE;
9478}
9479
c2f47e15 9480/* Fold function call to builtin copysign, copysignf or copysignl with
9481 arguments ARG1 and ARG2. Return NULL_TREE if no simplification can
9482 be made. */
467214fd 9483
9484static tree
389dd41b 9485fold_builtin_copysign (location_t loc, tree fndecl,
9486 tree arg1, tree arg2, tree type)
467214fd 9487{
c2f47e15 9488 tree tem;
467214fd 9489
c2f47e15 9490 if (!validate_arg (arg1, REAL_TYPE)
9491 || !validate_arg (arg2, REAL_TYPE))
467214fd 9492 return NULL_TREE;
9493
467214fd 9494 /* copysign(X,X) is X. */
9495 if (operand_equal_p (arg1, arg2, 0))
389dd41b 9496 return fold_convert_loc (loc, type, arg1);
467214fd 9497
9498 /* If ARG1 and ARG2 are compile-time constants, determine the result. */
9499 if (TREE_CODE (arg1) == REAL_CST
9500 && TREE_CODE (arg2) == REAL_CST
f96bd2bf 9501 && !TREE_OVERFLOW (arg1)
9502 && !TREE_OVERFLOW (arg2))
467214fd 9503 {
9504 REAL_VALUE_TYPE c1, c2;
9505
9506 c1 = TREE_REAL_CST (arg1);
9507 c2 = TREE_REAL_CST (arg2);
749680e2 9508 /* c1.sign := c2.sign. */
467214fd 9509 real_copysign (&c1, &c2);
9510 return build_real (type, c1);
467214fd 9511 }
9512
9513 /* copysign(X, Y) is fabs(X) when Y is always non-negative.
9514 Remember to evaluate Y for side-effects. */
9515 if (tree_expr_nonnegative_p (arg2))
389dd41b 9516 return omit_one_operand_loc (loc, type,
9517 fold_build1_loc (loc, ABS_EXPR, type, arg1),
467214fd 9518 arg2);
9519
198d9bbe 9520 /* Strip sign changing operations for the first argument. */
9521 tem = fold_strip_sign_ops (arg1);
9522 if (tem)
389dd41b 9523 return build_call_expr_loc (loc, fndecl, 2, tem, arg2);
198d9bbe 9524
467214fd 9525 return NULL_TREE;
9526}
9527
c2f47e15 9528/* Fold a call to builtin isascii with argument ARG. */
d49367d4 9529
9530static tree
389dd41b 9531fold_builtin_isascii (location_t loc, tree arg)
d49367d4 9532{
c2f47e15 9533 if (!validate_arg (arg, INTEGER_TYPE))
9534 return NULL_TREE;
d49367d4 9535 else
9536 {
9537 /* Transform isascii(c) -> ((c & ~0x7f) == 0). */
c90b5d40 9538 arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
7002a1c8 9539 build_int_cst (integer_type_node,
c90b5d40 9540 ~ (unsigned HOST_WIDE_INT) 0x7f));
389dd41b 9541 return fold_build2_loc (loc, EQ_EXPR, integer_type_node,
7002a1c8 9542 arg, integer_zero_node);
d49367d4 9543 }
9544}
9545
c2f47e15 9546/* Fold a call to builtin toascii with argument ARG. */
d49367d4 9547
9548static tree
389dd41b 9549fold_builtin_toascii (location_t loc, tree arg)
d49367d4 9550{
c2f47e15 9551 if (!validate_arg (arg, INTEGER_TYPE))
9552 return NULL_TREE;
48e1416a 9553
c2f47e15 9554 /* Transform toascii(c) -> (c & 0x7f). */
389dd41b 9555 return fold_build2_loc (loc, BIT_AND_EXPR, integer_type_node, arg,
7002a1c8 9556 build_int_cst (integer_type_node, 0x7f));
d49367d4 9557}
9558
c2f47e15 9559/* Fold a call to builtin isdigit with argument ARG. */
df1cf42e 9560
9561static tree
389dd41b 9562fold_builtin_isdigit (location_t loc, tree arg)
df1cf42e 9563{
c2f47e15 9564 if (!validate_arg (arg, INTEGER_TYPE))
9565 return NULL_TREE;
df1cf42e 9566 else
9567 {
9568 /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */
624d37a6 9569 /* According to the C standard, isdigit is unaffected by locale.
9570 However, it definitely is affected by the target character set. */
624d37a6 9571 unsigned HOST_WIDE_INT target_digit0
9572 = lang_hooks.to_target_charset ('0');
9573
9574 if (target_digit0 == 0)
9575 return NULL_TREE;
9576
389dd41b 9577 arg = fold_convert_loc (loc, unsigned_type_node, arg);
c90b5d40 9578 arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg,
9579 build_int_cst (unsigned_type_node, target_digit0));
389dd41b 9580 return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg,
f2532264 9581 build_int_cst (unsigned_type_node, 9));
df1cf42e 9582 }
9583}
27f261ef 9584
c2f47e15 9585/* Fold a call to fabs, fabsf or fabsl with argument ARG. */
d1aade50 9586
9587static tree
389dd41b 9588fold_builtin_fabs (location_t loc, tree arg, tree type)
d1aade50 9589{
c2f47e15 9590 if (!validate_arg (arg, REAL_TYPE))
9591 return NULL_TREE;
d1aade50 9592
389dd41b 9593 arg = fold_convert_loc (loc, type, arg);
d1aade50 9594 if (TREE_CODE (arg) == REAL_CST)
9595 return fold_abs_const (arg, type);
389dd41b 9596 return fold_build1_loc (loc, ABS_EXPR, type, arg);
d1aade50 9597}
9598
c2f47e15 9599/* Fold a call to abs, labs, llabs or imaxabs with argument ARG. */
d1aade50 9600
9601static tree
389dd41b 9602fold_builtin_abs (location_t loc, tree arg, tree type)
d1aade50 9603{
c2f47e15 9604 if (!validate_arg (arg, INTEGER_TYPE))
9605 return NULL_TREE;
d1aade50 9606
389dd41b 9607 arg = fold_convert_loc (loc, type, arg);
d1aade50 9608 if (TREE_CODE (arg) == INTEGER_CST)
9609 return fold_abs_const (arg, type);
389dd41b 9610 return fold_build1_loc (loc, ABS_EXPR, type, arg);
d1aade50 9611}
9612
b9be572e 9613/* Fold a fma operation with arguments ARG[012]. */
9614
9615tree
9616fold_fma (location_t loc ATTRIBUTE_UNUSED,
9617 tree type, tree arg0, tree arg1, tree arg2)
9618{
9619 if (TREE_CODE (arg0) == REAL_CST
9620 && TREE_CODE (arg1) == REAL_CST
9621 && TREE_CODE (arg2) == REAL_CST)
9622 return do_mpfr_arg3 (arg0, arg1, arg2, type, mpfr_fma);
9623
9624 return NULL_TREE;
9625}
9626
9627/* Fold a call to fma, fmaf, or fmal with arguments ARG[012]. */
9628
9629static tree
9630fold_builtin_fma (location_t loc, tree arg0, tree arg1, tree arg2, tree type)
9631{
9632 if (validate_arg (arg0, REAL_TYPE)
9af5ce0c 9633 && validate_arg (arg1, REAL_TYPE)
9634 && validate_arg (arg2, REAL_TYPE))
b9be572e 9635 {
9636 tree tem = fold_fma (loc, type, arg0, arg1, arg2);
9637 if (tem)
9638 return tem;
9639
9640 /* ??? Only expand to FMA_EXPR if it's directly supported. */
9641 if (optab_handler (fma_optab, TYPE_MODE (type)) != CODE_FOR_nothing)
9642 return fold_build3_loc (loc, FMA_EXPR, type, arg0, arg1, arg2);
9643 }
9644 return NULL_TREE;
9645}
9646
d4a43a03 9647/* Fold a call to builtin fmin or fmax. */
9648
9649static tree
389dd41b 9650fold_builtin_fmin_fmax (location_t loc, tree arg0, tree arg1,
9651 tree type, bool max)
d4a43a03 9652{
c2f47e15 9653 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, REAL_TYPE))
d4a43a03 9654 {
d4a43a03 9655 /* Calculate the result when the argument is a constant. */
9656 tree res = do_mpfr_arg2 (arg0, arg1, type, (max ? mpfr_max : mpfr_min));
9657
9658 if (res)
9659 return res;
9660
61fe3555 9661 /* If either argument is NaN, return the other one. Avoid the
9662 transformation if we get (and honor) a signalling NaN. Using
9663 omit_one_operand() ensures we create a non-lvalue. */
9664 if (TREE_CODE (arg0) == REAL_CST
9665 && real_isnan (&TREE_REAL_CST (arg0))
9666 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
9667 || ! TREE_REAL_CST (arg0).signalling))
389dd41b 9668 return omit_one_operand_loc (loc, type, arg1, arg0);
61fe3555 9669 if (TREE_CODE (arg1) == REAL_CST
9670 && real_isnan (&TREE_REAL_CST (arg1))
9671 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
9672 || ! TREE_REAL_CST (arg1).signalling))
389dd41b 9673 return omit_one_operand_loc (loc, type, arg0, arg1);
61fe3555 9674
d4a43a03 9675 /* Transform fmin/fmax(x,x) -> x. */
9676 if (operand_equal_p (arg0, arg1, OEP_PURE_SAME))
389dd41b 9677 return omit_one_operand_loc (loc, type, arg0, arg1);
48e1416a 9678
d4a43a03 9679 /* Convert fmin/fmax to MIN_EXPR/MAX_EXPR. C99 requires these
9680 functions to return the numeric arg if the other one is NaN.
9681 These tree codes don't honor that, so only transform if
9682 -ffinite-math-only is set. C99 doesn't require -0.0 to be
9683 handled, so we don't have to worry about it either. */
9684 if (flag_finite_math_only)
389dd41b 9685 return fold_build2_loc (loc, (max ? MAX_EXPR : MIN_EXPR), type,
9686 fold_convert_loc (loc, type, arg0),
9687 fold_convert_loc (loc, type, arg1));
d4a43a03 9688 }
9689 return NULL_TREE;
9690}
9691
abe4dcf6 9692/* Fold a call to builtin carg(a+bi) -> atan2(b,a). */
9693
9694static tree
389dd41b 9695fold_builtin_carg (location_t loc, tree arg, tree type)
abe4dcf6 9696{
239d491a 9697 if (validate_arg (arg, COMPLEX_TYPE)
9698 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
abe4dcf6 9699 {
9700 tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
48e1416a 9701
abe4dcf6 9702 if (atan2_fn)
9703 {
c2f47e15 9704 tree new_arg = builtin_save_expr (arg);
389dd41b 9705 tree r_arg = fold_build1_loc (loc, REALPART_EXPR, type, new_arg);
9706 tree i_arg = fold_build1_loc (loc, IMAGPART_EXPR, type, new_arg);
9707 return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg);
abe4dcf6 9708 }
9709 }
48e1416a 9710
abe4dcf6 9711 return NULL_TREE;
9712}
9713
cb2b9385 9714/* Fold a call to builtin logb/ilogb. */
9715
9716static tree
389dd41b 9717fold_builtin_logb (location_t loc, tree arg, tree rettype)
cb2b9385 9718{
9719 if (! validate_arg (arg, REAL_TYPE))
9720 return NULL_TREE;
48e1416a 9721
cb2b9385 9722 STRIP_NOPS (arg);
48e1416a 9723
cb2b9385 9724 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9725 {
9726 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
48e1416a 9727
cb2b9385 9728 switch (value->cl)
9729 {
9730 case rvc_nan:
9731 case rvc_inf:
9732 /* If arg is Inf or NaN and we're logb, return it. */
9733 if (TREE_CODE (rettype) == REAL_TYPE)
7695fea9 9734 {
9735 /* For logb(-Inf) we have to return +Inf. */
9736 if (real_isinf (value) && real_isneg (value))
9737 {
9738 REAL_VALUE_TYPE tem;
9739 real_inf (&tem);
9740 return build_real (rettype, tem);
9741 }
9742 return fold_convert_loc (loc, rettype, arg);
9743 }
cb2b9385 9744 /* Fall through... */
9745 case rvc_zero:
9746 /* Zero may set errno and/or raise an exception for logb, also
9747 for ilogb we don't know FP_ILOGB0. */
9748 return NULL_TREE;
9749 case rvc_normal:
9750 /* For normal numbers, proceed iff radix == 2. In GCC,
9751 normalized significands are in the range [0.5, 1.0). We
9752 want the exponent as if they were [1.0, 2.0) so get the
9753 exponent and subtract 1. */
9754 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
389dd41b 9755 return fold_convert_loc (loc, rettype,
7002a1c8 9756 build_int_cst (integer_type_node,
389dd41b 9757 REAL_EXP (value)-1));
cb2b9385 9758 break;
9759 }
9760 }
48e1416a 9761
cb2b9385 9762 return NULL_TREE;
9763}
9764
9765/* Fold a call to builtin significand, if radix == 2. */
9766
9767static tree
389dd41b 9768fold_builtin_significand (location_t loc, tree arg, tree rettype)
cb2b9385 9769{
9770 if (! validate_arg (arg, REAL_TYPE))
9771 return NULL_TREE;
48e1416a 9772
cb2b9385 9773 STRIP_NOPS (arg);
48e1416a 9774
cb2b9385 9775 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9776 {
9777 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
48e1416a 9778
cb2b9385 9779 switch (value->cl)
9780 {
9781 case rvc_zero:
9782 case rvc_nan:
9783 case rvc_inf:
9784 /* If arg is +-0, +-Inf or +-NaN, then return it. */
389dd41b 9785 return fold_convert_loc (loc, rettype, arg);
cb2b9385 9786 case rvc_normal:
9787 /* For normal numbers, proceed iff radix == 2. */
9788 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
9789 {
9790 REAL_VALUE_TYPE result = *value;
9791 /* In GCC, normalized significands are in the range [0.5,
9792 1.0). We want them to be [1.0, 2.0) so set the
9793 exponent to 1. */
9794 SET_REAL_EXP (&result, 1);
9795 return build_real (rettype, result);
9796 }
9797 break;
9798 }
9799 }
48e1416a 9800
cb2b9385 9801 return NULL_TREE;
9802}
9803
3838b9ae 9804/* Fold a call to builtin frexp, we can assume the base is 2. */
9805
9806static tree
389dd41b 9807fold_builtin_frexp (location_t loc, tree arg0, tree arg1, tree rettype)
3838b9ae 9808{
9809 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9810 return NULL_TREE;
48e1416a 9811
3838b9ae 9812 STRIP_NOPS (arg0);
48e1416a 9813
3838b9ae 9814 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9815 return NULL_TREE;
48e1416a 9816
389dd41b 9817 arg1 = build_fold_indirect_ref_loc (loc, arg1);
3838b9ae 9818
9819 /* Proceed if a valid pointer type was passed in. */
9820 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
9821 {
9822 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9823 tree frac, exp;
48e1416a 9824
3838b9ae 9825 switch (value->cl)
9826 {
9827 case rvc_zero:
9828 /* For +-0, return (*exp = 0, +-0). */
9829 exp = integer_zero_node;
9830 frac = arg0;
9831 break;
9832 case rvc_nan:
9833 case rvc_inf:
9834 /* For +-NaN or +-Inf, *exp is unspecified, return arg0. */
389dd41b 9835 return omit_one_operand_loc (loc, rettype, arg0, arg1);
3838b9ae 9836 case rvc_normal:
9837 {
9838 /* Since the frexp function always expects base 2, and in
9839 GCC normalized significands are already in the range
9840 [0.5, 1.0), we have exactly what frexp wants. */
9841 REAL_VALUE_TYPE frac_rvt = *value;
9842 SET_REAL_EXP (&frac_rvt, 0);
9843 frac = build_real (rettype, frac_rvt);
7002a1c8 9844 exp = build_int_cst (integer_type_node, REAL_EXP (value));
3838b9ae 9845 }
9846 break;
9847 default:
9848 gcc_unreachable ();
9849 }
48e1416a 9850
3838b9ae 9851 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
389dd41b 9852 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, exp);
3838b9ae 9853 TREE_SIDE_EFFECTS (arg1) = 1;
389dd41b 9854 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1, frac);
3838b9ae 9855 }
9856
9857 return NULL_TREE;
9858}
9859
7587301b 9860/* Fold a call to builtin ldexp or scalbn/scalbln. If LDEXP is true
9861 then we can assume the base is two. If it's false, then we have to
9862 check the mode of the TYPE parameter in certain cases. */
9863
9864static tree
389dd41b 9865fold_builtin_load_exponent (location_t loc, tree arg0, tree arg1,
9866 tree type, bool ldexp)
7587301b 9867{
9868 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, INTEGER_TYPE))
9869 {
9870 STRIP_NOPS (arg0);
9871 STRIP_NOPS (arg1);
9872
9873 /* If arg0 is 0, Inf or NaN, or if arg1 is 0, then return arg0. */
9874 if (real_zerop (arg0) || integer_zerop (arg1)
9875 || (TREE_CODE (arg0) == REAL_CST
776a7bab 9876 && !real_isfinite (&TREE_REAL_CST (arg0))))
389dd41b 9877 return omit_one_operand_loc (loc, type, arg0, arg1);
48e1416a 9878
7587301b 9879 /* If both arguments are constant, then try to evaluate it. */
9880 if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2)
9881 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
35ec552a 9882 && tree_fits_shwi_p (arg1))
7587301b 9883 {
9884 /* Bound the maximum adjustment to twice the range of the
9885 mode's valid exponents. Use abs to ensure the range is
9886 positive as a sanity check. */
48e1416a 9887 const long max_exp_adj = 2 *
7587301b 9888 labs (REAL_MODE_FORMAT (TYPE_MODE (type))->emax
9889 - REAL_MODE_FORMAT (TYPE_MODE (type))->emin);
9890
9891 /* Get the user-requested adjustment. */
fcb97e84 9892 const HOST_WIDE_INT req_exp_adj = tree_to_shwi (arg1);
48e1416a 9893
7587301b 9894 /* The requested adjustment must be inside this range. This
9895 is a preliminary cap to avoid things like overflow, we
9896 may still fail to compute the result for other reasons. */
9897 if (-max_exp_adj < req_exp_adj && req_exp_adj < max_exp_adj)
9898 {
9899 REAL_VALUE_TYPE initial_result;
48e1416a 9900
7587301b 9901 real_ldexp (&initial_result, &TREE_REAL_CST (arg0), req_exp_adj);
9902
9903 /* Ensure we didn't overflow. */
9904 if (! real_isinf (&initial_result))
9905 {
9906 const REAL_VALUE_TYPE trunc_result
9907 = real_value_truncate (TYPE_MODE (type), initial_result);
48e1416a 9908
7587301b 9909 /* Only proceed if the target mode can hold the
9910 resulting value. */
9911 if (REAL_VALUES_EQUAL (initial_result, trunc_result))
9912 return build_real (type, trunc_result);
9913 }
9914 }
9915 }
9916 }
9917
9918 return NULL_TREE;
9919}
9920
ebf8b4f5 9921/* Fold a call to builtin modf. */
9922
9923static tree
389dd41b 9924fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
ebf8b4f5 9925{
9926 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9927 return NULL_TREE;
48e1416a 9928
ebf8b4f5 9929 STRIP_NOPS (arg0);
48e1416a 9930
ebf8b4f5 9931 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9932 return NULL_TREE;
48e1416a 9933
389dd41b 9934 arg1 = build_fold_indirect_ref_loc (loc, arg1);
ebf8b4f5 9935
9936 /* Proceed if a valid pointer type was passed in. */
9937 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
9938 {
9939 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9940 REAL_VALUE_TYPE trunc, frac;
9941
9942 switch (value->cl)
9943 {
9944 case rvc_nan:
9945 case rvc_zero:
9946 /* For +-NaN or +-0, return (*arg1 = arg0, arg0). */
9947 trunc = frac = *value;
9948 break;
9949 case rvc_inf:
9950 /* For +-Inf, return (*arg1 = arg0, +-0). */
9951 frac = dconst0;
9952 frac.sign = value->sign;
9953 trunc = *value;
9954 break;
9955 case rvc_normal:
9956 /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)). */
9957 real_trunc (&trunc, VOIDmode, value);
9958 real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
9959 /* If the original number was negative and already
9960 integral, then the fractional part is -0.0. */
9961 if (value->sign && frac.cl == rvc_zero)
9962 frac.sign = value->sign;
9963 break;
9964 }
48e1416a 9965
ebf8b4f5 9966 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
389dd41b 9967 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1,
ebf8b4f5 9968 build_real (rettype, trunc));
9969 TREE_SIDE_EFFECTS (arg1) = 1;
389dd41b 9970 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1,
ebf8b4f5 9971 build_real (rettype, frac));
9972 }
48e1416a 9973
ebf8b4f5 9974 return NULL_TREE;
9975}
9976
a65c4d64 9977/* Given a location LOC, an interclass builtin function decl FNDECL
9978 and its single argument ARG, return an folded expression computing
9979 the same, or NULL_TREE if we either couldn't or didn't want to fold
9980 (the latter happen if there's an RTL instruction available). */
9981
9982static tree
9983fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
9984{
9985 enum machine_mode mode;
9986
9987 if (!validate_arg (arg, REAL_TYPE))
9988 return NULL_TREE;
9989
9990 if (interclass_mathfn_icode (arg, fndecl) != CODE_FOR_nothing)
9991 return NULL_TREE;
9992
9993 mode = TYPE_MODE (TREE_TYPE (arg));
9994
9995 /* If there is no optab, try generic code. */
9996 switch (DECL_FUNCTION_CODE (fndecl))
9997 {
9998 tree result;
9999
10000 CASE_FLT_FN (BUILT_IN_ISINF):
10001 {
10002 /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
b9a16870 10003 tree const isgr_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
a65c4d64 10004 tree const type = TREE_TYPE (arg);
10005 REAL_VALUE_TYPE r;
10006 char buf[128];
10007
10008 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
10009 real_from_string (&r, buf);
10010 result = build_call_expr (isgr_fn, 2,
10011 fold_build1_loc (loc, ABS_EXPR, type, arg),
10012 build_real (type, r));
10013 return result;
10014 }
10015 CASE_FLT_FN (BUILT_IN_FINITE):
10016 case BUILT_IN_ISFINITE:
10017 {
10018 /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
b9a16870 10019 tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
a65c4d64 10020 tree const type = TREE_TYPE (arg);
10021 REAL_VALUE_TYPE r;
10022 char buf[128];
10023
10024 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
10025 real_from_string (&r, buf);
10026 result = build_call_expr (isle_fn, 2,
10027 fold_build1_loc (loc, ABS_EXPR, type, arg),
10028 build_real (type, r));
10029 /*result = fold_build2_loc (loc, UNGT_EXPR,
10030 TREE_TYPE (TREE_TYPE (fndecl)),
10031 fold_build1_loc (loc, ABS_EXPR, type, arg),
10032 build_real (type, r));
10033 result = fold_build1_loc (loc, TRUTH_NOT_EXPR,
10034 TREE_TYPE (TREE_TYPE (fndecl)),
10035 result);*/
10036 return result;
10037 }
10038 case BUILT_IN_ISNORMAL:
10039 {
10040 /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
10041 islessequal(fabs(x),DBL_MAX). */
b9a16870 10042 tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
10043 tree const isge_fn = builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL);
a65c4d64 10044 tree const type = TREE_TYPE (arg);
10045 REAL_VALUE_TYPE rmax, rmin;
10046 char buf[128];
10047
10048 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
10049 real_from_string (&rmax, buf);
10050 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
10051 real_from_string (&rmin, buf);
10052 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
10053 result = build_call_expr (isle_fn, 2, arg,
10054 build_real (type, rmax));
10055 result = fold_build2 (BIT_AND_EXPR, integer_type_node, result,
10056 build_call_expr (isge_fn, 2, arg,
10057 build_real (type, rmin)));
10058 return result;
10059 }
10060 default:
10061 break;
10062 }
10063
10064 return NULL_TREE;
10065}
10066
726069ba 10067/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
c2f47e15 10068 ARG is the argument for the call. */
726069ba 10069
10070static tree
389dd41b 10071fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
726069ba 10072{
726069ba 10073 tree type = TREE_TYPE (TREE_TYPE (fndecl));
726069ba 10074 REAL_VALUE_TYPE r;
10075
c2f47e15 10076 if (!validate_arg (arg, REAL_TYPE))
d43cee80 10077 return NULL_TREE;
726069ba 10078
726069ba 10079 switch (builtin_index)
10080 {
10081 case BUILT_IN_ISINF:
b70bfd00 10082 if (!HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 10083 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
726069ba 10084
10085 if (TREE_CODE (arg) == REAL_CST)
10086 {
10087 r = TREE_REAL_CST (arg);
10088 if (real_isinf (&r))
10089 return real_compare (GT_EXPR, &r, &dconst0)
10090 ? integer_one_node : integer_minus_one_node;
10091 else
10092 return integer_zero_node;
10093 }
10094
10095 return NULL_TREE;
10096
c319d56a 10097 case BUILT_IN_ISINF_SIGN:
10098 {
10099 /* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */
10100 /* In a boolean context, GCC will fold the inner COND_EXPR to
10101 1. So e.g. "if (isinf_sign(x))" would be folded to just
10102 "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
10103 tree signbit_fn = mathfn_built_in_1 (TREE_TYPE (arg), BUILT_IN_SIGNBIT, 0);
b9a16870 10104 tree isinf_fn = builtin_decl_explicit (BUILT_IN_ISINF);
c319d56a 10105 tree tmp = NULL_TREE;
10106
10107 arg = builtin_save_expr (arg);
10108
10109 if (signbit_fn && isinf_fn)
10110 {
389dd41b 10111 tree signbit_call = build_call_expr_loc (loc, signbit_fn, 1, arg);
10112 tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg);
c319d56a 10113
389dd41b 10114 signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
c319d56a 10115 signbit_call, integer_zero_node);
389dd41b 10116 isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
c319d56a 10117 isinf_call, integer_zero_node);
48e1416a 10118
389dd41b 10119 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call,
c319d56a 10120 integer_minus_one_node, integer_one_node);
389dd41b 10121 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
10122 isinf_call, tmp,
c319d56a 10123 integer_zero_node);
10124 }
10125
10126 return tmp;
10127 }
10128
cde061c1 10129 case BUILT_IN_ISFINITE:
b70bfd00 10130 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
10131 && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 10132 return omit_one_operand_loc (loc, type, integer_one_node, arg);
726069ba 10133
10134 if (TREE_CODE (arg) == REAL_CST)
10135 {
10136 r = TREE_REAL_CST (arg);
776a7bab 10137 return real_isfinite (&r) ? integer_one_node : integer_zero_node;
726069ba 10138 }
10139
10140 return NULL_TREE;
10141
10142 case BUILT_IN_ISNAN:
b70bfd00 10143 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 10144 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
726069ba 10145
10146 if (TREE_CODE (arg) == REAL_CST)
10147 {
10148 r = TREE_REAL_CST (arg);
10149 return real_isnan (&r) ? integer_one_node : integer_zero_node;
10150 }
10151
10152 arg = builtin_save_expr (arg);
389dd41b 10153 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
726069ba 10154
10155 default:
64db345d 10156 gcc_unreachable ();
726069ba 10157 }
10158}
10159
19fbe3a4 10160/* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...).
10161 This builtin will generate code to return the appropriate floating
10162 point classification depending on the value of the floating point
10163 number passed in. The possible return values must be supplied as
921b27c0 10164 int arguments to the call in the following order: FP_NAN, FP_INFINITE,
19fbe3a4 10165 FP_NORMAL, FP_SUBNORMAL and FP_ZERO. The ellipses is for exactly
10166 one floating point argument which is "type generic". */
10167
10168static tree
389dd41b 10169fold_builtin_fpclassify (location_t loc, tree exp)
19fbe3a4 10170{
921b27c0 10171 tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
10172 arg, type, res, tmp;
19fbe3a4 10173 enum machine_mode mode;
10174 REAL_VALUE_TYPE r;
10175 char buf[128];
48e1416a 10176
19fbe3a4 10177 /* Verify the required arguments in the original call. */
10178 if (!validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE,
10179 INTEGER_TYPE, INTEGER_TYPE,
10180 INTEGER_TYPE, REAL_TYPE, VOID_TYPE))
10181 return NULL_TREE;
48e1416a 10182
19fbe3a4 10183 fp_nan = CALL_EXPR_ARG (exp, 0);
921b27c0 10184 fp_infinite = CALL_EXPR_ARG (exp, 1);
19fbe3a4 10185 fp_normal = CALL_EXPR_ARG (exp, 2);
10186 fp_subnormal = CALL_EXPR_ARG (exp, 3);
10187 fp_zero = CALL_EXPR_ARG (exp, 4);
10188 arg = CALL_EXPR_ARG (exp, 5);
10189 type = TREE_TYPE (arg);
10190 mode = TYPE_MODE (type);
389dd41b 10191 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
19fbe3a4 10192
48e1416a 10193 /* fpclassify(x) ->
19fbe3a4 10194 isnan(x) ? FP_NAN :
921b27c0 10195 (fabs(x) == Inf ? FP_INFINITE :
19fbe3a4 10196 (fabs(x) >= DBL_MIN ? FP_NORMAL :
10197 (x == 0 ? FP_ZERO : FP_SUBNORMAL))). */
48e1416a 10198
389dd41b 10199 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
19fbe3a4 10200 build_real (type, dconst0));
389dd41b 10201 res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
10202 tmp, fp_zero, fp_subnormal);
19fbe3a4 10203
10204 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
10205 real_from_string (&r, buf);
389dd41b 10206 tmp = fold_build2_loc (loc, GE_EXPR, integer_type_node,
10207 arg, build_real (type, r));
10208 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, fp_normal, res);
48e1416a 10209
19fbe3a4 10210 if (HONOR_INFINITIES (mode))
10211 {
10212 real_inf (&r);
389dd41b 10213 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
19fbe3a4 10214 build_real (type, r));
389dd41b 10215 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
10216 fp_infinite, res);
19fbe3a4 10217 }
10218
10219 if (HONOR_NANS (mode))
10220 {
389dd41b 10221 tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
10222 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, res, fp_nan);
19fbe3a4 10223 }
48e1416a 10224
19fbe3a4 10225 return res;
10226}
10227
9bc9f15f 10228/* Fold a call to an unordered comparison function such as
d5019fe8 10229 __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function
c2f47e15 10230 being called and ARG0 and ARG1 are the arguments for the call.
726069ba 10231 UNORDERED_CODE and ORDERED_CODE are comparison codes that give
10232 the opposite of the desired result. UNORDERED_CODE is used
10233 for modes that can hold NaNs and ORDERED_CODE is used for
10234 the rest. */
9bc9f15f 10235
10236static tree
389dd41b 10237fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
9bc9f15f 10238 enum tree_code unordered_code,
10239 enum tree_code ordered_code)
10240{
859f903a 10241 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9bc9f15f 10242 enum tree_code code;
6978db0d 10243 tree type0, type1;
10244 enum tree_code code0, code1;
10245 tree cmp_type = NULL_TREE;
9bc9f15f 10246
6978db0d 10247 type0 = TREE_TYPE (arg0);
10248 type1 = TREE_TYPE (arg1);
a0c938f0 10249
6978db0d 10250 code0 = TREE_CODE (type0);
10251 code1 = TREE_CODE (type1);
a0c938f0 10252
6978db0d 10253 if (code0 == REAL_TYPE && code1 == REAL_TYPE)
10254 /* Choose the wider of two real types. */
10255 cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
10256 ? type0 : type1;
10257 else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
10258 cmp_type = type0;
10259 else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
10260 cmp_type = type1;
a0c938f0 10261
389dd41b 10262 arg0 = fold_convert_loc (loc, cmp_type, arg0);
10263 arg1 = fold_convert_loc (loc, cmp_type, arg1);
859f903a 10264
10265 if (unordered_code == UNORDERED_EXPR)
10266 {
b70bfd00 10267 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
389dd41b 10268 return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
10269 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
859f903a 10270 }
9bc9f15f 10271
b70bfd00 10272 code = HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
10273 : ordered_code;
389dd41b 10274 return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
10275 fold_build2_loc (loc, code, type, arg0, arg1));
9bc9f15f 10276}
10277
c2f47e15 10278/* Fold a call to built-in function FNDECL with 0 arguments.
10279 IGNORE is true if the result of the function call is ignored. This
10280 function returns NULL_TREE if no simplification was possible. */
650e4c94 10281
4ee9c684 10282static tree
389dd41b 10283fold_builtin_0 (location_t loc, tree fndecl, bool ignore ATTRIBUTE_UNUSED)
650e4c94 10284{
e9f80ff5 10285 tree type = TREE_TYPE (TREE_TYPE (fndecl));
c2f47e15 10286 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
189b3398 10287 switch (fcode)
650e4c94 10288 {
c2f47e15 10289 CASE_FLT_FN (BUILT_IN_INF):
10290 case BUILT_IN_INFD32:
10291 case BUILT_IN_INFD64:
10292 case BUILT_IN_INFD128:
389dd41b 10293 return fold_builtin_inf (loc, type, true);
7c2f0500 10294
c2f47e15 10295 CASE_FLT_FN (BUILT_IN_HUGE_VAL):
389dd41b 10296 return fold_builtin_inf (loc, type, false);
7c2f0500 10297
c2f47e15 10298 case BUILT_IN_CLASSIFY_TYPE:
10299 return fold_builtin_classify_type (NULL_TREE);
7c2f0500 10300
9e46467d 10301 case BUILT_IN_UNREACHABLE:
05f893e1 10302 if (flag_sanitize & SANITIZE_UNREACHABLE
10303 && (current_function_decl == NULL
10304 || !lookup_attribute ("no_sanitize_undefined",
10305 DECL_ATTRIBUTES (current_function_decl))))
9e46467d 10306 return ubsan_instrument_unreachable (loc);
10307 break;
10308
c2f47e15 10309 default:
10310 break;
10311 }
10312 return NULL_TREE;
10313}
7c2f0500 10314
c2f47e15 10315/* Fold a call to built-in function FNDECL with 1 argument, ARG0.
10316 IGNORE is true if the result of the function call is ignored. This
10317 function returns NULL_TREE if no simplification was possible. */
7c2f0500 10318
c2f47e15 10319static tree
389dd41b 10320fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
c2f47e15 10321{
10322 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10323 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10324 switch (fcode)
10325 {
650e4c94 10326 case BUILT_IN_CONSTANT_P:
7c2f0500 10327 {
c2f47e15 10328 tree val = fold_builtin_constant_p (arg0);
7c2f0500 10329
7c2f0500 10330 /* Gimplification will pull the CALL_EXPR for the builtin out of
10331 an if condition. When not optimizing, we'll not CSE it back.
10332 To avoid link error types of regressions, return false now. */
10333 if (!val && !optimize)
10334 val = integer_zero_node;
10335
10336 return val;
10337 }
650e4c94 10338
539a3a92 10339 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 10340 return fold_builtin_classify_type (arg0);
539a3a92 10341
650e4c94 10342 case BUILT_IN_STRLEN:
c7cbde74 10343 return fold_builtin_strlen (loc, type, arg0);
650e4c94 10344
4f35b1fc 10345 CASE_FLT_FN (BUILT_IN_FABS):
8aa32773 10346 case BUILT_IN_FABSD32:
10347 case BUILT_IN_FABSD64:
10348 case BUILT_IN_FABSD128:
389dd41b 10349 return fold_builtin_fabs (loc, arg0, type);
d1aade50 10350
10351 case BUILT_IN_ABS:
10352 case BUILT_IN_LABS:
10353 case BUILT_IN_LLABS:
10354 case BUILT_IN_IMAXABS:
389dd41b 10355 return fold_builtin_abs (loc, arg0, type);
c63f4ad3 10356
4f35b1fc 10357 CASE_FLT_FN (BUILT_IN_CONJ):
239d491a 10358 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10359 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10360 return fold_build1_loc (loc, CONJ_EXPR, type, arg0);
c2f47e15 10361 break;
36d3581d 10362
4f35b1fc 10363 CASE_FLT_FN (BUILT_IN_CREAL):
239d491a 10364 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10365 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10366 return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));;
c2f47e15 10367 break;
36d3581d 10368
4f35b1fc 10369 CASE_FLT_FN (BUILT_IN_CIMAG):
b0ce8887 10370 if (validate_arg (arg0, COMPLEX_TYPE)
10371 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10372 return non_lvalue_loc (loc, fold_build1_loc (loc, IMAGPART_EXPR, type, arg0));
c2f47e15 10373 break;
36d3581d 10374
503733d5 10375 CASE_FLT_FN (BUILT_IN_CCOS):
9af5ce0c 10376 return fold_builtin_ccos (loc, arg0, type, fndecl, /*hyper=*/ false);
48e1416a 10377
503733d5 10378 CASE_FLT_FN (BUILT_IN_CCOSH):
9af5ce0c 10379 return fold_builtin_ccos (loc, arg0, type, fndecl, /*hyper=*/ true);
48e1416a 10380
c2373fdb 10381 CASE_FLT_FN (BUILT_IN_CPROJ):
9af5ce0c 10382 return fold_builtin_cproj (loc, arg0, type);
c2373fdb 10383
239d491a 10384 CASE_FLT_FN (BUILT_IN_CSIN):
10385 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10386 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10387 return do_mpc_arg1 (arg0, type, mpc_sin);
c2f47e15 10388 break;
48e1416a 10389
239d491a 10390 CASE_FLT_FN (BUILT_IN_CSINH):
10391 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10392 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10393 return do_mpc_arg1 (arg0, type, mpc_sinh);
10394 break;
48e1416a 10395
239d491a 10396 CASE_FLT_FN (BUILT_IN_CTAN):
10397 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10398 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10399 return do_mpc_arg1 (arg0, type, mpc_tan);
10400 break;
48e1416a 10401
239d491a 10402 CASE_FLT_FN (BUILT_IN_CTANH):
10403 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10404 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10405 return do_mpc_arg1 (arg0, type, mpc_tanh);
10406 break;
48e1416a 10407
239d491a 10408 CASE_FLT_FN (BUILT_IN_CLOG):
10409 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10410 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10411 return do_mpc_arg1 (arg0, type, mpc_log);
10412 break;
48e1416a 10413
239d491a 10414 CASE_FLT_FN (BUILT_IN_CSQRT):
10415 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10416 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10417 return do_mpc_arg1 (arg0, type, mpc_sqrt);
10418 break;
48e1416a 10419
0e7e6e7f 10420 CASE_FLT_FN (BUILT_IN_CASIN):
10421 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10422 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10423 return do_mpc_arg1 (arg0, type, mpc_asin);
10424 break;
48e1416a 10425
0e7e6e7f 10426 CASE_FLT_FN (BUILT_IN_CACOS):
10427 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10428 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10429 return do_mpc_arg1 (arg0, type, mpc_acos);
10430 break;
48e1416a 10431
0e7e6e7f 10432 CASE_FLT_FN (BUILT_IN_CATAN):
10433 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10434 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10435 return do_mpc_arg1 (arg0, type, mpc_atan);
10436 break;
48e1416a 10437
0e7e6e7f 10438 CASE_FLT_FN (BUILT_IN_CASINH):
10439 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10440 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10441 return do_mpc_arg1 (arg0, type, mpc_asinh);
10442 break;
48e1416a 10443
0e7e6e7f 10444 CASE_FLT_FN (BUILT_IN_CACOSH):
10445 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10446 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10447 return do_mpc_arg1 (arg0, type, mpc_acosh);
10448 break;
48e1416a 10449
0e7e6e7f 10450 CASE_FLT_FN (BUILT_IN_CATANH):
10451 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10452 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10453 return do_mpc_arg1 (arg0, type, mpc_atanh);
10454 break;
48e1416a 10455
4f35b1fc 10456 CASE_FLT_FN (BUILT_IN_CABS):
389dd41b 10457 return fold_builtin_cabs (loc, arg0, type, fndecl);
c63f4ad3 10458
abe4dcf6 10459 CASE_FLT_FN (BUILT_IN_CARG):
389dd41b 10460 return fold_builtin_carg (loc, arg0, type);
abe4dcf6 10461
4f35b1fc 10462 CASE_FLT_FN (BUILT_IN_SQRT):
389dd41b 10463 return fold_builtin_sqrt (loc, arg0, type);
805e22b2 10464
4f35b1fc 10465 CASE_FLT_FN (BUILT_IN_CBRT):
389dd41b 10466 return fold_builtin_cbrt (loc, arg0, type);
3bc5c41b 10467
728bac60 10468 CASE_FLT_FN (BUILT_IN_ASIN):
c2f47e15 10469 if (validate_arg (arg0, REAL_TYPE))
10470 return do_mpfr_arg1 (arg0, type, mpfr_asin,
728bac60 10471 &dconstm1, &dconst1, true);
10472 break;
10473
10474 CASE_FLT_FN (BUILT_IN_ACOS):
c2f47e15 10475 if (validate_arg (arg0, REAL_TYPE))
10476 return do_mpfr_arg1 (arg0, type, mpfr_acos,
728bac60 10477 &dconstm1, &dconst1, true);
10478 break;
10479
10480 CASE_FLT_FN (BUILT_IN_ATAN):
c2f47e15 10481 if (validate_arg (arg0, REAL_TYPE))
10482 return do_mpfr_arg1 (arg0, type, mpfr_atan, NULL, NULL, 0);
728bac60 10483 break;
10484
10485 CASE_FLT_FN (BUILT_IN_ASINH):
c2f47e15 10486 if (validate_arg (arg0, REAL_TYPE))
10487 return do_mpfr_arg1 (arg0, type, mpfr_asinh, NULL, NULL, 0);
728bac60 10488 break;
10489
10490 CASE_FLT_FN (BUILT_IN_ACOSH):
c2f47e15 10491 if (validate_arg (arg0, REAL_TYPE))
10492 return do_mpfr_arg1 (arg0, type, mpfr_acosh,
728bac60 10493 &dconst1, NULL, true);
10494 break;
10495
10496 CASE_FLT_FN (BUILT_IN_ATANH):
c2f47e15 10497 if (validate_arg (arg0, REAL_TYPE))
10498 return do_mpfr_arg1 (arg0, type, mpfr_atanh,
728bac60 10499 &dconstm1, &dconst1, false);
10500 break;
10501
4f35b1fc 10502 CASE_FLT_FN (BUILT_IN_SIN):
c2f47e15 10503 if (validate_arg (arg0, REAL_TYPE))
10504 return do_mpfr_arg1 (arg0, type, mpfr_sin, NULL, NULL, 0);
728bac60 10505 break;
77e89269 10506
4f35b1fc 10507 CASE_FLT_FN (BUILT_IN_COS):
389dd41b 10508 return fold_builtin_cos (loc, arg0, type, fndecl);
77e89269 10509
728bac60 10510 CASE_FLT_FN (BUILT_IN_TAN):
c2f47e15 10511 return fold_builtin_tan (arg0, type);
d735c391 10512
c5bb2c4b 10513 CASE_FLT_FN (BUILT_IN_CEXP):
389dd41b 10514 return fold_builtin_cexp (loc, arg0, type);
c5bb2c4b 10515
d735c391 10516 CASE_FLT_FN (BUILT_IN_CEXPI):
c2f47e15 10517 if (validate_arg (arg0, REAL_TYPE))
10518 return do_mpfr_sincos (arg0, NULL_TREE, NULL_TREE);
10519 break;
d92f994c 10520
728bac60 10521 CASE_FLT_FN (BUILT_IN_SINH):
c2f47e15 10522 if (validate_arg (arg0, REAL_TYPE))
10523 return do_mpfr_arg1 (arg0, type, mpfr_sinh, NULL, NULL, 0);
728bac60 10524 break;
10525
10526 CASE_FLT_FN (BUILT_IN_COSH):
389dd41b 10527 return fold_builtin_cosh (loc, arg0, type, fndecl);
728bac60 10528
10529 CASE_FLT_FN (BUILT_IN_TANH):
c2f47e15 10530 if (validate_arg (arg0, REAL_TYPE))
10531 return do_mpfr_arg1 (arg0, type, mpfr_tanh, NULL, NULL, 0);
728bac60 10532 break;
10533
29f4cd78 10534 CASE_FLT_FN (BUILT_IN_ERF):
c2f47e15 10535 if (validate_arg (arg0, REAL_TYPE))
10536 return do_mpfr_arg1 (arg0, type, mpfr_erf, NULL, NULL, 0);
29f4cd78 10537 break;
10538
10539 CASE_FLT_FN (BUILT_IN_ERFC):
c2f47e15 10540 if (validate_arg (arg0, REAL_TYPE))
10541 return do_mpfr_arg1 (arg0, type, mpfr_erfc, NULL, NULL, 0);
29f4cd78 10542 break;
10543
32dba52b 10544 CASE_FLT_FN (BUILT_IN_TGAMMA):
c2f47e15 10545 if (validate_arg (arg0, REAL_TYPE))
10546 return do_mpfr_arg1 (arg0, type, mpfr_gamma, NULL, NULL, 0);
32dba52b 10547 break;
48e1416a 10548
4f35b1fc 10549 CASE_FLT_FN (BUILT_IN_EXP):
389dd41b 10550 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp);
467214fd 10551
4f35b1fc 10552 CASE_FLT_FN (BUILT_IN_EXP2):
389dd41b 10553 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp2);
467214fd 10554
4f35b1fc 10555 CASE_FLT_FN (BUILT_IN_EXP10):
10556 CASE_FLT_FN (BUILT_IN_POW10):
389dd41b 10557 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp10);
467214fd 10558
29f4cd78 10559 CASE_FLT_FN (BUILT_IN_EXPM1):
c2f47e15 10560 if (validate_arg (arg0, REAL_TYPE))
10561 return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0);
29f4cd78 10562 break;
48e1416a 10563
4f35b1fc 10564 CASE_FLT_FN (BUILT_IN_LOG):
389dd41b 10565 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log);
467214fd 10566
4f35b1fc 10567 CASE_FLT_FN (BUILT_IN_LOG2):
389dd41b 10568 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log2);
467214fd 10569
4f35b1fc 10570 CASE_FLT_FN (BUILT_IN_LOG10):
389dd41b 10571 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log10);
29f4cd78 10572
10573 CASE_FLT_FN (BUILT_IN_LOG1P):
c2f47e15 10574 if (validate_arg (arg0, REAL_TYPE))
10575 return do_mpfr_arg1 (arg0, type, mpfr_log1p,
29f4cd78 10576 &dconstm1, NULL, false);
10577 break;
805e22b2 10578
65dd1378 10579 CASE_FLT_FN (BUILT_IN_J0):
10580 if (validate_arg (arg0, REAL_TYPE))
10581 return do_mpfr_arg1 (arg0, type, mpfr_j0,
10582 NULL, NULL, 0);
10583 break;
10584
10585 CASE_FLT_FN (BUILT_IN_J1):
10586 if (validate_arg (arg0, REAL_TYPE))
10587 return do_mpfr_arg1 (arg0, type, mpfr_j1,
10588 NULL, NULL, 0);
10589 break;
6ff9eeff 10590
10591 CASE_FLT_FN (BUILT_IN_Y0):
10592 if (validate_arg (arg0, REAL_TYPE))
10593 return do_mpfr_arg1 (arg0, type, mpfr_y0,
10594 &dconst0, NULL, false);
10595 break;
10596
10597 CASE_FLT_FN (BUILT_IN_Y1):
10598 if (validate_arg (arg0, REAL_TYPE))
10599 return do_mpfr_arg1 (arg0, type, mpfr_y1,
10600 &dconst0, NULL, false);
10601 break;
65dd1378 10602
4f35b1fc 10603 CASE_FLT_FN (BUILT_IN_NAN):
c4503c0a 10604 case BUILT_IN_NAND32:
10605 case BUILT_IN_NAND64:
10606 case BUILT_IN_NAND128:
c2f47e15 10607 return fold_builtin_nan (arg0, type, true);
b0db7939 10608
4f35b1fc 10609 CASE_FLT_FN (BUILT_IN_NANS):
c2f47e15 10610 return fold_builtin_nan (arg0, type, false);
b0db7939 10611
4f35b1fc 10612 CASE_FLT_FN (BUILT_IN_FLOOR):
389dd41b 10613 return fold_builtin_floor (loc, fndecl, arg0);
277f8dd2 10614
4f35b1fc 10615 CASE_FLT_FN (BUILT_IN_CEIL):
389dd41b 10616 return fold_builtin_ceil (loc, fndecl, arg0);
277f8dd2 10617
4f35b1fc 10618 CASE_FLT_FN (BUILT_IN_TRUNC):
389dd41b 10619 return fold_builtin_trunc (loc, fndecl, arg0);
277f8dd2 10620
4f35b1fc 10621 CASE_FLT_FN (BUILT_IN_ROUND):
389dd41b 10622 return fold_builtin_round (loc, fndecl, arg0);
89ab3887 10623
4f35b1fc 10624 CASE_FLT_FN (BUILT_IN_NEARBYINT):
10625 CASE_FLT_FN (BUILT_IN_RINT):
389dd41b 10626 return fold_trunc_transparent_mathfn (loc, fndecl, arg0);
6528f4f4 10627
80ff6494 10628 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 10629 CASE_FLT_FN (BUILT_IN_LCEIL):
10630 CASE_FLT_FN (BUILT_IN_LLCEIL):
10631 CASE_FLT_FN (BUILT_IN_LFLOOR):
80ff6494 10632 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 10633 CASE_FLT_FN (BUILT_IN_LLFLOOR):
80ff6494 10634 CASE_FLT_FN (BUILT_IN_IROUND):
a0c938f0 10635 CASE_FLT_FN (BUILT_IN_LROUND):
4f35b1fc 10636 CASE_FLT_FN (BUILT_IN_LLROUND):
389dd41b 10637 return fold_builtin_int_roundingfn (loc, fndecl, arg0);
34f17811 10638
80ff6494 10639 CASE_FLT_FN (BUILT_IN_IRINT):
4f35b1fc 10640 CASE_FLT_FN (BUILT_IN_LRINT):
10641 CASE_FLT_FN (BUILT_IN_LLRINT):
389dd41b 10642 return fold_fixed_mathfn (loc, fndecl, arg0);
9ed65c7f 10643
74bdbe96 10644 case BUILT_IN_BSWAP16:
42791117 10645 case BUILT_IN_BSWAP32:
10646 case BUILT_IN_BSWAP64:
c2f47e15 10647 return fold_builtin_bswap (fndecl, arg0);
42791117 10648
4f35b1fc 10649 CASE_INT_FN (BUILT_IN_FFS):
10650 CASE_INT_FN (BUILT_IN_CLZ):
10651 CASE_INT_FN (BUILT_IN_CTZ):
6aaa1f9e 10652 CASE_INT_FN (BUILT_IN_CLRSB):
4f35b1fc 10653 CASE_INT_FN (BUILT_IN_POPCOUNT):
10654 CASE_INT_FN (BUILT_IN_PARITY):
c2f47e15 10655 return fold_builtin_bitop (fndecl, arg0);
9c8a1629 10656
4f35b1fc 10657 CASE_FLT_FN (BUILT_IN_SIGNBIT):
389dd41b 10658 return fold_builtin_signbit (loc, arg0, type);
27f261ef 10659
cb2b9385 10660 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
389dd41b 10661 return fold_builtin_significand (loc, arg0, type);
cb2b9385 10662
10663 CASE_FLT_FN (BUILT_IN_ILOGB):
10664 CASE_FLT_FN (BUILT_IN_LOGB):
389dd41b 10665 return fold_builtin_logb (loc, arg0, type);
cb2b9385 10666
d49367d4 10667 case BUILT_IN_ISASCII:
389dd41b 10668 return fold_builtin_isascii (loc, arg0);
d49367d4 10669
10670 case BUILT_IN_TOASCII:
389dd41b 10671 return fold_builtin_toascii (loc, arg0);
d49367d4 10672
df1cf42e 10673 case BUILT_IN_ISDIGIT:
389dd41b 10674 return fold_builtin_isdigit (loc, arg0);
467214fd 10675
4f35b1fc 10676 CASE_FLT_FN (BUILT_IN_FINITE):
c4503c0a 10677 case BUILT_IN_FINITED32:
10678 case BUILT_IN_FINITED64:
10679 case BUILT_IN_FINITED128:
cde061c1 10680 case BUILT_IN_ISFINITE:
a65c4d64 10681 {
10682 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISFINITE);
10683 if (ret)
10684 return ret;
10685 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10686 }
726069ba 10687
4f35b1fc 10688 CASE_FLT_FN (BUILT_IN_ISINF):
c4503c0a 10689 case BUILT_IN_ISINFD32:
10690 case BUILT_IN_ISINFD64:
10691 case BUILT_IN_ISINFD128:
a65c4d64 10692 {
10693 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF);
10694 if (ret)
10695 return ret;
10696 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10697 }
10698
10699 case BUILT_IN_ISNORMAL:
10700 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
726069ba 10701
c319d56a 10702 case BUILT_IN_ISINF_SIGN:
389dd41b 10703 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF_SIGN);
c319d56a 10704
4f35b1fc 10705 CASE_FLT_FN (BUILT_IN_ISNAN):
c4503c0a 10706 case BUILT_IN_ISNAND32:
10707 case BUILT_IN_ISNAND64:
10708 case BUILT_IN_ISNAND128:
389dd41b 10709 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
c2f47e15 10710
10711 case BUILT_IN_PRINTF:
10712 case BUILT_IN_PRINTF_UNLOCKED:
10713 case BUILT_IN_VPRINTF:
389dd41b 10714 return fold_builtin_printf (loc, fndecl, arg0, NULL_TREE, ignore, fcode);
c2f47e15 10715
663870fc 10716 case BUILT_IN_FREE:
10717 if (integer_zerop (arg0))
10718 return build_empty_stmt (loc);
10719 break;
10720
c2f47e15 10721 default:
10722 break;
10723 }
10724
10725 return NULL_TREE;
10726
10727}
10728
10729/* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1.
10730 IGNORE is true if the result of the function call is ignored. This
10731 function returns NULL_TREE if no simplification was possible. */
10732
10733static tree
389dd41b 10734fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore)
c2f47e15 10735{
10736 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10737 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10738
10739 switch (fcode)
10740 {
65dd1378 10741 CASE_FLT_FN (BUILT_IN_JN):
10742 if (validate_arg (arg0, INTEGER_TYPE)
10743 && validate_arg (arg1, REAL_TYPE))
10744 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_jn, NULL, 0);
10745 break;
6ff9eeff 10746
10747 CASE_FLT_FN (BUILT_IN_YN):
10748 if (validate_arg (arg0, INTEGER_TYPE)
10749 && validate_arg (arg1, REAL_TYPE))
10750 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_yn,
10751 &dconst0, false);
10752 break;
e5407ca6 10753
10754 CASE_FLT_FN (BUILT_IN_DREM):
10755 CASE_FLT_FN (BUILT_IN_REMAINDER):
10756 if (validate_arg (arg0, REAL_TYPE)
9af5ce0c 10757 && validate_arg (arg1, REAL_TYPE))
e5407ca6 10758 return do_mpfr_arg2 (arg0, arg1, type, mpfr_remainder);
10759 break;
e84da7c1 10760
10761 CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
10762 CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
10763 if (validate_arg (arg0, REAL_TYPE)
9af5ce0c 10764 && validate_arg (arg1, POINTER_TYPE))
e84da7c1 10765 return do_mpfr_lgamma_r (arg0, arg1, type);
10766 break;
c2f47e15 10767
10768 CASE_FLT_FN (BUILT_IN_ATAN2):
10769 if (validate_arg (arg0, REAL_TYPE)
9af5ce0c 10770 && validate_arg (arg1, REAL_TYPE))
c2f47e15 10771 return do_mpfr_arg2 (arg0, arg1, type, mpfr_atan2);
10772 break;
10773
10774 CASE_FLT_FN (BUILT_IN_FDIM):
10775 if (validate_arg (arg0, REAL_TYPE)
9af5ce0c 10776 && validate_arg (arg1, REAL_TYPE))
c2f47e15 10777 return do_mpfr_arg2 (arg0, arg1, type, mpfr_dim);
10778 break;
10779
10780 CASE_FLT_FN (BUILT_IN_HYPOT):
389dd41b 10781 return fold_builtin_hypot (loc, fndecl, arg0, arg1, type);
c2f47e15 10782
c699fab8 10783 CASE_FLT_FN (BUILT_IN_CPOW):
10784 if (validate_arg (arg0, COMPLEX_TYPE)
10785 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
10786 && validate_arg (arg1, COMPLEX_TYPE)
48e1416a 10787 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE)
652d9409 10788 return do_mpc_arg2 (arg0, arg1, type, /*do_nonfinite=*/ 0, mpc_pow);
c699fab8 10789 break;
c699fab8 10790
7587301b 10791 CASE_FLT_FN (BUILT_IN_LDEXP):
389dd41b 10792 return fold_builtin_load_exponent (loc, arg0, arg1, type, /*ldexp=*/true);
7587301b 10793 CASE_FLT_FN (BUILT_IN_SCALBN):
10794 CASE_FLT_FN (BUILT_IN_SCALBLN):
389dd41b 10795 return fold_builtin_load_exponent (loc, arg0, arg1,
10796 type, /*ldexp=*/false);
7587301b 10797
3838b9ae 10798 CASE_FLT_FN (BUILT_IN_FREXP):
389dd41b 10799 return fold_builtin_frexp (loc, arg0, arg1, type);
3838b9ae 10800
ebf8b4f5 10801 CASE_FLT_FN (BUILT_IN_MODF):
389dd41b 10802 return fold_builtin_modf (loc, arg0, arg1, type);
ebf8b4f5 10803
c2f47e15 10804 case BUILT_IN_BZERO:
389dd41b 10805 return fold_builtin_bzero (loc, arg0, arg1, ignore);
c2f47e15 10806
10807 case BUILT_IN_FPUTS:
389dd41b 10808 return fold_builtin_fputs (loc, arg0, arg1, ignore, false, NULL_TREE);
c2f47e15 10809
10810 case BUILT_IN_FPUTS_UNLOCKED:
389dd41b 10811 return fold_builtin_fputs (loc, arg0, arg1, ignore, true, NULL_TREE);
c2f47e15 10812
10813 case BUILT_IN_STRSTR:
389dd41b 10814 return fold_builtin_strstr (loc, arg0, arg1, type);
c2f47e15 10815
10816 case BUILT_IN_STRCAT:
389dd41b 10817 return fold_builtin_strcat (loc, arg0, arg1);
c2f47e15 10818
10819 case BUILT_IN_STRSPN:
389dd41b 10820 return fold_builtin_strspn (loc, arg0, arg1);
c2f47e15 10821
10822 case BUILT_IN_STRCSPN:
389dd41b 10823 return fold_builtin_strcspn (loc, arg0, arg1);
c2f47e15 10824
10825 case BUILT_IN_STRCHR:
10826 case BUILT_IN_INDEX:
389dd41b 10827 return fold_builtin_strchr (loc, arg0, arg1, type);
c2f47e15 10828
10829 case BUILT_IN_STRRCHR:
10830 case BUILT_IN_RINDEX:
389dd41b 10831 return fold_builtin_strrchr (loc, arg0, arg1, type);
c2f47e15 10832
10833 case BUILT_IN_STRCPY:
389dd41b 10834 return fold_builtin_strcpy (loc, fndecl, arg0, arg1, NULL_TREE);
c2f47e15 10835
c8b17b2e 10836 case BUILT_IN_STPCPY:
10837 if (ignore)
10838 {
b9a16870 10839 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
c8b17b2e 10840 if (!fn)
10841 break;
10842
389dd41b 10843 return build_call_expr_loc (loc, fn, 2, arg0, arg1);
c8b17b2e 10844 }
a65c4d64 10845 else
10846 return fold_builtin_stpcpy (loc, fndecl, arg0, arg1);
c8b17b2e 10847 break;
10848
c2f47e15 10849 case BUILT_IN_STRCMP:
389dd41b 10850 return fold_builtin_strcmp (loc, arg0, arg1);
c2f47e15 10851
10852 case BUILT_IN_STRPBRK:
389dd41b 10853 return fold_builtin_strpbrk (loc, arg0, arg1, type);
c2f47e15 10854
10855 case BUILT_IN_EXPECT:
389dd41b 10856 return fold_builtin_expect (loc, arg0, arg1);
c2f47e15 10857
10858 CASE_FLT_FN (BUILT_IN_POW):
389dd41b 10859 return fold_builtin_pow (loc, fndecl, arg0, arg1, type);
c2f47e15 10860
10861 CASE_FLT_FN (BUILT_IN_POWI):
389dd41b 10862 return fold_builtin_powi (loc, fndecl, arg0, arg1, type);
c2f47e15 10863
10864 CASE_FLT_FN (BUILT_IN_COPYSIGN):
389dd41b 10865 return fold_builtin_copysign (loc, fndecl, arg0, arg1, type);
c2f47e15 10866
10867 CASE_FLT_FN (BUILT_IN_FMIN):
389dd41b 10868 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/false);
c2f47e15 10869
10870 CASE_FLT_FN (BUILT_IN_FMAX):
389dd41b 10871 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/true);
726069ba 10872
9bc9f15f 10873 case BUILT_IN_ISGREATER:
389dd41b 10874 return fold_builtin_unordered_cmp (loc, fndecl,
10875 arg0, arg1, UNLE_EXPR, LE_EXPR);
9bc9f15f 10876 case BUILT_IN_ISGREATEREQUAL:
389dd41b 10877 return fold_builtin_unordered_cmp (loc, fndecl,
10878 arg0, arg1, UNLT_EXPR, LT_EXPR);
9bc9f15f 10879 case BUILT_IN_ISLESS:
389dd41b 10880 return fold_builtin_unordered_cmp (loc, fndecl,
10881 arg0, arg1, UNGE_EXPR, GE_EXPR);
9bc9f15f 10882 case BUILT_IN_ISLESSEQUAL:
389dd41b 10883 return fold_builtin_unordered_cmp (loc, fndecl,
10884 arg0, arg1, UNGT_EXPR, GT_EXPR);
9bc9f15f 10885 case BUILT_IN_ISLESSGREATER:
389dd41b 10886 return fold_builtin_unordered_cmp (loc, fndecl,
10887 arg0, arg1, UNEQ_EXPR, EQ_EXPR);
9bc9f15f 10888 case BUILT_IN_ISUNORDERED:
389dd41b 10889 return fold_builtin_unordered_cmp (loc, fndecl,
10890 arg0, arg1, UNORDERED_EXPR,
d5019fe8 10891 NOP_EXPR);
9bc9f15f 10892
7c2f0500 10893 /* We do the folding for va_start in the expander. */
10894 case BUILT_IN_VA_START:
10895 break;
f0613857 10896
c2f47e15 10897 case BUILT_IN_SPRINTF:
389dd41b 10898 return fold_builtin_sprintf (loc, arg0, arg1, NULL_TREE, ignore);
c2f47e15 10899
0a39fd54 10900 case BUILT_IN_OBJECT_SIZE:
c2f47e15 10901 return fold_builtin_object_size (arg0, arg1);
0a39fd54 10902
10903 case BUILT_IN_PRINTF:
10904 case BUILT_IN_PRINTF_UNLOCKED:
10905 case BUILT_IN_VPRINTF:
389dd41b 10906 return fold_builtin_printf (loc, fndecl, arg0, arg1, ignore, fcode);
c2f47e15 10907
0a39fd54 10908 case BUILT_IN_PRINTF_CHK:
10909 case BUILT_IN_VPRINTF_CHK:
c2f47e15 10910 if (!validate_arg (arg0, INTEGER_TYPE)
10911 || TREE_SIDE_EFFECTS (arg0))
10912 return NULL_TREE;
10913 else
389dd41b 10914 return fold_builtin_printf (loc, fndecl,
10915 arg1, NULL_TREE, ignore, fcode);
c2f47e15 10916 break;
0a39fd54 10917
10918 case BUILT_IN_FPRINTF:
10919 case BUILT_IN_FPRINTF_UNLOCKED:
10920 case BUILT_IN_VFPRINTF:
389dd41b 10921 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, NULL_TREE,
c2f47e15 10922 ignore, fcode);
10923
1cd6e20d 10924 case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
10925 return fold_builtin_atomic_always_lock_free (arg0, arg1);
10926
10927 case BUILT_IN_ATOMIC_IS_LOCK_FREE:
10928 return fold_builtin_atomic_is_lock_free (arg0, arg1);
10929
c2f47e15 10930 default:
10931 break;
10932 }
10933 return NULL_TREE;
10934}
10935
10936/* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
10937 and ARG2. IGNORE is true if the result of the function call is ignored.
10938 This function returns NULL_TREE if no simplification was possible. */
10939
10940static tree
389dd41b 10941fold_builtin_3 (location_t loc, tree fndecl,
10942 tree arg0, tree arg1, tree arg2, bool ignore)
c2f47e15 10943{
10944 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10945 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10946 switch (fcode)
10947 {
10948
10949 CASE_FLT_FN (BUILT_IN_SINCOS):
389dd41b 10950 return fold_builtin_sincos (loc, arg0, arg1, arg2);
c2f47e15 10951
10952 CASE_FLT_FN (BUILT_IN_FMA):
b9be572e 10953 return fold_builtin_fma (loc, arg0, arg1, arg2, type);
c2f47e15 10954 break;
10955
e5407ca6 10956 CASE_FLT_FN (BUILT_IN_REMQUO):
10957 if (validate_arg (arg0, REAL_TYPE)
9af5ce0c 10958 && validate_arg (arg1, REAL_TYPE)
10959 && validate_arg (arg2, POINTER_TYPE))
e5407ca6 10960 return do_mpfr_remquo (arg0, arg1, arg2);
10961 break;
e5407ca6 10962
c2f47e15 10963 case BUILT_IN_MEMSET:
389dd41b 10964 return fold_builtin_memset (loc, arg0, arg1, arg2, type, ignore);
c2f47e15 10965
10966 case BUILT_IN_BCOPY:
389dd41b 10967 return fold_builtin_memory_op (loc, arg1, arg0, arg2,
10968 void_type_node, true, /*endp=*/3);
c2f47e15 10969
10970 case BUILT_IN_MEMCPY:
389dd41b 10971 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10972 type, ignore, /*endp=*/0);
c2f47e15 10973
10974 case BUILT_IN_MEMPCPY:
389dd41b 10975 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10976 type, ignore, /*endp=*/1);
c2f47e15 10977
10978 case BUILT_IN_MEMMOVE:
389dd41b 10979 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10980 type, ignore, /*endp=*/3);
c2f47e15 10981
10982 case BUILT_IN_STRNCAT:
389dd41b 10983 return fold_builtin_strncat (loc, arg0, arg1, arg2);
c2f47e15 10984
10985 case BUILT_IN_STRNCPY:
389dd41b 10986 return fold_builtin_strncpy (loc, fndecl, arg0, arg1, arg2, NULL_TREE);
c2f47e15 10987
10988 case BUILT_IN_STRNCMP:
389dd41b 10989 return fold_builtin_strncmp (loc, arg0, arg1, arg2);
c2f47e15 10990
7959b13b 10991 case BUILT_IN_MEMCHR:
389dd41b 10992 return fold_builtin_memchr (loc, arg0, arg1, arg2, type);
7959b13b 10993
c2f47e15 10994 case BUILT_IN_BCMP:
10995 case BUILT_IN_MEMCMP:
389dd41b 10996 return fold_builtin_memcmp (loc, arg0, arg1, arg2);;
c2f47e15 10997
10998 case BUILT_IN_SPRINTF:
389dd41b 10999 return fold_builtin_sprintf (loc, arg0, arg1, arg2, ignore);
c2f47e15 11000
750d7b16 11001 case BUILT_IN_SNPRINTF:
11002 return fold_builtin_snprintf (loc, arg0, arg1, arg2, NULL_TREE, ignore);
11003
c2f47e15 11004 case BUILT_IN_STRCPY_CHK:
11005 case BUILT_IN_STPCPY_CHK:
389dd41b 11006 return fold_builtin_stxcpy_chk (loc, fndecl, arg0, arg1, arg2, NULL_TREE,
c2f47e15 11007 ignore, fcode);
11008
11009 case BUILT_IN_STRCAT_CHK:
389dd41b 11010 return fold_builtin_strcat_chk (loc, fndecl, arg0, arg1, arg2);
c2f47e15 11011
11012 case BUILT_IN_PRINTF_CHK:
11013 case BUILT_IN_VPRINTF_CHK:
11014 if (!validate_arg (arg0, INTEGER_TYPE)
11015 || TREE_SIDE_EFFECTS (arg0))
11016 return NULL_TREE;
11017 else
389dd41b 11018 return fold_builtin_printf (loc, fndecl, arg1, arg2, ignore, fcode);
c2f47e15 11019 break;
11020
11021 case BUILT_IN_FPRINTF:
11022 case BUILT_IN_FPRINTF_UNLOCKED:
11023 case BUILT_IN_VFPRINTF:
389dd41b 11024 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, arg2,
11025 ignore, fcode);
c2f47e15 11026
0a39fd54 11027 case BUILT_IN_FPRINTF_CHK:
11028 case BUILT_IN_VFPRINTF_CHK:
c2f47e15 11029 if (!validate_arg (arg1, INTEGER_TYPE)
11030 || TREE_SIDE_EFFECTS (arg1))
11031 return NULL_TREE;
11032 else
389dd41b 11033 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, NULL_TREE,
c2f47e15 11034 ignore, fcode);
0a39fd54 11035
650e4c94 11036 default:
11037 break;
11038 }
c2f47e15 11039 return NULL_TREE;
11040}
650e4c94 11041
c2f47e15 11042/* Fold a call to built-in function FNDECL with 4 arguments, ARG0, ARG1,
11043 ARG2, and ARG3. IGNORE is true if the result of the function call is
11044 ignored. This function returns NULL_TREE if no simplification was
11045 possible. */
48e1416a 11046
c2f47e15 11047static tree
389dd41b 11048fold_builtin_4 (location_t loc, tree fndecl,
11049 tree arg0, tree arg1, tree arg2, tree arg3, bool ignore)
c2f47e15 11050{
11051 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
11052
11053 switch (fcode)
11054 {
11055 case BUILT_IN_MEMCPY_CHK:
11056 case BUILT_IN_MEMPCPY_CHK:
11057 case BUILT_IN_MEMMOVE_CHK:
11058 case BUILT_IN_MEMSET_CHK:
389dd41b 11059 return fold_builtin_memory_chk (loc, fndecl, arg0, arg1, arg2, arg3,
c2f47e15 11060 NULL_TREE, ignore,
11061 DECL_FUNCTION_CODE (fndecl));
11062
11063 case BUILT_IN_STRNCPY_CHK:
1063acde 11064 case BUILT_IN_STPNCPY_CHK:
11065 return fold_builtin_stxncpy_chk (loc, arg0, arg1, arg2, arg3, NULL_TREE,
11066 ignore, fcode);
c2f47e15 11067
11068 case BUILT_IN_STRNCAT_CHK:
389dd41b 11069 return fold_builtin_strncat_chk (loc, fndecl, arg0, arg1, arg2, arg3);
c2f47e15 11070
750d7b16 11071 case BUILT_IN_SNPRINTF:
11072 return fold_builtin_snprintf (loc, arg0, arg1, arg2, arg3, ignore);
11073
c2f47e15 11074 case BUILT_IN_FPRINTF_CHK:
11075 case BUILT_IN_VFPRINTF_CHK:
11076 if (!validate_arg (arg1, INTEGER_TYPE)
11077 || TREE_SIDE_EFFECTS (arg1))
11078 return NULL_TREE;
11079 else
389dd41b 11080 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, arg3,
c2f47e15 11081 ignore, fcode);
11082 break;
11083
11084 default:
11085 break;
11086 }
11087 return NULL_TREE;
11088}
11089
11090/* Fold a call to built-in function FNDECL. ARGS is an array of NARGS
11091 arguments, where NARGS <= 4. IGNORE is true if the result of the
11092 function call is ignored. This function returns NULL_TREE if no
11093 simplification was possible. Note that this only folds builtins with
11094 fixed argument patterns. Foldings that do varargs-to-varargs
11095 transformations, or that match calls with more than 4 arguments,
11096 need to be handled with fold_builtin_varargs instead. */
48e1416a 11097
c2f47e15 11098#define MAX_ARGS_TO_FOLD_BUILTIN 4
48e1416a 11099
c2f47e15 11100static tree
389dd41b 11101fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool ignore)
c2f47e15 11102{
11103 tree ret = NULL_TREE;
a7f5bb2d 11104
c2f47e15 11105 switch (nargs)
11106 {
11107 case 0:
389dd41b 11108 ret = fold_builtin_0 (loc, fndecl, ignore);
c2f47e15 11109 break;
11110 case 1:
389dd41b 11111 ret = fold_builtin_1 (loc, fndecl, args[0], ignore);
c2f47e15 11112 break;
11113 case 2:
389dd41b 11114 ret = fold_builtin_2 (loc, fndecl, args[0], args[1], ignore);
c2f47e15 11115 break;
11116 case 3:
389dd41b 11117 ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2], ignore);
c2f47e15 11118 break;
11119 case 4:
389dd41b 11120 ret = fold_builtin_4 (loc, fndecl, args[0], args[1], args[2], args[3],
c2f47e15 11121 ignore);
11122 break;
11123 default:
11124 break;
11125 }
11126 if (ret)
11127 {
75a70cf9 11128 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
389dd41b 11129 SET_EXPR_LOCATION (ret, loc);
c2f47e15 11130 TREE_NO_WARNING (ret) = 1;
11131 return ret;
11132 }
11133 return NULL_TREE;
11134}
11135
0e80b01d 11136/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
11137 list ARGS along with N new arguments in NEWARGS. SKIP is the number
11138 of arguments in ARGS to be omitted. OLDNARGS is the number of
11139 elements in ARGS. */
c2f47e15 11140
11141static tree
0e80b01d 11142rewrite_call_expr_valist (location_t loc, int oldnargs, tree *args,
11143 int skip, tree fndecl, int n, va_list newargs)
c2f47e15 11144{
0e80b01d 11145 int nargs = oldnargs - skip + n;
11146 tree *buffer;
c2f47e15 11147
0e80b01d 11148 if (n > 0)
c2f47e15 11149 {
0e80b01d 11150 int i, j;
c2f47e15 11151
0e80b01d 11152 buffer = XALLOCAVEC (tree, nargs);
11153 for (i = 0; i < n; i++)
11154 buffer[i] = va_arg (newargs, tree);
11155 for (j = skip; j < oldnargs; j++, i++)
11156 buffer[i] = args[j];
11157 }
11158 else
11159 buffer = args + skip;
19fbe3a4 11160
0e80b01d 11161 return build_call_expr_loc_array (loc, fndecl, nargs, buffer);
11162}
c2f47e15 11163
0e80b01d 11164/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
11165 list ARGS along with N new arguments specified as the "..."
11166 parameters. SKIP is the number of arguments in ARGS to be omitted.
11167 OLDNARGS is the number of elements in ARGS. */
11168
11169static tree
11170rewrite_call_expr_array (location_t loc, int oldnargs, tree *args,
11171 int skip, tree fndecl, int n, ...)
11172{
11173 va_list ap;
11174 tree t;
11175
11176 va_start (ap, n);
11177 t = rewrite_call_expr_valist (loc, oldnargs, args, skip, fndecl, n, ap);
11178 va_end (ap);
11179
11180 return t;
650e4c94 11181}
7e15618b 11182
198622c0 11183/* Return true if FNDECL shouldn't be folded right now.
11184 If a built-in function has an inline attribute always_inline
11185 wrapper, defer folding it after always_inline functions have
11186 been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
11187 might not be performed. */
11188
51d2c51e 11189bool
198622c0 11190avoid_folding_inline_builtin (tree fndecl)
11191{
11192 return (DECL_DECLARED_INLINE_P (fndecl)
11193 && DECL_DISREGARD_INLINE_LIMITS (fndecl)
11194 && cfun
11195 && !cfun->always_inline_functions_inlined
11196 && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)));
11197}
11198
4ee9c684 11199/* A wrapper function for builtin folding that prevents warnings for
491e04ef 11200 "statement without effect" and the like, caused by removing the
4ee9c684 11201 call node earlier than the warning is generated. */
11202
11203tree
389dd41b 11204fold_call_expr (location_t loc, tree exp, bool ignore)
4ee9c684 11205{
c2f47e15 11206 tree ret = NULL_TREE;
11207 tree fndecl = get_callee_fndecl (exp);
11208 if (fndecl
11209 && TREE_CODE (fndecl) == FUNCTION_DECL
48dc2227 11210 && DECL_BUILT_IN (fndecl)
11211 /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
11212 yet. Defer folding until we see all the arguments
11213 (after inlining). */
11214 && !CALL_EXPR_VA_ARG_PACK (exp))
11215 {
11216 int nargs = call_expr_nargs (exp);
11217
11218 /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
11219 instead last argument is __builtin_va_arg_pack (). Defer folding
11220 even in that case, until arguments are finalized. */
11221 if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
11222 {
11223 tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 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)
11228 return NULL_TREE;
11229 }
11230
198622c0 11231 if (avoid_folding_inline_builtin (fndecl))
11232 return NULL_TREE;
11233
c2f47e15 11234 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
97d67146 11235 return targetm.fold_builtin (fndecl, call_expr_nargs (exp),
11236 CALL_EXPR_ARGP (exp), ignore);
c2f47e15 11237 else
11238 {
c2f47e15 11239 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
11240 {
11241 tree *args = CALL_EXPR_ARGP (exp);
389dd41b 11242 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
c2f47e15 11243 }
11244 if (!ret)
389dd41b 11245 ret = fold_builtin_varargs (loc, fndecl, exp, ignore);
c2f47e15 11246 if (ret)
389dd41b 11247 return ret;
c2f47e15 11248 }
4ee9c684 11249 }
c2f47e15 11250 return NULL_TREE;
11251}
48e1416a 11252
c2f47e15 11253/* Conveniently construct a function call expression. FNDECL names the
414c3a2c 11254 function to be called and N arguments are passed in the array
11255 ARGARRAY. */
48e1416a 11256
c2f47e15 11257tree
414c3a2c 11258build_call_expr_loc_array (location_t loc, tree fndecl, int n, tree *argarray)
c2f47e15 11259{
11260 tree fntype = TREE_TYPE (fndecl);
11261 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
414c3a2c 11262
389dd41b 11263 return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray);
c2f47e15 11264}
11265
414c3a2c 11266/* Conveniently construct a function call expression. FNDECL names the
11267 function to be called and the arguments are passed in the vector
11268 VEC. */
11269
11270tree
f1f41a6c 11271build_call_expr_loc_vec (location_t loc, tree fndecl, vec<tree, va_gc> *vec)
414c3a2c 11272{
f1f41a6c 11273 return build_call_expr_loc_array (loc, fndecl, vec_safe_length (vec),
11274 vec_safe_address (vec));
414c3a2c 11275}
11276
11277
c2f47e15 11278/* Conveniently construct a function call expression. FNDECL names the
11279 function to be called, N is the number of arguments, and the "..."
11280 parameters are the argument expressions. */
48e1416a 11281
c2f47e15 11282tree
389dd41b 11283build_call_expr_loc (location_t loc, tree fndecl, int n, ...)
c2f47e15 11284{
11285 va_list ap;
414c3a2c 11286 tree *argarray = XALLOCAVEC (tree, n);
d01f58f9 11287 int i;
c2f47e15 11288
11289 va_start (ap, n);
d01f58f9 11290 for (i = 0; i < n; i++)
11291 argarray[i] = va_arg (ap, tree);
c2f47e15 11292 va_end (ap);
414c3a2c 11293 return build_call_expr_loc_array (loc, fndecl, n, argarray);
4ee9c684 11294}
11295
0568e9c1 11296/* Like build_call_expr_loc (UNKNOWN_LOCATION, ...). Duplicated because
11297 varargs macros aren't supported by all bootstrap compilers. */
11298
11299tree
11300build_call_expr (tree fndecl, int n, ...)
11301{
11302 va_list ap;
414c3a2c 11303 tree *argarray = XALLOCAVEC (tree, n);
0568e9c1 11304 int i;
11305
11306 va_start (ap, n);
11307 for (i = 0; i < n; i++)
11308 argarray[i] = va_arg (ap, tree);
11309 va_end (ap);
414c3a2c 11310 return build_call_expr_loc_array (UNKNOWN_LOCATION, fndecl, n, argarray);
0568e9c1 11311}
11312
c2f47e15 11313/* Construct a CALL_EXPR with type TYPE with FN as the function expression.
d01f58f9 11314 N arguments are passed in the array ARGARRAY. */
805e22b2 11315
11316tree
389dd41b 11317fold_builtin_call_array (location_t loc, tree type,
d01f58f9 11318 tree fn,
11319 int n,
11320 tree *argarray)
7e15618b 11321{
c2f47e15 11322 tree ret = NULL_TREE;
c2f47e15 11323 tree exp;
11324
11325 if (TREE_CODE (fn) == ADDR_EXPR)
11326 {
11327 tree fndecl = TREE_OPERAND (fn, 0);
11328 if (TREE_CODE (fndecl) == FUNCTION_DECL
11329 && DECL_BUILT_IN (fndecl))
11330 {
48dc2227 11331 /* If last argument is __builtin_va_arg_pack (), arguments to this
11332 function are not finalized yet. Defer folding until they are. */
11333 if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
11334 {
11335 tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
11336 if (fndecl2
11337 && TREE_CODE (fndecl2) == FUNCTION_DECL
11338 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
11339 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
389dd41b 11340 return build_call_array_loc (loc, type, fn, n, argarray);
48dc2227 11341 }
198622c0 11342 if (avoid_folding_inline_builtin (fndecl))
389dd41b 11343 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 11344 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
11345 {
97d67146 11346 ret = targetm.fold_builtin (fndecl, n, argarray, false);
11347 if (ret)
11348 return ret;
11349
389dd41b 11350 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 11351 }
11352 else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
11353 {
11354 /* First try the transformations that don't require consing up
11355 an exp. */
389dd41b 11356 ret = fold_builtin_n (loc, fndecl, argarray, n, false);
c2f47e15 11357 if (ret)
11358 return ret;
11359 }
11360
11361 /* If we got this far, we need to build an exp. */
389dd41b 11362 exp = build_call_array_loc (loc, type, fn, n, argarray);
11363 ret = fold_builtin_varargs (loc, fndecl, exp, false);
c2f47e15 11364 return ret ? ret : exp;
11365 }
11366 }
11367
389dd41b 11368 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 11369}
11370
af1409ad 11371/* Construct a new CALL_EXPR using the tail of the argument list of EXP
11372 along with N new arguments specified as the "..." parameters. SKIP
11373 is the number of arguments in EXP to be omitted. This function is used
11374 to do varargs-to-varargs transformations. */
11375
11376static tree
11377rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...)
11378{
11379 va_list ap;
11380 tree t;
11381
11382 va_start (ap, n);
11383 t = rewrite_call_expr_valist (loc, call_expr_nargs (exp),
11384 CALL_EXPR_ARGP (exp), skip, fndecl, n, ap);
11385 va_end (ap);
c2f47e15 11386
af1409ad 11387 return t;
c2f47e15 11388}
11389
11390/* Validate a single argument ARG against a tree code CODE representing
11391 a type. */
48e1416a 11392
c2f47e15 11393static bool
b7bf20db 11394validate_arg (const_tree arg, enum tree_code code)
c2f47e15 11395{
11396 if (!arg)
11397 return false;
11398 else if (code == POINTER_TYPE)
11399 return POINTER_TYPE_P (TREE_TYPE (arg));
c7f617c2 11400 else if (code == INTEGER_TYPE)
11401 return INTEGRAL_TYPE_P (TREE_TYPE (arg));
c2f47e15 11402 return code == TREE_CODE (TREE_TYPE (arg));
7e15618b 11403}
0eb671f7 11404
75a70cf9 11405/* This function validates the types of a function call argument list
11406 against a specified list of tree_codes. If the last specifier is a 0,
11407 that represents an ellipses, otherwise the last specifier must be a
11408 VOID_TYPE.
11409
11410 This is the GIMPLE version of validate_arglist. Eventually we want to
11411 completely convert builtins.c to work from GIMPLEs and the tree based
11412 validate_arglist will then be removed. */
11413
11414bool
11415validate_gimple_arglist (const_gimple call, ...)
11416{
11417 enum tree_code code;
11418 bool res = 0;
11419 va_list ap;
11420 const_tree arg;
11421 size_t i;
11422
11423 va_start (ap, call);
11424 i = 0;
11425
11426 do
11427 {
d62e827b 11428 code = (enum tree_code) va_arg (ap, int);
75a70cf9 11429 switch (code)
11430 {
11431 case 0:
11432 /* This signifies an ellipses, any further arguments are all ok. */
11433 res = true;
11434 goto end;
11435 case VOID_TYPE:
11436 /* This signifies an endlink, if no arguments remain, return
11437 true, otherwise return false. */
11438 res = (i == gimple_call_num_args (call));
11439 goto end;
11440 default:
11441 /* If no parameters remain or the parameter's code does not
11442 match the specified code, return false. Otherwise continue
11443 checking any remaining arguments. */
11444 arg = gimple_call_arg (call, i++);
11445 if (!validate_arg (arg, code))
11446 goto end;
11447 break;
11448 }
11449 }
11450 while (1);
11451
11452 /* We need gotos here since we can only have one VA_CLOSE in a
11453 function. */
11454 end: ;
11455 va_end (ap);
11456
11457 return res;
11458}
11459
fc2a2dcb 11460/* Default target-specific builtin expander that does nothing. */
11461
11462rtx
aecda0d6 11463default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
11464 rtx target ATTRIBUTE_UNUSED,
11465 rtx subtarget ATTRIBUTE_UNUSED,
11466 enum machine_mode mode ATTRIBUTE_UNUSED,
11467 int ignore ATTRIBUTE_UNUSED)
fc2a2dcb 11468{
11469 return NULL_RTX;
11470}
c7926a82 11471
01537105 11472/* Returns true is EXP represents data that would potentially reside
11473 in a readonly section. */
11474
11475static bool
11476readonly_data_expr (tree exp)
11477{
11478 STRIP_NOPS (exp);
11479
9ff0637e 11480 if (TREE_CODE (exp) != ADDR_EXPR)
11481 return false;
11482
11483 exp = get_base_address (TREE_OPERAND (exp, 0));
11484 if (!exp)
11485 return false;
11486
11487 /* Make sure we call decl_readonly_section only for trees it
11488 can handle (since it returns true for everything it doesn't
11489 understand). */
491e04ef 11490 if (TREE_CODE (exp) == STRING_CST
9ff0637e 11491 || TREE_CODE (exp) == CONSTRUCTOR
11492 || (TREE_CODE (exp) == VAR_DECL && TREE_STATIC (exp)))
11493 return decl_readonly_section (exp, 0);
01537105 11494 else
11495 return false;
11496}
4ee9c684 11497
c2f47e15 11498/* Simplify a call to the strstr builtin. S1 and S2 are the arguments
11499 to the call, and TYPE is its return type.
4ee9c684 11500
c2f47e15 11501 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11502 simplified form of the call as a tree.
11503
11504 The simplified form may be a constant or other expression which
11505 computes the same value, but in a more efficient manner (including
11506 calls to other builtin functions).
11507
11508 The call may contain arguments which need to be evaluated, but
11509 which are not useful to determine the result of the call. In
11510 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11511 COMPOUND_EXPR will be an argument which must be evaluated.
11512 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11513 COMPOUND_EXPR in the chain will contain the tree for the simplified
11514 form of the builtin function call. */
11515
11516static tree
389dd41b 11517fold_builtin_strstr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11518{
c2f47e15 11519 if (!validate_arg (s1, POINTER_TYPE)
11520 || !validate_arg (s2, POINTER_TYPE))
11521 return NULL_TREE;
4ee9c684 11522 else
11523 {
4ee9c684 11524 tree fn;
11525 const char *p1, *p2;
11526
11527 p2 = c_getstr (s2);
11528 if (p2 == NULL)
c2f47e15 11529 return NULL_TREE;
4ee9c684 11530
11531 p1 = c_getstr (s1);
11532 if (p1 != NULL)
11533 {
11534 const char *r = strstr (p1, p2);
daa1d5f5 11535 tree tem;
4ee9c684 11536
4ee9c684 11537 if (r == NULL)
779b4c41 11538 return build_int_cst (TREE_TYPE (s1), 0);
c0c67e38 11539
11540 /* Return an offset into the constant string argument. */
2cc66f2a 11541 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11542 return fold_convert_loc (loc, type, tem);
4ee9c684 11543 }
11544
7efa231c 11545 /* The argument is const char *, and the result is char *, so we need
11546 a type conversion here to avoid a warning. */
4ee9c684 11547 if (p2[0] == '\0')
389dd41b 11548 return fold_convert_loc (loc, type, s1);
4ee9c684 11549
11550 if (p2[1] != '\0')
c2f47e15 11551 return NULL_TREE;
4ee9c684 11552
b9a16870 11553 fn = builtin_decl_implicit (BUILT_IN_STRCHR);
4ee9c684 11554 if (!fn)
c2f47e15 11555 return NULL_TREE;
4ee9c684 11556
11557 /* New argument list transforming strstr(s1, s2) to
11558 strchr(s1, s2[0]). */
7002a1c8 11559 return build_call_expr_loc (loc, fn, 2, s1,
11560 build_int_cst (integer_type_node, p2[0]));
4ee9c684 11561 }
11562}
11563
c2f47e15 11564/* Simplify a call to the strchr builtin. S1 and S2 are the arguments to
11565 the call, and TYPE is its return type.
4ee9c684 11566
c2f47e15 11567 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11568 simplified form of the call as a tree.
11569
11570 The simplified form may be a constant or other expression which
11571 computes the same value, but in a more efficient manner (including
11572 calls to other builtin functions).
11573
11574 The call may contain arguments which need to be evaluated, but
11575 which are not useful to determine the result of the call. In
11576 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11577 COMPOUND_EXPR will be an argument which must be evaluated.
11578 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11579 COMPOUND_EXPR in the chain will contain the tree for the simplified
11580 form of the builtin function call. */
11581
11582static tree
389dd41b 11583fold_builtin_strchr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11584{
c2f47e15 11585 if (!validate_arg (s1, POINTER_TYPE)
11586 || !validate_arg (s2, INTEGER_TYPE))
11587 return NULL_TREE;
4ee9c684 11588 else
11589 {
4ee9c684 11590 const char *p1;
11591
11592 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 11593 return NULL_TREE;
4ee9c684 11594
11595 p1 = c_getstr (s1);
11596 if (p1 != NULL)
11597 {
11598 char c;
11599 const char *r;
daa1d5f5 11600 tree tem;
4ee9c684 11601
11602 if (target_char_cast (s2, &c))
c2f47e15 11603 return NULL_TREE;
4ee9c684 11604
11605 r = strchr (p1, c);
11606
11607 if (r == NULL)
779b4c41 11608 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11609
11610 /* Return an offset into the constant string argument. */
2cc66f2a 11611 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11612 return fold_convert_loc (loc, type, tem);
4ee9c684 11613 }
c2f47e15 11614 return NULL_TREE;
4ee9c684 11615 }
11616}
11617
c2f47e15 11618/* Simplify a call to the strrchr builtin. S1 and S2 are the arguments to
11619 the call, and TYPE is its return type.
4ee9c684 11620
c2f47e15 11621 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11622 simplified form of the call as a tree.
11623
11624 The simplified form may be a constant or other expression which
11625 computes the same value, but in a more efficient manner (including
11626 calls to other builtin functions).
11627
11628 The call may contain arguments which need to be evaluated, but
11629 which are not useful to determine the result of the call. In
11630 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11631 COMPOUND_EXPR will be an argument which must be evaluated.
11632 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11633 COMPOUND_EXPR in the chain will contain the tree for the simplified
11634 form of the builtin function call. */
11635
11636static tree
389dd41b 11637fold_builtin_strrchr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11638{
c2f47e15 11639 if (!validate_arg (s1, POINTER_TYPE)
11640 || !validate_arg (s2, INTEGER_TYPE))
11641 return NULL_TREE;
4ee9c684 11642 else
11643 {
4ee9c684 11644 tree fn;
11645 const char *p1;
11646
11647 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 11648 return NULL_TREE;
4ee9c684 11649
11650 p1 = c_getstr (s1);
11651 if (p1 != NULL)
11652 {
11653 char c;
11654 const char *r;
daa1d5f5 11655 tree tem;
4ee9c684 11656
11657 if (target_char_cast (s2, &c))
c2f47e15 11658 return NULL_TREE;
4ee9c684 11659
11660 r = strrchr (p1, c);
11661
11662 if (r == NULL)
779b4c41 11663 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11664
11665 /* Return an offset into the constant string argument. */
2cc66f2a 11666 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11667 return fold_convert_loc (loc, type, tem);
4ee9c684 11668 }
11669
11670 if (! integer_zerop (s2))
c2f47e15 11671 return NULL_TREE;
4ee9c684 11672
b9a16870 11673 fn = builtin_decl_implicit (BUILT_IN_STRCHR);
4ee9c684 11674 if (!fn)
c2f47e15 11675 return NULL_TREE;
4ee9c684 11676
11677 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
389dd41b 11678 return build_call_expr_loc (loc, fn, 2, s1, s2);
4ee9c684 11679 }
11680}
11681
c2f47e15 11682/* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments
11683 to the call, and TYPE is its return type.
4ee9c684 11684
c2f47e15 11685 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11686 simplified form of the call as a tree.
11687
11688 The simplified form may be a constant or other expression which
11689 computes the same value, but in a more efficient manner (including
11690 calls to other builtin functions).
11691
11692 The call may contain arguments which need to be evaluated, but
11693 which are not useful to determine the result of the call. In
11694 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11695 COMPOUND_EXPR will be an argument which must be evaluated.
11696 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11697 COMPOUND_EXPR in the chain will contain the tree for the simplified
11698 form of the builtin function call. */
11699
11700static tree
389dd41b 11701fold_builtin_strpbrk (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11702{
c2f47e15 11703 if (!validate_arg (s1, POINTER_TYPE)
11704 || !validate_arg (s2, POINTER_TYPE))
11705 return NULL_TREE;
4ee9c684 11706 else
11707 {
4ee9c684 11708 tree fn;
11709 const char *p1, *p2;
11710
11711 p2 = c_getstr (s2);
11712 if (p2 == NULL)
c2f47e15 11713 return NULL_TREE;
4ee9c684 11714
11715 p1 = c_getstr (s1);
11716 if (p1 != NULL)
11717 {
11718 const char *r = strpbrk (p1, p2);
daa1d5f5 11719 tree tem;
4ee9c684 11720
11721 if (r == NULL)
779b4c41 11722 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11723
11724 /* Return an offset into the constant string argument. */
2cc66f2a 11725 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11726 return fold_convert_loc (loc, type, tem);
4ee9c684 11727 }
11728
11729 if (p2[0] == '\0')
05abc81b 11730 /* strpbrk(x, "") == NULL.
11731 Evaluate and ignore s1 in case it had side-effects. */
389dd41b 11732 return omit_one_operand_loc (loc, TREE_TYPE (s1), integer_zero_node, s1);
4ee9c684 11733
11734 if (p2[1] != '\0')
c2f47e15 11735 return NULL_TREE; /* Really call strpbrk. */
4ee9c684 11736
b9a16870 11737 fn = builtin_decl_implicit (BUILT_IN_STRCHR);
4ee9c684 11738 if (!fn)
c2f47e15 11739 return NULL_TREE;
4ee9c684 11740
11741 /* New argument list transforming strpbrk(s1, s2) to
11742 strchr(s1, s2[0]). */
7002a1c8 11743 return build_call_expr_loc (loc, fn, 2, s1,
11744 build_int_cst (integer_type_node, p2[0]));
4ee9c684 11745 }
11746}
11747
c2f47e15 11748/* Simplify a call to the strcat builtin. DST and SRC are the arguments
11749 to the call.
4ee9c684 11750
c2f47e15 11751 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11752 simplified form of the call as a tree.
11753
11754 The simplified form may be a constant or other expression which
11755 computes the same value, but in a more efficient manner (including
11756 calls to other builtin functions).
11757
11758 The call may contain arguments which need to be evaluated, but
11759 which are not useful to determine the result of the call. In
11760 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11761 COMPOUND_EXPR will be an argument which must be evaluated.
11762 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11763 COMPOUND_EXPR in the chain will contain the tree for the simplified
11764 form of the builtin function call. */
11765
11766static tree
389dd41b 11767fold_builtin_strcat (location_t loc ATTRIBUTE_UNUSED, tree dst, tree src)
4ee9c684 11768{
c2f47e15 11769 if (!validate_arg (dst, POINTER_TYPE)
11770 || !validate_arg (src, POINTER_TYPE))
11771 return NULL_TREE;
4ee9c684 11772 else
11773 {
4ee9c684 11774 const char *p = c_getstr (src);
11775
11776 /* If the string length is zero, return the dst parameter. */
11777 if (p && *p == '\0')
11778 return dst;
11779
a65c4d64 11780 if (optimize_insn_for_speed_p ())
11781 {
11782 /* See if we can store by pieces into (dst + strlen(dst)). */
11783 tree newdst, call;
b9a16870 11784 tree strlen_fn = builtin_decl_implicit (BUILT_IN_STRLEN);
11785 tree strcpy_fn = builtin_decl_implicit (BUILT_IN_STRCPY);
a65c4d64 11786
11787 if (!strlen_fn || !strcpy_fn)
11788 return NULL_TREE;
11789
11790 /* If we don't have a movstr we don't want to emit an strcpy
11791 call. We have to do that if the length of the source string
11792 isn't computable (in that case we can use memcpy probably
48e1416a 11793 later expanding to a sequence of mov instructions). If we
a65c4d64 11794 have movstr instructions we can emit strcpy calls. */
11795 if (!HAVE_movstr)
11796 {
11797 tree len = c_strlen (src, 1);
11798 if (! len || TREE_SIDE_EFFECTS (len))
11799 return NULL_TREE;
11800 }
11801
11802 /* Stabilize the argument list. */
11803 dst = builtin_save_expr (dst);
11804
11805 /* Create strlen (dst). */
11806 newdst = build_call_expr_loc (loc, strlen_fn, 1, dst);
11807 /* Create (dst p+ strlen (dst)). */
11808
2cc66f2a 11809 newdst = fold_build_pointer_plus_loc (loc, dst, newdst);
a65c4d64 11810 newdst = builtin_save_expr (newdst);
11811
11812 call = build_call_expr_loc (loc, strcpy_fn, 2, newdst, src);
11813 return build2 (COMPOUND_EXPR, TREE_TYPE (dst), call, dst);
11814 }
c2f47e15 11815 return NULL_TREE;
4ee9c684 11816 }
11817}
11818
c2f47e15 11819/* Simplify a call to the strncat builtin. DST, SRC, and LEN are the
11820 arguments to the call.
4ee9c684 11821
c2f47e15 11822 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11823 simplified form of the call as a tree.
11824
11825 The simplified form may be a constant or other expression which
11826 computes the same value, but in a more efficient manner (including
11827 calls to other builtin functions).
11828
11829 The call may contain arguments which need to be evaluated, but
11830 which are not useful to determine the result of the call. In
11831 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11832 COMPOUND_EXPR will be an argument which must be evaluated.
11833 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11834 COMPOUND_EXPR in the chain will contain the tree for the simplified
11835 form of the builtin function call. */
11836
11837static tree
389dd41b 11838fold_builtin_strncat (location_t loc, tree dst, tree src, tree len)
4ee9c684 11839{
c2f47e15 11840 if (!validate_arg (dst, POINTER_TYPE)
11841 || !validate_arg (src, POINTER_TYPE)
11842 || !validate_arg (len, INTEGER_TYPE))
11843 return NULL_TREE;
4ee9c684 11844 else
11845 {
4ee9c684 11846 const char *p = c_getstr (src);
11847
11848 /* If the requested length is zero, or the src parameter string
0a39fd54 11849 length is zero, return the dst parameter. */
4ee9c684 11850 if (integer_zerop (len) || (p && *p == '\0'))
389dd41b 11851 return omit_two_operands_loc (loc, TREE_TYPE (dst), dst, src, len);
4ee9c684 11852
11853 /* If the requested len is greater than or equal to the string
a0c938f0 11854 length, call strcat. */
4ee9c684 11855 if (TREE_CODE (len) == INTEGER_CST && p
11856 && compare_tree_int (len, strlen (p)) >= 0)
11857 {
b9a16870 11858 tree fn = builtin_decl_implicit (BUILT_IN_STRCAT);
4ee9c684 11859
11860 /* If the replacement _DECL isn't initialized, don't do the
11861 transformation. */
11862 if (!fn)
c2f47e15 11863 return NULL_TREE;
4ee9c684 11864
389dd41b 11865 return build_call_expr_loc (loc, fn, 2, dst, src);
4ee9c684 11866 }
c2f47e15 11867 return NULL_TREE;
4ee9c684 11868 }
11869}
11870
c2f47e15 11871/* Simplify a call to the strspn builtin. S1 and S2 are the arguments
11872 to the call.
4ee9c684 11873
c2f47e15 11874 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11875 simplified form of the call as a tree.
11876
11877 The simplified form may be a constant or other expression which
11878 computes the same value, but in a more efficient manner (including
11879 calls to other builtin functions).
11880
11881 The call may contain arguments which need to be evaluated, but
11882 which are not useful to determine the result of the call. In
11883 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11884 COMPOUND_EXPR will be an argument which must be evaluated.
11885 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11886 COMPOUND_EXPR in the chain will contain the tree for the simplified
11887 form of the builtin function call. */
11888
11889static tree
389dd41b 11890fold_builtin_strspn (location_t loc, tree s1, tree s2)
4ee9c684 11891{
c2f47e15 11892 if (!validate_arg (s1, POINTER_TYPE)
11893 || !validate_arg (s2, POINTER_TYPE))
11894 return NULL_TREE;
4ee9c684 11895 else
11896 {
4ee9c684 11897 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11898
11899 /* If both arguments are constants, evaluate at compile-time. */
11900 if (p1 && p2)
11901 {
11902 const size_t r = strspn (p1, p2);
547b938d 11903 return build_int_cst (size_type_node, r);
4ee9c684 11904 }
11905
c2f47e15 11906 /* If either argument is "", return NULL_TREE. */
4ee9c684 11907 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9bc9f15f 11908 /* Evaluate and ignore both arguments in case either one has
11909 side-effects. */
389dd41b 11910 return omit_two_operands_loc (loc, size_type_node, size_zero_node,
9bc9f15f 11911 s1, s2);
c2f47e15 11912 return NULL_TREE;
4ee9c684 11913 }
11914}
11915
c2f47e15 11916/* Simplify a call to the strcspn builtin. S1 and S2 are the arguments
11917 to the call.
4ee9c684 11918
c2f47e15 11919 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11920 simplified form of the call as a tree.
11921
11922 The simplified form may be a constant or other expression which
11923 computes the same value, but in a more efficient manner (including
11924 calls to other builtin functions).
11925
11926 The call may contain arguments which need to be evaluated, but
11927 which are not useful to determine the result of the call. In
11928 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11929 COMPOUND_EXPR will be an argument which must be evaluated.
11930 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11931 COMPOUND_EXPR in the chain will contain the tree for the simplified
11932 form of the builtin function call. */
11933
11934static tree
389dd41b 11935fold_builtin_strcspn (location_t loc, tree s1, tree s2)
4ee9c684 11936{
c2f47e15 11937 if (!validate_arg (s1, POINTER_TYPE)
11938 || !validate_arg (s2, POINTER_TYPE))
11939 return NULL_TREE;
4ee9c684 11940 else
11941 {
4ee9c684 11942 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11943
11944 /* If both arguments are constants, evaluate at compile-time. */
11945 if (p1 && p2)
11946 {
11947 const size_t r = strcspn (p1, p2);
547b938d 11948 return build_int_cst (size_type_node, r);
4ee9c684 11949 }
11950
c2f47e15 11951 /* If the first argument is "", return NULL_TREE. */
4ee9c684 11952 if (p1 && *p1 == '\0')
11953 {
11954 /* Evaluate and ignore argument s2 in case it has
11955 side-effects. */
389dd41b 11956 return omit_one_operand_loc (loc, size_type_node,
39761420 11957 size_zero_node, s2);
4ee9c684 11958 }
11959
11960 /* If the second argument is "", return __builtin_strlen(s1). */
11961 if (p2 && *p2 == '\0')
11962 {
b9a16870 11963 tree fn = builtin_decl_implicit (BUILT_IN_STRLEN);
4ee9c684 11964
11965 /* If the replacement _DECL isn't initialized, don't do the
11966 transformation. */
11967 if (!fn)
c2f47e15 11968 return NULL_TREE;
4ee9c684 11969
389dd41b 11970 return build_call_expr_loc (loc, fn, 1, s1);
4ee9c684 11971 }
c2f47e15 11972 return NULL_TREE;
4ee9c684 11973 }
11974}
11975
c2f47e15 11976/* Fold a call to the fputs builtin. ARG0 and ARG1 are the arguments
11977 to the call. IGNORE is true if the value returned
f0613857 11978 by the builtin will be ignored. UNLOCKED is true is true if this
11979 actually a call to fputs_unlocked. If LEN in non-NULL, it represents
11980 the known length of the string. Return NULL_TREE if no simplification
11981 was possible. */
4ee9c684 11982
11983tree
389dd41b 11984fold_builtin_fputs (location_t loc, tree arg0, tree arg1,
11985 bool ignore, bool unlocked, tree len)
4ee9c684 11986{
6d77ed92 11987 /* If we're using an unlocked function, assume the other unlocked
11988 functions exist explicitly. */
b9a16870 11989 tree const fn_fputc = (unlocked
11990 ? builtin_decl_explicit (BUILT_IN_FPUTC_UNLOCKED)
11991 : builtin_decl_implicit (BUILT_IN_FPUTC));
11992 tree const fn_fwrite = (unlocked
11993 ? builtin_decl_explicit (BUILT_IN_FWRITE_UNLOCKED)
11994 : builtin_decl_implicit (BUILT_IN_FWRITE));
4ee9c684 11995
c403edd4 11996 /* If the return value is used, don't do the transformation. */
11997 if (!ignore)
c2f47e15 11998 return NULL_TREE;
4ee9c684 11999
12000 /* Verify the arguments in the original call. */
c2f47e15 12001 if (!validate_arg (arg0, POINTER_TYPE)
12002 || !validate_arg (arg1, POINTER_TYPE))
12003 return NULL_TREE;
4ee9c684 12004
f0613857 12005 if (! len)
c2f47e15 12006 len = c_strlen (arg0, 0);
4ee9c684 12007
12008 /* Get the length of the string passed to fputs. If the length
12009 can't be determined, punt. */
12010 if (!len
12011 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 12012 return NULL_TREE;
4ee9c684 12013
12014 switch (compare_tree_int (len, 1))
12015 {
12016 case -1: /* length is 0, delete the call entirely . */
389dd41b 12017 return omit_one_operand_loc (loc, integer_type_node,
12018 integer_zero_node, arg1);;
05abc81b 12019
4ee9c684 12020 case 0: /* length is 1, call fputc. */
12021 {
c2f47e15 12022 const char *p = c_getstr (arg0);
4ee9c684 12023
12024 if (p != NULL)
12025 {
c2f47e15 12026 if (fn_fputc)
389dd41b 12027 return build_call_expr_loc (loc, fn_fputc, 2,
7002a1c8 12028 build_int_cst
12029 (integer_type_node, p[0]), arg1);
c2f47e15 12030 else
12031 return NULL_TREE;
4ee9c684 12032 }
12033 }
12034 /* FALLTHROUGH */
12035 case 1: /* length is greater than 1, call fwrite. */
12036 {
0bed3869 12037 /* If optimizing for size keep fputs. */
0bfd8d5c 12038 if (optimize_function_for_size_p (cfun))
c2f47e15 12039 return NULL_TREE;
4ee9c684 12040 /* New argument list transforming fputs(string, stream) to
12041 fwrite(string, 1, len, stream). */
c2f47e15 12042 if (fn_fwrite)
389dd41b 12043 return build_call_expr_loc (loc, fn_fwrite, 4, arg0,
12044 size_one_node, len, arg1);
c2f47e15 12045 else
12046 return NULL_TREE;
4ee9c684 12047 }
12048 default:
64db345d 12049 gcc_unreachable ();
4ee9c684 12050 }
c2f47e15 12051 return NULL_TREE;
4ee9c684 12052}
12053
c2f47e15 12054/* Fold the next_arg or va_start call EXP. Returns true if there was an error
743b0c6a 12055 produced. False otherwise. This is done so that we don't output the error
12056 or warning twice or three times. */
75a70cf9 12057
743b0c6a 12058bool
c2f47e15 12059fold_builtin_next_arg (tree exp, bool va_start_p)
4ee9c684 12060{
12061 tree fntype = TREE_TYPE (current_function_decl);
c2f47e15 12062 int nargs = call_expr_nargs (exp);
12063 tree arg;
d98fd4a4 12064 /* There is good chance the current input_location points inside the
12065 definition of the va_start macro (perhaps on the token for
12066 builtin) in a system header, so warnings will not be emitted.
12067 Use the location in real source code. */
12068 source_location current_location =
12069 linemap_unwind_to_first_non_reserved_loc (line_table, input_location,
12070 NULL);
4ee9c684 12071
257d99c3 12072 if (!stdarg_p (fntype))
743b0c6a 12073 {
12074 error ("%<va_start%> used in function with fixed args");
12075 return true;
12076 }
c2f47e15 12077
12078 if (va_start_p)
79012a9d 12079 {
c2f47e15 12080 if (va_start_p && (nargs != 2))
12081 {
12082 error ("wrong number of arguments to function %<va_start%>");
12083 return true;
12084 }
12085 arg = CALL_EXPR_ARG (exp, 1);
79012a9d 12086 }
12087 /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
12088 when we checked the arguments and if needed issued a warning. */
c2f47e15 12089 else
4ee9c684 12090 {
c2f47e15 12091 if (nargs == 0)
12092 {
12093 /* Evidently an out of date version of <stdarg.h>; can't validate
12094 va_start's second argument, but can still work as intended. */
d98fd4a4 12095 warning_at (current_location,
7edb1062 12096 OPT_Wvarargs,
12097 "%<__builtin_next_arg%> called without an argument");
c2f47e15 12098 return true;
12099 }
12100 else if (nargs > 1)
a0c938f0 12101 {
c2f47e15 12102 error ("wrong number of arguments to function %<__builtin_next_arg%>");
a0c938f0 12103 return true;
12104 }
c2f47e15 12105 arg = CALL_EXPR_ARG (exp, 0);
12106 }
12107
a8dd994c 12108 if (TREE_CODE (arg) == SSA_NAME)
12109 arg = SSA_NAME_VAR (arg);
12110
c2f47e15 12111 /* We destructively modify the call to be __builtin_va_start (ap, 0)
48e1416a 12112 or __builtin_next_arg (0) the first time we see it, after checking
c2f47e15 12113 the arguments and if needed issuing a warning. */
12114 if (!integer_zerop (arg))
12115 {
12116 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
79012a9d 12117
4ee9c684 12118 /* Strip off all nops for the sake of the comparison. This
12119 is not quite the same as STRIP_NOPS. It does more.
12120 We must also strip off INDIRECT_EXPR for C++ reference
12121 parameters. */
72dd6141 12122 while (CONVERT_EXPR_P (arg)
4ee9c684 12123 || TREE_CODE (arg) == INDIRECT_REF)
12124 arg = TREE_OPERAND (arg, 0);
12125 if (arg != last_parm)
a0c938f0 12126 {
b08cf617 12127 /* FIXME: Sometimes with the tree optimizers we can get the
12128 not the last argument even though the user used the last
12129 argument. We just warn and set the arg to be the last
12130 argument so that we will get wrong-code because of
12131 it. */
d98fd4a4 12132 warning_at (current_location,
7edb1062 12133 OPT_Wvarargs,
d98fd4a4 12134 "second parameter of %<va_start%> not last named argument");
743b0c6a 12135 }
24158ad7 12136
12137 /* Undefined by C99 7.15.1.4p4 (va_start):
12138 "If the parameter parmN is declared with the register storage
12139 class, with a function or array type, or with a type that is
12140 not compatible with the type that results after application of
12141 the default argument promotions, the behavior is undefined."
12142 */
12143 else if (DECL_REGISTER (arg))
d98fd4a4 12144 {
12145 warning_at (current_location,
7edb1062 12146 OPT_Wvarargs,
d98fd4a4 12147 "undefined behaviour when second parameter of "
12148 "%<va_start%> is declared with %<register%> storage");
12149 }
24158ad7 12150
79012a9d 12151 /* We want to verify the second parameter just once before the tree
a0c938f0 12152 optimizers are run and then avoid keeping it in the tree,
12153 as otherwise we could warn even for correct code like:
12154 void foo (int i, ...)
12155 { va_list ap; i++; va_start (ap, i); va_end (ap); } */
c2f47e15 12156 if (va_start_p)
12157 CALL_EXPR_ARG (exp, 1) = integer_zero_node;
12158 else
12159 CALL_EXPR_ARG (exp, 0) = integer_zero_node;
743b0c6a 12160 }
12161 return false;
4ee9c684 12162}
12163
12164
c2f47e15 12165/* Simplify a call to the sprintf builtin with arguments DEST, FMT, and ORIG.
12166 ORIG may be null if this is a 2-argument call. We don't attempt to
12167 simplify calls with more than 3 arguments.
4ee9c684 12168
c2f47e15 12169 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 12170 simplified form of the call as a tree. If IGNORED is true, it means that
12171 the caller does not use the returned value of the function. */
12172
12173static tree
389dd41b 12174fold_builtin_sprintf (location_t loc, tree dest, tree fmt,
12175 tree orig, int ignored)
4ee9c684 12176{
c2f47e15 12177 tree call, retval;
4ee9c684 12178 const char *fmt_str = NULL;
12179
12180 /* Verify the required arguments in the original call. We deal with two
12181 types of sprintf() calls: 'sprintf (str, fmt)' and
12182 'sprintf (dest, "%s", orig)'. */
c2f47e15 12183 if (!validate_arg (dest, POINTER_TYPE)
12184 || !validate_arg (fmt, POINTER_TYPE))
12185 return NULL_TREE;
12186 if (orig && !validate_arg (orig, POINTER_TYPE))
4ee9c684 12187 return NULL_TREE;
4ee9c684 12188
12189 /* Check whether the format is a literal string constant. */
12190 fmt_str = c_getstr (fmt);
12191 if (fmt_str == NULL)
12192 return NULL_TREE;
12193
12194 call = NULL_TREE;
12195 retval = NULL_TREE;
12196
d4473c84 12197 if (!init_target_chars ())
c2f47e15 12198 return NULL_TREE;
99eabcc1 12199
4ee9c684 12200 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 12201 if (strchr (fmt_str, target_percent) == NULL)
4ee9c684 12202 {
b9a16870 12203 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
4ee9c684 12204
12205 if (!fn)
12206 return NULL_TREE;
12207
72dfb3f2 12208 /* Don't optimize sprintf (buf, "abc", ptr++). */
c2f47e15 12209 if (orig)
72dfb3f2 12210 return NULL_TREE;
12211
4ee9c684 12212 /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
12213 'format' is known to contain no % formats. */
389dd41b 12214 call = build_call_expr_loc (loc, fn, 2, dest, fmt);
4ee9c684 12215 if (!ignored)
7002a1c8 12216 retval = build_int_cst (integer_type_node, strlen (fmt_str));
4ee9c684 12217 }
12218
12219 /* If the format is "%s", use strcpy if the result isn't used. */
99eabcc1 12220 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
4ee9c684 12221 {
c2f47e15 12222 tree fn;
b9a16870 12223 fn = builtin_decl_implicit (BUILT_IN_STRCPY);
4ee9c684 12224
12225 if (!fn)
12226 return NULL_TREE;
12227
72dfb3f2 12228 /* Don't crash on sprintf (str1, "%s"). */
c2f47e15 12229 if (!orig)
72dfb3f2 12230 return NULL_TREE;
12231
4ee9c684 12232 /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2). */
4ee9c684 12233 if (!ignored)
12234 {
12235 retval = c_strlen (orig, 1);
12236 if (!retval || TREE_CODE (retval) != INTEGER_CST)
12237 return NULL_TREE;
12238 }
389dd41b 12239 call = build_call_expr_loc (loc, fn, 2, dest, orig);
4ee9c684 12240 }
12241
12242 if (call && retval)
12243 {
389dd41b 12244 retval = fold_convert_loc
b9a16870 12245 (loc, TREE_TYPE (TREE_TYPE (builtin_decl_implicit (BUILT_IN_SPRINTF))),
4ee9c684 12246 retval);
05abc81b 12247 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
4ee9c684 12248 }
12249 else
12250 return call;
12251}
0a39fd54 12252
750d7b16 12253/* Simplify a call to the snprintf builtin with arguments DEST, DESTSIZE,
12254 FMT, and ORIG. ORIG may be null if this is a 3-argument call. We don't
12255 attempt to simplify calls with more than 4 arguments.
12256
12257 Return NULL_TREE if no simplification was possible, otherwise return the
12258 simplified form of the call as a tree. If IGNORED is true, it means that
12259 the caller does not use the returned value of the function. */
12260
12261static tree
12262fold_builtin_snprintf (location_t loc, tree dest, tree destsize, tree fmt,
12263 tree orig, int ignored)
12264{
12265 tree call, retval;
12266 const char *fmt_str = NULL;
12267 unsigned HOST_WIDE_INT destlen;
12268
12269 /* Verify the required arguments in the original call. We deal with two
12270 types of snprintf() calls: 'snprintf (str, cst, fmt)' and
12271 'snprintf (dest, cst, "%s", orig)'. */
12272 if (!validate_arg (dest, POINTER_TYPE)
12273 || !validate_arg (destsize, INTEGER_TYPE)
12274 || !validate_arg (fmt, POINTER_TYPE))
12275 return NULL_TREE;
12276 if (orig && !validate_arg (orig, POINTER_TYPE))
12277 return NULL_TREE;
12278
cd4547bf 12279 if (!tree_fits_uhwi_p (destsize))
750d7b16 12280 return NULL_TREE;
12281
12282 /* Check whether the format is a literal string constant. */
12283 fmt_str = c_getstr (fmt);
12284 if (fmt_str == NULL)
12285 return NULL_TREE;
12286
12287 call = NULL_TREE;
12288 retval = NULL_TREE;
12289
12290 if (!init_target_chars ())
12291 return NULL_TREE;
12292
6a0712d4 12293 destlen = tree_to_uhwi (destsize);
750d7b16 12294
12295 /* If the format doesn't contain % args or %%, use strcpy. */
12296 if (strchr (fmt_str, target_percent) == NULL)
12297 {
b9a16870 12298 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
750d7b16 12299 size_t len = strlen (fmt_str);
12300
12301 /* Don't optimize snprintf (buf, 4, "abc", ptr++). */
12302 if (orig)
12303 return NULL_TREE;
12304
12305 /* We could expand this as
12306 memcpy (str, fmt, cst - 1); str[cst - 1] = '\0';
12307 or to
12308 memcpy (str, fmt_with_nul_at_cstm1, cst);
12309 but in the former case that might increase code size
12310 and in the latter case grow .rodata section too much.
12311 So punt for now. */
12312 if (len >= destlen)
12313 return NULL_TREE;
12314
12315 if (!fn)
12316 return NULL_TREE;
12317
12318 /* Convert snprintf (str, cst, fmt) into strcpy (str, fmt) when
12319 'format' is known to contain no % formats and
12320 strlen (fmt) < cst. */
12321 call = build_call_expr_loc (loc, fn, 2, dest, fmt);
12322
12323 if (!ignored)
7002a1c8 12324 retval = build_int_cst (integer_type_node, strlen (fmt_str));
750d7b16 12325 }
12326
12327 /* If the format is "%s", use strcpy if the result isn't used. */
12328 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
12329 {
b9a16870 12330 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
750d7b16 12331 unsigned HOST_WIDE_INT origlen;
12332
12333 /* Don't crash on snprintf (str1, cst, "%s"). */
12334 if (!orig)
12335 return NULL_TREE;
12336
12337 retval = c_strlen (orig, 1);
cd4547bf 12338 if (!retval || !tree_fits_uhwi_p (retval))
750d7b16 12339 return NULL_TREE;
12340
6a0712d4 12341 origlen = tree_to_uhwi (retval);
750d7b16 12342 /* We could expand this as
12343 memcpy (str1, str2, cst - 1); str1[cst - 1] = '\0';
12344 or to
12345 memcpy (str1, str2_with_nul_at_cstm1, cst);
12346 but in the former case that might increase code size
12347 and in the latter case grow .rodata section too much.
12348 So punt for now. */
12349 if (origlen >= destlen)
12350 return NULL_TREE;
12351
12352 /* Convert snprintf (str1, cst, "%s", str2) into
12353 strcpy (str1, str2) if strlen (str2) < cst. */
12354 if (!fn)
12355 return NULL_TREE;
12356
12357 call = build_call_expr_loc (loc, fn, 2, dest, orig);
12358
12359 if (ignored)
12360 retval = NULL_TREE;
12361 }
12362
12363 if (call && retval)
12364 {
b9a16870 12365 tree fn = builtin_decl_explicit (BUILT_IN_SNPRINTF);
1914d98e 12366 retval = fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fn)), retval);
750d7b16 12367 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
12368 }
12369 else
12370 return call;
12371}
12372
c2f47e15 12373/* Expand a call EXP to __builtin_object_size. */
0a39fd54 12374
12375rtx
12376expand_builtin_object_size (tree exp)
12377{
12378 tree ost;
12379 int object_size_type;
12380 tree fndecl = get_callee_fndecl (exp);
0a39fd54 12381
c2f47e15 12382 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
0a39fd54 12383 {
b8c23db3 12384 error ("%Kfirst argument of %D must be a pointer, second integer constant",
12385 exp, fndecl);
0a39fd54 12386 expand_builtin_trap ();
12387 return const0_rtx;
12388 }
12389
c2f47e15 12390 ost = CALL_EXPR_ARG (exp, 1);
0a39fd54 12391 STRIP_NOPS (ost);
12392
12393 if (TREE_CODE (ost) != INTEGER_CST
12394 || tree_int_cst_sgn (ost) < 0
12395 || compare_tree_int (ost, 3) > 0)
12396 {
b8c23db3 12397 error ("%Klast argument of %D is not integer constant between 0 and 3",
12398 exp, fndecl);
0a39fd54 12399 expand_builtin_trap ();
12400 return const0_rtx;
12401 }
12402
fcb97e84 12403 object_size_type = tree_to_shwi (ost);
0a39fd54 12404
12405 return object_size_type < 2 ? constm1_rtx : const0_rtx;
12406}
12407
12408/* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
12409 FCODE is the BUILT_IN_* to use.
c2f47e15 12410 Return NULL_RTX if we failed; the caller should emit a normal call,
0a39fd54 12411 otherwise try to get the result in TARGET, if convenient (and in
12412 mode MODE if that's convenient). */
12413
12414static rtx
12415expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
12416 enum built_in_function fcode)
12417{
0a39fd54 12418 tree dest, src, len, size;
12419
c2f47e15 12420 if (!validate_arglist (exp,
0a39fd54 12421 POINTER_TYPE,
12422 fcode == BUILT_IN_MEMSET_CHK
12423 ? INTEGER_TYPE : POINTER_TYPE,
12424 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
c2f47e15 12425 return NULL_RTX;
0a39fd54 12426
c2f47e15 12427 dest = CALL_EXPR_ARG (exp, 0);
12428 src = CALL_EXPR_ARG (exp, 1);
12429 len = CALL_EXPR_ARG (exp, 2);
12430 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 12431
cd4547bf 12432 if (! tree_fits_uhwi_p (size))
c2f47e15 12433 return NULL_RTX;
0a39fd54 12434
cd4547bf 12435 if (tree_fits_uhwi_p (len) || integer_all_onesp (size))
0a39fd54 12436 {
12437 tree fn;
12438
12439 if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
12440 {
b430e8d9 12441 warning_at (tree_nonartificial_location (exp),
12442 0, "%Kcall to %D will always overflow destination buffer",
12443 exp, get_callee_fndecl (exp));
c2f47e15 12444 return NULL_RTX;
0a39fd54 12445 }
12446
0a39fd54 12447 fn = NULL_TREE;
12448 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
12449 mem{cpy,pcpy,move,set} is available. */
12450 switch (fcode)
12451 {
12452 case BUILT_IN_MEMCPY_CHK:
b9a16870 12453 fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
0a39fd54 12454 break;
12455 case BUILT_IN_MEMPCPY_CHK:
b9a16870 12456 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
0a39fd54 12457 break;
12458 case BUILT_IN_MEMMOVE_CHK:
b9a16870 12459 fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
0a39fd54 12460 break;
12461 case BUILT_IN_MEMSET_CHK:
b9a16870 12462 fn = builtin_decl_explicit (BUILT_IN_MEMSET);
0a39fd54 12463 break;
12464 default:
12465 break;
12466 }
12467
12468 if (! fn)
c2f47e15 12469 return NULL_RTX;
0a39fd54 12470
0568e9c1 12471 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 3, dest, src, len);
a65c4d64 12472 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
12473 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0a39fd54 12474 return expand_expr (fn, target, mode, EXPAND_NORMAL);
12475 }
12476 else if (fcode == BUILT_IN_MEMSET_CHK)
c2f47e15 12477 return NULL_RTX;
0a39fd54 12478 else
12479 {
957d0361 12480 unsigned int dest_align = get_pointer_alignment (dest);
0a39fd54 12481
12482 /* If DEST is not a pointer type, call the normal function. */
12483 if (dest_align == 0)
c2f47e15 12484 return NULL_RTX;
0a39fd54 12485
12486 /* If SRC and DEST are the same (and not volatile), do nothing. */
12487 if (operand_equal_p (src, dest, 0))
12488 {
12489 tree expr;
12490
12491 if (fcode != BUILT_IN_MEMPCPY_CHK)
12492 {
12493 /* Evaluate and ignore LEN in case it has side-effects. */
12494 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
12495 return expand_expr (dest, target, mode, EXPAND_NORMAL);
12496 }
12497
2cc66f2a 12498 expr = fold_build_pointer_plus (dest, len);
0a39fd54 12499 return expand_expr (expr, target, mode, EXPAND_NORMAL);
12500 }
12501
12502 /* __memmove_chk special case. */
12503 if (fcode == BUILT_IN_MEMMOVE_CHK)
12504 {
957d0361 12505 unsigned int src_align = get_pointer_alignment (src);
0a39fd54 12506
12507 if (src_align == 0)
c2f47e15 12508 return NULL_RTX;
0a39fd54 12509
12510 /* If src is categorized for a readonly section we can use
12511 normal __memcpy_chk. */
12512 if (readonly_data_expr (src))
12513 {
b9a16870 12514 tree fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
0a39fd54 12515 if (!fn)
c2f47e15 12516 return NULL_RTX;
0568e9c1 12517 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 4,
12518 dest, src, len, size);
a65c4d64 12519 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
12520 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0a39fd54 12521 return expand_expr (fn, target, mode, EXPAND_NORMAL);
12522 }
12523 }
c2f47e15 12524 return NULL_RTX;
0a39fd54 12525 }
12526}
12527
12528/* Emit warning if a buffer overflow is detected at compile time. */
12529
12530static void
12531maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
12532{
c2f47e15 12533 int is_strlen = 0;
0a39fd54 12534 tree len, size;
b430e8d9 12535 location_t loc = tree_nonartificial_location (exp);
0a39fd54 12536
12537 switch (fcode)
12538 {
12539 case BUILT_IN_STRCPY_CHK:
12540 case BUILT_IN_STPCPY_CHK:
12541 /* For __strcat_chk the warning will be emitted only if overflowing
12542 by at least strlen (dest) + 1 bytes. */
12543 case BUILT_IN_STRCAT_CHK:
c2f47e15 12544 len = CALL_EXPR_ARG (exp, 1);
12545 size = CALL_EXPR_ARG (exp, 2);
0a39fd54 12546 is_strlen = 1;
12547 break;
b356dfef 12548 case BUILT_IN_STRNCAT_CHK:
0a39fd54 12549 case BUILT_IN_STRNCPY_CHK:
1063acde 12550 case BUILT_IN_STPNCPY_CHK:
c2f47e15 12551 len = CALL_EXPR_ARG (exp, 2);
12552 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 12553 break;
12554 case BUILT_IN_SNPRINTF_CHK:
12555 case BUILT_IN_VSNPRINTF_CHK:
c2f47e15 12556 len = CALL_EXPR_ARG (exp, 1);
12557 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 12558 break;
12559 default:
12560 gcc_unreachable ();
12561 }
12562
0a39fd54 12563 if (!len || !size)
12564 return;
12565
cd4547bf 12566 if (! tree_fits_uhwi_p (size) || integer_all_onesp (size))
0a39fd54 12567 return;
12568
12569 if (is_strlen)
12570 {
12571 len = c_strlen (len, 1);
cd4547bf 12572 if (! len || ! tree_fits_uhwi_p (len) || tree_int_cst_lt (len, size))
0a39fd54 12573 return;
12574 }
b356dfef 12575 else if (fcode == BUILT_IN_STRNCAT_CHK)
12576 {
c2f47e15 12577 tree src = CALL_EXPR_ARG (exp, 1);
cd4547bf 12578 if (! src || ! tree_fits_uhwi_p (len) || tree_int_cst_lt (len, size))
b356dfef 12579 return;
12580 src = c_strlen (src, 1);
cd4547bf 12581 if (! src || ! tree_fits_uhwi_p (src))
b356dfef 12582 {
b430e8d9 12583 warning_at (loc, 0, "%Kcall to %D might overflow destination buffer",
12584 exp, get_callee_fndecl (exp));
b356dfef 12585 return;
12586 }
12587 else if (tree_int_cst_lt (src, size))
12588 return;
12589 }
cd4547bf 12590 else if (! tree_fits_uhwi_p (len) || ! tree_int_cst_lt (size, len))
0a39fd54 12591 return;
12592
b430e8d9 12593 warning_at (loc, 0, "%Kcall to %D will always overflow destination buffer",
12594 exp, get_callee_fndecl (exp));
0a39fd54 12595}
12596
12597/* Emit warning if a buffer overflow is detected at compile time
12598 in __sprintf_chk/__vsprintf_chk calls. */
12599
12600static void
12601maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
12602{
1e4adcfc 12603 tree size, len, fmt;
0a39fd54 12604 const char *fmt_str;
c2f47e15 12605 int nargs = call_expr_nargs (exp);
0a39fd54 12606
12607 /* Verify the required arguments in the original call. */
48e1416a 12608
c2f47e15 12609 if (nargs < 4)
0a39fd54 12610 return;
c2f47e15 12611 size = CALL_EXPR_ARG (exp, 2);
12612 fmt = CALL_EXPR_ARG (exp, 3);
0a39fd54 12613
cd4547bf 12614 if (! tree_fits_uhwi_p (size) || integer_all_onesp (size))
0a39fd54 12615 return;
12616
12617 /* Check whether the format is a literal string constant. */
12618 fmt_str = c_getstr (fmt);
12619 if (fmt_str == NULL)
12620 return;
12621
d4473c84 12622 if (!init_target_chars ())
99eabcc1 12623 return;
12624
0a39fd54 12625 /* If the format doesn't contain % args or %%, we know its size. */
99eabcc1 12626 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 12627 len = build_int_cstu (size_type_node, strlen (fmt_str));
12628 /* If the format is "%s" and first ... argument is a string literal,
12629 we know it too. */
c2f47e15 12630 else if (fcode == BUILT_IN_SPRINTF_CHK
12631 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12632 {
12633 tree arg;
12634
c2f47e15 12635 if (nargs < 5)
0a39fd54 12636 return;
c2f47e15 12637 arg = CALL_EXPR_ARG (exp, 4);
0a39fd54 12638 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
12639 return;
12640
12641 len = c_strlen (arg, 1);
cd4547bf 12642 if (!len || ! tree_fits_uhwi_p (len))
0a39fd54 12643 return;
12644 }
12645 else
12646 return;
12647
12648 if (! tree_int_cst_lt (len, size))
b430e8d9 12649 warning_at (tree_nonartificial_location (exp),
12650 0, "%Kcall to %D will always overflow destination buffer",
12651 exp, get_callee_fndecl (exp));
0a39fd54 12652}
12653
2c281b15 12654/* Emit warning if a free is called with address of a variable. */
12655
12656static void
12657maybe_emit_free_warning (tree exp)
12658{
12659 tree arg = CALL_EXPR_ARG (exp, 0);
12660
12661 STRIP_NOPS (arg);
12662 if (TREE_CODE (arg) != ADDR_EXPR)
12663 return;
12664
12665 arg = get_base_address (TREE_OPERAND (arg, 0));
182cf5a9 12666 if (arg == NULL || INDIRECT_REF_P (arg) || TREE_CODE (arg) == MEM_REF)
2c281b15 12667 return;
12668
12669 if (SSA_VAR_P (arg))
f74ea1c2 12670 warning_at (tree_nonartificial_location (exp), OPT_Wfree_nonheap_object,
12671 "%Kattempt to free a non-heap object %qD", exp, arg);
2c281b15 12672 else
f74ea1c2 12673 warning_at (tree_nonartificial_location (exp), OPT_Wfree_nonheap_object,
12674 "%Kattempt to free a non-heap object", exp);
2c281b15 12675}
12676
c2f47e15 12677/* Fold a call to __builtin_object_size with arguments PTR and OST,
12678 if possible. */
0a39fd54 12679
12680tree
c2f47e15 12681fold_builtin_object_size (tree ptr, tree ost)
0a39fd54 12682{
a6caa15f 12683 unsigned HOST_WIDE_INT bytes;
0a39fd54 12684 int object_size_type;
12685
c2f47e15 12686 if (!validate_arg (ptr, POINTER_TYPE)
12687 || !validate_arg (ost, INTEGER_TYPE))
12688 return NULL_TREE;
0a39fd54 12689
0a39fd54 12690 STRIP_NOPS (ost);
12691
12692 if (TREE_CODE (ost) != INTEGER_CST
12693 || tree_int_cst_sgn (ost) < 0
12694 || compare_tree_int (ost, 3) > 0)
c2f47e15 12695 return NULL_TREE;
0a39fd54 12696
fcb97e84 12697 object_size_type = tree_to_shwi (ost);
0a39fd54 12698
12699 /* __builtin_object_size doesn't evaluate side-effects in its arguments;
12700 if there are any side-effects, it returns (size_t) -1 for types 0 and 1
12701 and (size_t) 0 for types 2 and 3. */
12702 if (TREE_SIDE_EFFECTS (ptr))
697bbc3f 12703 return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
0a39fd54 12704
12705 if (TREE_CODE (ptr) == ADDR_EXPR)
a6caa15f 12706 {
12707 bytes = compute_builtin_object_size (ptr, object_size_type);
12708 if (double_int_fits_to_tree_p (size_type_node,
cf8f0e63 12709 double_int::from_uhwi (bytes)))
a6caa15f 12710 return build_int_cstu (size_type_node, bytes);
12711 }
0a39fd54 12712 else if (TREE_CODE (ptr) == SSA_NAME)
12713 {
0a39fd54 12714 /* If object size is not known yet, delay folding until
12715 later. Maybe subsequent passes will help determining
12716 it. */
12717 bytes = compute_builtin_object_size (ptr, object_size_type);
a6caa15f 12718 if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2 ? -1 : 0)
12719 && double_int_fits_to_tree_p (size_type_node,
cf8f0e63 12720 double_int::from_uhwi (bytes)))
a6caa15f 12721 return build_int_cstu (size_type_node, bytes);
0a39fd54 12722 }
12723
a6caa15f 12724 return NULL_TREE;
0a39fd54 12725}
12726
12727/* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
c2f47e15 12728 DEST, SRC, LEN, and SIZE are the arguments to the call.
0a39fd54 12729 IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_*
12730 code of the builtin. If MAXLEN is not NULL, it is maximum length
12731 passed as third argument. */
12732
12733tree
389dd41b 12734fold_builtin_memory_chk (location_t loc, tree fndecl,
c2f47e15 12735 tree dest, tree src, tree len, tree size,
12736 tree maxlen, bool ignore,
0a39fd54 12737 enum built_in_function fcode)
12738{
c2f47e15 12739 tree fn;
0a39fd54 12740
c2f47e15 12741 if (!validate_arg (dest, POINTER_TYPE)
12742 || !validate_arg (src,
12743 (fcode == BUILT_IN_MEMSET_CHK
12744 ? INTEGER_TYPE : POINTER_TYPE))
12745 || !validate_arg (len, INTEGER_TYPE)
12746 || !validate_arg (size, INTEGER_TYPE))
12747 return NULL_TREE;
0a39fd54 12748
12749 /* If SRC and DEST are the same (and not volatile), return DEST
12750 (resp. DEST+LEN for __mempcpy_chk). */
12751 if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
12752 {
12753 if (fcode != BUILT_IN_MEMPCPY_CHK)
389dd41b 12754 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
12755 dest, len);
0a39fd54 12756 else
12757 {
2cc66f2a 12758 tree temp = fold_build_pointer_plus_loc (loc, dest, len);
389dd41b 12759 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), temp);
0a39fd54 12760 }
12761 }
12762
cd4547bf 12763 if (! tree_fits_uhwi_p (size))
c2f47e15 12764 return NULL_TREE;
0a39fd54 12765
12766 if (! integer_all_onesp (size))
12767 {
cd4547bf 12768 if (! tree_fits_uhwi_p (len))
0a39fd54 12769 {
12770 /* If LEN is not constant, try MAXLEN too.
12771 For MAXLEN only allow optimizing into non-_ocs function
12772 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
cd4547bf 12773 if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen))
0a39fd54 12774 {
12775 if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
12776 {
12777 /* (void) __mempcpy_chk () can be optimized into
12778 (void) __memcpy_chk (). */
b9a16870 12779 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
0a39fd54 12780 if (!fn)
c2f47e15 12781 return NULL_TREE;
0a39fd54 12782
389dd41b 12783 return build_call_expr_loc (loc, fn, 4, dest, src, len, size);
0a39fd54 12784 }
c2f47e15 12785 return NULL_TREE;
0a39fd54 12786 }
0a39fd54 12787 }
ad89623c 12788 else
12789 maxlen = len;
0a39fd54 12790
ad89623c 12791 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12792 return NULL_TREE;
0a39fd54 12793 }
12794
0a39fd54 12795 fn = NULL_TREE;
12796 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
12797 mem{cpy,pcpy,move,set} is available. */
12798 switch (fcode)
12799 {
12800 case BUILT_IN_MEMCPY_CHK:
b9a16870 12801 fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
0a39fd54 12802 break;
12803 case BUILT_IN_MEMPCPY_CHK:
b9a16870 12804 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
0a39fd54 12805 break;
12806 case BUILT_IN_MEMMOVE_CHK:
b9a16870 12807 fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
0a39fd54 12808 break;
12809 case BUILT_IN_MEMSET_CHK:
b9a16870 12810 fn = builtin_decl_explicit (BUILT_IN_MEMSET);
0a39fd54 12811 break;
12812 default:
12813 break;
12814 }
12815
12816 if (!fn)
c2f47e15 12817 return NULL_TREE;
0a39fd54 12818
389dd41b 12819 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12820}
12821
12822/* Fold a call to the __st[rp]cpy_chk builtin.
c2f47e15 12823 DEST, SRC, and SIZE are the arguments to the call.
12824 IGNORE is true if return value can be ignored. FCODE is the BUILT_IN_*
0a39fd54 12825 code of the builtin. If MAXLEN is not NULL, it is maximum length of
12826 strings passed as second argument. */
12827
12828tree
389dd41b 12829fold_builtin_stxcpy_chk (location_t loc, tree fndecl, tree dest,
12830 tree src, tree size,
c2f47e15 12831 tree maxlen, bool ignore,
0a39fd54 12832 enum built_in_function fcode)
12833{
c2f47e15 12834 tree len, fn;
0a39fd54 12835
c2f47e15 12836 if (!validate_arg (dest, POINTER_TYPE)
12837 || !validate_arg (src, POINTER_TYPE)
12838 || !validate_arg (size, INTEGER_TYPE))
12839 return NULL_TREE;
0a39fd54 12840
12841 /* If SRC and DEST are the same (and not volatile), return DEST. */
12842 if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
389dd41b 12843 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
a0c938f0 12844
cd4547bf 12845 if (! tree_fits_uhwi_p (size))
c2f47e15 12846 return NULL_TREE;
0a39fd54 12847
12848 if (! integer_all_onesp (size))
12849 {
12850 len = c_strlen (src, 1);
cd4547bf 12851 if (! len || ! tree_fits_uhwi_p (len))
0a39fd54 12852 {
12853 /* If LEN is not constant, try MAXLEN too.
12854 For MAXLEN only allow optimizing into non-_ocs function
12855 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
cd4547bf 12856 if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen))
0a39fd54 12857 {
12858 if (fcode == BUILT_IN_STPCPY_CHK)
12859 {
12860 if (! ignore)
c2f47e15 12861 return NULL_TREE;
0a39fd54 12862
12863 /* If return value of __stpcpy_chk is ignored,
12864 optimize into __strcpy_chk. */
b9a16870 12865 fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
0a39fd54 12866 if (!fn)
c2f47e15 12867 return NULL_TREE;
0a39fd54 12868
389dd41b 12869 return build_call_expr_loc (loc, fn, 3, dest, src, size);
0a39fd54 12870 }
12871
12872 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 12873 return NULL_TREE;
0a39fd54 12874
12875 /* If c_strlen returned something, but not a constant,
12876 transform __strcpy_chk into __memcpy_chk. */
b9a16870 12877 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
0a39fd54 12878 if (!fn)
c2f47e15 12879 return NULL_TREE;
0a39fd54 12880
bd6dcc04 12881 len = fold_convert_loc (loc, size_type_node, len);
12882 len = size_binop_loc (loc, PLUS_EXPR, len,
12883 build_int_cst (size_type_node, 1));
389dd41b 12884 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
12885 build_call_expr_loc (loc, fn, 4,
12886 dest, src, len, size));
0a39fd54 12887 }
0a39fd54 12888 }
ad89623c 12889 else
12890 maxlen = len;
12891
12892 if (! tree_int_cst_lt (maxlen, size))
c2f47e15 12893 return NULL_TREE;
0a39fd54 12894 }
12895
0a39fd54 12896 /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available. */
b9a16870 12897 fn = builtin_decl_explicit (fcode == BUILT_IN_STPCPY_CHK
12898 ? BUILT_IN_STPCPY : BUILT_IN_STRCPY);
0a39fd54 12899 if (!fn)
c2f47e15 12900 return NULL_TREE;
0a39fd54 12901
389dd41b 12902 return build_call_expr_loc (loc, fn, 2, dest, src);
0a39fd54 12903}
12904
1063acde 12905/* Fold a call to the __st{r,p}ncpy_chk builtin. DEST, SRC, LEN, and SIZE
c2f47e15 12906 are the arguments to the call. If MAXLEN is not NULL, it is maximum
1063acde 12907 length passed as third argument. IGNORE is true if return value can be
12908 ignored. FCODE is the BUILT_IN_* code of the builtin. */
0a39fd54 12909
12910tree
1063acde 12911fold_builtin_stxncpy_chk (location_t loc, tree dest, tree src,
12912 tree len, tree size, tree maxlen, bool ignore,
12913 enum built_in_function fcode)
0a39fd54 12914{
c2f47e15 12915 tree fn;
0a39fd54 12916
c2f47e15 12917 if (!validate_arg (dest, POINTER_TYPE)
12918 || !validate_arg (src, POINTER_TYPE)
12919 || !validate_arg (len, INTEGER_TYPE)
12920 || !validate_arg (size, INTEGER_TYPE))
12921 return NULL_TREE;
0a39fd54 12922
1063acde 12923 if (fcode == BUILT_IN_STPNCPY_CHK && ignore)
12924 {
12925 /* If return value of __stpncpy_chk is ignored,
12926 optimize into __strncpy_chk. */
12927 fn = builtin_decl_explicit (BUILT_IN_STRNCPY_CHK);
12928 if (fn)
12929 return build_call_expr_loc (loc, fn, 4, dest, src, len, size);
12930 }
12931
cd4547bf 12932 if (! tree_fits_uhwi_p (size))
c2f47e15 12933 return NULL_TREE;
0a39fd54 12934
12935 if (! integer_all_onesp (size))
12936 {
cd4547bf 12937 if (! tree_fits_uhwi_p (len))
0a39fd54 12938 {
12939 /* If LEN is not constant, try MAXLEN too.
12940 For MAXLEN only allow optimizing into non-_ocs function
12941 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
cd4547bf 12942 if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen))
c2f47e15 12943 return NULL_TREE;
0a39fd54 12944 }
ad89623c 12945 else
12946 maxlen = len;
0a39fd54 12947
ad89623c 12948 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12949 return NULL_TREE;
0a39fd54 12950 }
12951
1063acde 12952 /* If __builtin_st{r,p}ncpy_chk is used, assume st{r,p}ncpy is available. */
12953 fn = builtin_decl_explicit (fcode == BUILT_IN_STPNCPY_CHK
12954 ? BUILT_IN_STPNCPY : BUILT_IN_STRNCPY);
0a39fd54 12955 if (!fn)
c2f47e15 12956 return NULL_TREE;
0a39fd54 12957
389dd41b 12958 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12959}
12960
c2f47e15 12961/* Fold a call to the __strcat_chk builtin FNDECL. DEST, SRC, and SIZE
12962 are the arguments to the call. */
0a39fd54 12963
12964static tree
389dd41b 12965fold_builtin_strcat_chk (location_t loc, tree fndecl, tree dest,
12966 tree src, tree size)
0a39fd54 12967{
c2f47e15 12968 tree fn;
0a39fd54 12969 const char *p;
12970
c2f47e15 12971 if (!validate_arg (dest, POINTER_TYPE)
12972 || !validate_arg (src, POINTER_TYPE)
12973 || !validate_arg (size, INTEGER_TYPE))
12974 return NULL_TREE;
0a39fd54 12975
12976 p = c_getstr (src);
12977 /* If the SRC parameter is "", return DEST. */
12978 if (p && *p == '\0')
389dd41b 12979 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
0a39fd54 12980
cd4547bf 12981 if (! tree_fits_uhwi_p (size) || ! integer_all_onesp (size))
c2f47e15 12982 return NULL_TREE;
0a39fd54 12983
12984 /* If __builtin_strcat_chk is used, assume strcat is available. */
b9a16870 12985 fn = builtin_decl_explicit (BUILT_IN_STRCAT);
0a39fd54 12986 if (!fn)
c2f47e15 12987 return NULL_TREE;
0a39fd54 12988
389dd41b 12989 return build_call_expr_loc (loc, fn, 2, dest, src);
0a39fd54 12990}
12991
c2f47e15 12992/* Fold a call to the __strncat_chk builtin with arguments DEST, SRC,
12993 LEN, and SIZE. */
0a39fd54 12994
12995static tree
389dd41b 12996fold_builtin_strncat_chk (location_t loc, tree fndecl,
c2f47e15 12997 tree dest, tree src, tree len, tree size)
0a39fd54 12998{
c2f47e15 12999 tree fn;
0a39fd54 13000 const char *p;
13001
c2f47e15 13002 if (!validate_arg (dest, POINTER_TYPE)
13003 || !validate_arg (src, POINTER_TYPE)
13004 || !validate_arg (size, INTEGER_TYPE)
13005 || !validate_arg (size, INTEGER_TYPE))
13006 return NULL_TREE;
0a39fd54 13007
13008 p = c_getstr (src);
13009 /* If the SRC parameter is "" or if LEN is 0, return DEST. */
13010 if (p && *p == '\0')
389dd41b 13011 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
0a39fd54 13012 else if (integer_zerop (len))
389dd41b 13013 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
0a39fd54 13014
cd4547bf 13015 if (! tree_fits_uhwi_p (size))
c2f47e15 13016 return NULL_TREE;
0a39fd54 13017
13018 if (! integer_all_onesp (size))
13019 {
13020 tree src_len = c_strlen (src, 1);
13021 if (src_len
cd4547bf 13022 && tree_fits_uhwi_p (src_len)
13023 && tree_fits_uhwi_p (len)
0a39fd54 13024 && ! tree_int_cst_lt (len, src_len))
13025 {
13026 /* If LEN >= strlen (SRC), optimize into __strcat_chk. */
b9a16870 13027 fn = builtin_decl_explicit (BUILT_IN_STRCAT_CHK);
0a39fd54 13028 if (!fn)
c2f47e15 13029 return NULL_TREE;
0a39fd54 13030
389dd41b 13031 return build_call_expr_loc (loc, fn, 3, dest, src, size);
0a39fd54 13032 }
c2f47e15 13033 return NULL_TREE;
0a39fd54 13034 }
13035
0a39fd54 13036 /* If __builtin_strncat_chk is used, assume strncat is available. */
b9a16870 13037 fn = builtin_decl_explicit (BUILT_IN_STRNCAT);
0a39fd54 13038 if (!fn)
c2f47e15 13039 return NULL_TREE;
0a39fd54 13040
389dd41b 13041 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 13042}
13043
af1409ad 13044/* Fold a call EXP to __{,v}sprintf_chk having NARGS passed as ARGS.
13045 Return NULL_TREE if a normal call should be emitted rather than
13046 expanding the function inline. FCODE is either BUILT_IN_SPRINTF_CHK
13047 or BUILT_IN_VSPRINTF_CHK. */
0a39fd54 13048
13049static tree
af1409ad 13050fold_builtin_sprintf_chk_1 (location_t loc, int nargs, tree *args,
13051 enum built_in_function fcode)
0a39fd54 13052{
13053 tree dest, size, len, fn, fmt, flag;
13054 const char *fmt_str;
13055
13056 /* Verify the required arguments in the original call. */
c2f47e15 13057 if (nargs < 4)
13058 return NULL_TREE;
af1409ad 13059 dest = args[0];
c2f47e15 13060 if (!validate_arg (dest, POINTER_TYPE))
13061 return NULL_TREE;
af1409ad 13062 flag = args[1];
c2f47e15 13063 if (!validate_arg (flag, INTEGER_TYPE))
13064 return NULL_TREE;
af1409ad 13065 size = args[2];
c2f47e15 13066 if (!validate_arg (size, INTEGER_TYPE))
13067 return NULL_TREE;
af1409ad 13068 fmt = args[3];
c2f47e15 13069 if (!validate_arg (fmt, POINTER_TYPE))
13070 return NULL_TREE;
0a39fd54 13071
cd4547bf 13072 if (! tree_fits_uhwi_p (size))
c2f47e15 13073 return NULL_TREE;
0a39fd54 13074
13075 len = NULL_TREE;
13076
d4473c84 13077 if (!init_target_chars ())
c2f47e15 13078 return NULL_TREE;
99eabcc1 13079
0a39fd54 13080 /* Check whether the format is a literal string constant. */
13081 fmt_str = c_getstr (fmt);
13082 if (fmt_str != NULL)
13083 {
13084 /* If the format doesn't contain % args or %%, we know the size. */
99eabcc1 13085 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 13086 {
c2f47e15 13087 if (fcode != BUILT_IN_SPRINTF_CHK || nargs == 4)
0a39fd54 13088 len = build_int_cstu (size_type_node, strlen (fmt_str));
13089 }
13090 /* If the format is "%s" and first ... argument is a string literal,
13091 we know the size too. */
c2f47e15 13092 else if (fcode == BUILT_IN_SPRINTF_CHK
13093 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 13094 {
13095 tree arg;
13096
c2f47e15 13097 if (nargs == 5)
0a39fd54 13098 {
af1409ad 13099 arg = args[4];
c2f47e15 13100 if (validate_arg (arg, POINTER_TYPE))
0a39fd54 13101 {
13102 len = c_strlen (arg, 1);
cd4547bf 13103 if (! len || ! tree_fits_uhwi_p (len))
0a39fd54 13104 len = NULL_TREE;
13105 }
13106 }
13107 }
13108 }
13109
13110 if (! integer_all_onesp (size))
13111 {
13112 if (! len || ! tree_int_cst_lt (len, size))
c2f47e15 13113 return NULL_TREE;
0a39fd54 13114 }
13115
13116 /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
13117 or if format doesn't contain % chars or is "%s". */
13118 if (! integer_zerop (flag))
13119 {
13120 if (fmt_str == NULL)
c2f47e15 13121 return NULL_TREE;
13122 if (strchr (fmt_str, target_percent) != NULL
13123 && strcmp (fmt_str, target_percent_s))
13124 return NULL_TREE;
0a39fd54 13125 }
13126
0a39fd54 13127 /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
b9a16870 13128 fn = builtin_decl_explicit (fcode == BUILT_IN_VSPRINTF_CHK
13129 ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF);
0a39fd54 13130 if (!fn)
c2f47e15 13131 return NULL_TREE;
0a39fd54 13132
af1409ad 13133 return rewrite_call_expr_array (loc, nargs, args, 4, fn, 2, dest, fmt);
0a39fd54 13134}
13135
af1409ad 13136/* Fold a call EXP to __{,v}sprintf_chk. Return NULL_TREE if
0a39fd54 13137 a normal call should be emitted rather than expanding the function
af1409ad 13138 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
13139
13140static tree
13141fold_builtin_sprintf_chk (location_t loc, tree exp,
13142 enum built_in_function fcode)
13143{
13144 return fold_builtin_sprintf_chk_1 (loc, call_expr_nargs (exp),
13145 CALL_EXPR_ARGP (exp), fcode);
13146}
13147
13148/* Fold a call EXP to {,v}snprintf having NARGS passed as ARGS. Return
13149 NULL_TREE if a normal call should be emitted rather than expanding
13150 the function inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
0a39fd54 13151 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
13152 passed as second argument. */
13153
af1409ad 13154static tree
13155fold_builtin_snprintf_chk_1 (location_t loc, int nargs, tree *args,
13156 tree maxlen, enum built_in_function fcode)
0a39fd54 13157{
13158 tree dest, size, len, fn, fmt, flag;
13159 const char *fmt_str;
13160
13161 /* Verify the required arguments in the original call. */
af1409ad 13162 if (nargs < 5)
c2f47e15 13163 return NULL_TREE;
af1409ad 13164 dest = args[0];
c2f47e15 13165 if (!validate_arg (dest, POINTER_TYPE))
13166 return NULL_TREE;
af1409ad 13167 len = args[1];
c2f47e15 13168 if (!validate_arg (len, INTEGER_TYPE))
13169 return NULL_TREE;
af1409ad 13170 flag = args[2];
c2f47e15 13171 if (!validate_arg (flag, INTEGER_TYPE))
13172 return NULL_TREE;
af1409ad 13173 size = args[3];
c2f47e15 13174 if (!validate_arg (size, INTEGER_TYPE))
13175 return NULL_TREE;
af1409ad 13176 fmt = args[4];
c2f47e15 13177 if (!validate_arg (fmt, POINTER_TYPE))
13178 return NULL_TREE;
0a39fd54 13179
cd4547bf 13180 if (! tree_fits_uhwi_p (size))
c2f47e15 13181 return NULL_TREE;
0a39fd54 13182
13183 if (! integer_all_onesp (size))
13184 {
cd4547bf 13185 if (! tree_fits_uhwi_p (len))
0a39fd54 13186 {
13187 /* If LEN is not constant, try MAXLEN too.
13188 For MAXLEN only allow optimizing into non-_ocs function
13189 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
cd4547bf 13190 if (maxlen == NULL_TREE || ! tree_fits_uhwi_p (maxlen))
c2f47e15 13191 return NULL_TREE;
0a39fd54 13192 }
ad89623c 13193 else
13194 maxlen = len;
0a39fd54 13195
ad89623c 13196 if (tree_int_cst_lt (size, maxlen))
c2f47e15 13197 return NULL_TREE;
0a39fd54 13198 }
13199
d4473c84 13200 if (!init_target_chars ())
c2f47e15 13201 return NULL_TREE;
99eabcc1 13202
0a39fd54 13203 /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
13204 or if format doesn't contain % chars or is "%s". */
13205 if (! integer_zerop (flag))
13206 {
13207 fmt_str = c_getstr (fmt);
13208 if (fmt_str == NULL)
c2f47e15 13209 return NULL_TREE;
13210 if (strchr (fmt_str, target_percent) != NULL
13211 && strcmp (fmt_str, target_percent_s))
13212 return NULL_TREE;
0a39fd54 13213 }
13214
0a39fd54 13215 /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
13216 available. */
b9a16870 13217 fn = builtin_decl_explicit (fcode == BUILT_IN_VSNPRINTF_CHK
13218 ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF);
0a39fd54 13219 if (!fn)
c2f47e15 13220 return NULL_TREE;
0a39fd54 13221
af1409ad 13222 return rewrite_call_expr_array (loc, nargs, args, 5, fn, 3, dest, len, fmt);
13223}
13224
13225/* Fold a call EXP to {,v}snprintf. Return NULL_TREE if
13226 a normal call should be emitted rather than expanding the function
13227 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
13228 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
13229 passed as second argument. */
13230
0e80b01d 13231static tree
af1409ad 13232fold_builtin_snprintf_chk (location_t loc, tree exp, tree maxlen,
13233 enum built_in_function fcode)
13234{
13235 return fold_builtin_snprintf_chk_1 (loc, call_expr_nargs (exp),
13236 CALL_EXPR_ARGP (exp), maxlen, fcode);
0a39fd54 13237}
13238
0e80b01d 13239/* Builtins with folding operations that operate on "..." arguments
13240 need special handling; we need to store the arguments in a convenient
13241 data structure before attempting any folding. Fortunately there are
13242 only a few builtins that fall into this category. FNDECL is the
13243 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
13244 result of the function call is ignored. */
13245
13246static tree
13247fold_builtin_varargs (location_t loc, tree fndecl, tree exp,
13248 bool ignore ATTRIBUTE_UNUSED)
13249{
13250 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
13251 tree ret = NULL_TREE;
13252
13253 switch (fcode)
13254 {
13255 case BUILT_IN_SPRINTF_CHK:
13256 case BUILT_IN_VSPRINTF_CHK:
13257 ret = fold_builtin_sprintf_chk (loc, exp, fcode);
13258 break;
13259
13260 case BUILT_IN_SNPRINTF_CHK:
13261 case BUILT_IN_VSNPRINTF_CHK:
13262 ret = fold_builtin_snprintf_chk (loc, exp, NULL_TREE, fcode);
13263 break;
13264
13265 case BUILT_IN_FPCLASSIFY:
13266 ret = fold_builtin_fpclassify (loc, exp);
13267 break;
13268
13269 default:
13270 break;
13271 }
13272 if (ret)
13273 {
13274 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
13275 SET_EXPR_LOCATION (ret, loc);
13276 TREE_NO_WARNING (ret) = 1;
13277 return ret;
13278 }
13279 return NULL_TREE;
13280}
13281
0a39fd54 13282/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 13283 FMT and ARG are the arguments to the call; we don't fold cases with
13284 more than 2 arguments, and ARG may be null if this is a 1-argument case.
0a39fd54 13285
c2f47e15 13286 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 13287 simplified form of the call as a tree. FCODE is the BUILT_IN_*
13288 code of the function to be simplified. */
13289
13290static tree
389dd41b 13291fold_builtin_printf (location_t loc, tree fndecl, tree fmt,
13292 tree arg, bool ignore,
0a39fd54 13293 enum built_in_function fcode)
13294{
c2f47e15 13295 tree fn_putchar, fn_puts, newarg, call = NULL_TREE;
0a39fd54 13296 const char *fmt_str = NULL;
13297
13298 /* If the return value is used, don't do the transformation. */
13299 if (! ignore)
c2f47e15 13300 return NULL_TREE;
0a39fd54 13301
13302 /* Verify the required arguments in the original call. */
c2f47e15 13303 if (!validate_arg (fmt, POINTER_TYPE))
13304 return NULL_TREE;
0a39fd54 13305
13306 /* Check whether the format is a literal string constant. */
13307 fmt_str = c_getstr (fmt);
13308 if (fmt_str == NULL)
13309 return NULL_TREE;
13310
13311 if (fcode == BUILT_IN_PRINTF_UNLOCKED)
13312 {
6d77ed92 13313 /* If we're using an unlocked function, assume the other
13314 unlocked functions exist explicitly. */
b9a16870 13315 fn_putchar = builtin_decl_explicit (BUILT_IN_PUTCHAR_UNLOCKED);
13316 fn_puts = builtin_decl_explicit (BUILT_IN_PUTS_UNLOCKED);
0a39fd54 13317 }
13318 else
13319 {
b9a16870 13320 fn_putchar = builtin_decl_implicit (BUILT_IN_PUTCHAR);
13321 fn_puts = builtin_decl_implicit (BUILT_IN_PUTS);
0a39fd54 13322 }
13323
d4473c84 13324 if (!init_target_chars ())
c2f47e15 13325 return NULL_TREE;
a0c938f0 13326
c2f47e15 13327 if (strcmp (fmt_str, target_percent_s) == 0
13328 || strchr (fmt_str, target_percent) == NULL)
0a39fd54 13329 {
13330 const char *str;
13331
99eabcc1 13332 if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 13333 {
13334 if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 13335 return NULL_TREE;
0a39fd54 13336
c2f47e15 13337 if (!arg || !validate_arg (arg, POINTER_TYPE))
13338 return NULL_TREE;
0a39fd54 13339
c2f47e15 13340 str = c_getstr (arg);
0a39fd54 13341 if (str == NULL)
c2f47e15 13342 return NULL_TREE;
0a39fd54 13343 }
13344 else
13345 {
13346 /* The format specifier doesn't contain any '%' characters. */
13347 if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
c2f47e15 13348 && arg)
13349 return NULL_TREE;
0a39fd54 13350 str = fmt_str;
13351 }
13352
13353 /* If the string was "", printf does nothing. */
13354 if (str[0] == '\0')
13355 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
13356
13357 /* If the string has length of 1, call putchar. */
13358 if (str[1] == '\0')
13359 {
13360 /* Given printf("c"), (where c is any one character,)
13361 convert "c"[0] to an int and pass that to the replacement
13362 function. */
7002a1c8 13363 newarg = build_int_cst (integer_type_node, str[0]);
c2f47e15 13364 if (fn_putchar)
389dd41b 13365 call = build_call_expr_loc (loc, fn_putchar, 1, newarg);
0a39fd54 13366 }
13367 else
13368 {
13369 /* If the string was "string\n", call puts("string"). */
13370 size_t len = strlen (str);
663dbd5e 13371 if ((unsigned char)str[len - 1] == target_newline
13372 && (size_t) (int) len == len
13373 && (int) len > 0)
0a39fd54 13374 {
663dbd5e 13375 char *newstr;
13376 tree offset_node, string_cst;
13377
0a39fd54 13378 /* Create a NUL-terminated string that's one char shorter
13379 than the original, stripping off the trailing '\n'. */
663dbd5e 13380 newarg = build_string_literal (len, str);
13381 string_cst = string_constant (newarg, &offset_node);
13382 gcc_checking_assert (string_cst
13383 && (TREE_STRING_LENGTH (string_cst)
13384 == (int) len)
13385 && integer_zerop (offset_node)
13386 && (unsigned char)
13387 TREE_STRING_POINTER (string_cst)[len - 1]
13388 == target_newline);
13389 /* build_string_literal creates a new STRING_CST,
13390 modify it in place to avoid double copying. */
13391 newstr = CONST_CAST (char *, TREE_STRING_POINTER (string_cst));
13392 newstr[len - 1] = '\0';
c2f47e15 13393 if (fn_puts)
389dd41b 13394 call = build_call_expr_loc (loc, fn_puts, 1, newarg);
0a39fd54 13395 }
13396 else
13397 /* We'd like to arrange to call fputs(string,stdout) here,
13398 but we need stdout and don't have a way to get it yet. */
c2f47e15 13399 return NULL_TREE;
0a39fd54 13400 }
13401 }
13402
13403 /* The other optimizations can be done only on the non-va_list variants. */
13404 else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 13405 return NULL_TREE;
0a39fd54 13406
13407 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
99eabcc1 13408 else if (strcmp (fmt_str, target_percent_s_newline) == 0)
0a39fd54 13409 {
c2f47e15 13410 if (!arg || !validate_arg (arg, POINTER_TYPE))
13411 return NULL_TREE;
13412 if (fn_puts)
389dd41b 13413 call = build_call_expr_loc (loc, fn_puts, 1, arg);
0a39fd54 13414 }
13415
13416 /* If the format specifier was "%c", call __builtin_putchar(arg). */
99eabcc1 13417 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 13418 {
c2f47e15 13419 if (!arg || !validate_arg (arg, INTEGER_TYPE))
13420 return NULL_TREE;
13421 if (fn_putchar)
389dd41b 13422 call = build_call_expr_loc (loc, fn_putchar, 1, arg);
0a39fd54 13423 }
13424
c2f47e15 13425 if (!call)
13426 return NULL_TREE;
0a39fd54 13427
389dd41b 13428 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
0a39fd54 13429}
13430
13431/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 13432 FP, FMT, and ARG are the arguments to the call. We don't fold calls with
13433 more than 3 arguments, and ARG may be null in the 2-argument case.
0a39fd54 13434
c2f47e15 13435 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 13436 simplified form of the call as a tree. FCODE is the BUILT_IN_*
13437 code of the function to be simplified. */
13438
13439static tree
389dd41b 13440fold_builtin_fprintf (location_t loc, tree fndecl, tree fp,
13441 tree fmt, tree arg, bool ignore,
0a39fd54 13442 enum built_in_function fcode)
13443{
c2f47e15 13444 tree fn_fputc, fn_fputs, call = NULL_TREE;
0a39fd54 13445 const char *fmt_str = NULL;
13446
13447 /* If the return value is used, don't do the transformation. */
13448 if (! ignore)
c2f47e15 13449 return NULL_TREE;
0a39fd54 13450
13451 /* Verify the required arguments in the original call. */
c2f47e15 13452 if (!validate_arg (fp, POINTER_TYPE))
13453 return NULL_TREE;
13454 if (!validate_arg (fmt, POINTER_TYPE))
13455 return NULL_TREE;
0a39fd54 13456
13457 /* Check whether the format is a literal string constant. */
13458 fmt_str = c_getstr (fmt);
13459 if (fmt_str == NULL)
13460 return NULL_TREE;
13461
13462 if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
13463 {
6d77ed92 13464 /* If we're using an unlocked function, assume the other
13465 unlocked functions exist explicitly. */
b9a16870 13466 fn_fputc = builtin_decl_explicit (BUILT_IN_FPUTC_UNLOCKED);
13467 fn_fputs = builtin_decl_explicit (BUILT_IN_FPUTS_UNLOCKED);
0a39fd54 13468 }
13469 else
13470 {
b9a16870 13471 fn_fputc = builtin_decl_implicit (BUILT_IN_FPUTC);
13472 fn_fputs = builtin_decl_implicit (BUILT_IN_FPUTS);
0a39fd54 13473 }
13474
d4473c84 13475 if (!init_target_chars ())
c2f47e15 13476 return NULL_TREE;
a0c938f0 13477
0a39fd54 13478 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 13479 if (strchr (fmt_str, target_percent) == NULL)
0a39fd54 13480 {
13481 if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
c2f47e15 13482 && arg)
13483 return NULL_TREE;
0a39fd54 13484
13485 /* If the format specifier was "", fprintf does nothing. */
13486 if (fmt_str[0] == '\0')
13487 {
13488 /* If FP has side-effects, just wait until gimplification is
13489 done. */
13490 if (TREE_SIDE_EFFECTS (fp))
c2f47e15 13491 return NULL_TREE;
0a39fd54 13492
13493 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
13494 }
13495
13496 /* When "string" doesn't contain %, replace all cases of
13497 fprintf (fp, string) with fputs (string, fp). The fputs
13498 builtin will take care of special cases like length == 1. */
c2f47e15 13499 if (fn_fputs)
389dd41b 13500 call = build_call_expr_loc (loc, fn_fputs, 2, fmt, fp);
0a39fd54 13501 }
13502
13503 /* The other optimizations can be done only on the non-va_list variants. */
13504 else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
c2f47e15 13505 return NULL_TREE;
0a39fd54 13506
13507 /* If the format specifier was "%s", call __builtin_fputs (arg, fp). */
99eabcc1 13508 else if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 13509 {
c2f47e15 13510 if (!arg || !validate_arg (arg, POINTER_TYPE))
13511 return NULL_TREE;
13512 if (fn_fputs)
389dd41b 13513 call = build_call_expr_loc (loc, fn_fputs, 2, arg, fp);
0a39fd54 13514 }
13515
13516 /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */
99eabcc1 13517 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 13518 {
c2f47e15 13519 if (!arg || !validate_arg (arg, INTEGER_TYPE))
13520 return NULL_TREE;
13521 if (fn_fputc)
389dd41b 13522 call = build_call_expr_loc (loc, fn_fputc, 2, arg, fp);
0a39fd54 13523 }
13524
c2f47e15 13525 if (!call)
13526 return NULL_TREE;
389dd41b 13527 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
0a39fd54 13528}
99eabcc1 13529
13530/* Initialize format string characters in the target charset. */
13531
13532static bool
13533init_target_chars (void)
13534{
13535 static bool init;
13536 if (!init)
13537 {
13538 target_newline = lang_hooks.to_target_charset ('\n');
13539 target_percent = lang_hooks.to_target_charset ('%');
13540 target_c = lang_hooks.to_target_charset ('c');
13541 target_s = lang_hooks.to_target_charset ('s');
13542 if (target_newline == 0 || target_percent == 0 || target_c == 0
13543 || target_s == 0)
13544 return false;
13545
13546 target_percent_c[0] = target_percent;
13547 target_percent_c[1] = target_c;
13548 target_percent_c[2] = '\0';
13549
13550 target_percent_s[0] = target_percent;
13551 target_percent_s[1] = target_s;
13552 target_percent_s[2] = '\0';
13553
13554 target_percent_s_newline[0] = target_percent;
13555 target_percent_s_newline[1] = target_s;
13556 target_percent_s_newline[2] = target_newline;
13557 target_percent_s_newline[3] = '\0';
a0c938f0 13558
99eabcc1 13559 init = true;
13560 }
13561 return true;
13562}
bffb7645 13563
f0c477f2 13564/* Helper function for do_mpfr_arg*(). Ensure M is a normal number
13565 and no overflow/underflow occurred. INEXACT is true if M was not
fa7637bd 13566 exactly calculated. TYPE is the tree type for the result. This
f0c477f2 13567 function assumes that you cleared the MPFR flags and then
13568 calculated M to see if anything subsequently set a flag prior to
13569 entering this function. Return NULL_TREE if any checks fail. */
13570
13571static tree
d4473c84 13572do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
f0c477f2 13573{
13574 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
13575 overflow/underflow occurred. If -frounding-math, proceed iff the
13576 result of calling FUNC was exact. */
d4473c84 13577 if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
f0c477f2 13578 && (!flag_rounding_math || !inexact))
13579 {
13580 REAL_VALUE_TYPE rr;
13581
66fa16e6 13582 real_from_mpfr (&rr, m, type, GMP_RNDN);
f0c477f2 13583 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
13584 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
13585 but the mpft_t is not, then we underflowed in the
13586 conversion. */
776a7bab 13587 if (real_isfinite (&rr)
f0c477f2 13588 && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
13589 {
13590 REAL_VALUE_TYPE rmode;
13591
13592 real_convert (&rmode, TYPE_MODE (type), &rr);
13593 /* Proceed iff the specified mode can hold the value. */
13594 if (real_identical (&rmode, &rr))
13595 return build_real (type, rmode);
13596 }
13597 }
13598 return NULL_TREE;
13599}
13600
239d491a 13601/* Helper function for do_mpc_arg*(). Ensure M is a normal complex
13602 number and no overflow/underflow occurred. INEXACT is true if M
13603 was not exactly calculated. TYPE is the tree type for the result.
13604 This function assumes that you cleared the MPFR flags and then
13605 calculated M to see if anything subsequently set a flag prior to
652d9409 13606 entering this function. Return NULL_TREE if any checks fail, if
13607 FORCE_CONVERT is true, then bypass the checks. */
239d491a 13608
13609static tree
652d9409 13610do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert)
239d491a 13611{
13612 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
13613 overflow/underflow occurred. If -frounding-math, proceed iff the
13614 result of calling FUNC was exact. */
652d9409 13615 if (force_convert
13616 || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m))
13617 && !mpfr_overflow_p () && !mpfr_underflow_p ()
13618 && (!flag_rounding_math || !inexact)))
239d491a 13619 {
13620 REAL_VALUE_TYPE re, im;
13621
b0e7c4d4 13622 real_from_mpfr (&re, mpc_realref (m), TREE_TYPE (type), GMP_RNDN);
13623 real_from_mpfr (&im, mpc_imagref (m), TREE_TYPE (type), GMP_RNDN);
239d491a 13624 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
13625 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
13626 but the mpft_t is not, then we underflowed in the
13627 conversion. */
652d9409 13628 if (force_convert
13629 || (real_isfinite (&re) && real_isfinite (&im)
13630 && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0)
13631 && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0)))
239d491a 13632 {
13633 REAL_VALUE_TYPE re_mode, im_mode;
13634
13635 real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re);
13636 real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im);
13637 /* Proceed iff the specified mode can hold the value. */
652d9409 13638 if (force_convert
13639 || (real_identical (&re_mode, &re)
13640 && real_identical (&im_mode, &im)))
239d491a 13641 return build_complex (type, build_real (TREE_TYPE (type), re_mode),
13642 build_real (TREE_TYPE (type), im_mode));
13643 }
13644 }
13645 return NULL_TREE;
13646}
239d491a 13647
bffb7645 13648/* If argument ARG is a REAL_CST, call the one-argument mpfr function
13649 FUNC on it and return the resulting value as a tree with type TYPE.
728bac60 13650 If MIN and/or MAX are not NULL, then the supplied ARG must be
13651 within those bounds. If INCLUSIVE is true, then MIN/MAX are
13652 acceptable values, otherwise they are not. The mpfr precision is
13653 set to the precision of TYPE. We assume that function FUNC returns
13654 zero if the result could be calculated exactly within the requested
13655 precision. */
bffb7645 13656
13657static tree
728bac60 13658do_mpfr_arg1 (tree arg, tree type, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
13659 const REAL_VALUE_TYPE *min, const REAL_VALUE_TYPE *max,
13660 bool inclusive)
bffb7645 13661{
13662 tree result = NULL_TREE;
48e1416a 13663
bffb7645 13664 STRIP_NOPS (arg);
13665
bd7d6fa4 13666 /* To proceed, MPFR must exactly represent the target floating point
13667 format, which only happens when the target base equals two. */
13668 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13669 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
bffb7645 13670 {
f0c477f2 13671 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
bffb7645 13672
776a7bab 13673 if (real_isfinite (ra)
f0c477f2 13674 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min))
13675 && (!max || real_compare (inclusive ? LE_EXPR: LT_EXPR , ra, max)))
bffb7645 13676 {
e2eb2b7f 13677 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13678 const int prec = fmt->p;
13679 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
debf9994 13680 int inexact;
bffb7645 13681 mpfr_t m;
13682
13683 mpfr_init2 (m, prec);
66fa16e6 13684 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 13685 mpfr_clear_flags ();
e2eb2b7f 13686 inexact = func (m, m, rnd);
f0c477f2 13687 result = do_mpfr_ckconv (m, type, inexact);
bffb7645 13688 mpfr_clear (m);
13689 }
13690 }
48e1416a 13691
bffb7645 13692 return result;
13693}
f0c477f2 13694
13695/* If argument ARG is a REAL_CST, call the two-argument mpfr function
13696 FUNC on it and return the resulting value as a tree with type TYPE.
13697 The mpfr precision is set to the precision of TYPE. We assume that
13698 function FUNC returns zero if the result could be calculated
13699 exactly within the requested precision. */
13700
13701static tree
13702do_mpfr_arg2 (tree arg1, tree arg2, tree type,
13703 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
13704{
13705 tree result = NULL_TREE;
48e1416a 13706
f0c477f2 13707 STRIP_NOPS (arg1);
13708 STRIP_NOPS (arg2);
13709
bd7d6fa4 13710 /* To proceed, MPFR must exactly represent the target floating point
13711 format, which only happens when the target base equals two. */
13712 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13713 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
13714 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
f0c477f2 13715 {
13716 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
13717 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
13718
776a7bab 13719 if (real_isfinite (ra1) && real_isfinite (ra2))
f0c477f2 13720 {
e2eb2b7f 13721 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13722 const int prec = fmt->p;
13723 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
f0c477f2 13724 int inexact;
13725 mpfr_t m1, m2;
13726
13727 mpfr_inits2 (prec, m1, m2, NULL);
66fa16e6 13728 mpfr_from_real (m1, ra1, GMP_RNDN);
13729 mpfr_from_real (m2, ra2, GMP_RNDN);
d4473c84 13730 mpfr_clear_flags ();
e2eb2b7f 13731 inexact = func (m1, m1, m2, rnd);
f0c477f2 13732 result = do_mpfr_ckconv (m1, type, inexact);
13733 mpfr_clears (m1, m2, NULL);
13734 }
13735 }
48e1416a 13736
f0c477f2 13737 return result;
13738}
d92f994c 13739
9917422b 13740/* If argument ARG is a REAL_CST, call the three-argument mpfr function
13741 FUNC on it and return the resulting value as a tree with type TYPE.
13742 The mpfr precision is set to the precision of TYPE. We assume that
13743 function FUNC returns zero if the result could be calculated
13744 exactly within the requested precision. */
13745
13746static tree
13747do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type,
13748 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
13749{
13750 tree result = NULL_TREE;
48e1416a 13751
9917422b 13752 STRIP_NOPS (arg1);
13753 STRIP_NOPS (arg2);
13754 STRIP_NOPS (arg3);
13755
bd7d6fa4 13756 /* To proceed, MPFR must exactly represent the target floating point
13757 format, which only happens when the target base equals two. */
13758 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13759 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
13760 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2)
13761 && TREE_CODE (arg3) == REAL_CST && !TREE_OVERFLOW (arg3))
9917422b 13762 {
13763 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
13764 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
13765 const REAL_VALUE_TYPE *const ra3 = &TREE_REAL_CST (arg3);
13766
776a7bab 13767 if (real_isfinite (ra1) && real_isfinite (ra2) && real_isfinite (ra3))
9917422b 13768 {
e2eb2b7f 13769 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13770 const int prec = fmt->p;
13771 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
9917422b 13772 int inexact;
13773 mpfr_t m1, m2, m3;
13774
13775 mpfr_inits2 (prec, m1, m2, m3, NULL);
66fa16e6 13776 mpfr_from_real (m1, ra1, GMP_RNDN);
13777 mpfr_from_real (m2, ra2, GMP_RNDN);
13778 mpfr_from_real (m3, ra3, GMP_RNDN);
d4473c84 13779 mpfr_clear_flags ();
e2eb2b7f 13780 inexact = func (m1, m1, m2, m3, rnd);
9917422b 13781 result = do_mpfr_ckconv (m1, type, inexact);
13782 mpfr_clears (m1, m2, m3, NULL);
13783 }
13784 }
48e1416a 13785
9917422b 13786 return result;
13787}
13788
d92f994c 13789/* If argument ARG is a REAL_CST, call mpfr_sin_cos() on it and set
13790 the pointers *(ARG_SINP) and *(ARG_COSP) to the resulting values.
d735c391 13791 If ARG_SINP and ARG_COSP are NULL then the result is returned
13792 as a complex value.
d92f994c 13793 The type is taken from the type of ARG and is used for setting the
13794 precision of the calculation and results. */
13795
13796static tree
13797do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp)
13798{
bd7d6fa4 13799 tree const type = TREE_TYPE (arg);
d92f994c 13800 tree result = NULL_TREE;
48e1416a 13801
d92f994c 13802 STRIP_NOPS (arg);
48e1416a 13803
bd7d6fa4 13804 /* To proceed, MPFR must exactly represent the target floating point
13805 format, which only happens when the target base equals two. */
13806 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13807 && TREE_CODE (arg) == REAL_CST
13808 && !TREE_OVERFLOW (arg))
d92f994c 13809 {
13810 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
13811
776a7bab 13812 if (real_isfinite (ra))
d92f994c 13813 {
e2eb2b7f 13814 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13815 const int prec = fmt->p;
13816 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
d92f994c 13817 tree result_s, result_c;
13818 int inexact;
13819 mpfr_t m, ms, mc;
13820
13821 mpfr_inits2 (prec, m, ms, mc, NULL);
66fa16e6 13822 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 13823 mpfr_clear_flags ();
e2eb2b7f 13824 inexact = mpfr_sin_cos (ms, mc, m, rnd);
d92f994c 13825 result_s = do_mpfr_ckconv (ms, type, inexact);
13826 result_c = do_mpfr_ckconv (mc, type, inexact);
13827 mpfr_clears (m, ms, mc, NULL);
13828 if (result_s && result_c)
13829 {
d735c391 13830 /* If we are to return in a complex value do so. */
13831 if (!arg_sinp && !arg_cosp)
13832 return build_complex (build_complex_type (type),
13833 result_c, result_s);
13834
d92f994c 13835 /* Dereference the sin/cos pointer arguments. */
13836 arg_sinp = build_fold_indirect_ref (arg_sinp);
13837 arg_cosp = build_fold_indirect_ref (arg_cosp);
13838 /* Proceed if valid pointer type were passed in. */
13839 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_sinp)) == TYPE_MAIN_VARIANT (type)
13840 && TYPE_MAIN_VARIANT (TREE_TYPE (arg_cosp)) == TYPE_MAIN_VARIANT (type))
13841 {
13842 /* Set the values. */
41076ef6 13843 result_s = fold_build2 (MODIFY_EXPR, type, arg_sinp,
35cc02b5 13844 result_s);
d92f994c 13845 TREE_SIDE_EFFECTS (result_s) = 1;
41076ef6 13846 result_c = fold_build2 (MODIFY_EXPR, type, arg_cosp,
35cc02b5 13847 result_c);
d92f994c 13848 TREE_SIDE_EFFECTS (result_c) = 1;
13849 /* Combine the assignments into a compound expr. */
13850 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13851 result_s, result_c));
13852 }
13853 }
13854 }
13855 }
13856 return result;
13857}
65dd1378 13858
65dd1378 13859/* If argument ARG1 is an INTEGER_CST and ARG2 is a REAL_CST, call the
13860 two-argument mpfr order N Bessel function FUNC on them and return
13861 the resulting value as a tree with type TYPE. The mpfr precision
13862 is set to the precision of TYPE. We assume that function FUNC
13863 returns zero if the result could be calculated exactly within the
13864 requested precision. */
13865static tree
13866do_mpfr_bessel_n (tree arg1, tree arg2, tree type,
13867 int (*func)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
13868 const REAL_VALUE_TYPE *min, bool inclusive)
13869{
13870 tree result = NULL_TREE;
13871
13872 STRIP_NOPS (arg1);
13873 STRIP_NOPS (arg2);
13874
13875 /* To proceed, MPFR must exactly represent the target floating point
13876 format, which only happens when the target base equals two. */
13877 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
35ec552a 13878 && tree_fits_shwi_p (arg1)
65dd1378 13879 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
13880 {
fcb97e84 13881 const HOST_WIDE_INT n = tree_to_shwi (arg1);
65dd1378 13882 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg2);
13883
13884 if (n == (long)n
776a7bab 13885 && real_isfinite (ra)
65dd1378 13886 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min)))
13887 {
e2eb2b7f 13888 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13889 const int prec = fmt->p;
13890 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
65dd1378 13891 int inexact;
13892 mpfr_t m;
13893
13894 mpfr_init2 (m, prec);
13895 mpfr_from_real (m, ra, GMP_RNDN);
13896 mpfr_clear_flags ();
e2eb2b7f 13897 inexact = func (m, n, m, rnd);
65dd1378 13898 result = do_mpfr_ckconv (m, type, inexact);
13899 mpfr_clear (m);
13900 }
13901 }
48e1416a 13902
65dd1378 13903 return result;
13904}
e5407ca6 13905
13906/* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
13907 the pointer *(ARG_QUO) and return the result. The type is taken
13908 from the type of ARG0 and is used for setting the precision of the
13909 calculation and results. */
13910
13911static tree
13912do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
13913{
13914 tree const type = TREE_TYPE (arg0);
13915 tree result = NULL_TREE;
48e1416a 13916
e5407ca6 13917 STRIP_NOPS (arg0);
13918 STRIP_NOPS (arg1);
48e1416a 13919
e5407ca6 13920 /* To proceed, MPFR must exactly represent the target floating point
13921 format, which only happens when the target base equals two. */
13922 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13923 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
13924 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
13925 {
13926 const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
13927 const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
13928
776a7bab 13929 if (real_isfinite (ra0) && real_isfinite (ra1))
e5407ca6 13930 {
e2eb2b7f 13931 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13932 const int prec = fmt->p;
13933 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
e5407ca6 13934 tree result_rem;
13935 long integer_quo;
13936 mpfr_t m0, m1;
13937
13938 mpfr_inits2 (prec, m0, m1, NULL);
13939 mpfr_from_real (m0, ra0, GMP_RNDN);
13940 mpfr_from_real (m1, ra1, GMP_RNDN);
13941 mpfr_clear_flags ();
e2eb2b7f 13942 mpfr_remquo (m0, &integer_quo, m0, m1, rnd);
e5407ca6 13943 /* Remquo is independent of the rounding mode, so pass
13944 inexact=0 to do_mpfr_ckconv(). */
13945 result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
13946 mpfr_clears (m0, m1, NULL);
13947 if (result_rem)
13948 {
13949 /* MPFR calculates quo in the host's long so it may
13950 return more bits in quo than the target int can hold
13951 if sizeof(host long) > sizeof(target int). This can
13952 happen even for native compilers in LP64 mode. In
13953 these cases, modulo the quo value with the largest
13954 number that the target int can hold while leaving one
13955 bit for the sign. */
13956 if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
13957 integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
13958
13959 /* Dereference the quo pointer argument. */
13960 arg_quo = build_fold_indirect_ref (arg_quo);
13961 /* Proceed iff a valid pointer type was passed in. */
13962 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
13963 {
13964 /* Set the value. */
7002a1c8 13965 tree result_quo
13966 = fold_build2 (MODIFY_EXPR, TREE_TYPE (arg_quo), arg_quo,
13967 build_int_cst (TREE_TYPE (arg_quo),
13968 integer_quo));
e5407ca6 13969 TREE_SIDE_EFFECTS (result_quo) = 1;
13970 /* Combine the quo assignment with the rem. */
13971 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13972 result_quo, result_rem));
13973 }
13974 }
13975 }
13976 }
13977 return result;
13978}
e84da7c1 13979
13980/* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
13981 resulting value as a tree with type TYPE. The mpfr precision is
13982 set to the precision of TYPE. We assume that this mpfr function
13983 returns zero if the result could be calculated exactly within the
13984 requested precision. In addition, the integer pointer represented
13985 by ARG_SG will be dereferenced and set to the appropriate signgam
13986 (-1,1) value. */
13987
13988static tree
13989do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
13990{
13991 tree result = NULL_TREE;
13992
13993 STRIP_NOPS (arg);
48e1416a 13994
e84da7c1 13995 /* To proceed, MPFR must exactly represent the target floating point
13996 format, which only happens when the target base equals two. Also
13997 verify ARG is a constant and that ARG_SG is an int pointer. */
13998 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13999 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
14000 && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
14001 && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
14002 {
14003 const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
14004
14005 /* In addition to NaN and Inf, the argument cannot be zero or a
14006 negative integer. */
776a7bab 14007 if (real_isfinite (ra)
e84da7c1 14008 && ra->cl != rvc_zero
9af5ce0c 14009 && !(real_isneg (ra) && real_isinteger (ra, TYPE_MODE (type))))
e84da7c1 14010 {
e2eb2b7f 14011 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
14012 const int prec = fmt->p;
14013 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
e84da7c1 14014 int inexact, sg;
14015 mpfr_t m;
14016 tree result_lg;
14017
14018 mpfr_init2 (m, prec);
14019 mpfr_from_real (m, ra, GMP_RNDN);
14020 mpfr_clear_flags ();
e2eb2b7f 14021 inexact = mpfr_lgamma (m, &sg, m, rnd);
e84da7c1 14022 result_lg = do_mpfr_ckconv (m, type, inexact);
14023 mpfr_clear (m);
14024 if (result_lg)
14025 {
14026 tree result_sg;
14027
14028 /* Dereference the arg_sg pointer argument. */
14029 arg_sg = build_fold_indirect_ref (arg_sg);
14030 /* Assign the signgam value into *arg_sg. */
14031 result_sg = fold_build2 (MODIFY_EXPR,
14032 TREE_TYPE (arg_sg), arg_sg,
7002a1c8 14033 build_int_cst (TREE_TYPE (arg_sg), sg));
e84da7c1 14034 TREE_SIDE_EFFECTS (result_sg) = 1;
14035 /* Combine the signgam assignment with the lgamma result. */
14036 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
14037 result_sg, result_lg));
14038 }
14039 }
14040 }
14041
14042 return result;
14043}
75a70cf9 14044
239d491a 14045/* If argument ARG is a COMPLEX_CST, call the one-argument mpc
14046 function FUNC on it and return the resulting value as a tree with
14047 type TYPE. The mpfr precision is set to the precision of TYPE. We
14048 assume that function FUNC returns zero if the result could be
14049 calculated exactly within the requested precision. */
14050
14051static tree
14052do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t))
14053{
14054 tree result = NULL_TREE;
48e1416a 14055
239d491a 14056 STRIP_NOPS (arg);
14057
14058 /* To proceed, MPFR must exactly represent the target floating point
14059 format, which only happens when the target base equals two. */
14060 if (TREE_CODE (arg) == COMPLEX_CST && !TREE_OVERFLOW (arg)
14061 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE
14062 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))))->b == 2)
14063 {
14064 const REAL_VALUE_TYPE *const re = TREE_REAL_CST_PTR (TREE_REALPART (arg));
14065 const REAL_VALUE_TYPE *const im = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
14066
14067 if (real_isfinite (re) && real_isfinite (im))
14068 {
14069 const struct real_format *const fmt =
14070 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
14071 const int prec = fmt->p;
14072 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
44d89feb 14073 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
239d491a 14074 int inexact;
14075 mpc_t m;
48e1416a 14076
239d491a 14077 mpc_init2 (m, prec);
9af5ce0c 14078 mpfr_from_real (mpc_realref (m), re, rnd);
14079 mpfr_from_real (mpc_imagref (m), im, rnd);
239d491a 14080 mpfr_clear_flags ();
44d89feb 14081 inexact = func (m, m, crnd);
652d9409 14082 result = do_mpc_ckconv (m, type, inexact, /*force_convert=*/ 0);
239d491a 14083 mpc_clear (m);
14084 }
14085 }
14086
14087 return result;
14088}
c699fab8 14089
14090/* If arguments ARG0 and ARG1 are a COMPLEX_CST, call the two-argument
14091 mpc function FUNC on it and return the resulting value as a tree
14092 with type TYPE. The mpfr precision is set to the precision of
14093 TYPE. We assume that function FUNC returns zero if the result
652d9409 14094 could be calculated exactly within the requested precision. If
14095 DO_NONFINITE is true, then fold expressions containing Inf or NaN
14096 in the arguments and/or results. */
c699fab8 14097
63e89698 14098tree
652d9409 14099do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
c699fab8 14100 int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
14101{
14102 tree result = NULL_TREE;
48e1416a 14103
c699fab8 14104 STRIP_NOPS (arg0);
14105 STRIP_NOPS (arg1);
14106
14107 /* To proceed, MPFR must exactly represent the target floating point
14108 format, which only happens when the target base equals two. */
14109 if (TREE_CODE (arg0) == COMPLEX_CST && !TREE_OVERFLOW (arg0)
14110 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
14111 && TREE_CODE (arg1) == COMPLEX_CST && !TREE_OVERFLOW (arg1)
14112 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE
14113 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))))->b == 2)
14114 {
14115 const REAL_VALUE_TYPE *const re0 = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
14116 const REAL_VALUE_TYPE *const im0 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
14117 const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1));
14118 const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1));
14119
652d9409 14120 if (do_nonfinite
14121 || (real_isfinite (re0) && real_isfinite (im0)
14122 && real_isfinite (re1) && real_isfinite (im1)))
c699fab8 14123 {
14124 const struct real_format *const fmt =
14125 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
14126 const int prec = fmt->p;
14127 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
14128 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
14129 int inexact;
14130 mpc_t m0, m1;
48e1416a 14131
c699fab8 14132 mpc_init2 (m0, prec);
14133 mpc_init2 (m1, prec);
9af5ce0c 14134 mpfr_from_real (mpc_realref (m0), re0, rnd);
14135 mpfr_from_real (mpc_imagref (m0), im0, rnd);
14136 mpfr_from_real (mpc_realref (m1), re1, rnd);
14137 mpfr_from_real (mpc_imagref (m1), im1, rnd);
c699fab8 14138 mpfr_clear_flags ();
14139 inexact = func (m0, m0, m1, crnd);
652d9409 14140 result = do_mpc_ckconv (m0, type, inexact, do_nonfinite);
c699fab8 14141 mpc_clear (m0);
14142 mpc_clear (m1);
14143 }
14144 }
14145
14146 return result;
14147}
239d491a 14148
75a70cf9 14149/* Fold a call STMT to __{,v}sprintf_chk. Return NULL_TREE if
14150 a normal call should be emitted rather than expanding the function
14151 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
14152
14153static tree
14154gimple_fold_builtin_sprintf_chk (gimple stmt, enum built_in_function fcode)
14155{
75a70cf9 14156 int nargs = gimple_call_num_args (stmt);
14157
af1409ad 14158 return fold_builtin_sprintf_chk_1 (gimple_location (stmt), nargs,
14159 (nargs > 0
14160 ? gimple_call_arg_ptr (stmt, 0)
14161 : &error_mark_node), fcode);
75a70cf9 14162}
14163
14164/* Fold a call STMT to {,v}snprintf. Return NULL_TREE if
14165 a normal call should be emitted rather than expanding the function
14166 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
14167 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
14168 passed as second argument. */
14169
14170tree
14171gimple_fold_builtin_snprintf_chk (gimple stmt, tree maxlen,
14172 enum built_in_function fcode)
14173{
af1409ad 14174 int nargs = gimple_call_num_args (stmt);
75a70cf9 14175
af1409ad 14176 return fold_builtin_snprintf_chk_1 (gimple_location (stmt), nargs,
14177 (nargs > 0
14178 ? gimple_call_arg_ptr (stmt, 0)
14179 : &error_mark_node), maxlen, fcode);
75a70cf9 14180}
14181
14182/* Builtins with folding operations that operate on "..." arguments
14183 need special handling; we need to store the arguments in a convenient
14184 data structure before attempting any folding. Fortunately there are
14185 only a few builtins that fall into this category. FNDECL is the
14186 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
14187 result of the function call is ignored. */
14188
14189static tree
389dd41b 14190gimple_fold_builtin_varargs (tree fndecl, gimple stmt,
14191 bool ignore ATTRIBUTE_UNUSED)
75a70cf9 14192{
14193 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
14194 tree ret = NULL_TREE;
14195
14196 switch (fcode)
14197 {
14198 case BUILT_IN_SPRINTF_CHK:
14199 case BUILT_IN_VSPRINTF_CHK:
14200 ret = gimple_fold_builtin_sprintf_chk (stmt, fcode);
14201 break;
14202
14203 case BUILT_IN_SNPRINTF_CHK:
14204 case BUILT_IN_VSNPRINTF_CHK:
14205 ret = gimple_fold_builtin_snprintf_chk (stmt, NULL_TREE, fcode);
14206
14207 default:
14208 break;
14209 }
14210 if (ret)
14211 {
14212 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
14213 TREE_NO_WARNING (ret) = 1;
14214 return ret;
14215 }
14216 return NULL_TREE;
14217}
14218
14219/* A wrapper function for builtin folding that prevents warnings for
14220 "statement without effect" and the like, caused by removing the
14221 call node earlier than the warning is generated. */
14222
14223tree
14224fold_call_stmt (gimple stmt, bool ignore)
14225{
14226 tree ret = NULL_TREE;
14227 tree fndecl = gimple_call_fndecl (stmt);
389dd41b 14228 location_t loc = gimple_location (stmt);
75a70cf9 14229 if (fndecl
14230 && TREE_CODE (fndecl) == FUNCTION_DECL
14231 && DECL_BUILT_IN (fndecl)
14232 && !gimple_call_va_arg_pack_p (stmt))
14233 {
14234 int nargs = gimple_call_num_args (stmt);
9845fb99 14235 tree *args = (nargs > 0
14236 ? gimple_call_arg_ptr (stmt, 0)
14237 : &error_mark_node);
75a70cf9 14238
198622c0 14239 if (avoid_folding_inline_builtin (fndecl))
14240 return NULL_TREE;
75a70cf9 14241 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
14242 {
9845fb99 14243 return targetm.fold_builtin (fndecl, nargs, args, ignore);
75a70cf9 14244 }
14245 else
14246 {
14247 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
9845fb99 14248 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
75a70cf9 14249 if (!ret)
14250 ret = gimple_fold_builtin_varargs (fndecl, stmt, ignore);
14251 if (ret)
14252 {
14253 /* Propagate location information from original call to
14254 expansion of builtin. Otherwise things like
14255 maybe_emit_chk_warning, that operate on the expansion
14256 of a builtin, will use the wrong location information. */
14257 if (gimple_has_location (stmt))
14258 {
14259 tree realret = ret;
14260 if (TREE_CODE (ret) == NOP_EXPR)
14261 realret = TREE_OPERAND (ret, 0);
14262 if (CAN_HAVE_LOCATION_P (realret)
14263 && !EXPR_HAS_LOCATION (realret))
389dd41b 14264 SET_EXPR_LOCATION (realret, loc);
75a70cf9 14265 return realret;
14266 }
14267 return ret;
14268 }
14269 }
14270 }
14271 return NULL_TREE;
14272}
7bfefa9d 14273
b9a16870 14274/* Look up the function in builtin_decl that corresponds to DECL
7bfefa9d 14275 and set ASMSPEC as its user assembler name. DECL must be a
14276 function decl that declares a builtin. */
14277
14278void
14279set_builtin_user_assembler_name (tree decl, const char *asmspec)
14280{
14281 tree builtin;
14282 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
14283 && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
14284 && asmspec != 0);
14285
b9a16870 14286 builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
4d8e0d6d 14287 set_user_assembler_name (builtin, asmspec);
7bfefa9d 14288 switch (DECL_FUNCTION_CODE (decl))
14289 {
14290 case BUILT_IN_MEMCPY:
14291 init_block_move_fn (asmspec);
14292 memcpy_libfunc = set_user_assembler_libfunc ("memcpy", asmspec);
14293 break;
14294 case BUILT_IN_MEMSET:
14295 init_block_clear_fn (asmspec);
14296 memset_libfunc = set_user_assembler_libfunc ("memset", asmspec);
14297 break;
14298 case BUILT_IN_MEMMOVE:
14299 memmove_libfunc = set_user_assembler_libfunc ("memmove", asmspec);
14300 break;
14301 case BUILT_IN_MEMCMP:
14302 memcmp_libfunc = set_user_assembler_libfunc ("memcmp", asmspec);
14303 break;
14304 case BUILT_IN_ABORT:
14305 abort_libfunc = set_user_assembler_libfunc ("abort", asmspec);
14306 break;
5a80a58b 14307 case BUILT_IN_FFS:
14308 if (INT_TYPE_SIZE < BITS_PER_WORD)
14309 {
14310 set_user_assembler_libfunc ("ffs", asmspec);
14311 set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE,
14312 MODE_INT, 0), "ffs");
14313 }
14314 break;
7bfefa9d 14315 default:
14316 break;
14317 }
14318}
a6b74a67 14319
14320/* Return true if DECL is a builtin that expands to a constant or similarly
14321 simple code. */
14322bool
14323is_simple_builtin (tree decl)
14324{
14325 if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
14326 switch (DECL_FUNCTION_CODE (decl))
14327 {
14328 /* Builtins that expand to constants. */
14329 case BUILT_IN_CONSTANT_P:
14330 case BUILT_IN_EXPECT:
14331 case BUILT_IN_OBJECT_SIZE:
14332 case BUILT_IN_UNREACHABLE:
14333 /* Simple register moves or loads from stack. */
fca0886c 14334 case BUILT_IN_ASSUME_ALIGNED:
a6b74a67 14335 case BUILT_IN_RETURN_ADDRESS:
14336 case BUILT_IN_EXTRACT_RETURN_ADDR:
14337 case BUILT_IN_FROB_RETURN_ADDR:
14338 case BUILT_IN_RETURN:
14339 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
14340 case BUILT_IN_FRAME_ADDRESS:
14341 case BUILT_IN_VA_END:
14342 case BUILT_IN_STACK_SAVE:
14343 case BUILT_IN_STACK_RESTORE:
14344 /* Exception state returns or moves registers around. */
14345 case BUILT_IN_EH_FILTER:
14346 case BUILT_IN_EH_POINTER:
14347 case BUILT_IN_EH_COPY_VALUES:
14348 return true;
14349
14350 default:
14351 return false;
14352 }
14353
14354 return false;
14355}
14356
14357/* Return true if DECL is a builtin that is not expensive, i.e., they are
14358 most probably expanded inline into reasonably simple code. This is a
14359 superset of is_simple_builtin. */
14360bool
14361is_inexpensive_builtin (tree decl)
14362{
14363 if (!decl)
14364 return false;
14365 else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_MD)
14366 return true;
14367 else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
14368 switch (DECL_FUNCTION_CODE (decl))
14369 {
14370 case BUILT_IN_ABS:
14371 case BUILT_IN_ALLOCA:
581bf1c2 14372 case BUILT_IN_ALLOCA_WITH_ALIGN:
74bdbe96 14373 case BUILT_IN_BSWAP16:
a6b74a67 14374 case BUILT_IN_BSWAP32:
14375 case BUILT_IN_BSWAP64:
14376 case BUILT_IN_CLZ:
14377 case BUILT_IN_CLZIMAX:
14378 case BUILT_IN_CLZL:
14379 case BUILT_IN_CLZLL:
14380 case BUILT_IN_CTZ:
14381 case BUILT_IN_CTZIMAX:
14382 case BUILT_IN_CTZL:
14383 case BUILT_IN_CTZLL:
14384 case BUILT_IN_FFS:
14385 case BUILT_IN_FFSIMAX:
14386 case BUILT_IN_FFSL:
14387 case BUILT_IN_FFSLL:
14388 case BUILT_IN_IMAXABS:
14389 case BUILT_IN_FINITE:
14390 case BUILT_IN_FINITEF:
14391 case BUILT_IN_FINITEL:
14392 case BUILT_IN_FINITED32:
14393 case BUILT_IN_FINITED64:
14394 case BUILT_IN_FINITED128:
14395 case BUILT_IN_FPCLASSIFY:
14396 case BUILT_IN_ISFINITE:
14397 case BUILT_IN_ISINF_SIGN:
14398 case BUILT_IN_ISINF:
14399 case BUILT_IN_ISINFF:
14400 case BUILT_IN_ISINFL:
14401 case BUILT_IN_ISINFD32:
14402 case BUILT_IN_ISINFD64:
14403 case BUILT_IN_ISINFD128:
14404 case BUILT_IN_ISNAN:
14405 case BUILT_IN_ISNANF:
14406 case BUILT_IN_ISNANL:
14407 case BUILT_IN_ISNAND32:
14408 case BUILT_IN_ISNAND64:
14409 case BUILT_IN_ISNAND128:
14410 case BUILT_IN_ISNORMAL:
14411 case BUILT_IN_ISGREATER:
14412 case BUILT_IN_ISGREATEREQUAL:
14413 case BUILT_IN_ISLESS:
14414 case BUILT_IN_ISLESSEQUAL:
14415 case BUILT_IN_ISLESSGREATER:
14416 case BUILT_IN_ISUNORDERED:
14417 case BUILT_IN_VA_ARG_PACK:
14418 case BUILT_IN_VA_ARG_PACK_LEN:
14419 case BUILT_IN_VA_COPY:
14420 case BUILT_IN_TRAP:
14421 case BUILT_IN_SAVEREGS:
14422 case BUILT_IN_POPCOUNTL:
14423 case BUILT_IN_POPCOUNTLL:
14424 case BUILT_IN_POPCOUNTIMAX:
14425 case BUILT_IN_POPCOUNT:
14426 case BUILT_IN_PARITYL:
14427 case BUILT_IN_PARITYLL:
14428 case BUILT_IN_PARITYIMAX:
14429 case BUILT_IN_PARITY:
14430 case BUILT_IN_LABS:
14431 case BUILT_IN_LLABS:
14432 case BUILT_IN_PREFETCH:
14433 return true;
14434
14435 default:
14436 return is_simple_builtin (decl);
14437 }
14438
14439 return false;
14440}