]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/builtins.c
PR bootstrap/55370
[thirdparty/gcc.git] / gcc / builtins.c
CommitLineData
53800dbe 1/* Expand builtin functions.
61f1dccc 2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
c307f106 3 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
4 2012 Free Software Foundation, Inc.
53800dbe 5
f12b58b3 6This file is part of GCC.
53800dbe 7
f12b58b3 8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
8c4c00c1 10Software Foundation; either version 3, or (at your option) any later
f12b58b3 11version.
53800dbe 12
f12b58b3 13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
53800dbe 17
18You should have received a copy of the GNU General Public License
8c4c00c1 19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
53800dbe 21
22#include "config.h"
23#include "system.h"
805e22b2 24#include "coretypes.h"
25#include "tm.h"
53800dbe 26#include "machmode.h"
27#include "rtl.h"
28#include "tree.h"
dae0b5cb 29#include "realmpfr.h"
75a70cf9 30#include "gimple.h"
53800dbe 31#include "flags.h"
32#include "regs.h"
33#include "hard-reg-set.h"
34#include "except.h"
35#include "function.h"
53800dbe 36#include "insn-config.h"
37#include "expr.h"
d8fc4d0b 38#include "optabs.h"
39#include "libfuncs.h"
53800dbe 40#include "recog.h"
41#include "output.h"
42#include "typeclass.h"
689df48e 43#include "predict.h"
1dd6c958 44#include "tm_p.h"
fc2a2dcb 45#include "target.h"
63c62881 46#include "langhooks.h"
0ec80471 47#include "basic-block.h"
fd62c19a 48#include "tree-mudflap.h"
5a84fdd6 49#include "tree-flow.h"
162719b3 50#include "value-prof.h"
852f689e 51#include "diagnostic-core.h"
3b9c3a16 52#include "builtins.h"
53800dbe 53
5383fb56 54
726e2588 55#ifndef PAD_VARARGS_DOWN
56#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
57#endif
239d491a 58static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_rnd_t));
726e2588 59
3b9c3a16 60struct target_builtins default_target_builtins;
61#if SWITCHABLE_TARGET
62struct target_builtins *this_target_builtins = &default_target_builtins;
63#endif
64
ab7943b9 65/* Define the names of the builtin function types and codes. */
8934cb0c 66const char *const built_in_class_names[4]
ab7943b9 67 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
68
9cfddb70 69#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
0dfc45b5 70const char * built_in_names[(int) END_BUILTINS] =
4e9d90c7 71{
72#include "builtins.def"
73};
74#undef DEF_BUILTIN
ab7943b9 75
df94cd3b 76/* Setup an array of _DECL trees, make sure each element is
77 initialized to NULL_TREE. */
b9a16870 78builtin_info_type builtin_info;
df94cd3b 79
aecda0d6 80static const char *c_getstr (tree);
81static rtx c_readstr (const char *, enum machine_mode);
82static int target_char_cast (tree, char *);
d8ae1baa 83static rtx get_memory_rtx (tree, tree);
aecda0d6 84static int apply_args_size (void);
85static int apply_result_size (void);
d8c9779c 86#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
aecda0d6 87static rtx result_vector (int, rtx);
d8c9779c 88#endif
843d08a9 89static void expand_builtin_update_setjmp_buf (rtx);
aecda0d6 90static void expand_builtin_prefetch (tree);
91static rtx expand_builtin_apply_args (void);
92static rtx expand_builtin_apply_args_1 (void);
93static rtx expand_builtin_apply (rtx, rtx, rtx);
94static void expand_builtin_return (rtx);
95static enum type_class type_to_class (tree);
96static rtx expand_builtin_classify_type (tree);
97static void expand_errno_check (tree, rtx);
98static rtx expand_builtin_mathfn (tree, rtx, rtx);
99static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
6b43bae4 100static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
7e0713b1 101static rtx expand_builtin_mathfn_ternary (tree, rtx, rtx);
f97eea22 102static rtx expand_builtin_interclass_mathfn (tree, rtx);
c3147c1a 103static rtx expand_builtin_sincos (tree);
f97eea22 104static rtx expand_builtin_cexpi (tree, rtx);
ff1b14e4 105static rtx expand_builtin_int_roundingfn (tree, rtx);
106static rtx expand_builtin_int_roundingfn_2 (tree, rtx);
79012a9d 107static rtx expand_builtin_next_arg (void);
aecda0d6 108static rtx expand_builtin_va_start (tree);
109static rtx expand_builtin_va_end (tree);
110static rtx expand_builtin_va_copy (tree);
c2f47e15 111static rtx expand_builtin_memcmp (tree, rtx, enum machine_mode);
a65c4d64 112static rtx expand_builtin_strcmp (tree, rtx);
aecda0d6 113static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
114static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
a65c4d64 115static rtx expand_builtin_memcpy (tree, rtx);
c2f47e15 116static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode);
48e1416a 117static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx,
c2f47e15 118 enum machine_mode, int);
a65c4d64 119static rtx expand_builtin_strcpy (tree, rtx);
120static rtx expand_builtin_strcpy_args (tree, tree, rtx);
aecda0d6 121static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
a65c4d64 122static rtx expand_builtin_strncpy (tree, rtx);
aecda0d6 123static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
c2f47e15 124static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
125static rtx expand_builtin_memset_args (tree, tree, tree, rtx, enum machine_mode, tree);
aecda0d6 126static rtx expand_builtin_bzero (tree);
127static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
5be42b39 128static rtx expand_builtin_alloca (tree, bool);
aecda0d6 129static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
130static rtx expand_builtin_frame_address (tree, tree);
389dd41b 131static tree stabilize_va_list_loc (location_t, tree, int);
aecda0d6 132static rtx expand_builtin_expect (tree, rtx);
133static tree fold_builtin_constant_p (tree);
389dd41b 134static tree fold_builtin_expect (location_t, tree, tree);
aecda0d6 135static tree fold_builtin_classify_type (tree);
c7cbde74 136static tree fold_builtin_strlen (location_t, tree, tree);
389dd41b 137static tree fold_builtin_inf (location_t, tree, int);
aecda0d6 138static tree fold_builtin_nan (tree, tree, int);
389dd41b 139static tree rewrite_call_expr (location_t, tree, int, tree, int, ...);
b7bf20db 140static bool validate_arg (const_tree, enum tree_code code);
277f8dd2 141static bool integer_valued_real_p (tree);
389dd41b 142static tree fold_trunc_transparent_mathfn (location_t, tree, tree);
aecda0d6 143static bool readonly_data_expr (tree);
144static rtx expand_builtin_fabs (tree, rtx, rtx);
27f261ef 145static rtx expand_builtin_signbit (tree, rtx);
389dd41b 146static tree fold_builtin_sqrt (location_t, tree, tree);
147static tree fold_builtin_cbrt (location_t, tree, tree);
148static tree fold_builtin_pow (location_t, tree, tree, tree, tree);
149static tree fold_builtin_powi (location_t, tree, tree, tree, tree);
150static tree fold_builtin_cos (location_t, tree, tree, tree);
151static tree fold_builtin_cosh (location_t, tree, tree, tree);
bffb7645 152static tree fold_builtin_tan (tree, tree);
389dd41b 153static tree fold_builtin_trunc (location_t, tree, tree);
154static tree fold_builtin_floor (location_t, tree, tree);
155static tree fold_builtin_ceil (location_t, tree, tree);
156static tree fold_builtin_round (location_t, tree, tree);
157static tree fold_builtin_int_roundingfn (location_t, tree, tree);
10b9666f 158static tree fold_builtin_bitop (tree, tree);
389dd41b 159static tree fold_builtin_memory_op (location_t, tree, tree, tree, tree, bool, int);
160static tree fold_builtin_strchr (location_t, tree, tree, tree);
161static tree fold_builtin_memchr (location_t, tree, tree, tree, tree);
162static tree fold_builtin_memcmp (location_t, tree, tree, tree);
163static tree fold_builtin_strcmp (location_t, tree, tree);
164static tree fold_builtin_strncmp (location_t, tree, tree, tree);
165static tree fold_builtin_signbit (location_t, tree, tree);
166static tree fold_builtin_copysign (location_t, tree, tree, tree, tree);
167static tree fold_builtin_isascii (location_t, tree);
168static tree fold_builtin_toascii (location_t, tree);
169static tree fold_builtin_isdigit (location_t, tree);
170static tree fold_builtin_fabs (location_t, tree, tree);
171static tree fold_builtin_abs (location_t, tree, tree);
172static tree fold_builtin_unordered_cmp (location_t, tree, tree, tree, enum tree_code,
d5019fe8 173 enum tree_code);
389dd41b 174static tree fold_builtin_n (location_t, tree, tree *, int, bool);
175static tree fold_builtin_0 (location_t, tree, bool);
176static tree fold_builtin_1 (location_t, tree, tree, bool);
177static tree fold_builtin_2 (location_t, tree, tree, tree, bool);
178static tree fold_builtin_3 (location_t, tree, tree, tree, tree, bool);
179static tree fold_builtin_4 (location_t, tree, tree, tree, tree, tree, bool);
180static tree fold_builtin_varargs (location_t, tree, tree, bool);
181
182static tree fold_builtin_strpbrk (location_t, tree, tree, tree);
183static tree fold_builtin_strstr (location_t, tree, tree, tree);
184static tree fold_builtin_strrchr (location_t, tree, tree, tree);
185static tree fold_builtin_strcat (location_t, tree, tree);
186static tree fold_builtin_strncat (location_t, tree, tree, tree);
187static tree fold_builtin_strspn (location_t, tree, tree);
188static tree fold_builtin_strcspn (location_t, tree, tree);
189static tree fold_builtin_sprintf (location_t, tree, tree, tree, int);
750d7b16 190static tree fold_builtin_snprintf (location_t, tree, tree, tree, tree, int);
4ee9c684 191
0a39fd54 192static rtx expand_builtin_object_size (tree);
193static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
194 enum built_in_function);
195static void maybe_emit_chk_warning (tree, enum built_in_function);
196static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
2c281b15 197static void maybe_emit_free_warning (tree);
c2f47e15 198static tree fold_builtin_object_size (tree, tree);
389dd41b 199static tree fold_builtin_strcat_chk (location_t, tree, tree, tree, tree);
200static tree fold_builtin_strncat_chk (location_t, tree, tree, tree, tree, tree);
201static tree fold_builtin_sprintf_chk (location_t, tree, enum built_in_function);
202static tree fold_builtin_printf (location_t, tree, tree, tree, bool, enum built_in_function);
203static tree fold_builtin_fprintf (location_t, tree, tree, tree, tree, bool,
c2f47e15 204 enum built_in_function);
99eabcc1 205static bool init_target_chars (void);
206
207static unsigned HOST_WIDE_INT target_newline;
208static unsigned HOST_WIDE_INT target_percent;
209static unsigned HOST_WIDE_INT target_c;
210static unsigned HOST_WIDE_INT target_s;
211static char target_percent_c[3];
212static char target_percent_s[3];
213static char target_percent_s_newline[4];
728bac60 214static tree do_mpfr_arg1 (tree, tree, int (*)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
215 const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, bool);
f0c477f2 216static tree do_mpfr_arg2 (tree, tree, tree,
217 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
9917422b 218static tree do_mpfr_arg3 (tree, tree, tree, tree,
219 int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
d92f994c 220static tree do_mpfr_sincos (tree, tree, tree);
65dd1378 221static tree do_mpfr_bessel_n (tree, tree, tree,
222 int (*)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
223 const REAL_VALUE_TYPE *, bool);
e5407ca6 224static tree do_mpfr_remquo (tree, tree, tree);
e84da7c1 225static tree do_mpfr_lgamma_r (tree, tree, tree);
1cd6e20d 226static void expand_builtin_sync_synchronize (void);
0a39fd54 227
7bfefa9d 228/* Return true if NAME starts with __builtin_ or __sync_. */
229
b29139ad 230static bool
1c47b3e8 231is_builtin_name (const char *name)
b6a5fc45 232{
b6a5fc45 233 if (strncmp (name, "__builtin_", 10) == 0)
234 return true;
235 if (strncmp (name, "__sync_", 7) == 0)
236 return true;
1cd6e20d 237 if (strncmp (name, "__atomic_", 9) == 0)
238 return true;
b6a5fc45 239 return false;
240}
4ee9c684 241
7bfefa9d 242
243/* Return true if DECL is a function symbol representing a built-in. */
244
245bool
246is_builtin_fn (tree decl)
247{
248 return TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl);
249}
250
251
1c47b3e8 252/* Return true if NODE should be considered for inline expansion regardless
253 of the optimization level. This means whenever a function is invoked with
254 its "internal" name, which normally contains the prefix "__builtin". */
255
256static bool
257called_as_built_in (tree node)
258{
259 /* Note that we must use DECL_NAME, not DECL_ASSEMBLER_NAME_SET_P since
260 we want the name used to call the function, not the name it
261 will have. */
262 const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
263 return is_builtin_name (name);
264}
265
ceea063b 266/* Compute values M and N such that M divides (address of EXP - N) and such
267 that N < M. If these numbers can be determined, store M in alignp and N in
268 *BITPOSP and return true. Otherwise return false and store BITS_PER_UNIT to
269 *alignp and any bit-offset to *bitposp.
0d8f7716 270
271 Note that the address (and thus the alignment) computed here is based
272 on the address to which a symbol resolves, whereas DECL_ALIGN is based
273 on the address at which an object is actually located. These two
274 addresses are not always the same. For example, on ARM targets,
275 the address &foo of a Thumb function foo() has the lowest bit set,
3482bf13 276 whereas foo() itself starts on an even address.
698537d1 277
3482bf13 278 If ADDR_P is true we are taking the address of the memory reference EXP
279 and thus cannot rely on the access taking place. */
280
281static bool
282get_object_alignment_2 (tree exp, unsigned int *alignp,
283 unsigned HOST_WIDE_INT *bitposp, bool addr_p)
698537d1 284{
98ab9e8f 285 HOST_WIDE_INT bitsize, bitpos;
286 tree offset;
287 enum machine_mode mode;
288 int unsignedp, volatilep;
ceea063b 289 unsigned int inner, align = BITS_PER_UNIT;
290 bool known_alignment = false;
698537d1 291
98ab9e8f 292 /* Get the innermost object and the constant (bitpos) and possibly
293 variable (offset) offset of the access. */
294 exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
295 &mode, &unsignedp, &volatilep, true);
296
297 /* Extract alignment information from the innermost object and
298 possibly adjust bitpos and offset. */
3482bf13 299 if (TREE_CODE (exp) == FUNCTION_DECL)
0d8f7716 300 {
3482bf13 301 /* Function addresses can encode extra information besides their
302 alignment. However, if TARGET_PTRMEMFUNC_VBIT_LOCATION
303 allows the low bit to be used as a virtual bit, we know
304 that the address itself must be at least 2-byte aligned. */
305 if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn)
306 align = 2 * BITS_PER_UNIT;
0d8f7716 307 }
3482bf13 308 else if (TREE_CODE (exp) == LABEL_DECL)
309 ;
310 else if (TREE_CODE (exp) == CONST_DECL)
98ab9e8f 311 {
3482bf13 312 /* The alignment of a CONST_DECL is determined by its initializer. */
313 exp = DECL_INITIAL (exp);
98ab9e8f 314 align = TYPE_ALIGN (TREE_TYPE (exp));
315#ifdef CONSTANT_ALIGNMENT
3482bf13 316 if (CONSTANT_CLASS_P (exp))
317 align = (unsigned) CONSTANT_ALIGNMENT (exp, align);
698537d1 318#endif
3482bf13 319 known_alignment = true;
98ab9e8f 320 }
3482bf13 321 else if (DECL_P (exp))
ceea063b 322 {
3482bf13 323 align = DECL_ALIGN (exp);
ceea063b 324 known_alignment = true;
ceea063b 325 }
3482bf13 326 else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR)
ceea063b 327 {
ceea063b 328 align = TYPE_ALIGN (TREE_TYPE (exp));
329 }
3482bf13 330 else if (TREE_CODE (exp) == INDIRECT_REF
331 || TREE_CODE (exp) == MEM_REF
332 || TREE_CODE (exp) == TARGET_MEM_REF)
98ab9e8f 333 {
334 tree addr = TREE_OPERAND (exp, 0);
ceea063b 335 unsigned ptr_align;
336 unsigned HOST_WIDE_INT ptr_bitpos;
337
98ab9e8f 338 if (TREE_CODE (addr) == BIT_AND_EXPR
339 && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
340 {
341 align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))
342 & -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)));
343 align *= BITS_PER_UNIT;
344 addr = TREE_OPERAND (addr, 0);
345 }
ceea063b 346
3482bf13 347 known_alignment
348 = get_pointer_alignment_1 (addr, &ptr_align, &ptr_bitpos);
3482bf13 349 align = MAX (ptr_align, align);
350
4083990a 351 /* The alignment of the pointer operand in a TARGET_MEM_REF
352 has to take the variable offset parts into account. */
3482bf13 353 if (TREE_CODE (exp) == TARGET_MEM_REF)
153c3b50 354 {
3482bf13 355 if (TMR_INDEX (exp))
356 {
357 unsigned HOST_WIDE_INT step = 1;
358 if (TMR_STEP (exp))
359 step = TREE_INT_CST_LOW (TMR_STEP (exp));
360 align = MIN (align, (step & -step) * BITS_PER_UNIT);
361 }
362 if (TMR_INDEX2 (exp))
363 align = BITS_PER_UNIT;
364 known_alignment = false;
153c3b50 365 }
ceea063b 366
3482bf13 367 /* When EXP is an actual memory reference then we can use
368 TYPE_ALIGN of a pointer indirection to derive alignment.
369 Do so only if get_pointer_alignment_1 did not reveal absolute
4083990a 370 alignment knowledge and if using that alignment would
371 improve the situation. */
372 if (!addr_p && !known_alignment
373 && TYPE_ALIGN (TREE_TYPE (exp)) > align)
374 align = TYPE_ALIGN (TREE_TYPE (exp));
375 else
376 {
377 /* Else adjust bitpos accordingly. */
378 bitpos += ptr_bitpos;
379 if (TREE_CODE (exp) == MEM_REF
380 || TREE_CODE (exp) == TARGET_MEM_REF)
381 bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT;
382 }
98ab9e8f 383 }
3482bf13 384 else if (TREE_CODE (exp) == STRING_CST)
153c3b50 385 {
3482bf13 386 /* STRING_CST are the only constant objects we allow to be not
387 wrapped inside a CONST_DECL. */
388 align = TYPE_ALIGN (TREE_TYPE (exp));
389#ifdef CONSTANT_ALIGNMENT
390 if (CONSTANT_CLASS_P (exp))
391 align = (unsigned) CONSTANT_ALIGNMENT (exp, align);
392#endif
393 known_alignment = true;
98ab9e8f 394 }
98ab9e8f 395
396 /* If there is a non-constant offset part extract the maximum
397 alignment that can prevail. */
0c883ef3 398 inner = ~0U;
98ab9e8f 399 while (offset)
400 {
401 tree next_offset;
402
403 if (TREE_CODE (offset) == PLUS_EXPR)
404 {
405 next_offset = TREE_OPERAND (offset, 0);
406 offset = TREE_OPERAND (offset, 1);
407 }
408 else
409 next_offset = NULL;
410 if (host_integerp (offset, 1))
411 {
412 /* Any overflow in calculating offset_bits won't change
413 the alignment. */
414 unsigned offset_bits
415 = ((unsigned) tree_low_cst (offset, 1) * BITS_PER_UNIT);
416
417 if (offset_bits)
418 inner = MIN (inner, (offset_bits & -offset_bits));
419 }
420 else if (TREE_CODE (offset) == MULT_EXPR
421 && host_integerp (TREE_OPERAND (offset, 1), 1))
422 {
423 /* Any overflow in calculating offset_factor won't change
424 the alignment. */
425 unsigned offset_factor
426 = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
427 * BITS_PER_UNIT);
428
429 if (offset_factor)
430 inner = MIN (inner, (offset_factor & -offset_factor));
431 }
432 else
433 {
3482bf13 434 inner = MIN (inner, BITS_PER_UNIT);
98ab9e8f 435 break;
436 }
437 offset = next_offset;
438 }
3482bf13 439 /* Alignment is innermost object alignment adjusted by the constant
440 and non-constant offset parts. */
441 align = MIN (align, inner);
98ab9e8f 442
3482bf13 443 *alignp = align;
444 *bitposp = bitpos & (*alignp - 1);
ceea063b 445 return known_alignment;
0c883ef3 446}
447
3482bf13 448/* For a memory reference expression EXP compute values M and N such that M
449 divides (&EXP - N) and such that N < M. If these numbers can be determined,
450 store M in alignp and N in *BITPOSP and return true. Otherwise return false
451 and store BITS_PER_UNIT to *alignp and any bit-offset to *bitposp. */
452
453bool
454get_object_alignment_1 (tree exp, unsigned int *alignp,
455 unsigned HOST_WIDE_INT *bitposp)
456{
457 return get_object_alignment_2 (exp, alignp, bitposp, false);
458}
459
957d0361 460/* Return the alignment in bits of EXP, an object. */
0c883ef3 461
462unsigned int
957d0361 463get_object_alignment (tree exp)
0c883ef3 464{
465 unsigned HOST_WIDE_INT bitpos = 0;
466 unsigned int align;
467
ceea063b 468 get_object_alignment_1 (exp, &align, &bitpos);
0c883ef3 469
98ab9e8f 470 /* align and bitpos now specify known low bits of the pointer.
471 ptr & (align - 1) == bitpos. */
472
473 if (bitpos != 0)
474 align = (bitpos & -bitpos);
957d0361 475 return align;
698537d1 476}
477
ceea063b 478/* For a pointer valued expression EXP compute values M and N such that M
479 divides (EXP - N) and such that N < M. If these numbers can be determined,
3482bf13 480 store M in alignp and N in *BITPOSP and return true. Return false if
481 the results are just a conservative approximation.
53800dbe 482
ceea063b 483 If EXP is not a pointer, false is returned too. */
53800dbe 484
ceea063b 485bool
486get_pointer_alignment_1 (tree exp, unsigned int *alignp,
487 unsigned HOST_WIDE_INT *bitposp)
53800dbe 488{
153c3b50 489 STRIP_NOPS (exp);
535e2026 490
153c3b50 491 if (TREE_CODE (exp) == ADDR_EXPR)
3482bf13 492 return get_object_alignment_2 (TREE_OPERAND (exp, 0),
493 alignp, bitposp, true);
153c3b50 494 else if (TREE_CODE (exp) == SSA_NAME
495 && POINTER_TYPE_P (TREE_TYPE (exp)))
53800dbe 496 {
ceea063b 497 unsigned int ptr_align, ptr_misalign;
153c3b50 498 struct ptr_info_def *pi = SSA_NAME_PTR_INFO (exp);
ceea063b 499
500 if (pi && get_ptr_info_alignment (pi, &ptr_align, &ptr_misalign))
501 {
502 *bitposp = ptr_misalign * BITS_PER_UNIT;
503 *alignp = ptr_align * BITS_PER_UNIT;
3482bf13 504 /* We cannot really tell whether this result is an approximation. */
ceea063b 505 return true;
506 }
507 else
69fbc3aa 508 {
509 *bitposp = 0;
ceea063b 510 *alignp = BITS_PER_UNIT;
511 return false;
69fbc3aa 512 }
53800dbe 513 }
0bb8b39a 514 else if (TREE_CODE (exp) == INTEGER_CST)
515 {
516 *alignp = BIGGEST_ALIGNMENT;
517 *bitposp = ((TREE_INT_CST_LOW (exp) * BITS_PER_UNIT)
518 & (BIGGEST_ALIGNMENT - 1));
519 return true;
520 }
153c3b50 521
69fbc3aa 522 *bitposp = 0;
ceea063b 523 *alignp = BITS_PER_UNIT;
524 return false;
53800dbe 525}
526
69fbc3aa 527/* Return the alignment in bits of EXP, a pointer valued expression.
528 The alignment returned is, by default, the alignment of the thing that
529 EXP points to. If it is not a POINTER_TYPE, 0 is returned.
530
531 Otherwise, look at the expression to see if we can do better, i.e., if the
532 expression is actually pointing at an object whose alignment is tighter. */
533
534unsigned int
535get_pointer_alignment (tree exp)
536{
537 unsigned HOST_WIDE_INT bitpos = 0;
538 unsigned int align;
ceea063b 539
540 get_pointer_alignment_1 (exp, &align, &bitpos);
69fbc3aa 541
542 /* align and bitpos now specify known low bits of the pointer.
543 ptr & (align - 1) == bitpos. */
544
545 if (bitpos != 0)
546 align = (bitpos & -bitpos);
547
548 return align;
549}
550
53800dbe 551/* Compute the length of a C string. TREE_STRING_LENGTH is not the right
552 way, because it could contain a zero byte in the middle.
553 TREE_STRING_LENGTH is the size of the character array, not the string.
554
4172d65e 555 ONLY_VALUE should be nonzero if the result is not going to be emitted
c09841f6 556 into the instruction stream and zero if it is going to be expanded.
4172d65e 557 E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
681fab1e 558 is returned, otherwise NULL, since
559 len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
560 evaluate the side-effects.
561
902de8ed 562 The value returned is of type `ssizetype'.
563
53800dbe 564 Unfortunately, string_constant can't access the values of const char
565 arrays with initializers, so neither can we do so here. */
566
4ee9c684 567tree
681fab1e 568c_strlen (tree src, int only_value)
53800dbe 569{
570 tree offset_node;
27d0c333 571 HOST_WIDE_INT offset;
572 int max;
44acf429 573 const char *ptr;
da136652 574 location_t loc;
53800dbe 575
681fab1e 576 STRIP_NOPS (src);
577 if (TREE_CODE (src) == COND_EXPR
578 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
579 {
580 tree len1, len2;
581
582 len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
583 len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
0862b7e9 584 if (tree_int_cst_equal (len1, len2))
681fab1e 585 return len1;
586 }
587
588 if (TREE_CODE (src) == COMPOUND_EXPR
589 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
590 return c_strlen (TREE_OPERAND (src, 1), only_value);
591
8637f1db 592 loc = EXPR_LOC_OR_HERE (src);
da136652 593
53800dbe 594 src = string_constant (src, &offset_node);
595 if (src == 0)
c2f47e15 596 return NULL_TREE;
902de8ed 597
83d79705 598 max = TREE_STRING_LENGTH (src) - 1;
53800dbe 599 ptr = TREE_STRING_POINTER (src);
902de8ed 600
53800dbe 601 if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
602 {
603 /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
604 compute the offset to the following null if we don't know where to
605 start searching for it. */
606 int i;
902de8ed 607
53800dbe 608 for (i = 0; i < max; i++)
609 if (ptr[i] == 0)
c2f47e15 610 return NULL_TREE;
902de8ed 611
53800dbe 612 /* We don't know the starting offset, but we do know that the string
613 has no internal zero bytes. We can assume that the offset falls
614 within the bounds of the string; otherwise, the programmer deserves
615 what he gets. Subtract the offset from the length of the string,
902de8ed 616 and return that. This would perhaps not be valid if we were dealing
617 with named arrays in addition to literal string constants. */
618
da136652 619 return size_diffop_loc (loc, size_int (max), offset_node);
53800dbe 620 }
621
622 /* We have a known offset into the string. Start searching there for
27d0c333 623 a null character if we can represent it as a single HOST_WIDE_INT. */
dabc4084 624 if (offset_node == 0)
53800dbe 625 offset = 0;
dabc4084 626 else if (! host_integerp (offset_node, 0))
627 offset = -1;
53800dbe 628 else
27d0c333 629 offset = tree_low_cst (offset_node, 0);
902de8ed 630
1f63a7d6 631 /* If the offset is known to be out of bounds, warn, and call strlen at
632 runtime. */
53800dbe 633 if (offset < 0 || offset > max)
634 {
1f63a7d6 635 /* Suppress multiple warnings for propagated constant strings. */
636 if (! TREE_NO_WARNING (src))
637 {
da136652 638 warning_at (loc, 0, "offset outside bounds of constant string");
1f63a7d6 639 TREE_NO_WARNING (src) = 1;
640 }
c2f47e15 641 return NULL_TREE;
53800dbe 642 }
902de8ed 643
53800dbe 644 /* Use strlen to search for the first zero byte. Since any strings
645 constructed with build_string will have nulls appended, we win even
646 if we get handed something like (char[4])"abcd".
647
648 Since OFFSET is our starting index into the string, no further
649 calculation is needed. */
902de8ed 650 return ssize_int (strlen (ptr + offset));
53800dbe 651}
652
83d79705 653/* Return a char pointer for a C string if it is a string constant
654 or sum of string constant and integer constant. */
655
656static const char *
aecda0d6 657c_getstr (tree src)
83d79705 658{
659 tree offset_node;
83d79705 660
661 src = string_constant (src, &offset_node);
662 if (src == 0)
663 return 0;
664
8c85fcb7 665 if (offset_node == 0)
666 return TREE_STRING_POINTER (src);
667 else if (!host_integerp (offset_node, 1)
668 || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
83d79705 669 return 0;
83d79705 670
8c85fcb7 671 return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
83d79705 672}
673
8c85fcb7 674/* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
675 GET_MODE_BITSIZE (MODE) bits from string constant STR. */
ecc318ff 676
6840589f 677static rtx
aecda0d6 678c_readstr (const char *str, enum machine_mode mode)
6840589f 679{
680 HOST_WIDE_INT c[2];
681 HOST_WIDE_INT ch;
682 unsigned int i, j;
683
64db345d 684 gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
7d3f6cc7 685
6840589f 686 c[0] = 0;
687 c[1] = 0;
688 ch = 1;
689 for (i = 0; i < GET_MODE_SIZE (mode); i++)
690 {
691 j = i;
692 if (WORDS_BIG_ENDIAN)
693 j = GET_MODE_SIZE (mode) - i - 1;
694 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
ad8f8e52 695 && GET_MODE_SIZE (mode) >= UNITS_PER_WORD)
6840589f 696 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
697 j *= BITS_PER_UNIT;
24cd46a7 698 gcc_assert (j < HOST_BITS_PER_DOUBLE_INT);
7d3f6cc7 699
6840589f 700 if (ch)
701 ch = (unsigned char) str[i];
702 c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
703 }
704 return immed_double_const (c[0], c[1], mode);
705}
706
ecc318ff 707/* Cast a target constant CST to target CHAR and if that value fits into
5206b159 708 host char type, return zero and put that value into variable pointed to by
ecc318ff 709 P. */
710
711static int
aecda0d6 712target_char_cast (tree cst, char *p)
ecc318ff 713{
714 unsigned HOST_WIDE_INT val, hostval;
715
c19686c5 716 if (TREE_CODE (cst) != INTEGER_CST
ecc318ff 717 || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
718 return 1;
719
c19686c5 720 val = TREE_INT_CST_LOW (cst);
ecc318ff 721 if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
722 val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
723
724 hostval = val;
725 if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
726 hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
727
728 if (val != hostval)
729 return 1;
730
731 *p = hostval;
732 return 0;
733}
734
4ee9c684 735/* Similar to save_expr, but assumes that arbitrary code is not executed
736 in between the multiple evaluations. In particular, we assume that a
737 non-addressable local variable will not be modified. */
738
739static tree
740builtin_save_expr (tree exp)
741{
f6c35aa4 742 if (TREE_CODE (exp) == SSA_NAME
743 || (TREE_ADDRESSABLE (exp) == 0
744 && (TREE_CODE (exp) == PARM_DECL
745 || (TREE_CODE (exp) == VAR_DECL && !TREE_STATIC (exp)))))
4ee9c684 746 return exp;
747
748 return save_expr (exp);
749}
750
53800dbe 751/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
752 times to get the address of either a higher stack frame, or a return
753 address located within it (depending on FNDECL_CODE). */
902de8ed 754
c626df3d 755static rtx
869d0ef0 756expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
53800dbe 757{
758 int i;
759
869d0ef0 760#ifdef INITIAL_FRAME_ADDRESS_RTX
761 rtx tem = INITIAL_FRAME_ADDRESS_RTX;
762#else
e3e15c50 763 rtx tem;
764
1b74fde7 765 /* For a zero count with __builtin_return_address, we don't care what
766 frame address we return, because target-specific definitions will
767 override us. Therefore frame pointer elimination is OK, and using
768 the soft frame pointer is OK.
769
fa7637bd 770 For a nonzero count, or a zero count with __builtin_frame_address,
1b74fde7 771 we require a stable offset from the current frame pointer to the
772 previous one, so we must use the hard frame pointer, and
e3e15c50 773 we must disable frame pointer elimination. */
1b74fde7 774 if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
e3e15c50 775 tem = frame_pointer_rtx;
a0c938f0 776 else
e3e15c50 777 {
778 tem = hard_frame_pointer_rtx;
779
780 /* Tell reload not to eliminate the frame pointer. */
18d50ae6 781 crtl->accesses_prior_frames = 1;
e3e15c50 782 }
869d0ef0 783#endif
784
53800dbe 785 /* Some machines need special handling before we can access
3a69c60c 786 arbitrary frames. For example, on the SPARC, we must first flush
53800dbe 787 all register windows to the stack. */
788#ifdef SETUP_FRAME_ADDRESSES
789 if (count > 0)
790 SETUP_FRAME_ADDRESSES ();
791#endif
792
3a69c60c 793 /* On the SPARC, the return address is not in the frame, it is in a
53800dbe 794 register. There is no way to access it off of the current frame
795 pointer, but it can be accessed off the previous frame pointer by
796 reading the value from the register window save area. */
797#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
798 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
799 count--;
800#endif
801
802 /* Scan back COUNT frames to the specified frame. */
803 for (i = 0; i < count; i++)
804 {
805 /* Assume the dynamic chain pointer is in the word that the
806 frame address points to, unless otherwise specified. */
807#ifdef DYNAMIC_CHAIN_ADDRESS
808 tem = DYNAMIC_CHAIN_ADDRESS (tem);
809#endif
810 tem = memory_address (Pmode, tem);
00060fc2 811 tem = gen_frame_mem (Pmode, tem);
83fc1478 812 tem = copy_to_reg (tem);
53800dbe 813 }
814
3a69c60c 815 /* For __builtin_frame_address, return what we've got. But, on
816 the SPARC for example, we may have to add a bias. */
53800dbe 817 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
3a69c60c 818#ifdef FRAME_ADDR_RTX
819 return FRAME_ADDR_RTX (tem);
820#else
53800dbe 821 return tem;
3a69c60c 822#endif
53800dbe 823
3a69c60c 824 /* For __builtin_return_address, get the return address from that frame. */
53800dbe 825#ifdef RETURN_ADDR_RTX
826 tem = RETURN_ADDR_RTX (count, tem);
827#else
828 tem = memory_address (Pmode,
29c05e22 829 plus_constant (Pmode, tem, GET_MODE_SIZE (Pmode)));
00060fc2 830 tem = gen_frame_mem (Pmode, tem);
53800dbe 831#endif
832 return tem;
833}
834
f7c44134 835/* Alias set used for setjmp buffer. */
32c2fdea 836static alias_set_type setjmp_alias_set = -1;
f7c44134 837
6b7f6858 838/* Construct the leading half of a __builtin_setjmp call. Control will
2c8a1497 839 return to RECEIVER_LABEL. This is also called directly by the SJLJ
840 exception handling code. */
53800dbe 841
6b7f6858 842void
aecda0d6 843expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
53800dbe 844{
53800dbe 845 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
53800dbe 846 rtx stack_save;
f7c44134 847 rtx mem;
53800dbe 848
f7c44134 849 if (setjmp_alias_set == -1)
850 setjmp_alias_set = new_alias_set ();
851
85d654dd 852 buf_addr = convert_memory_address (Pmode, buf_addr);
53800dbe 853
37ae8504 854 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
53800dbe 855
6b7f6858 856 /* We store the frame pointer and the address of receiver_label in
857 the buffer and use the rest of it for the stack save area, which
858 is machine-dependent. */
53800dbe 859
f7c44134 860 mem = gen_rtx_MEM (Pmode, buf_addr);
ab6ab77e 861 set_mem_alias_set (mem, setjmp_alias_set);
e3e026e8 862 emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
f7c44134 863
29c05e22 864 mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
865 GET_MODE_SIZE (Pmode))),
ab6ab77e 866 set_mem_alias_set (mem, setjmp_alias_set);
f7c44134 867
868 emit_move_insn (validize_mem (mem),
6b7f6858 869 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
53800dbe 870
871 stack_save = gen_rtx_MEM (sa_mode,
29c05e22 872 plus_constant (Pmode, buf_addr,
53800dbe 873 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 874 set_mem_alias_set (stack_save, setjmp_alias_set);
e9c97615 875 emit_stack_save (SAVE_NONLOCAL, &stack_save);
53800dbe 876
877 /* If there is further processing to do, do it. */
878#ifdef HAVE_builtin_setjmp_setup
879 if (HAVE_builtin_setjmp_setup)
880 emit_insn (gen_builtin_setjmp_setup (buf_addr));
881#endif
882
29f09705 883 /* We have a nonlocal label. */
18d50ae6 884 cfun->has_nonlocal_label = 1;
6b7f6858 885}
53800dbe 886
2c8a1497 887/* Construct the trailing part of a __builtin_setjmp call. This is
36a8ce77 888 also called directly by the SJLJ exception handling code. */
6b7f6858 889
890void
aecda0d6 891expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
6b7f6858 892{
82c7907c 893 rtx chain;
894
36a8ce77 895 /* Clobber the FP 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
36a8ce77 910 {
911 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
912 /* This might change the hard frame pointer in ways that aren't
913 apparent to early optimization passes, so force a clobber. */
914 emit_clobber (hard_frame_pointer_rtx);
915 }
53800dbe 916
5ae82d58 917#if !HARD_FRAME_POINTER_IS_ARG_POINTER
53800dbe 918 if (fixed_regs[ARG_POINTER_REGNUM])
919 {
920#ifdef ELIMINABLE_REGS
921 size_t i;
e99c3a1d 922 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
53800dbe 923
3098b2d3 924 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
53800dbe 925 if (elim_regs[i].from == ARG_POINTER_REGNUM
926 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
927 break;
928
3098b2d3 929 if (i == ARRAY_SIZE (elim_regs))
53800dbe 930#endif
931 {
932 /* Now restore our arg pointer from the address at which it
05927e40 933 was saved in our stack frame. */
27a7a23a 934 emit_move_insn (crtl->args.internal_arg_pointer,
b079a207 935 copy_to_reg (get_arg_pointer_save_area ()));
53800dbe 936 }
937 }
938#endif
939
940#ifdef HAVE_builtin_setjmp_receiver
36a8ce77 941 if (HAVE_builtin_setjmp_receiver)
6b7f6858 942 emit_insn (gen_builtin_setjmp_receiver (receiver_label));
53800dbe 943 else
944#endif
945#ifdef HAVE_nonlocal_goto_receiver
946 if (HAVE_nonlocal_goto_receiver)
947 emit_insn (gen_nonlocal_goto_receiver ());
948 else
949#endif
6b7f6858 950 { /* Nothing */ }
57f6bb94 951
3072d30e 952 /* We must not allow the code we just generated to be reordered by
953 scheduling. Specifically, the update of the frame pointer must
954 happen immediately, not later. */
955 emit_insn (gen_blockage ());
6b7f6858 956}
53800dbe 957
53800dbe 958/* __builtin_longjmp is passed a pointer to an array of five words (not
959 all will be used on all machines). It operates similarly to the C
960 library function of the same name, but is more efficient. Much of
2c8a1497 961 the code below is copied from the handling of non-local gotos. */
53800dbe 962
c626df3d 963static void
aecda0d6 964expand_builtin_longjmp (rtx buf_addr, rtx value)
53800dbe 965{
4712c7d6 966 rtx fp, lab, stack, insn, last;
53800dbe 967 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
968
48e1416a 969 /* DRAP is needed for stack realign if longjmp is expanded to current
27a7a23a 970 function */
971 if (SUPPORTS_STACK_ALIGNMENT)
972 crtl->need_drap = true;
973
f7c44134 974 if (setjmp_alias_set == -1)
975 setjmp_alias_set = new_alias_set ();
976
85d654dd 977 buf_addr = convert_memory_address (Pmode, buf_addr);
479e4d5e 978
53800dbe 979 buf_addr = force_reg (Pmode, buf_addr);
980
82c7907c 981 /* We require that the user must pass a second argument of 1, because
982 that is what builtin_setjmp will return. */
64db345d 983 gcc_assert (value == const1_rtx);
53800dbe 984
4712c7d6 985 last = get_last_insn ();
53800dbe 986#ifdef HAVE_builtin_longjmp
987 if (HAVE_builtin_longjmp)
988 emit_insn (gen_builtin_longjmp (buf_addr));
989 else
990#endif
991 {
992 fp = gen_rtx_MEM (Pmode, buf_addr);
29c05e22 993 lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
53800dbe 994 GET_MODE_SIZE (Pmode)));
995
29c05e22 996 stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, buf_addr,
53800dbe 997 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 998 set_mem_alias_set (fp, setjmp_alias_set);
999 set_mem_alias_set (lab, setjmp_alias_set);
1000 set_mem_alias_set (stack, setjmp_alias_set);
53800dbe 1001
1002 /* Pick up FP, label, and SP from the block and jump. This code is
1003 from expand_goto in stmt.c; see there for detailed comments. */
03fd9d2c 1004#ifdef HAVE_nonlocal_goto
53800dbe 1005 if (HAVE_nonlocal_goto)
1006 /* We have to pass a value to the nonlocal_goto pattern that will
1007 get copied into the static_chain pointer, but it does not matter
1008 what that value is, because builtin_setjmp does not use it. */
28d202a8 1009 emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
53800dbe 1010 else
1011#endif
1012 {
1013 lab = copy_to_reg (lab);
1014
18b42941 1015 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
1016 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
2a871ad1 1017
53800dbe 1018 emit_move_insn (hard_frame_pointer_rtx, fp);
e9c97615 1019 emit_stack_restore (SAVE_NONLOCAL, stack);
53800dbe 1020
18b42941 1021 emit_use (hard_frame_pointer_rtx);
1022 emit_use (stack_pointer_rtx);
53800dbe 1023 emit_indirect_jump (lab);
1024 }
1025 }
615166bb 1026
1027 /* Search backwards and mark the jump insn as a non-local goto.
1028 Note that this precludes the use of __builtin_longjmp to a
1029 __builtin_setjmp target in the same function. However, we've
1030 already cautioned the user that these functions are for
1031 internal exception handling use only. */
449c0509 1032 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
1033 {
64db345d 1034 gcc_assert (insn != last);
7d3f6cc7 1035
6d7dc5b9 1036 if (JUMP_P (insn))
449c0509 1037 {
a1ddb869 1038 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
449c0509 1039 break;
1040 }
6d7dc5b9 1041 else if (CALL_P (insn))
9342ee68 1042 break;
449c0509 1043 }
53800dbe 1044}
1045
4ee9c684 1046/* Expand a call to __builtin_nonlocal_goto. We're passed the target label
1047 and the address of the save area. */
1048
1049static rtx
c2f47e15 1050expand_builtin_nonlocal_goto (tree exp)
4ee9c684 1051{
1052 tree t_label, t_save_area;
1053 rtx r_label, r_save_area, r_fp, r_sp, insn;
1054
c2f47e15 1055 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4ee9c684 1056 return NULL_RTX;
1057
c2f47e15 1058 t_label = CALL_EXPR_ARG (exp, 0);
1059 t_save_area = CALL_EXPR_ARG (exp, 1);
4ee9c684 1060
8ec3c5c2 1061 r_label = expand_normal (t_label);
3dce56cc 1062 r_label = convert_memory_address (Pmode, r_label);
8ec3c5c2 1063 r_save_area = expand_normal (t_save_area);
3dce56cc 1064 r_save_area = convert_memory_address (Pmode, r_save_area);
d1ff492e 1065 /* Copy the address of the save location to a register just in case it was
1066 based on the frame pointer. */
51adbc8a 1067 r_save_area = copy_to_reg (r_save_area);
4ee9c684 1068 r_fp = gen_rtx_MEM (Pmode, r_save_area);
1069 r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
29c05e22 1070 plus_constant (Pmode, r_save_area,
1071 GET_MODE_SIZE (Pmode)));
4ee9c684 1072
18d50ae6 1073 crtl->has_nonlocal_goto = 1;
4ee9c684 1074
03fd9d2c 1075#ifdef HAVE_nonlocal_goto
4ee9c684 1076 /* ??? We no longer need to pass the static chain value, afaik. */
1077 if (HAVE_nonlocal_goto)
1078 emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
1079 else
1080#endif
1081 {
1082 r_label = copy_to_reg (r_label);
1083
18b42941 1084 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
1085 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
491e04ef 1086
d1ff492e 1087 /* Restore frame pointer for containing function. */
4ee9c684 1088 emit_move_insn (hard_frame_pointer_rtx, r_fp);
e9c97615 1089 emit_stack_restore (SAVE_NONLOCAL, r_sp);
491e04ef 1090
4ee9c684 1091 /* USE of hard_frame_pointer_rtx added for consistency;
1092 not clear if really needed. */
18b42941 1093 emit_use (hard_frame_pointer_rtx);
1094 emit_use (stack_pointer_rtx);
ad0d0af8 1095
1096 /* If the architecture is using a GP register, we must
1097 conservatively assume that the target function makes use of it.
1098 The prologue of functions with nonlocal gotos must therefore
1099 initialize the GP register to the appropriate value, and we
1100 must then make sure that this value is live at the point
1101 of the jump. (Note that this doesn't necessarily apply
1102 to targets with a nonlocal_goto pattern; they are free
1103 to implement it in their own way. Note also that this is
1104 a no-op if the GP register is a global invariant.) */
1105 if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
1106 && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
18b42941 1107 emit_use (pic_offset_table_rtx);
ad0d0af8 1108
4ee9c684 1109 emit_indirect_jump (r_label);
1110 }
491e04ef 1111
4ee9c684 1112 /* Search backwards to the jump insn and mark it as a
1113 non-local goto. */
1114 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
1115 {
6d7dc5b9 1116 if (JUMP_P (insn))
4ee9c684 1117 {
a1ddb869 1118 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
4ee9c684 1119 break;
1120 }
6d7dc5b9 1121 else if (CALL_P (insn))
4ee9c684 1122 break;
1123 }
1124
1125 return const0_rtx;
1126}
1127
843d08a9 1128/* __builtin_update_setjmp_buf is passed a pointer to an array of five words
1129 (not all will be used on all machines) that was passed to __builtin_setjmp.
1130 It updates the stack pointer in that block to correspond to the current
1131 stack pointer. */
1132
1133static void
1134expand_builtin_update_setjmp_buf (rtx buf_addr)
1135{
d1ff492e 1136 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
1137 rtx stack_save
843d08a9 1138 = gen_rtx_MEM (sa_mode,
1139 memory_address
1140 (sa_mode,
29c05e22 1141 plus_constant (Pmode, buf_addr,
1142 2 * GET_MODE_SIZE (Pmode))));
843d08a9 1143
e9c97615 1144 emit_stack_save (SAVE_NONLOCAL, &stack_save);
843d08a9 1145}
1146
5e3608d8 1147/* Expand a call to __builtin_prefetch. For a target that does not support
1148 data prefetch, evaluate the memory address argument in case it has side
1149 effects. */
1150
1151static void
c2f47e15 1152expand_builtin_prefetch (tree exp)
5e3608d8 1153{
1154 tree arg0, arg1, arg2;
c2f47e15 1155 int nargs;
5e3608d8 1156 rtx op0, op1, op2;
1157
c2f47e15 1158 if (!validate_arglist (exp, POINTER_TYPE, 0))
26a5cadb 1159 return;
1160
c2f47e15 1161 arg0 = CALL_EXPR_ARG (exp, 0);
1162
26a5cadb 1163 /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
1164 zero (read) and argument 2 (locality) defaults to 3 (high degree of
1165 locality). */
c2f47e15 1166 nargs = call_expr_nargs (exp);
1167 if (nargs > 1)
1168 arg1 = CALL_EXPR_ARG (exp, 1);
26a5cadb 1169 else
c2f47e15 1170 arg1 = integer_zero_node;
1171 if (nargs > 2)
1172 arg2 = CALL_EXPR_ARG (exp, 2);
1173 else
2512209b 1174 arg2 = integer_three_node;
5e3608d8 1175
1176 /* Argument 0 is an address. */
1177 op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
1178
1179 /* Argument 1 (read/write flag) must be a compile-time constant int. */
1180 if (TREE_CODE (arg1) != INTEGER_CST)
1181 {
07e3a3d2 1182 error ("second argument to %<__builtin_prefetch%> must be a constant");
9342ee68 1183 arg1 = integer_zero_node;
5e3608d8 1184 }
8ec3c5c2 1185 op1 = expand_normal (arg1);
5e3608d8 1186 /* Argument 1 must be either zero or one. */
1187 if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
1188 {
c3ceba8e 1189 warning (0, "invalid second argument to %<__builtin_prefetch%>;"
07e3a3d2 1190 " using zero");
5e3608d8 1191 op1 = const0_rtx;
1192 }
1193
1194 /* Argument 2 (locality) must be a compile-time constant int. */
1195 if (TREE_CODE (arg2) != INTEGER_CST)
1196 {
07e3a3d2 1197 error ("third argument to %<__builtin_prefetch%> must be a constant");
5e3608d8 1198 arg2 = integer_zero_node;
1199 }
8ec3c5c2 1200 op2 = expand_normal (arg2);
5e3608d8 1201 /* Argument 2 must be 0, 1, 2, or 3. */
1202 if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
1203 {
c3ceba8e 1204 warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
5e3608d8 1205 op2 = const0_rtx;
1206 }
1207
1208#ifdef HAVE_prefetch
1209 if (HAVE_prefetch)
1210 {
8786db1e 1211 struct expand_operand ops[3];
1212
1213 create_address_operand (&ops[0], op0);
1214 create_integer_operand (&ops[1], INTVAL (op1));
1215 create_integer_operand (&ops[2], INTVAL (op2));
1216 if (maybe_expand_insn (CODE_FOR_prefetch, 3, ops))
1217 return;
5e3608d8 1218 }
5e3608d8 1219#endif
0a534ba7 1220
f0ce3b1f 1221 /* Don't do anything with direct references to volatile memory, but
1222 generate code to handle other side effects. */
e16ceb8e 1223 if (!MEM_P (op0) && side_effects_p (op0))
f0ce3b1f 1224 emit_insn (op0);
5e3608d8 1225}
1226
f7c44134 1227/* Get a MEM rtx for expression EXP which is the address of an operand
d8ae1baa 1228 to be used in a string instruction (cmpstrsi, movmemsi, ..). LEN is
1229 the maximum length of the block of memory that might be accessed or
1230 NULL if unknown. */
f7c44134 1231
53800dbe 1232static rtx
d8ae1baa 1233get_memory_rtx (tree exp, tree len)
53800dbe 1234{
ad0a178f 1235 tree orig_exp = exp;
1236 rtx addr, mem;
ad0a178f 1237
1238 /* When EXP is not resolved SAVE_EXPR, MEM_ATTRS can be still derived
1239 from its expression, for expr->a.b only <variable>.a.b is recorded. */
1240 if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp))
1241 exp = TREE_OPERAND (exp, 0);
1242
1243 addr = expand_expr (orig_exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
1244 mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
2a631e19 1245
f7c44134 1246 /* Get an expression we can use to find the attributes to assign to MEM.
5dd3f78f 1247 First remove any nops. */
72dd6141 1248 while (CONVERT_EXPR_P (exp)
f7c44134 1249 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
1250 exp = TREE_OPERAND (exp, 0);
1251
5dd3f78f 1252 /* Build a MEM_REF representing the whole accessed area as a byte blob,
1253 (as builtin stringops may alias with anything). */
1254 exp = fold_build2 (MEM_REF,
1255 build_array_type (char_type_node,
1256 build_range_type (sizetype,
1257 size_one_node, len)),
1258 exp, build_int_cst (ptr_type_node, 0));
1259
1260 /* If the MEM_REF has no acceptable address, try to get the base object
1261 from the original address we got, and build an all-aliasing
1262 unknown-sized access to that one. */
1263 if (is_gimple_mem_ref_addr (TREE_OPERAND (exp, 0)))
1264 set_mem_attributes (mem, exp, 0);
1265 else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
1266 && (exp = get_base_address (TREE_OPERAND (TREE_OPERAND (exp, 0),
1267 0))))
eec8e941 1268 {
5dd3f78f 1269 exp = build_fold_addr_expr (exp);
1270 exp = fold_build2 (MEM_REF,
1271 build_array_type (char_type_node,
1272 build_range_type (sizetype,
1273 size_zero_node,
1274 NULL)),
1275 exp, build_int_cst (ptr_type_node, 0));
a1a25d19 1276 set_mem_attributes (mem, exp, 0);
eec8e941 1277 }
5dd3f78f 1278 set_mem_alias_set (mem, 0);
53800dbe 1279 return mem;
1280}
1281\f
1282/* Built-in functions to perform an untyped call and return. */
1283
3b9c3a16 1284#define apply_args_mode \
1285 (this_target_builtins->x_apply_args_mode)
1286#define apply_result_mode \
1287 (this_target_builtins->x_apply_result_mode)
53800dbe 1288
53800dbe 1289/* Return the size required for the block returned by __builtin_apply_args,
1290 and initialize apply_args_mode. */
1291
1292static int
aecda0d6 1293apply_args_size (void)
53800dbe 1294{
1295 static int size = -1;
58e9ce8f 1296 int align;
1297 unsigned int regno;
53800dbe 1298 enum machine_mode mode;
1299
1300 /* The values computed by this function never change. */
1301 if (size < 0)
1302 {
1303 /* The first value is the incoming arg-pointer. */
1304 size = GET_MODE_SIZE (Pmode);
1305
1306 /* The second value is the structure value address unless this is
1307 passed as an "invisible" first argument. */
6812c89e 1308 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1309 size += GET_MODE_SIZE (Pmode);
1310
1311 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1312 if (FUNCTION_ARG_REGNO_P (regno))
1313 {
4bac51c9 1314 mode = targetm.calls.get_raw_arg_mode (regno);
0862b7e9 1315
64db345d 1316 gcc_assert (mode != VOIDmode);
53800dbe 1317
1318 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1319 if (size % align != 0)
1320 size = CEIL (size, align) * align;
53800dbe 1321 size += GET_MODE_SIZE (mode);
1322 apply_args_mode[regno] = mode;
1323 }
1324 else
1325 {
1326 apply_args_mode[regno] = VOIDmode;
53800dbe 1327 }
1328 }
1329 return size;
1330}
1331
1332/* Return the size required for the block returned by __builtin_apply,
1333 and initialize apply_result_mode. */
1334
1335static int
aecda0d6 1336apply_result_size (void)
53800dbe 1337{
1338 static int size = -1;
1339 int align, regno;
1340 enum machine_mode mode;
1341
1342 /* The values computed by this function never change. */
1343 if (size < 0)
1344 {
1345 size = 0;
1346
1347 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
e1ce1485 1348 if (targetm.calls.function_value_regno_p (regno))
53800dbe 1349 {
4bac51c9 1350 mode = targetm.calls.get_raw_result_mode (regno);
0862b7e9 1351
64db345d 1352 gcc_assert (mode != VOIDmode);
53800dbe 1353
1354 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1355 if (size % align != 0)
1356 size = CEIL (size, align) * align;
1357 size += GET_MODE_SIZE (mode);
1358 apply_result_mode[regno] = mode;
1359 }
1360 else
1361 apply_result_mode[regno] = VOIDmode;
1362
1363 /* Allow targets that use untyped_call and untyped_return to override
1364 the size so that machine-specific information can be stored here. */
1365#ifdef APPLY_RESULT_SIZE
1366 size = APPLY_RESULT_SIZE;
1367#endif
1368 }
1369 return size;
1370}
1371
1372#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1373/* Create a vector describing the result block RESULT. If SAVEP is true,
1374 the result block is used to save the values; otherwise it is used to
1375 restore the values. */
1376
1377static rtx
aecda0d6 1378result_vector (int savep, rtx result)
53800dbe 1379{
1380 int regno, size, align, nelts;
1381 enum machine_mode mode;
1382 rtx reg, mem;
364c0c59 1383 rtx *savevec = XALLOCAVEC (rtx, FIRST_PSEUDO_REGISTER);
bf8e3599 1384
53800dbe 1385 size = nelts = 0;
1386 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1387 if ((mode = apply_result_mode[regno]) != VOIDmode)
1388 {
1389 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1390 if (size % align != 0)
1391 size = CEIL (size, align) * align;
1392 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
e513d163 1393 mem = adjust_address (result, mode, size);
53800dbe 1394 savevec[nelts++] = (savep
1395 ? gen_rtx_SET (VOIDmode, mem, reg)
1396 : gen_rtx_SET (VOIDmode, reg, mem));
1397 size += GET_MODE_SIZE (mode);
1398 }
1399 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1400}
1401#endif /* HAVE_untyped_call or HAVE_untyped_return */
1402
1403/* Save the state required to perform an untyped call with the same
1404 arguments as were passed to the current function. */
1405
1406static rtx
aecda0d6 1407expand_builtin_apply_args_1 (void)
53800dbe 1408{
1c7e61a7 1409 rtx registers, tem;
53800dbe 1410 int size, align, regno;
1411 enum machine_mode mode;
6812c89e 1412 rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
53800dbe 1413
1414 /* Create a block where the arg-pointer, structure value address,
1415 and argument registers can be saved. */
1416 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1417
1418 /* Walk past the arg-pointer and structure value address. */
1419 size = GET_MODE_SIZE (Pmode);
6812c89e 1420 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1421 size += GET_MODE_SIZE (Pmode);
1422
1423 /* Save each register used in calling a function to the block. */
1424 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1425 if ((mode = apply_args_mode[regno]) != VOIDmode)
1426 {
53800dbe 1427 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1428 if (size % align != 0)
1429 size = CEIL (size, align) * align;
1430
1431 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1432
e513d163 1433 emit_move_insn (adjust_address (registers, mode, size), tem);
53800dbe 1434 size += GET_MODE_SIZE (mode);
1435 }
1436
1437 /* Save the arg pointer to the block. */
27a7a23a 1438 tem = copy_to_reg (crtl->args.internal_arg_pointer);
f083a92b 1439#ifdef STACK_GROWS_DOWNWARD
1c7e61a7 1440 /* We need the pointer as the caller actually passed them to us, not
9d4b544c 1441 as we might have pretended they were passed. Make sure it's a valid
1442 operand, as emit_move_insn isn't expected to handle a PLUS. */
1443 tem
29c05e22 1444 = force_operand (plus_constant (Pmode, tem, crtl->args.pretend_args_size),
9d4b544c 1445 NULL_RTX);
1c7e61a7 1446#endif
1447 emit_move_insn (adjust_address (registers, Pmode, 0), tem);
0862b7e9 1448
53800dbe 1449 size = GET_MODE_SIZE (Pmode);
1450
1451 /* Save the structure value address unless this is passed as an
1452 "invisible" first argument. */
45550790 1453 if (struct_incoming_value)
53800dbe 1454 {
e513d163 1455 emit_move_insn (adjust_address (registers, Pmode, size),
45550790 1456 copy_to_reg (struct_incoming_value));
53800dbe 1457 size += GET_MODE_SIZE (Pmode);
1458 }
1459
1460 /* Return the address of the block. */
1461 return copy_addr_to_reg (XEXP (registers, 0));
1462}
1463
1464/* __builtin_apply_args returns block of memory allocated on
1465 the stack into which is stored the arg pointer, structure
1466 value address, static chain, and all the registers that might
1467 possibly be used in performing a function call. The code is
1468 moved to the start of the function so the incoming values are
1469 saved. */
27d0c333 1470
53800dbe 1471static rtx
aecda0d6 1472expand_builtin_apply_args (void)
53800dbe 1473{
1474 /* Don't do __builtin_apply_args more than once in a function.
1475 Save the result of the first call and reuse it. */
1476 if (apply_args_value != 0)
1477 return apply_args_value;
1478 {
1479 /* When this function is called, it means that registers must be
1480 saved on entry to this function. So we migrate the
1481 call to the first insn of this function. */
1482 rtx temp;
1483 rtx seq;
1484
1485 start_sequence ();
1486 temp = expand_builtin_apply_args_1 ();
1487 seq = get_insns ();
1488 end_sequence ();
1489
1490 apply_args_value = temp;
1491
31d3e01c 1492 /* Put the insns after the NOTE that starts the function.
1493 If this is inside a start_sequence, make the outer-level insn
53800dbe 1494 chain current, so the code is placed at the start of the
0ef1a651 1495 function. If internal_arg_pointer is a non-virtual pseudo,
1496 it needs to be placed after the function that initializes
1497 that pseudo. */
53800dbe 1498 push_topmost_sequence ();
0ef1a651 1499 if (REG_P (crtl->args.internal_arg_pointer)
1500 && REGNO (crtl->args.internal_arg_pointer) > LAST_VIRTUAL_REGISTER)
1501 emit_insn_before (seq, parm_birth_insn);
1502 else
1503 emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
53800dbe 1504 pop_topmost_sequence ();
1505 return temp;
1506 }
1507}
1508
1509/* Perform an untyped call and save the state required to perform an
1510 untyped return of whatever value was returned by the given function. */
1511
1512static rtx
aecda0d6 1513expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
53800dbe 1514{
1515 int size, align, regno;
1516 enum machine_mode mode;
2a631e19 1517 rtx incoming_args, result, reg, dest, src, call_insn;
53800dbe 1518 rtx old_stack_level = 0;
1519 rtx call_fusage = 0;
6812c89e 1520 rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
53800dbe 1521
85d654dd 1522 arguments = convert_memory_address (Pmode, arguments);
726ec87c 1523
53800dbe 1524 /* Create a block where the return registers can be saved. */
1525 result = assign_stack_local (BLKmode, apply_result_size (), -1);
1526
53800dbe 1527 /* Fetch the arg pointer from the ARGUMENTS block. */
1528 incoming_args = gen_reg_rtx (Pmode);
726ec87c 1529 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
53800dbe 1530#ifndef STACK_GROWS_DOWNWARD
ad99e708 1531 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1532 incoming_args, 0, OPTAB_LIB_WIDEN);
53800dbe 1533#endif
1534
04a46d40 1535 /* Push a new argument block and copy the arguments. Do not allow
1536 the (potential) memcpy call below to interfere with our stack
1537 manipulations. */
53800dbe 1538 do_pending_stack_adjust ();
04a46d40 1539 NO_DEFER_POP;
53800dbe 1540
2358393e 1541 /* Save the stack with nonlocal if available. */
53800dbe 1542#ifdef HAVE_save_stack_nonlocal
1543 if (HAVE_save_stack_nonlocal)
e9c97615 1544 emit_stack_save (SAVE_NONLOCAL, &old_stack_level);
53800dbe 1545 else
1546#endif
e9c97615 1547 emit_stack_save (SAVE_BLOCK, &old_stack_level);
53800dbe 1548
59647703 1549 /* Allocate a block of memory onto the stack and copy the memory
990495a7 1550 arguments to the outgoing arguments address. We can pass TRUE
1551 as the 4th argument because we just saved the stack pointer
1552 and will restore it right after the call. */
5be42b39 1553 allocate_dynamic_stack_space (argsize, 0, BIGGEST_ALIGNMENT, true);
27a7a23a 1554
1555 /* Set DRAP flag to true, even though allocate_dynamic_stack_space
1556 may have already set current_function_calls_alloca to true.
1557 current_function_calls_alloca won't be set if argsize is zero,
1558 so we have to guarantee need_drap is true here. */
1559 if (SUPPORTS_STACK_ALIGNMENT)
1560 crtl->need_drap = true;
1561
59647703 1562 dest = virtual_outgoing_args_rtx;
1563#ifndef STACK_GROWS_DOWNWARD
971ba038 1564 if (CONST_INT_P (argsize))
29c05e22 1565 dest = plus_constant (Pmode, dest, -INTVAL (argsize));
59647703 1566 else
1567 dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1568#endif
2a631e19 1569 dest = gen_rtx_MEM (BLKmode, dest);
1570 set_mem_align (dest, PARM_BOUNDARY);
1571 src = gen_rtx_MEM (BLKmode, incoming_args);
1572 set_mem_align (src, PARM_BOUNDARY);
0378dbdc 1573 emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
53800dbe 1574
1575 /* Refer to the argument block. */
1576 apply_args_size ();
1577 arguments = gen_rtx_MEM (BLKmode, arguments);
2a631e19 1578 set_mem_align (arguments, PARM_BOUNDARY);
53800dbe 1579
1580 /* Walk past the arg-pointer and structure value address. */
1581 size = GET_MODE_SIZE (Pmode);
45550790 1582 if (struct_value)
53800dbe 1583 size += GET_MODE_SIZE (Pmode);
1584
1585 /* Restore each of the registers previously saved. Make USE insns
1586 for each of these registers for use in making the call. */
1587 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1588 if ((mode = apply_args_mode[regno]) != VOIDmode)
1589 {
1590 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1591 if (size % align != 0)
1592 size = CEIL (size, align) * align;
1593 reg = gen_rtx_REG (mode, regno);
e513d163 1594 emit_move_insn (reg, adjust_address (arguments, mode, size));
53800dbe 1595 use_reg (&call_fusage, reg);
1596 size += GET_MODE_SIZE (mode);
1597 }
1598
1599 /* Restore the structure value address unless this is passed as an
1600 "invisible" first argument. */
1601 size = GET_MODE_SIZE (Pmode);
45550790 1602 if (struct_value)
53800dbe 1603 {
1604 rtx value = gen_reg_rtx (Pmode);
e513d163 1605 emit_move_insn (value, adjust_address (arguments, Pmode, size));
45550790 1606 emit_move_insn (struct_value, value);
8ad4c111 1607 if (REG_P (struct_value))
45550790 1608 use_reg (&call_fusage, struct_value);
53800dbe 1609 size += GET_MODE_SIZE (Pmode);
1610 }
1611
1612 /* All arguments and registers used for the call are set up by now! */
82c7907c 1613 function = prepare_call_address (NULL, function, NULL, &call_fusage, 0, 0);
53800dbe 1614
1615 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1616 and we don't want to load it into a register as an optimization,
1617 because prepare_call_address already did it if it should be done. */
1618 if (GET_CODE (function) != SYMBOL_REF)
1619 function = memory_address (FUNCTION_MODE, function);
1620
1621 /* Generate the actual call instruction and save the return value. */
1622#ifdef HAVE_untyped_call
1623 if (HAVE_untyped_call)
1624 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1625 result, result_vector (1, result)));
1626 else
1627#endif
1628#ifdef HAVE_call_value
1629 if (HAVE_call_value)
1630 {
1631 rtx valreg = 0;
1632
1633 /* Locate the unique return register. It is not possible to
1634 express a call that sets more than one return register using
1635 call_value; use untyped_call for that. In fact, untyped_call
1636 only needs to save the return registers in the given block. */
1637 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1638 if ((mode = apply_result_mode[regno]) != VOIDmode)
1639 {
64db345d 1640 gcc_assert (!valreg); /* HAVE_untyped_call required. */
7d3f6cc7 1641
53800dbe 1642 valreg = gen_rtx_REG (mode, regno);
1643 }
1644
2ed6c343 1645 emit_call_insn (GEN_CALL_VALUE (valreg,
53800dbe 1646 gen_rtx_MEM (FUNCTION_MODE, function),
1647 const0_rtx, NULL_RTX, const0_rtx));
1648
e513d163 1649 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
53800dbe 1650 }
1651 else
1652#endif
64db345d 1653 gcc_unreachable ();
53800dbe 1654
d5f9786f 1655 /* Find the CALL insn we just emitted, and attach the register usage
1656 information. */
1657 call_insn = last_call_insn ();
1658 add_function_usage_to (call_insn, call_fusage);
53800dbe 1659
1660 /* Restore the stack. */
1661#ifdef HAVE_save_stack_nonlocal
1662 if (HAVE_save_stack_nonlocal)
e9c97615 1663 emit_stack_restore (SAVE_NONLOCAL, old_stack_level);
53800dbe 1664 else
1665#endif
e9c97615 1666 emit_stack_restore (SAVE_BLOCK, old_stack_level);
4bb7c660 1667 fixup_args_size_notes (call_insn, get_last_insn(), 0);
53800dbe 1668
04a46d40 1669 OK_DEFER_POP;
1670
53800dbe 1671 /* Return the address of the result block. */
85d654dd 1672 result = copy_addr_to_reg (XEXP (result, 0));
1673 return convert_memory_address (ptr_mode, result);
53800dbe 1674}
1675
1676/* Perform an untyped return. */
1677
1678static void
aecda0d6 1679expand_builtin_return (rtx result)
53800dbe 1680{
1681 int size, align, regno;
1682 enum machine_mode mode;
1683 rtx reg;
1684 rtx call_fusage = 0;
1685
85d654dd 1686 result = convert_memory_address (Pmode, result);
726ec87c 1687
53800dbe 1688 apply_result_size ();
1689 result = gen_rtx_MEM (BLKmode, result);
1690
1691#ifdef HAVE_untyped_return
1692 if (HAVE_untyped_return)
1693 {
1694 emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1695 emit_barrier ();
1696 return;
1697 }
1698#endif
1699
1700 /* Restore the return value and note that each value is used. */
1701 size = 0;
1702 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1703 if ((mode = apply_result_mode[regno]) != VOIDmode)
1704 {
1705 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1706 if (size % align != 0)
1707 size = CEIL (size, align) * align;
1708 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
e513d163 1709 emit_move_insn (reg, adjust_address (result, mode, size));
53800dbe 1710
1711 push_to_sequence (call_fusage);
18b42941 1712 emit_use (reg);
53800dbe 1713 call_fusage = get_insns ();
1714 end_sequence ();
1715 size += GET_MODE_SIZE (mode);
1716 }
1717
1718 /* Put the USE insns before the return. */
31d3e01c 1719 emit_insn (call_fusage);
53800dbe 1720
1721 /* Return whatever values was restored by jumping directly to the end
1722 of the function. */
62380d2d 1723 expand_naked_return ();
53800dbe 1724}
1725
539a3a92 1726/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
27d0c333 1727
539a3a92 1728static enum type_class
aecda0d6 1729type_to_class (tree type)
539a3a92 1730{
1731 switch (TREE_CODE (type))
1732 {
1733 case VOID_TYPE: return void_type_class;
1734 case INTEGER_TYPE: return integer_type_class;
539a3a92 1735 case ENUMERAL_TYPE: return enumeral_type_class;
1736 case BOOLEAN_TYPE: return boolean_type_class;
1737 case POINTER_TYPE: return pointer_type_class;
1738 case REFERENCE_TYPE: return reference_type_class;
1739 case OFFSET_TYPE: return offset_type_class;
1740 case REAL_TYPE: return real_type_class;
1741 case COMPLEX_TYPE: return complex_type_class;
1742 case FUNCTION_TYPE: return function_type_class;
1743 case METHOD_TYPE: return method_type_class;
1744 case RECORD_TYPE: return record_type_class;
1745 case UNION_TYPE:
1746 case QUAL_UNION_TYPE: return union_type_class;
1747 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1748 ? string_type_class : array_type_class);
539a3a92 1749 case LANG_TYPE: return lang_type_class;
1750 default: return no_type_class;
1751 }
1752}
bf8e3599 1753
c2f47e15 1754/* Expand a call EXP to __builtin_classify_type. */
27d0c333 1755
53800dbe 1756static rtx
c2f47e15 1757expand_builtin_classify_type (tree exp)
53800dbe 1758{
c2f47e15 1759 if (call_expr_nargs (exp))
1760 return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0))));
53800dbe 1761 return GEN_INT (no_type_class);
1762}
1763
07976da7 1764/* This helper macro, meant to be used in mathfn_built_in below,
1765 determines which among a set of three builtin math functions is
1766 appropriate for a given type mode. The `F' and `L' cases are
1767 automatically generated from the `double' case. */
1768#define CASE_MATHFN(BUILT_IN_MATHFN) \
1769 case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1770 fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1771 fcodel = BUILT_IN_MATHFN##L ; break;
cd2656b0 1772/* Similar to above, but appends _R after any F/L suffix. */
1773#define CASE_MATHFN_REENT(BUILT_IN_MATHFN) \
1774 case BUILT_IN_MATHFN##_R: case BUILT_IN_MATHFN##F_R: case BUILT_IN_MATHFN##L_R: \
1775 fcode = BUILT_IN_MATHFN##_R; fcodef = BUILT_IN_MATHFN##F_R ; \
1776 fcodel = BUILT_IN_MATHFN##L_R ; break;
07976da7 1777
b9a16870 1778/* Return mathematic function equivalent to FN but operating directly on TYPE,
1779 if available. If IMPLICIT is true use the implicit builtin declaration,
1780 otherwise use the explicit declaration. If we can't do the conversion,
1781 return zero. */
c319d56a 1782
1783static tree
b9a16870 1784mathfn_built_in_1 (tree type, enum built_in_function fn, bool implicit_p)
0a68165a 1785{
b9a16870 1786 enum built_in_function fcode, fcodef, fcodel, fcode2;
07976da7 1787
1788 switch (fn)
1789 {
746114e8 1790 CASE_MATHFN (BUILT_IN_ACOS)
1791 CASE_MATHFN (BUILT_IN_ACOSH)
1792 CASE_MATHFN (BUILT_IN_ASIN)
1793 CASE_MATHFN (BUILT_IN_ASINH)
07976da7 1794 CASE_MATHFN (BUILT_IN_ATAN)
746114e8 1795 CASE_MATHFN (BUILT_IN_ATAN2)
1796 CASE_MATHFN (BUILT_IN_ATANH)
1797 CASE_MATHFN (BUILT_IN_CBRT)
07976da7 1798 CASE_MATHFN (BUILT_IN_CEIL)
d735c391 1799 CASE_MATHFN (BUILT_IN_CEXPI)
746114e8 1800 CASE_MATHFN (BUILT_IN_COPYSIGN)
07976da7 1801 CASE_MATHFN (BUILT_IN_COS)
746114e8 1802 CASE_MATHFN (BUILT_IN_COSH)
1803 CASE_MATHFN (BUILT_IN_DREM)
1804 CASE_MATHFN (BUILT_IN_ERF)
1805 CASE_MATHFN (BUILT_IN_ERFC)
07976da7 1806 CASE_MATHFN (BUILT_IN_EXP)
746114e8 1807 CASE_MATHFN (BUILT_IN_EXP10)
1808 CASE_MATHFN (BUILT_IN_EXP2)
1809 CASE_MATHFN (BUILT_IN_EXPM1)
1810 CASE_MATHFN (BUILT_IN_FABS)
1811 CASE_MATHFN (BUILT_IN_FDIM)
07976da7 1812 CASE_MATHFN (BUILT_IN_FLOOR)
746114e8 1813 CASE_MATHFN (BUILT_IN_FMA)
1814 CASE_MATHFN (BUILT_IN_FMAX)
1815 CASE_MATHFN (BUILT_IN_FMIN)
1816 CASE_MATHFN (BUILT_IN_FMOD)
1817 CASE_MATHFN (BUILT_IN_FREXP)
1818 CASE_MATHFN (BUILT_IN_GAMMA)
cd2656b0 1819 CASE_MATHFN_REENT (BUILT_IN_GAMMA) /* GAMMA_R */
746114e8 1820 CASE_MATHFN (BUILT_IN_HUGE_VAL)
1821 CASE_MATHFN (BUILT_IN_HYPOT)
1822 CASE_MATHFN (BUILT_IN_ILOGB)
80ff6494 1823 CASE_MATHFN (BUILT_IN_ICEIL)
1824 CASE_MATHFN (BUILT_IN_IFLOOR)
746114e8 1825 CASE_MATHFN (BUILT_IN_INF)
80ff6494 1826 CASE_MATHFN (BUILT_IN_IRINT)
1827 CASE_MATHFN (BUILT_IN_IROUND)
69b779ea 1828 CASE_MATHFN (BUILT_IN_ISINF)
746114e8 1829 CASE_MATHFN (BUILT_IN_J0)
1830 CASE_MATHFN (BUILT_IN_J1)
1831 CASE_MATHFN (BUILT_IN_JN)
ac148751 1832 CASE_MATHFN (BUILT_IN_LCEIL)
746114e8 1833 CASE_MATHFN (BUILT_IN_LDEXP)
ad52b9b7 1834 CASE_MATHFN (BUILT_IN_LFLOOR)
746114e8 1835 CASE_MATHFN (BUILT_IN_LGAMMA)
cd2656b0 1836 CASE_MATHFN_REENT (BUILT_IN_LGAMMA) /* LGAMMA_R */
ac148751 1837 CASE_MATHFN (BUILT_IN_LLCEIL)
ad52b9b7 1838 CASE_MATHFN (BUILT_IN_LLFLOOR)
746114e8 1839 CASE_MATHFN (BUILT_IN_LLRINT)
1840 CASE_MATHFN (BUILT_IN_LLROUND)
07976da7 1841 CASE_MATHFN (BUILT_IN_LOG)
746114e8 1842 CASE_MATHFN (BUILT_IN_LOG10)
1843 CASE_MATHFN (BUILT_IN_LOG1P)
1844 CASE_MATHFN (BUILT_IN_LOG2)
1845 CASE_MATHFN (BUILT_IN_LOGB)
1846 CASE_MATHFN (BUILT_IN_LRINT)
1847 CASE_MATHFN (BUILT_IN_LROUND)
1848 CASE_MATHFN (BUILT_IN_MODF)
1849 CASE_MATHFN (BUILT_IN_NAN)
1850 CASE_MATHFN (BUILT_IN_NANS)
07976da7 1851 CASE_MATHFN (BUILT_IN_NEARBYINT)
746114e8 1852 CASE_MATHFN (BUILT_IN_NEXTAFTER)
1853 CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1854 CASE_MATHFN (BUILT_IN_POW)
757c219d 1855 CASE_MATHFN (BUILT_IN_POWI)
746114e8 1856 CASE_MATHFN (BUILT_IN_POW10)
1857 CASE_MATHFN (BUILT_IN_REMAINDER)
1858 CASE_MATHFN (BUILT_IN_REMQUO)
1859 CASE_MATHFN (BUILT_IN_RINT)
07976da7 1860 CASE_MATHFN (BUILT_IN_ROUND)
746114e8 1861 CASE_MATHFN (BUILT_IN_SCALB)
1862 CASE_MATHFN (BUILT_IN_SCALBLN)
1863 CASE_MATHFN (BUILT_IN_SCALBN)
c319d56a 1864 CASE_MATHFN (BUILT_IN_SIGNBIT)
746114e8 1865 CASE_MATHFN (BUILT_IN_SIGNIFICAND)
07976da7 1866 CASE_MATHFN (BUILT_IN_SIN)
746114e8 1867 CASE_MATHFN (BUILT_IN_SINCOS)
1868 CASE_MATHFN (BUILT_IN_SINH)
07976da7 1869 CASE_MATHFN (BUILT_IN_SQRT)
1870 CASE_MATHFN (BUILT_IN_TAN)
746114e8 1871 CASE_MATHFN (BUILT_IN_TANH)
1872 CASE_MATHFN (BUILT_IN_TGAMMA)
07976da7 1873 CASE_MATHFN (BUILT_IN_TRUNC)
746114e8 1874 CASE_MATHFN (BUILT_IN_Y0)
1875 CASE_MATHFN (BUILT_IN_Y1)
1876 CASE_MATHFN (BUILT_IN_YN)
07976da7 1877
0a68165a 1878 default:
c2f47e15 1879 return NULL_TREE;
0a68165a 1880 }
07976da7 1881
96b9f485 1882 if (TYPE_MAIN_VARIANT (type) == double_type_node)
b9a16870 1883 fcode2 = fcode;
96b9f485 1884 else if (TYPE_MAIN_VARIANT (type) == float_type_node)
b9a16870 1885 fcode2 = fcodef;
96b9f485 1886 else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
b9a16870 1887 fcode2 = fcodel;
07976da7 1888 else
c2f47e15 1889 return NULL_TREE;
b9a16870 1890
1891 if (implicit_p && !builtin_decl_implicit_p (fcode2))
1892 return NULL_TREE;
1893
1894 return builtin_decl_explicit (fcode2);
0a68165a 1895}
1896
c319d56a 1897/* Like mathfn_built_in_1(), but always use the implicit array. */
1898
1899tree
1900mathfn_built_in (tree type, enum built_in_function fn)
1901{
1902 return mathfn_built_in_1 (type, fn, /*implicit=*/ 1);
1903}
1904
0fd605a5 1905/* If errno must be maintained, expand the RTL to check if the result,
1906 TARGET, of a built-in function call, EXP, is NaN, and if so set
1907 errno to EDOM. */
1908
1909static void
aecda0d6 1910expand_errno_check (tree exp, rtx target)
0fd605a5 1911{
7f05340e 1912 rtx lab = gen_label_rtx ();
0fd605a5 1913
7f05340e 1914 /* Test the result; if it is NaN, set errno=EDOM because
1915 the argument was not in the domain. */
3fcf767f 1916 do_compare_rtx_and_jump (target, target, EQ, 0, GET_MODE (target),
79ab74cc 1917 NULL_RTX, NULL_RTX, lab,
1918 /* The jump is very likely. */
1919 REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1));
0fd605a5 1920
1921#ifdef TARGET_EDOM
7f05340e 1922 /* If this built-in doesn't throw an exception, set errno directly. */
c2f47e15 1923 if (TREE_NOTHROW (TREE_OPERAND (CALL_EXPR_FN (exp), 0)))
7f05340e 1924 {
0fd605a5 1925#ifdef GEN_ERRNO_RTX
7f05340e 1926 rtx errno_rtx = GEN_ERRNO_RTX;
0fd605a5 1927#else
7f05340e 1928 rtx errno_rtx
0fd605a5 1929 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1930#endif
7f05340e 1931 emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
0fd605a5 1932 emit_label (lab);
7f05340e 1933 return;
0fd605a5 1934 }
7f05340e 1935#endif
1936
08491912 1937 /* Make sure the library call isn't expanded as a tail call. */
1938 CALL_EXPR_TAILCALL (exp) = 0;
1939
7f05340e 1940 /* We can't set errno=EDOM directly; let the library call do it.
1941 Pop the arguments right away in case the call gets deleted. */
1942 NO_DEFER_POP;
1943 expand_call (exp, target, 0);
1944 OK_DEFER_POP;
1945 emit_label (lab);
0fd605a5 1946}
1947
6b43bae4 1948/* Expand a call to one of the builtin math functions (sqrt, exp, or log).
c2f47e15 1949 Return NULL_RTX if a normal call should be emitted rather than expanding
1950 the function in-line. EXP is the expression that is a call to the builtin
53800dbe 1951 function; if convenient, the result should be placed in TARGET.
1952 SUBTARGET may be used as the target for computing one of EXP's operands. */
27d0c333 1953
53800dbe 1954static rtx
aecda0d6 1955expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
53800dbe 1956{
bf8e3599 1957 optab builtin_optab;
1e4adcfc 1958 rtx op0, insns;
c6e6ecb1 1959 tree fndecl = get_callee_fndecl (exp);
7f05340e 1960 enum machine_mode mode;
528ee710 1961 bool errno_set = false;
abfea505 1962 tree arg;
53800dbe 1963
c2f47e15 1964 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
1965 return NULL_RTX;
53800dbe 1966
c2f47e15 1967 arg = CALL_EXPR_ARG (exp, 0);
53800dbe 1968
1969 switch (DECL_FUNCTION_CODE (fndecl))
1970 {
4f35b1fc 1971 CASE_FLT_FN (BUILT_IN_SQRT):
7f05340e 1972 errno_set = ! tree_expr_nonnegative_p (arg);
1973 builtin_optab = sqrt_optab;
1974 break;
4f35b1fc 1975 CASE_FLT_FN (BUILT_IN_EXP):
528ee710 1976 errno_set = true; builtin_optab = exp_optab; break;
4f35b1fc 1977 CASE_FLT_FN (BUILT_IN_EXP10):
1978 CASE_FLT_FN (BUILT_IN_POW10):
750ef9f5 1979 errno_set = true; builtin_optab = exp10_optab; break;
4f35b1fc 1980 CASE_FLT_FN (BUILT_IN_EXP2):
750ef9f5 1981 errno_set = true; builtin_optab = exp2_optab; break;
4f35b1fc 1982 CASE_FLT_FN (BUILT_IN_EXPM1):
a6b4eed2 1983 errno_set = true; builtin_optab = expm1_optab; break;
4f35b1fc 1984 CASE_FLT_FN (BUILT_IN_LOGB):
4efbc641 1985 errno_set = true; builtin_optab = logb_optab; break;
4f35b1fc 1986 CASE_FLT_FN (BUILT_IN_LOG):
528ee710 1987 errno_set = true; builtin_optab = log_optab; break;
4f35b1fc 1988 CASE_FLT_FN (BUILT_IN_LOG10):
d3cd9bde 1989 errno_set = true; builtin_optab = log10_optab; break;
4f35b1fc 1990 CASE_FLT_FN (BUILT_IN_LOG2):
d3cd9bde 1991 errno_set = true; builtin_optab = log2_optab; break;
4f35b1fc 1992 CASE_FLT_FN (BUILT_IN_LOG1P):
f474cd93 1993 errno_set = true; builtin_optab = log1p_optab; break;
4f35b1fc 1994 CASE_FLT_FN (BUILT_IN_ASIN):
8de2f465 1995 builtin_optab = asin_optab; break;
4f35b1fc 1996 CASE_FLT_FN (BUILT_IN_ACOS):
8de2f465 1997 builtin_optab = acos_optab; break;
4f35b1fc 1998 CASE_FLT_FN (BUILT_IN_TAN):
528ee710 1999 builtin_optab = tan_optab; break;
4f35b1fc 2000 CASE_FLT_FN (BUILT_IN_ATAN):
528ee710 2001 builtin_optab = atan_optab; break;
4f35b1fc 2002 CASE_FLT_FN (BUILT_IN_FLOOR):
528ee710 2003 builtin_optab = floor_optab; break;
4f35b1fc 2004 CASE_FLT_FN (BUILT_IN_CEIL):
528ee710 2005 builtin_optab = ceil_optab; break;
4f35b1fc 2006 CASE_FLT_FN (BUILT_IN_TRUNC):
a7cc195f 2007 builtin_optab = btrunc_optab; break;
4f35b1fc 2008 CASE_FLT_FN (BUILT_IN_ROUND):
528ee710 2009 builtin_optab = round_optab; break;
4f35b1fc 2010 CASE_FLT_FN (BUILT_IN_NEARBYINT):
0ddf4ad9 2011 builtin_optab = nearbyint_optab;
2012 if (flag_trapping_math)
2013 break;
2014 /* Else fallthrough and expand as rint. */
4f35b1fc 2015 CASE_FLT_FN (BUILT_IN_RINT):
aef94a0f 2016 builtin_optab = rint_optab; break;
b3154a1f 2017 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
2018 builtin_optab = significand_optab; break;
42721db0 2019 default:
64db345d 2020 gcc_unreachable ();
53800dbe 2021 }
2022
7f05340e 2023 /* Make a suitable register to place result in. */
2024 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2025
7f05340e 2026 if (! flag_errno_math || ! HONOR_NANS (mode))
2027 errno_set = false;
2028
bd421108 2029 /* Before working hard, check whether the instruction is available. */
f2aca212 2030 if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing
2031 && (!errno_set || !optimize_insn_for_size_p ()))
68e6cb9d 2032 {
bd421108 2033 target = gen_reg_rtx (mode);
7f05340e 2034
bd421108 2035 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2036 need to expand the argument again. This way, we will not perform
2037 side-effects more the once. */
abfea505 2038 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7f05340e 2039
1db6d067 2040 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
7f05340e 2041
bd421108 2042 start_sequence ();
53800dbe 2043
bd421108 2044 /* Compute into TARGET.
2045 Set TARGET to wherever the result comes back. */
2046 target = expand_unop (mode, builtin_optab, op0, target, 0);
2047
2048 if (target != 0)
2049 {
2050 if (errno_set)
2051 expand_errno_check (exp, target);
2052
2053 /* Output the entire sequence. */
2054 insns = get_insns ();
2055 end_sequence ();
2056 emit_insn (insns);
2057 return target;
2058 }
2059
2060 /* If we were unable to expand via the builtin, stop the sequence
2061 (without outputting the insns) and call to the library function
2062 with the stabilized argument list. */
53800dbe 2063 end_sequence ();
53800dbe 2064 }
2065
1e5b92fa 2066 return expand_call (exp, target, target == const0_rtx);
0fd605a5 2067}
2068
2069/* Expand a call to the builtin binary math functions (pow and atan2).
c2f47e15 2070 Return NULL_RTX if a normal call should be emitted rather than expanding the
0fd605a5 2071 function in-line. EXP is the expression that is a call to the builtin
2072 function; if convenient, the result should be placed in TARGET.
2073 SUBTARGET may be used as the target for computing one of EXP's
2074 operands. */
2075
2076static rtx
aecda0d6 2077expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
0fd605a5 2078{
2079 optab builtin_optab;
2080 rtx op0, op1, insns;
4737caf2 2081 int op1_type = REAL_TYPE;
c6e6ecb1 2082 tree fndecl = get_callee_fndecl (exp);
abfea505 2083 tree arg0, arg1;
7f05340e 2084 enum machine_mode mode;
0fd605a5 2085 bool errno_set = true;
0fd605a5 2086
73a954a1 2087 switch (DECL_FUNCTION_CODE (fndecl))
2088 {
2089 CASE_FLT_FN (BUILT_IN_SCALBN):
2090 CASE_FLT_FN (BUILT_IN_SCALBLN):
2091 CASE_FLT_FN (BUILT_IN_LDEXP):
2092 op1_type = INTEGER_TYPE;
2093 default:
2094 break;
2095 }
4737caf2 2096
c2f47e15 2097 if (!validate_arglist (exp, REAL_TYPE, op1_type, VOID_TYPE))
2098 return NULL_RTX;
0fd605a5 2099
c2f47e15 2100 arg0 = CALL_EXPR_ARG (exp, 0);
2101 arg1 = CALL_EXPR_ARG (exp, 1);
0fd605a5 2102
0fd605a5 2103 switch (DECL_FUNCTION_CODE (fndecl))
2104 {
4f35b1fc 2105 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 2106 builtin_optab = pow_optab; break;
4f35b1fc 2107 CASE_FLT_FN (BUILT_IN_ATAN2):
0fd605a5 2108 builtin_optab = atan2_optab; break;
73a954a1 2109 CASE_FLT_FN (BUILT_IN_SCALB):
2110 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2111 return 0;
2112 builtin_optab = scalb_optab; break;
2113 CASE_FLT_FN (BUILT_IN_SCALBN):
2114 CASE_FLT_FN (BUILT_IN_SCALBLN):
2115 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2116 return 0;
2117 /* Fall through... */
4f35b1fc 2118 CASE_FLT_FN (BUILT_IN_LDEXP):
4737caf2 2119 builtin_optab = ldexp_optab; break;
4f35b1fc 2120 CASE_FLT_FN (BUILT_IN_FMOD):
80ed5c06 2121 builtin_optab = fmod_optab; break;
ef722005 2122 CASE_FLT_FN (BUILT_IN_REMAINDER):
4f35b1fc 2123 CASE_FLT_FN (BUILT_IN_DREM):
ef722005 2124 builtin_optab = remainder_optab; break;
0fd605a5 2125 default:
64db345d 2126 gcc_unreachable ();
0fd605a5 2127 }
2128
7f05340e 2129 /* Make a suitable register to place result in. */
2130 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2131
2132 /* Before working hard, check whether the instruction is available. */
d6bf3b14 2133 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
c2f47e15 2134 return NULL_RTX;
fc4eef90 2135
7f05340e 2136 target = gen_reg_rtx (mode);
2137
2138 if (! flag_errno_math || ! HONOR_NANS (mode))
2139 errno_set = false;
2140
f2aca212 2141 if (errno_set && optimize_insn_for_size_p ())
2142 return 0;
2143
4ee9c684 2144 /* Always stabilize the argument list. */
abfea505 2145 CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
2146 CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
7f05340e 2147
8ec3c5c2 2148 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2149 op1 = expand_normal (arg1);
7f05340e 2150
7f05340e 2151 start_sequence ();
2152
0fd605a5 2153 /* Compute into TARGET.
2154 Set TARGET to wherever the result comes back. */
7f05340e 2155 target = expand_binop (mode, builtin_optab, op0, op1,
0fd605a5 2156 target, 0, OPTAB_DIRECT);
53800dbe 2157
68e6cb9d 2158 /* If we were unable to expand via the builtin, stop the sequence
2159 (without outputting the insns) and call to the library function
2160 with the stabilized argument list. */
0fd605a5 2161 if (target == 0)
2162 {
2163 end_sequence ();
68e6cb9d 2164 return expand_call (exp, target, target == const0_rtx);
53800dbe 2165 }
2166
a4356fb9 2167 if (errno_set)
2168 expand_errno_check (exp, target);
0fd605a5 2169
53800dbe 2170 /* Output the entire sequence. */
2171 insns = get_insns ();
2172 end_sequence ();
31d3e01c 2173 emit_insn (insns);
bf8e3599 2174
53800dbe 2175 return target;
2176}
2177
7e0713b1 2178/* Expand a call to the builtin trinary math functions (fma).
2179 Return NULL_RTX if a normal call should be emitted rather than expanding the
2180 function in-line. EXP is the expression that is a call to the builtin
2181 function; if convenient, the result should be placed in TARGET.
2182 SUBTARGET may be used as the target for computing one of EXP's
2183 operands. */
2184
2185static rtx
2186expand_builtin_mathfn_ternary (tree exp, rtx target, rtx subtarget)
2187{
2188 optab builtin_optab;
2189 rtx op0, op1, op2, insns;
2190 tree fndecl = get_callee_fndecl (exp);
2191 tree arg0, arg1, arg2;
2192 enum machine_mode mode;
2193
2194 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2195 return NULL_RTX;
2196
2197 arg0 = CALL_EXPR_ARG (exp, 0);
2198 arg1 = CALL_EXPR_ARG (exp, 1);
2199 arg2 = CALL_EXPR_ARG (exp, 2);
2200
2201 switch (DECL_FUNCTION_CODE (fndecl))
2202 {
2203 CASE_FLT_FN (BUILT_IN_FMA):
2204 builtin_optab = fma_optab; break;
2205 default:
2206 gcc_unreachable ();
2207 }
2208
2209 /* Make a suitable register to place result in. */
2210 mode = TYPE_MODE (TREE_TYPE (exp));
2211
2212 /* Before working hard, check whether the instruction is available. */
2213 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
2214 return NULL_RTX;
2215
2216 target = gen_reg_rtx (mode);
2217
2218 /* Always stabilize the argument list. */
2219 CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
2220 CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
2221 CALL_EXPR_ARG (exp, 2) = arg2 = builtin_save_expr (arg2);
2222
2223 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2224 op1 = expand_normal (arg1);
2225 op2 = expand_normal (arg2);
2226
2227 start_sequence ();
2228
2229 /* Compute into TARGET.
2230 Set TARGET to wherever the result comes back. */
2231 target = expand_ternary_op (mode, builtin_optab, op0, op1, op2,
2232 target, 0);
2233
2234 /* If we were unable to expand via the builtin, stop the sequence
2235 (without outputting the insns) and call to the library function
2236 with the stabilized argument list. */
2237 if (target == 0)
2238 {
2239 end_sequence ();
2240 return expand_call (exp, target, target == const0_rtx);
2241 }
2242
2243 /* Output the entire sequence. */
2244 insns = get_insns ();
2245 end_sequence ();
2246 emit_insn (insns);
2247
2248 return target;
2249}
2250
6b43bae4 2251/* Expand a call to the builtin sin and cos math functions.
c2f47e15 2252 Return NULL_RTX if a normal call should be emitted rather than expanding the
6b43bae4 2253 function in-line. EXP is the expression that is a call to the builtin
2254 function; if convenient, the result should be placed in TARGET.
2255 SUBTARGET may be used as the target for computing one of EXP's
2256 operands. */
2257
2258static rtx
2259expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
2260{
2261 optab builtin_optab;
7511b819 2262 rtx op0, insns;
6b43bae4 2263 tree fndecl = get_callee_fndecl (exp);
6b43bae4 2264 enum machine_mode mode;
abfea505 2265 tree arg;
6b43bae4 2266
c2f47e15 2267 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2268 return NULL_RTX;
6b43bae4 2269
c2f47e15 2270 arg = CALL_EXPR_ARG (exp, 0);
6b43bae4 2271
2272 switch (DECL_FUNCTION_CODE (fndecl))
2273 {
4f35b1fc 2274 CASE_FLT_FN (BUILT_IN_SIN):
2275 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2276 builtin_optab = sincos_optab; break;
2277 default:
64db345d 2278 gcc_unreachable ();
6b43bae4 2279 }
2280
2281 /* Make a suitable register to place result in. */
2282 mode = TYPE_MODE (TREE_TYPE (exp));
2283
6b43bae4 2284 /* Check if sincos insn is available, otherwise fallback
0bed3869 2285 to sin or cos insn. */
d6bf3b14 2286 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
6b43bae4 2287 switch (DECL_FUNCTION_CODE (fndecl))
2288 {
4f35b1fc 2289 CASE_FLT_FN (BUILT_IN_SIN):
6b43bae4 2290 builtin_optab = sin_optab; break;
4f35b1fc 2291 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2292 builtin_optab = cos_optab; break;
2293 default:
64db345d 2294 gcc_unreachable ();
6b43bae4 2295 }
6b43bae4 2296
2297 /* Before working hard, check whether the instruction is available. */
d6bf3b14 2298 if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing)
6b43bae4 2299 {
2300 target = gen_reg_rtx (mode);
2301
2302 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2303 need to expand the argument again. This way, we will not perform
2304 side-effects more the once. */
abfea505 2305 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
6b43bae4 2306
1db6d067 2307 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
6b43bae4 2308
6b43bae4 2309 start_sequence ();
2310
2311 /* Compute into TARGET.
2312 Set TARGET to wherever the result comes back. */
2313 if (builtin_optab == sincos_optab)
2314 {
64db345d 2315 int result;
7d3f6cc7 2316
6b43bae4 2317 switch (DECL_FUNCTION_CODE (fndecl))
2318 {
4f35b1fc 2319 CASE_FLT_FN (BUILT_IN_SIN):
64db345d 2320 result = expand_twoval_unop (builtin_optab, op0, 0, target, 0);
6b43bae4 2321 break;
4f35b1fc 2322 CASE_FLT_FN (BUILT_IN_COS):
64db345d 2323 result = expand_twoval_unop (builtin_optab, op0, target, 0, 0);
6b43bae4 2324 break;
2325 default:
64db345d 2326 gcc_unreachable ();
6b43bae4 2327 }
64db345d 2328 gcc_assert (result);
6b43bae4 2329 }
2330 else
2331 {
2332 target = expand_unop (mode, builtin_optab, op0, target, 0);
2333 }
2334
2335 if (target != 0)
2336 {
6b43bae4 2337 /* Output the entire sequence. */
2338 insns = get_insns ();
2339 end_sequence ();
2340 emit_insn (insns);
2341 return target;
2342 }
2343
2344 /* If we were unable to expand via the builtin, stop the sequence
2345 (without outputting the insns) and call to the library function
2346 with the stabilized argument list. */
2347 end_sequence ();
2348 }
2349
6b43bae4 2350 target = expand_call (exp, target, target == const0_rtx);
2351
2352 return target;
2353}
2354
a65c4d64 2355/* Given an interclass math builtin decl FNDECL and it's argument ARG
2356 return an RTL instruction code that implements the functionality.
2357 If that isn't possible or available return CODE_FOR_nothing. */
a67a90e5 2358
a65c4d64 2359static enum insn_code
2360interclass_mathfn_icode (tree arg, tree fndecl)
a67a90e5 2361{
a65c4d64 2362 bool errno_set = false;
6cdd383a 2363 optab builtin_optab = unknown_optab;
a67a90e5 2364 enum machine_mode mode;
a67a90e5 2365
2366 switch (DECL_FUNCTION_CODE (fndecl))
2367 {
2368 CASE_FLT_FN (BUILT_IN_ILOGB):
2369 errno_set = true; builtin_optab = ilogb_optab; break;
69b779ea 2370 CASE_FLT_FN (BUILT_IN_ISINF):
2371 builtin_optab = isinf_optab; break;
8a1a9cb7 2372 case BUILT_IN_ISNORMAL:
cde061c1 2373 case BUILT_IN_ISFINITE:
2374 CASE_FLT_FN (BUILT_IN_FINITE):
a65c4d64 2375 case BUILT_IN_FINITED32:
2376 case BUILT_IN_FINITED64:
2377 case BUILT_IN_FINITED128:
2378 case BUILT_IN_ISINFD32:
2379 case BUILT_IN_ISINFD64:
2380 case BUILT_IN_ISINFD128:
cde061c1 2381 /* These builtins have no optabs (yet). */
2382 break;
a67a90e5 2383 default:
2384 gcc_unreachable ();
2385 }
2386
2387 /* There's no easy way to detect the case we need to set EDOM. */
2388 if (flag_errno_math && errno_set)
a65c4d64 2389 return CODE_FOR_nothing;
a67a90e5 2390
2391 /* Optab mode depends on the mode of the input argument. */
2392 mode = TYPE_MODE (TREE_TYPE (arg));
2393
cde061c1 2394 if (builtin_optab)
d6bf3b14 2395 return optab_handler (builtin_optab, mode);
a65c4d64 2396 return CODE_FOR_nothing;
2397}
2398
2399/* Expand a call to one of the builtin math functions that operate on
2400 floating point argument and output an integer result (ilogb, isinf,
2401 isnan, etc).
2402 Return 0 if a normal call should be emitted rather than expanding the
2403 function in-line. EXP is the expression that is a call to the builtin
f97eea22 2404 function; if convenient, the result should be placed in TARGET. */
a65c4d64 2405
2406static rtx
f97eea22 2407expand_builtin_interclass_mathfn (tree exp, rtx target)
a65c4d64 2408{
2409 enum insn_code icode = CODE_FOR_nothing;
2410 rtx op0;
2411 tree fndecl = get_callee_fndecl (exp);
2412 enum machine_mode mode;
2413 tree arg;
2414
2415 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2416 return NULL_RTX;
2417
2418 arg = CALL_EXPR_ARG (exp, 0);
2419 icode = interclass_mathfn_icode (arg, fndecl);
2420 mode = TYPE_MODE (TREE_TYPE (arg));
2421
a67a90e5 2422 if (icode != CODE_FOR_nothing)
2423 {
8786db1e 2424 struct expand_operand ops[1];
4e2a2fb4 2425 rtx last = get_last_insn ();
2426 tree orig_arg = arg;
a67a90e5 2427
2428 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2429 need to expand the argument again. This way, we will not perform
2430 side-effects more the once. */
abfea505 2431 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
a67a90e5 2432
f97eea22 2433 op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
a67a90e5 2434
2435 if (mode != GET_MODE (op0))
2436 op0 = convert_to_mode (mode, op0, 0);
2437
8786db1e 2438 create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
2439 if (maybe_legitimize_operands (icode, 0, 1, ops)
2440 && maybe_emit_unop_insn (icode, ops[0].value, op0, UNKNOWN))
2441 return ops[0].value;
2442
4e2a2fb4 2443 delete_insns_since (last);
2444 CALL_EXPR_ARG (exp, 0) = orig_arg;
a67a90e5 2445 }
2446
a65c4d64 2447 return NULL_RTX;
a67a90e5 2448}
2449
c3147c1a 2450/* Expand a call to the builtin sincos math function.
c2f47e15 2451 Return NULL_RTX if a normal call should be emitted rather than expanding the
c3147c1a 2452 function in-line. EXP is the expression that is a call to the builtin
2453 function. */
2454
2455static rtx
2456expand_builtin_sincos (tree exp)
2457{
2458 rtx op0, op1, op2, target1, target2;
c3147c1a 2459 enum machine_mode mode;
2460 tree arg, sinp, cosp;
2461 int result;
389dd41b 2462 location_t loc = EXPR_LOCATION (exp);
be5575b2 2463 tree alias_type, alias_off;
c3147c1a 2464
c2f47e15 2465 if (!validate_arglist (exp, REAL_TYPE,
2466 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2467 return NULL_RTX;
c3147c1a 2468
c2f47e15 2469 arg = CALL_EXPR_ARG (exp, 0);
2470 sinp = CALL_EXPR_ARG (exp, 1);
2471 cosp = CALL_EXPR_ARG (exp, 2);
c3147c1a 2472
2473 /* Make a suitable register to place result in. */
2474 mode = TYPE_MODE (TREE_TYPE (arg));
2475
2476 /* Check if sincos insn is available, otherwise emit the call. */
d6bf3b14 2477 if (optab_handler (sincos_optab, mode) == CODE_FOR_nothing)
c3147c1a 2478 return NULL_RTX;
2479
2480 target1 = gen_reg_rtx (mode);
2481 target2 = gen_reg_rtx (mode);
2482
8ec3c5c2 2483 op0 = expand_normal (arg);
be5575b2 2484 alias_type = build_pointer_type_for_mode (TREE_TYPE (arg), ptr_mode, true);
2485 alias_off = build_int_cst (alias_type, 0);
2486 op1 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
2487 sinp, alias_off));
2488 op2 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
2489 cosp, alias_off));
c3147c1a 2490
2491 /* Compute into target1 and target2.
2492 Set TARGET to wherever the result comes back. */
2493 result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
2494 gcc_assert (result);
2495
2496 /* Move target1 and target2 to the memory locations indicated
2497 by op1 and op2. */
2498 emit_move_insn (op1, target1);
2499 emit_move_insn (op2, target2);
2500
2501 return const0_rtx;
2502}
2503
d735c391 2504/* Expand a call to the internal cexpi builtin to the sincos math function.
2505 EXP is the expression that is a call to the builtin function; if convenient,
f97eea22 2506 the result should be placed in TARGET. */
d735c391 2507
2508static rtx
f97eea22 2509expand_builtin_cexpi (tree exp, rtx target)
d735c391 2510{
2511 tree fndecl = get_callee_fndecl (exp);
d735c391 2512 tree arg, type;
c2f47e15 2513 enum machine_mode mode;
d735c391 2514 rtx op0, op1, op2;
389dd41b 2515 location_t loc = EXPR_LOCATION (exp);
d735c391 2516
c2f47e15 2517 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2518 return NULL_RTX;
d735c391 2519
c2f47e15 2520 arg = CALL_EXPR_ARG (exp, 0);
d735c391 2521 type = TREE_TYPE (arg);
2522 mode = TYPE_MODE (TREE_TYPE (arg));
2523
2524 /* Try expanding via a sincos optab, fall back to emitting a libcall
18b8d8ae 2525 to sincos or cexp. We are sure we have sincos or cexp because cexpi
2526 is only generated from sincos, cexp or if we have either of them. */
d6bf3b14 2527 if (optab_handler (sincos_optab, mode) != CODE_FOR_nothing)
d735c391 2528 {
2529 op1 = gen_reg_rtx (mode);
2530 op2 = gen_reg_rtx (mode);
2531
f97eea22 2532 op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
d735c391 2533
2534 /* Compute into op1 and op2. */
2535 expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
2536 }
18b8d8ae 2537 else if (TARGET_HAS_SINCOS)
d735c391 2538 {
c2f47e15 2539 tree call, fn = NULL_TREE;
d735c391 2540 tree top1, top2;
2541 rtx op1a, op2a;
2542
2543 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
b9a16870 2544 fn = builtin_decl_explicit (BUILT_IN_SINCOSF);
d735c391 2545 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
b9a16870 2546 fn = builtin_decl_explicit (BUILT_IN_SINCOS);
d735c391 2547 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
b9a16870 2548 fn = builtin_decl_explicit (BUILT_IN_SINCOSL);
c2f47e15 2549 else
2550 gcc_unreachable ();
48e1416a 2551
0ab48139 2552 op1 = assign_temp (TREE_TYPE (arg), 1, 1);
2553 op2 = assign_temp (TREE_TYPE (arg), 1, 1);
99182918 2554 op1a = copy_addr_to_reg (XEXP (op1, 0));
2555 op2a = copy_addr_to_reg (XEXP (op2, 0));
d735c391 2556 top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
2557 top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
2558
d735c391 2559 /* Make sure not to fold the sincos call again. */
2560 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
c2f47e15 2561 expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
2562 call, 3, arg, top1, top2));
d735c391 2563 }
18b8d8ae 2564 else
2565 {
0ecbc158 2566 tree call, fn = NULL_TREE, narg;
18b8d8ae 2567 tree ctype = build_complex_type (type);
2568
0ecbc158 2569 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
b9a16870 2570 fn = builtin_decl_explicit (BUILT_IN_CEXPF);
0ecbc158 2571 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
b9a16870 2572 fn = builtin_decl_explicit (BUILT_IN_CEXP);
0ecbc158 2573 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
b9a16870 2574 fn = builtin_decl_explicit (BUILT_IN_CEXPL);
c2f47e15 2575 else
2576 gcc_unreachable ();
fc0dfa6e 2577
2578 /* If we don't have a decl for cexp create one. This is the
2579 friendliest fallback if the user calls __builtin_cexpi
2580 without full target C99 function support. */
2581 if (fn == NULL_TREE)
2582 {
2583 tree fntype;
2584 const char *name = NULL;
2585
2586 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2587 name = "cexpf";
2588 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2589 name = "cexp";
2590 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2591 name = "cexpl";
2592
2593 fntype = build_function_type_list (ctype, ctype, NULL_TREE);
2594 fn = build_fn_decl (name, fntype);
2595 }
2596
389dd41b 2597 narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype,
18b8d8ae 2598 build_real (type, dconst0), arg);
2599
2600 /* Make sure not to fold the cexp call again. */
2601 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
48e1416a 2602 return expand_expr (build_call_nary (ctype, call, 1, narg),
1db6d067 2603 target, VOIDmode, EXPAND_NORMAL);
18b8d8ae 2604 }
d735c391 2605
2606 /* Now build the proper return type. */
2607 return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
2608 make_tree (TREE_TYPE (arg), op2),
2609 make_tree (TREE_TYPE (arg), op1)),
1db6d067 2610 target, VOIDmode, EXPAND_NORMAL);
d735c391 2611}
2612
a65c4d64 2613/* Conveniently construct a function call expression. FNDECL names the
2614 function to be called, N is the number of arguments, and the "..."
2615 parameters are the argument expressions. Unlike build_call_exr
2616 this doesn't fold the call, hence it will always return a CALL_EXPR. */
2617
2618static tree
2619build_call_nofold_loc (location_t loc, tree fndecl, int n, ...)
2620{
2621 va_list ap;
2622 tree fntype = TREE_TYPE (fndecl);
2623 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
2624
2625 va_start (ap, n);
2626 fn = build_call_valist (TREE_TYPE (fntype), fn, n, ap);
2627 va_end (ap);
2628 SET_EXPR_LOCATION (fn, loc);
2629 return fn;
2630}
a65c4d64 2631
7d3afc77 2632/* Expand a call to one of the builtin rounding functions gcc defines
2633 as an extension (lfloor and lceil). As these are gcc extensions we
2634 do not need to worry about setting errno to EDOM.
ad52b9b7 2635 If expanding via optab fails, lower expression to (int)(floor(x)).
2636 EXP is the expression that is a call to the builtin function;
ff1b14e4 2637 if convenient, the result should be placed in TARGET. */
ad52b9b7 2638
2639static rtx
ff1b14e4 2640expand_builtin_int_roundingfn (tree exp, rtx target)
ad52b9b7 2641{
9c42dd28 2642 convert_optab builtin_optab;
ad52b9b7 2643 rtx op0, insns, tmp;
2644 tree fndecl = get_callee_fndecl (exp);
ad52b9b7 2645 enum built_in_function fallback_fn;
2646 tree fallback_fndecl;
2647 enum machine_mode mode;
4de0924f 2648 tree arg;
ad52b9b7 2649
c2f47e15 2650 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
ad52b9b7 2651 gcc_unreachable ();
2652
c2f47e15 2653 arg = CALL_EXPR_ARG (exp, 0);
ad52b9b7 2654
2655 switch (DECL_FUNCTION_CODE (fndecl))
2656 {
80ff6494 2657 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 2658 CASE_FLT_FN (BUILT_IN_LCEIL):
2659 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 2660 builtin_optab = lceil_optab;
2661 fallback_fn = BUILT_IN_CEIL;
2662 break;
2663
80ff6494 2664 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 2665 CASE_FLT_FN (BUILT_IN_LFLOOR):
2666 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 2667 builtin_optab = lfloor_optab;
2668 fallback_fn = BUILT_IN_FLOOR;
2669 break;
2670
2671 default:
2672 gcc_unreachable ();
2673 }
2674
2675 /* Make a suitable register to place result in. */
2676 mode = TYPE_MODE (TREE_TYPE (exp));
2677
9c42dd28 2678 target = gen_reg_rtx (mode);
ad52b9b7 2679
9c42dd28 2680 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2681 need to expand the argument again. This way, we will not perform
2682 side-effects more the once. */
abfea505 2683 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
ad52b9b7 2684
ff1b14e4 2685 op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
ad52b9b7 2686
9c42dd28 2687 start_sequence ();
ad52b9b7 2688
9c42dd28 2689 /* Compute into TARGET. */
2690 if (expand_sfix_optab (target, op0, builtin_optab))
2691 {
2692 /* Output the entire sequence. */
2693 insns = get_insns ();
ad52b9b7 2694 end_sequence ();
9c42dd28 2695 emit_insn (insns);
2696 return target;
ad52b9b7 2697 }
2698
9c42dd28 2699 /* If we were unable to expand via the builtin, stop the sequence
2700 (without outputting the insns). */
2701 end_sequence ();
2702
ad52b9b7 2703 /* Fall back to floating point rounding optab. */
2704 fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
fc0dfa6e 2705
2706 /* For non-C99 targets we may end up without a fallback fndecl here
2707 if the user called __builtin_lfloor directly. In this case emit
2708 a call to the floor/ceil variants nevertheless. This should result
2709 in the best user experience for not full C99 targets. */
2710 if (fallback_fndecl == NULL_TREE)
2711 {
2712 tree fntype;
2713 const char *name = NULL;
2714
2715 switch (DECL_FUNCTION_CODE (fndecl))
2716 {
80ff6494 2717 case BUILT_IN_ICEIL:
fc0dfa6e 2718 case BUILT_IN_LCEIL:
2719 case BUILT_IN_LLCEIL:
2720 name = "ceil";
2721 break;
80ff6494 2722 case BUILT_IN_ICEILF:
fc0dfa6e 2723 case BUILT_IN_LCEILF:
2724 case BUILT_IN_LLCEILF:
2725 name = "ceilf";
2726 break;
80ff6494 2727 case BUILT_IN_ICEILL:
fc0dfa6e 2728 case BUILT_IN_LCEILL:
2729 case BUILT_IN_LLCEILL:
2730 name = "ceill";
2731 break;
80ff6494 2732 case BUILT_IN_IFLOOR:
fc0dfa6e 2733 case BUILT_IN_LFLOOR:
2734 case BUILT_IN_LLFLOOR:
2735 name = "floor";
2736 break;
80ff6494 2737 case BUILT_IN_IFLOORF:
fc0dfa6e 2738 case BUILT_IN_LFLOORF:
2739 case BUILT_IN_LLFLOORF:
2740 name = "floorf";
2741 break;
80ff6494 2742 case BUILT_IN_IFLOORL:
fc0dfa6e 2743 case BUILT_IN_LFLOORL:
2744 case BUILT_IN_LLFLOORL:
2745 name = "floorl";
2746 break;
2747 default:
2748 gcc_unreachable ();
2749 }
2750
2751 fntype = build_function_type_list (TREE_TYPE (arg),
2752 TREE_TYPE (arg), NULL_TREE);
2753 fallback_fndecl = build_fn_decl (name, fntype);
2754 }
2755
0568e9c1 2756 exp = build_call_nofold_loc (EXPR_LOCATION (exp), fallback_fndecl, 1, arg);
ad52b9b7 2757
d4c690af 2758 tmp = expand_normal (exp);
ad52b9b7 2759
2760 /* Truncate the result of floating point optab to integer
2761 via expand_fix (). */
2762 target = gen_reg_rtx (mode);
2763 expand_fix (target, tmp, 0);
2764
2765 return target;
2766}
2767
7d3afc77 2768/* Expand a call to one of the builtin math functions doing integer
2769 conversion (lrint).
2770 Return 0 if a normal call should be emitted rather than expanding the
2771 function in-line. EXP is the expression that is a call to the builtin
ff1b14e4 2772 function; if convenient, the result should be placed in TARGET. */
7d3afc77 2773
2774static rtx
ff1b14e4 2775expand_builtin_int_roundingfn_2 (tree exp, rtx target)
7d3afc77 2776{
5f51ee59 2777 convert_optab builtin_optab;
7d3afc77 2778 rtx op0, insns;
2779 tree fndecl = get_callee_fndecl (exp);
4de0924f 2780 tree arg;
c2f47e15 2781 enum machine_mode mode;
e951f9a4 2782 enum built_in_function fallback_fn = BUILT_IN_NONE;
7d3afc77 2783
c2f47e15 2784 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2785 gcc_unreachable ();
48e1416a 2786
c2f47e15 2787 arg = CALL_EXPR_ARG (exp, 0);
7d3afc77 2788
2789 switch (DECL_FUNCTION_CODE (fndecl))
2790 {
80ff6494 2791 CASE_FLT_FN (BUILT_IN_IRINT):
e951f9a4 2792 fallback_fn = BUILT_IN_LRINT;
2793 /* FALLTHRU */
7d3afc77 2794 CASE_FLT_FN (BUILT_IN_LRINT):
2795 CASE_FLT_FN (BUILT_IN_LLRINT):
e951f9a4 2796 builtin_optab = lrint_optab;
2797 break;
80ff6494 2798
2799 CASE_FLT_FN (BUILT_IN_IROUND):
e951f9a4 2800 fallback_fn = BUILT_IN_LROUND;
2801 /* FALLTHRU */
ef2f1a10 2802 CASE_FLT_FN (BUILT_IN_LROUND):
2803 CASE_FLT_FN (BUILT_IN_LLROUND):
e951f9a4 2804 builtin_optab = lround_optab;
2805 break;
80ff6494 2806
7d3afc77 2807 default:
2808 gcc_unreachable ();
2809 }
2810
e951f9a4 2811 /* There's no easy way to detect the case we need to set EDOM. */
2812 if (flag_errno_math && fallback_fn == BUILT_IN_NONE)
2813 return NULL_RTX;
2814
7d3afc77 2815 /* Make a suitable register to place result in. */
2816 mode = TYPE_MODE (TREE_TYPE (exp));
2817
e951f9a4 2818 /* There's no easy way to detect the case we need to set EDOM. */
2819 if (!flag_errno_math)
2820 {
2821 target = gen_reg_rtx (mode);
7d3afc77 2822
e951f9a4 2823 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2824 need to expand the argument again. This way, we will not perform
2825 side-effects more the once. */
2826 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7d3afc77 2827
e951f9a4 2828 op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
7d3afc77 2829
e951f9a4 2830 start_sequence ();
7d3afc77 2831
e951f9a4 2832 if (expand_sfix_optab (target, op0, builtin_optab))
2833 {
2834 /* Output the entire sequence. */
2835 insns = get_insns ();
2836 end_sequence ();
2837 emit_insn (insns);
2838 return target;
2839 }
2840
2841 /* If we were unable to expand via the builtin, stop the sequence
2842 (without outputting the insns) and call to the library function
2843 with the stabilized argument list. */
7d3afc77 2844 end_sequence ();
2845 }
2846
e951f9a4 2847 if (fallback_fn != BUILT_IN_NONE)
2848 {
2849 /* Fall back to rounding to long int. Use implicit_p 0 - for non-C99
2850 targets, (int) round (x) should never be transformed into
2851 BUILT_IN_IROUND and if __builtin_iround is called directly, emit
2852 a call to lround in the hope that the target provides at least some
2853 C99 functions. This should result in the best user experience for
2854 not full C99 targets. */
2855 tree fallback_fndecl = mathfn_built_in_1 (TREE_TYPE (arg),
2856 fallback_fn, 0);
2857
2858 exp = build_call_nofold_loc (EXPR_LOCATION (exp),
2859 fallback_fndecl, 1, arg);
2860
2861 target = expand_call (exp, NULL_RTX, target == const0_rtx);
2862 return convert_to_mode (mode, target, 0);
2863 }
5f51ee59 2864
7d3afc77 2865 target = expand_call (exp, target, target == const0_rtx);
2866
2867 return target;
2868}
2869
c2f47e15 2870/* Expand a call to the powi built-in mathematical function. Return NULL_RTX if
757c219d 2871 a normal call should be emitted rather than expanding the function
2872 in-line. EXP is the expression that is a call to the builtin
2873 function; if convenient, the result should be placed in TARGET. */
2874
2875static rtx
f97eea22 2876expand_builtin_powi (tree exp, rtx target)
757c219d 2877{
757c219d 2878 tree arg0, arg1;
2879 rtx op0, op1;
2880 enum machine_mode mode;
d0405f40 2881 enum machine_mode mode2;
757c219d 2882
c2f47e15 2883 if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
2884 return NULL_RTX;
757c219d 2885
c2f47e15 2886 arg0 = CALL_EXPR_ARG (exp, 0);
2887 arg1 = CALL_EXPR_ARG (exp, 1);
757c219d 2888 mode = TYPE_MODE (TREE_TYPE (exp));
2889
757c219d 2890 /* Emit a libcall to libgcc. */
2891
c2f47e15 2892 /* Mode of the 2nd argument must match that of an int. */
d0405f40 2893 mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
2894
757c219d 2895 if (target == NULL_RTX)
2896 target = gen_reg_rtx (mode);
2897
f97eea22 2898 op0 = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
757c219d 2899 if (GET_MODE (op0) != mode)
2900 op0 = convert_to_mode (mode, op0, 0);
1db6d067 2901 op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
d0405f40 2902 if (GET_MODE (op1) != mode2)
2903 op1 = convert_to_mode (mode2, op1, 0);
757c219d 2904
f36b9f69 2905 target = emit_library_call_value (optab_libfunc (powi_optab, mode),
2dd6f9ed 2906 target, LCT_CONST, mode, 2,
d0405f40 2907 op0, mode, op1, mode2);
757c219d 2908
2909 return target;
2910}
2911
48e1416a 2912/* Expand expression EXP which is a call to the strlen builtin. Return
c2f47e15 2913 NULL_RTX if we failed the caller should emit a normal call, otherwise
aed0bd19 2914 try to get the result in TARGET, if convenient. */
f7c44134 2915
53800dbe 2916static rtx
c2f47e15 2917expand_builtin_strlen (tree exp, rtx target,
aecda0d6 2918 enum machine_mode target_mode)
53800dbe 2919{
c2f47e15 2920 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2921 return NULL_RTX;
53800dbe 2922 else
2923 {
8786db1e 2924 struct expand_operand ops[4];
911c0150 2925 rtx pat;
c2f47e15 2926 tree len;
2927 tree src = CALL_EXPR_ARG (exp, 0);
8786db1e 2928 rtx src_reg, before_strlen;
2929 enum machine_mode insn_mode = target_mode;
ef2c4a29 2930 enum insn_code icode = CODE_FOR_nothing;
153c3b50 2931 unsigned int align;
6248e345 2932
2933 /* If the length can be computed at compile-time, return it. */
681fab1e 2934 len = c_strlen (src, 0);
6248e345 2935 if (len)
80cd7a5e 2936 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
6248e345 2937
681fab1e 2938 /* If the length can be computed at compile-time and is constant
2939 integer, but there are side-effects in src, evaluate
2940 src for side-effects, then return len.
2941 E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
2942 can be optimized into: i++; x = 3; */
2943 len = c_strlen (src, 1);
2944 if (len && TREE_CODE (len) == INTEGER_CST)
2945 {
2946 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2947 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
2948 }
2949
957d0361 2950 align = get_pointer_alignment (src) / BITS_PER_UNIT;
53800dbe 2951
53800dbe 2952 /* If SRC is not a pointer type, don't do this operation inline. */
2953 if (align == 0)
c2f47e15 2954 return NULL_RTX;
53800dbe 2955
911c0150 2956 /* Bail out if we can't compute strlen in the right mode. */
53800dbe 2957 while (insn_mode != VOIDmode)
2958 {
d6bf3b14 2959 icode = optab_handler (strlen_optab, insn_mode);
53800dbe 2960 if (icode != CODE_FOR_nothing)
c28ae87f 2961 break;
53800dbe 2962
2963 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
2964 }
2965 if (insn_mode == VOIDmode)
c2f47e15 2966 return NULL_RTX;
53800dbe 2967
911c0150 2968 /* Make a place to hold the source address. We will not expand
2969 the actual source until we are sure that the expansion will
2970 not fail -- there are trees that cannot be expanded twice. */
2971 src_reg = gen_reg_rtx (Pmode);
53800dbe 2972
911c0150 2973 /* Mark the beginning of the strlen sequence so we can emit the
2974 source operand later. */
f0ce3b1f 2975 before_strlen = get_last_insn ();
53800dbe 2976
8786db1e 2977 create_output_operand (&ops[0], target, insn_mode);
2978 create_fixed_operand (&ops[1], gen_rtx_MEM (BLKmode, src_reg));
2979 create_integer_operand (&ops[2], 0);
2980 create_integer_operand (&ops[3], align);
2981 if (!maybe_expand_insn (icode, 4, ops))
c2f47e15 2982 return NULL_RTX;
911c0150 2983
2984 /* Now that we are assured of success, expand the source. */
2985 start_sequence ();
499eee58 2986 pat = expand_expr (src, src_reg, Pmode, EXPAND_NORMAL);
911c0150 2987 if (pat != src_reg)
499eee58 2988 {
2989#ifdef POINTERS_EXTEND_UNSIGNED
2990 if (GET_MODE (pat) != Pmode)
2991 pat = convert_to_mode (Pmode, pat,
2992 POINTERS_EXTEND_UNSIGNED);
2993#endif
2994 emit_move_insn (src_reg, pat);
2995 }
31d3e01c 2996 pat = get_insns ();
911c0150 2997 end_sequence ();
bceb0d1f 2998
2999 if (before_strlen)
3000 emit_insn_after (pat, before_strlen);
3001 else
3002 emit_insn_before (pat, get_insns ());
53800dbe 3003
3004 /* Return the value in the proper mode for this function. */
8786db1e 3005 if (GET_MODE (ops[0].value) == target_mode)
3006 target = ops[0].value;
53800dbe 3007 else if (target != 0)
8786db1e 3008 convert_move (target, ops[0].value, 0);
53800dbe 3009 else
8786db1e 3010 target = convert_to_mode (target_mode, ops[0].value, 0);
911c0150 3011
3012 return target;
53800dbe 3013 }
3014}
3015
6840589f 3016/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3017 bytes from constant string DATA + OFFSET and return it as target
3018 constant. */
3019
3020static rtx
aecda0d6 3021builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
3022 enum machine_mode mode)
6840589f 3023{
3024 const char *str = (const char *) data;
3025
64db345d 3026 gcc_assert (offset >= 0
3027 && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
3028 <= strlen (str) + 1));
6840589f 3029
3030 return c_readstr (str + offset, mode);
3031}
3032
c2f47e15 3033/* Expand a call EXP to the memcpy builtin.
3034 Return NULL_RTX if we failed, the caller should emit a normal call,
3b824fa6 3035 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3036 mode MODE if that's convenient). */
c2f47e15 3037
53800dbe 3038static rtx
a65c4d64 3039expand_builtin_memcpy (tree exp, rtx target)
53800dbe 3040{
c2f47e15 3041 if (!validate_arglist (exp,
3042 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3043 return NULL_RTX;
53800dbe 3044 else
3045 {
c2f47e15 3046 tree dest = CALL_EXPR_ARG (exp, 0);
3047 tree src = CALL_EXPR_ARG (exp, 1);
3048 tree len = CALL_EXPR_ARG (exp, 2);
6840589f 3049 const char *src_str;
957d0361 3050 unsigned int src_align = get_pointer_alignment (src);
3051 unsigned int dest_align = get_pointer_alignment (dest);
53800dbe 3052 rtx dest_mem, src_mem, dest_addr, len_rtx;
162719b3 3053 HOST_WIDE_INT expected_size = -1;
3054 unsigned int expected_align = 0;
5a0de151 3055
6f428e8b 3056 /* If DEST is not a pointer type, call the normal function. */
3057 if (dest_align == 0)
c2f47e15 3058 return NULL_RTX;
6f428e8b 3059
6f428e8b 3060 /* If either SRC is not a pointer type, don't do this
a0c938f0 3061 operation in-line. */
6f428e8b 3062 if (src_align == 0)
c2f47e15 3063 return NULL_RTX;
48e1416a 3064
8cee8dc0 3065 if (currently_expanding_gimple_stmt)
3066 stringop_block_profile (currently_expanding_gimple_stmt,
3067 &expected_align, &expected_size);
75a70cf9 3068
162719b3 3069 if (expected_align < dest_align)
3070 expected_align = dest_align;
d8ae1baa 3071 dest_mem = get_memory_rtx (dest, len);
2a631e19 3072 set_mem_align (dest_mem, dest_align);
8ec3c5c2 3073 len_rtx = expand_normal (len);
6840589f 3074 src_str = c_getstr (src);
3075
3076 /* If SRC is a string constant and block move would be done
3077 by pieces, we can avoid loading the string from memory
3078 and only stored the computed constants. */
3079 if (src_str
971ba038 3080 && CONST_INT_P (len_rtx)
6840589f 3081 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3082 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3083 CONST_CAST (char *, src_str),
3084 dest_align, false))
6840589f 3085 {
9fe0e1b8 3086 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3087 builtin_memcpy_read_str,
364c0c59 3088 CONST_CAST (char *, src_str),
3089 dest_align, false, 0);
a65c4d64 3090 dest_mem = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3091 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3092 return dest_mem;
6840589f 3093 }
3094
d8ae1baa 3095 src_mem = get_memory_rtx (src, len);
2a631e19 3096 set_mem_align (src_mem, src_align);
53800dbe 3097
53800dbe 3098 /* Copy word part most expediently. */
162719b3 3099 dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
3100 CALL_EXPR_TAILCALL (exp)
3101 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3102 expected_align, expected_size);
53800dbe 3103
3104 if (dest_addr == 0)
e5716f7e 3105 {
a65c4d64 3106 dest_addr = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3107 dest_addr = convert_memory_address (ptr_mode, dest_addr);
e5716f7e 3108 }
9fe0e1b8 3109 return dest_addr;
53800dbe 3110 }
3111}
3112
c2f47e15 3113/* Expand a call EXP to the mempcpy builtin.
3114 Return NULL_RTX if we failed; the caller should emit a normal call,
647661c6 3115 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3116 mode MODE if that's convenient). If ENDP is 0 return the
3117 destination pointer, if ENDP is 1 return the end pointer ala
3118 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3119 stpcpy. */
647661c6 3120
3121static rtx
c8b17b2e 3122expand_builtin_mempcpy (tree exp, rtx target, enum machine_mode mode)
647661c6 3123{
c2f47e15 3124 if (!validate_arglist (exp,
3125 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3126 return NULL_RTX;
3127 else
3128 {
3129 tree dest = CALL_EXPR_ARG (exp, 0);
3130 tree src = CALL_EXPR_ARG (exp, 1);
3131 tree len = CALL_EXPR_ARG (exp, 2);
3132 return expand_builtin_mempcpy_args (dest, src, len,
c2f47e15 3133 target, mode, /*endp=*/ 1);
3134 }
3135}
3136
3137/* Helper function to do the actual work for expand_builtin_mempcpy. The
3138 arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out
3139 so that this can also be called without constructing an actual CALL_EXPR.
a65c4d64 3140 The other arguments and return value are the same as for
3141 expand_builtin_mempcpy. */
c2f47e15 3142
3143static rtx
a65c4d64 3144expand_builtin_mempcpy_args (tree dest, tree src, tree len,
c2f47e15 3145 rtx target, enum machine_mode mode, int endp)
3146{
3147 /* If return value is ignored, transform mempcpy into memcpy. */
b9a16870 3148 if (target == const0_rtx && builtin_decl_implicit_p (BUILT_IN_MEMCPY))
9fe0e1b8 3149 {
b9a16870 3150 tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
0568e9c1 3151 tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3,
3152 dest, src, len);
c8b17b2e 3153 return expand_expr (result, target, mode, EXPAND_NORMAL);
9fe0e1b8 3154 }
647661c6 3155 else
3156 {
9fe0e1b8 3157 const char *src_str;
957d0361 3158 unsigned int src_align = get_pointer_alignment (src);
3159 unsigned int dest_align = get_pointer_alignment (dest);
9fe0e1b8 3160 rtx dest_mem, src_mem, len_rtx;
a0c938f0 3161
7da1412b 3162 /* If either SRC or DEST is not a pointer type, don't do this
a0c938f0 3163 operation in-line. */
7da1412b 3164 if (dest_align == 0 || src_align == 0)
c2f47e15 3165 return NULL_RTX;
9fe0e1b8 3166
6217c238 3167 /* If LEN is not constant, call the normal function. */
3168 if (! host_integerp (len, 1))
c2f47e15 3169 return NULL_RTX;
0862b7e9 3170
8ec3c5c2 3171 len_rtx = expand_normal (len);
9fe0e1b8 3172 src_str = c_getstr (src);
647661c6 3173
9fe0e1b8 3174 /* If SRC is a string constant and block move would be done
3175 by pieces, we can avoid loading the string from memory
3176 and only stored the computed constants. */
3177 if (src_str
971ba038 3178 && CONST_INT_P (len_rtx)
9fe0e1b8 3179 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3180 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3181 CONST_CAST (char *, src_str),
3182 dest_align, false))
9fe0e1b8 3183 {
d8ae1baa 3184 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3185 set_mem_align (dest_mem, dest_align);
3186 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3187 builtin_memcpy_read_str,
364c0c59 3188 CONST_CAST (char *, src_str),
3189 dest_align, false, endp);
9fe0e1b8 3190 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3191 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3192 return dest_mem;
647661c6 3193 }
3194
971ba038 3195 if (CONST_INT_P (len_rtx)
9fe0e1b8 3196 && can_move_by_pieces (INTVAL (len_rtx),
3197 MIN (dest_align, src_align)))
3198 {
d8ae1baa 3199 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3200 set_mem_align (dest_mem, dest_align);
d8ae1baa 3201 src_mem = get_memory_rtx (src, len);
9fe0e1b8 3202 set_mem_align (src_mem, src_align);
3203 dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
3204 MIN (dest_align, src_align), endp);
3205 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3206 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3207 return dest_mem;
3208 }
3209
c2f47e15 3210 return NULL_RTX;
647661c6 3211 }
3212}
3213
727c62dd 3214#ifndef HAVE_movstr
3215# define HAVE_movstr 0
3216# define CODE_FOR_movstr CODE_FOR_nothing
3217#endif
3218
c2f47e15 3219/* Expand into a movstr instruction, if one is available. Return NULL_RTX if
727c62dd 3220 we failed, the caller should emit a normal call, otherwise try to
3221 get the result in TARGET, if convenient. If ENDP is 0 return the
3222 destination pointer, if ENDP is 1 return the end pointer ala
3223 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3224 stpcpy. */
3225
3226static rtx
3227expand_movstr (tree dest, tree src, rtx target, int endp)
3228{
8786db1e 3229 struct expand_operand ops[3];
727c62dd 3230 rtx dest_mem;
3231 rtx src_mem;
727c62dd 3232
3233 if (!HAVE_movstr)
c2f47e15 3234 return NULL_RTX;
727c62dd 3235
d8ae1baa 3236 dest_mem = get_memory_rtx (dest, NULL);
3237 src_mem = get_memory_rtx (src, NULL);
727c62dd 3238 if (!endp)
3239 {
3240 target = force_reg (Pmode, XEXP (dest_mem, 0));
3241 dest_mem = replace_equiv_address (dest_mem, target);
727c62dd 3242 }
3243
8786db1e 3244 create_output_operand (&ops[0], endp ? target : NULL_RTX, Pmode);
3245 create_fixed_operand (&ops[1], dest_mem);
3246 create_fixed_operand (&ops[2], src_mem);
3247 expand_insn (CODE_FOR_movstr, 3, ops);
727c62dd 3248
8786db1e 3249 if (endp && target != const0_rtx)
c5aba89c 3250 {
8786db1e 3251 target = ops[0].value;
3252 /* movstr is supposed to set end to the address of the NUL
3253 terminator. If the caller requested a mempcpy-like return value,
3254 adjust it. */
3255 if (endp == 1)
3256 {
29c05e22 3257 rtx tem = plus_constant (GET_MODE (target),
3258 gen_lowpart (GET_MODE (target), target), 1);
8786db1e 3259 emit_move_insn (target, force_operand (tem, NULL_RTX));
3260 }
c5aba89c 3261 }
727c62dd 3262 return target;
3263}
3264
48e1416a 3265/* Expand expression EXP, which is a call to the strcpy builtin. Return
3266 NULL_RTX if we failed the caller should emit a normal call, otherwise
c2f47e15 3267 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3268 convenient). */
902de8ed 3269
53800dbe 3270static rtx
a65c4d64 3271expand_builtin_strcpy (tree exp, rtx target)
53800dbe 3272{
c2f47e15 3273 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3274 {
3275 tree dest = CALL_EXPR_ARG (exp, 0);
3276 tree src = CALL_EXPR_ARG (exp, 1);
a65c4d64 3277 return expand_builtin_strcpy_args (dest, src, target);
c2f47e15 3278 }
3279 return NULL_RTX;
3280}
3281
3282/* Helper function to do the actual work for expand_builtin_strcpy. The
3283 arguments to the builtin_strcpy call DEST and SRC are broken out
3284 so that this can also be called without constructing an actual CALL_EXPR.
3285 The other arguments and return value are the same as for
3286 expand_builtin_strcpy. */
3287
3288static rtx
a65c4d64 3289expand_builtin_strcpy_args (tree dest, tree src, rtx target)
c2f47e15 3290{
c2f47e15 3291 return expand_movstr (dest, src, target, /*endp=*/0);
53800dbe 3292}
3293
c2f47e15 3294/* Expand a call EXP to the stpcpy builtin.
3295 Return NULL_RTX if we failed the caller should emit a normal call,
3b824fa6 3296 otherwise try to get the result in TARGET, if convenient (and in
3297 mode MODE if that's convenient). */
3298
3299static rtx
dc369150 3300expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
3b824fa6 3301{
c2f47e15 3302 tree dst, src;
389dd41b 3303 location_t loc = EXPR_LOCATION (exp);
c2f47e15 3304
3305 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3306 return NULL_RTX;
3307
3308 dst = CALL_EXPR_ARG (exp, 0);
3309 src = CALL_EXPR_ARG (exp, 1);
3310
727c62dd 3311 /* If return value is ignored, transform stpcpy into strcpy. */
b9a16870 3312 if (target == const0_rtx && builtin_decl_implicit (BUILT_IN_STRCPY))
978836e5 3313 {
b9a16870 3314 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
0568e9c1 3315 tree result = build_call_nofold_loc (loc, fn, 2, dst, src);
c8b17b2e 3316 return expand_expr (result, target, mode, EXPAND_NORMAL);
978836e5 3317 }
3b824fa6 3318 else
3319 {
c2f47e15 3320 tree len, lenp1;
727c62dd 3321 rtx ret;
647661c6 3322
9fe0e1b8 3323 /* Ensure we get an actual string whose length can be evaluated at
a0c938f0 3324 compile-time, not an expression containing a string. This is
3325 because the latter will potentially produce pessimized code
3326 when used to produce the return value. */
681fab1e 3327 if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
c2f47e15 3328 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3329
389dd41b 3330 lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
a65c4d64 3331 ret = expand_builtin_mempcpy_args (dst, src, lenp1,
c2f47e15 3332 target, mode, /*endp=*/2);
727c62dd 3333
3334 if (ret)
3335 return ret;
3336
3337 if (TREE_CODE (len) == INTEGER_CST)
3338 {
8ec3c5c2 3339 rtx len_rtx = expand_normal (len);
727c62dd 3340
971ba038 3341 if (CONST_INT_P (len_rtx))
727c62dd 3342 {
a65c4d64 3343 ret = expand_builtin_strcpy_args (dst, src, target);
727c62dd 3344
3345 if (ret)
3346 {
3347 if (! target)
7ac87324 3348 {
3349 if (mode != VOIDmode)
3350 target = gen_reg_rtx (mode);
3351 else
3352 target = gen_reg_rtx (GET_MODE (ret));
3353 }
727c62dd 3354 if (GET_MODE (target) != GET_MODE (ret))
3355 ret = gen_lowpart (GET_MODE (target), ret);
3356
29c05e22 3357 ret = plus_constant (GET_MODE (ret), ret, INTVAL (len_rtx));
c5aba89c 3358 ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
64db345d 3359 gcc_assert (ret);
727c62dd 3360
3361 return target;
3362 }
3363 }
3364 }
3365
c2f47e15 3366 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3367 }
3368}
3369
6840589f 3370/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3371 bytes from constant string DATA + OFFSET and return it as target
3372 constant. */
3373
09879952 3374rtx
aecda0d6 3375builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
3376 enum machine_mode mode)
6840589f 3377{
3378 const char *str = (const char *) data;
3379
3380 if ((unsigned HOST_WIDE_INT) offset > strlen (str))
3381 return const0_rtx;
3382
3383 return c_readstr (str + offset, mode);
3384}
3385
48e1416a 3386/* Expand expression EXP, which is a call to the strncpy builtin. Return
c2f47e15 3387 NULL_RTX if we failed the caller should emit a normal call. */
ed09096d 3388
3389static rtx
a65c4d64 3390expand_builtin_strncpy (tree exp, rtx target)
ed09096d 3391{
389dd41b 3392 location_t loc = EXPR_LOCATION (exp);
c2f47e15 3393
3394 if (validate_arglist (exp,
3395 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
ed09096d 3396 {
c2f47e15 3397 tree dest = CALL_EXPR_ARG (exp, 0);
3398 tree src = CALL_EXPR_ARG (exp, 1);
3399 tree len = CALL_EXPR_ARG (exp, 2);
3400 tree slen = c_strlen (src, 1);
6840589f 3401
8ff6a5cd 3402 /* We must be passed a constant len and src parameter. */
3403 if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
c2f47e15 3404 return NULL_RTX;
ed09096d 3405
389dd41b 3406 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
ed09096d 3407
3408 /* We're required to pad with trailing zeros if the requested
a0c938f0 3409 len is greater than strlen(s2)+1. In that case try to
6840589f 3410 use store_by_pieces, if it fails, punt. */
ed09096d 3411 if (tree_int_cst_lt (slen, len))
6840589f 3412 {
957d0361 3413 unsigned int dest_align = get_pointer_alignment (dest);
c2f47e15 3414 const char *p = c_getstr (src);
6840589f 3415 rtx dest_mem;
3416
27d0c333 3417 if (!p || dest_align == 0 || !host_integerp (len, 1)
3418 || !can_store_by_pieces (tree_low_cst (len, 1),
6840589f 3419 builtin_strncpy_read_str,
364c0c59 3420 CONST_CAST (char *, p),
3421 dest_align, false))
c2f47e15 3422 return NULL_RTX;
6840589f 3423
d8ae1baa 3424 dest_mem = get_memory_rtx (dest, len);
27d0c333 3425 store_by_pieces (dest_mem, tree_low_cst (len, 1),
6840589f 3426 builtin_strncpy_read_str,
364c0c59 3427 CONST_CAST (char *, p), dest_align, false, 0);
a65c4d64 3428 dest_mem = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3429 dest_mem = convert_memory_address (ptr_mode, dest_mem);
e5716f7e 3430 return dest_mem;
6840589f 3431 }
ed09096d 3432 }
c2f47e15 3433 return NULL_RTX;
ed09096d 3434}
3435
ecc318ff 3436/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3437 bytes from constant string DATA + OFFSET and return it as target
3438 constant. */
3439
f656b751 3440rtx
aecda0d6 3441builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3442 enum machine_mode mode)
ecc318ff 3443{
3444 const char *c = (const char *) data;
364c0c59 3445 char *p = XALLOCAVEC (char, GET_MODE_SIZE (mode));
ecc318ff 3446
3447 memset (p, *c, GET_MODE_SIZE (mode));
3448
3449 return c_readstr (p, mode);
3450}
3451
a7ec6974 3452/* Callback routine for store_by_pieces. Return the RTL of a register
3453 containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
3454 char value given in the RTL register data. For example, if mode is
3455 4 bytes wide, return the RTL for 0x01010101*data. */
3456
3457static rtx
aecda0d6 3458builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3459 enum machine_mode mode)
a7ec6974 3460{
3461 rtx target, coeff;
3462 size_t size;
3463 char *p;
3464
3465 size = GET_MODE_SIZE (mode);
f0ce3b1f 3466 if (size == 1)
3467 return (rtx) data;
a7ec6974 3468
364c0c59 3469 p = XALLOCAVEC (char, size);
a7ec6974 3470 memset (p, 1, size);
3471 coeff = c_readstr (p, mode);
3472
f0ce3b1f 3473 target = convert_to_mode (mode, (rtx) data, 1);
a7ec6974 3474 target = expand_mult (mode, target, coeff, NULL_RTX, 1);
3475 return force_reg (mode, target);
3476}
3477
48e1416a 3478/* Expand expression EXP, which is a call to the memset builtin. Return
3479 NULL_RTX if we failed the caller should emit a normal call, otherwise
c2f47e15 3480 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3481 convenient). */
902de8ed 3482
53800dbe 3483static rtx
c2f47e15 3484expand_builtin_memset (tree exp, rtx target, enum machine_mode mode)
53800dbe 3485{
c2f47e15 3486 if (!validate_arglist (exp,
3487 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
3488 return NULL_RTX;
53800dbe 3489 else
3490 {
c2f47e15 3491 tree dest = CALL_EXPR_ARG (exp, 0);
3492 tree val = CALL_EXPR_ARG (exp, 1);
3493 tree len = CALL_EXPR_ARG (exp, 2);
3494 return expand_builtin_memset_args (dest, val, len, target, mode, exp);
3495 }
3496}
53800dbe 3497
c2f47e15 3498/* Helper function to do the actual work for expand_builtin_memset. The
3499 arguments to the builtin_memset call DEST, VAL, and LEN are broken out
3500 so that this can also be called without constructing an actual CALL_EXPR.
3501 The other arguments and return value are the same as for
3502 expand_builtin_memset. */
6b961939 3503
c2f47e15 3504static rtx
3505expand_builtin_memset_args (tree dest, tree val, tree len,
3506 rtx target, enum machine_mode mode, tree orig_exp)
3507{
3508 tree fndecl, fn;
3509 enum built_in_function fcode;
03a5dda9 3510 enum machine_mode val_mode;
c2f47e15 3511 char c;
3512 unsigned int dest_align;
3513 rtx dest_mem, dest_addr, len_rtx;
3514 HOST_WIDE_INT expected_size = -1;
3515 unsigned int expected_align = 0;
53800dbe 3516
957d0361 3517 dest_align = get_pointer_alignment (dest);
162719b3 3518
c2f47e15 3519 /* If DEST is not a pointer type, don't do this operation in-line. */
3520 if (dest_align == 0)
3521 return NULL_RTX;
6f428e8b 3522
8cee8dc0 3523 if (currently_expanding_gimple_stmt)
3524 stringop_block_profile (currently_expanding_gimple_stmt,
3525 &expected_align, &expected_size);
75a70cf9 3526
c2f47e15 3527 if (expected_align < dest_align)
3528 expected_align = dest_align;
6b961939 3529
c2f47e15 3530 /* If the LEN parameter is zero, return DEST. */
3531 if (integer_zerop (len))
3532 {
3533 /* Evaluate and ignore VAL in case it has side-effects. */
3534 expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
3535 return expand_expr (dest, target, mode, EXPAND_NORMAL);
3536 }
7a3e5564 3537
c2f47e15 3538 /* Stabilize the arguments in case we fail. */
3539 dest = builtin_save_expr (dest);
3540 val = builtin_save_expr (val);
3541 len = builtin_save_expr (len);
a7ec6974 3542
c2f47e15 3543 len_rtx = expand_normal (len);
3544 dest_mem = get_memory_rtx (dest, len);
03a5dda9 3545 val_mode = TYPE_MODE (unsigned_char_type_node);
a7ec6974 3546
c2f47e15 3547 if (TREE_CODE (val) != INTEGER_CST)
3548 {
3549 rtx val_rtx;
a7ec6974 3550
c2f47e15 3551 val_rtx = expand_normal (val);
03a5dda9 3552 val_rtx = convert_to_mode (val_mode, val_rtx, 0);
53800dbe 3553
c2f47e15 3554 /* Assume that we can memset by pieces if we can store
3555 * the coefficients by pieces (in the required modes).
3556 * We can't pass builtin_memset_gen_str as that emits RTL. */
3557 c = 1;
3558 if (host_integerp (len, 1)
c2f47e15 3559 && can_store_by_pieces (tree_low_cst (len, 1),
4b297e2e 3560 builtin_memset_read_str, &c, dest_align,
3561 true))
c2f47e15 3562 {
03a5dda9 3563 val_rtx = force_reg (val_mode, val_rtx);
c2f47e15 3564 store_by_pieces (dest_mem, tree_low_cst (len, 1),
4b297e2e 3565 builtin_memset_gen_str, val_rtx, dest_align,
3566 true, 0);
c2f47e15 3567 }
3568 else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
3569 dest_align, expected_align,
3570 expected_size))
6b961939 3571 goto do_libcall;
48e1416a 3572
c2f47e15 3573 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3574 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3575 return dest_mem;
3576 }
53800dbe 3577
c2f47e15 3578 if (target_char_cast (val, &c))
3579 goto do_libcall;
ecc318ff 3580
c2f47e15 3581 if (c)
3582 {
3583 if (host_integerp (len, 1)
c2f47e15 3584 && can_store_by_pieces (tree_low_cst (len, 1),
4b297e2e 3585 builtin_memset_read_str, &c, dest_align,
3586 true))
c2f47e15 3587 store_by_pieces (dest_mem, tree_low_cst (len, 1),
4b297e2e 3588 builtin_memset_read_str, &c, dest_align, true, 0);
03a5dda9 3589 else if (!set_storage_via_setmem (dest_mem, len_rtx,
3590 gen_int_mode (c, val_mode),
c2f47e15 3591 dest_align, expected_align,
3592 expected_size))
3593 goto do_libcall;
48e1416a 3594
c2f47e15 3595 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3596 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3597 return dest_mem;
3598 }
ecc318ff 3599
c2f47e15 3600 set_mem_align (dest_mem, dest_align);
3601 dest_addr = clear_storage_hints (dest_mem, len_rtx,
3602 CALL_EXPR_TAILCALL (orig_exp)
3603 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3604 expected_align, expected_size);
53800dbe 3605
c2f47e15 3606 if (dest_addr == 0)
3607 {
3608 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3609 dest_addr = convert_memory_address (ptr_mode, dest_addr);
3610 }
53800dbe 3611
c2f47e15 3612 return dest_addr;
6b961939 3613
c2f47e15 3614 do_libcall:
3615 fndecl = get_callee_fndecl (orig_exp);
3616 fcode = DECL_FUNCTION_CODE (fndecl);
3617 if (fcode == BUILT_IN_MEMSET)
0568e9c1 3618 fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 3,
3619 dest, val, len);
c2f47e15 3620 else if (fcode == BUILT_IN_BZERO)
0568e9c1 3621 fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 2,
3622 dest, len);
c2f47e15 3623 else
3624 gcc_unreachable ();
a65c4d64 3625 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
3626 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
c2f47e15 3627 return expand_call (fn, target, target == const0_rtx);
53800dbe 3628}
3629
48e1416a 3630/* Expand expression EXP, which is a call to the bzero builtin. Return
c2f47e15 3631 NULL_RTX if we failed the caller should emit a normal call. */
27d0c333 3632
ffc83088 3633static rtx
0b25db21 3634expand_builtin_bzero (tree exp)
ffc83088 3635{
c2f47e15 3636 tree dest, size;
389dd41b 3637 location_t loc = EXPR_LOCATION (exp);
ffc83088 3638
c2f47e15 3639 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
7369e7ba 3640 return NULL_RTX;
ffc83088 3641
c2f47e15 3642 dest = CALL_EXPR_ARG (exp, 0);
3643 size = CALL_EXPR_ARG (exp, 1);
bf8e3599 3644
7369e7ba 3645 /* New argument list transforming bzero(ptr x, int y) to
6f428e8b 3646 memset(ptr x, int 0, size_t y). This is done this way
3647 so that if it isn't expanded inline, we fallback to
3648 calling bzero instead of memset. */
bf8e3599 3649
c2f47e15 3650 return expand_builtin_memset_args (dest, integer_zero_node,
a0553bff 3651 fold_convert_loc (loc,
3652 size_type_node, size),
c2f47e15 3653 const0_rtx, VOIDmode, exp);
ffc83088 3654}
3655
7a3f89b5 3656/* Expand expression EXP, which is a call to the memcmp built-in function.
bd021c1c 3657 Return NULL_RTX if we failed and the caller should emit a normal call,
3658 otherwise try to get the result in TARGET, if convenient (and in mode
3659 MODE, if that's convenient). */
27d0c333 3660
53800dbe 3661static rtx
a65c4d64 3662expand_builtin_memcmp (tree exp, ATTRIBUTE_UNUSED rtx target,
3663 ATTRIBUTE_UNUSED enum machine_mode mode)
53800dbe 3664{
a65c4d64 3665 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
389dd41b 3666
c2f47e15 3667 if (!validate_arglist (exp,
3668 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3669 return NULL_RTX;
6f428e8b 3670
bd021c1c 3671 /* Note: The cmpstrnsi pattern, if it exists, is not suitable for
3672 implementing memcmp because it will stop if it encounters two
3673 zero bytes. */
3674#if defined HAVE_cmpmemsi
53800dbe 3675 {
0cd832f0 3676 rtx arg1_rtx, arg2_rtx, arg3_rtx;
53800dbe 3677 rtx result;
0cd832f0 3678 rtx insn;
c2f47e15 3679 tree arg1 = CALL_EXPR_ARG (exp, 0);
3680 tree arg2 = CALL_EXPR_ARG (exp, 1);
3681 tree len = CALL_EXPR_ARG (exp, 2);
53800dbe 3682
957d0361 3683 unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
3684 unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
b428c0a5 3685 enum machine_mode insn_mode;
3686
b428c0a5 3687 if (HAVE_cmpmemsi)
3688 insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
3689 else
c2f47e15 3690 return NULL_RTX;
53800dbe 3691
3692 /* If we don't have POINTER_TYPE, call the function. */
3693 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 3694 return NULL_RTX;
53800dbe 3695
3696 /* Make a place to write the result of the instruction. */
3697 result = target;
3698 if (! (result != 0
8ad4c111 3699 && REG_P (result) && GET_MODE (result) == insn_mode
53800dbe 3700 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3701 result = gen_reg_rtx (insn_mode);
3702
d8ae1baa 3703 arg1_rtx = get_memory_rtx (arg1, len);
3704 arg2_rtx = get_memory_rtx (arg2, len);
389dd41b 3705 arg3_rtx = expand_normal (fold_convert_loc (loc, sizetype, len));
83f88f8e 3706
3707 /* Set MEM_SIZE as appropriate. */
971ba038 3708 if (CONST_INT_P (arg3_rtx))
83f88f8e 3709 {
5b2a69fa 3710 set_mem_size (arg1_rtx, INTVAL (arg3_rtx));
3711 set_mem_size (arg2_rtx, INTVAL (arg3_rtx));
83f88f8e 3712 }
3713
b428c0a5 3714 if (HAVE_cmpmemsi)
3715 insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3716 GEN_INT (MIN (arg1_align, arg2_align)));
0cd832f0 3717 else
64db345d 3718 gcc_unreachable ();
0cd832f0 3719
3720 if (insn)
3721 emit_insn (insn);
3722 else
2dd6f9ed 3723 emit_library_call_value (memcmp_libfunc, result, LCT_PURE,
0cd832f0 3724 TYPE_MODE (integer_type_node), 3,
3725 XEXP (arg1_rtx, 0), Pmode,
3726 XEXP (arg2_rtx, 0), Pmode,
3727 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
78a8ed03 3728 TYPE_UNSIGNED (sizetype)),
0cd832f0 3729 TYPE_MODE (sizetype));
53800dbe 3730
3731 /* Return the value in the proper mode for this function. */
3732 mode = TYPE_MODE (TREE_TYPE (exp));
3733 if (GET_MODE (result) == mode)
3734 return result;
3735 else if (target != 0)
3736 {
3737 convert_move (target, result, 0);
3738 return target;
3739 }
3740 else
3741 return convert_to_mode (mode, result, 0);
3742 }
bd021c1c 3743#endif /* HAVE_cmpmemsi. */
53800dbe 3744
c2f47e15 3745 return NULL_RTX;
6f428e8b 3746}
3747
c2f47e15 3748/* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX
53800dbe 3749 if we failed the caller should emit a normal call, otherwise try to get
3750 the result in TARGET, if convenient. */
902de8ed 3751
53800dbe 3752static rtx
a65c4d64 3753expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
53800dbe 3754{
c2f47e15 3755 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3756 return NULL_RTX;
bf8e3599 3757
6ac5504b 3758#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
6b531606 3759 if (direct_optab_handler (cmpstr_optab, SImode) != CODE_FOR_nothing
3760 || direct_optab_handler (cmpstrn_optab, SImode) != CODE_FOR_nothing)
6ac5504b 3761 {
3762 rtx arg1_rtx, arg2_rtx;
3763 rtx result, insn = NULL_RTX;
3764 tree fndecl, fn;
c2f47e15 3765 tree arg1 = CALL_EXPR_ARG (exp, 0);
3766 tree arg2 = CALL_EXPR_ARG (exp, 1);
a0c938f0 3767
957d0361 3768 unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
3769 unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
6ac5504b 3770
3771 /* If we don't have POINTER_TYPE, call the function. */
3772 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 3773 return NULL_RTX;
7a3f89b5 3774
6ac5504b 3775 /* Stabilize the arguments in case gen_cmpstr(n)si fail. */
3776 arg1 = builtin_save_expr (arg1);
3777 arg2 = builtin_save_expr (arg2);
7a3f89b5 3778
d8ae1baa 3779 arg1_rtx = get_memory_rtx (arg1, NULL);
3780 arg2_rtx = get_memory_rtx (arg2, NULL);
53800dbe 3781
6ac5504b 3782#ifdef HAVE_cmpstrsi
3783 /* Try to call cmpstrsi. */
3784 if (HAVE_cmpstrsi)
3785 {
a0c938f0 3786 enum machine_mode insn_mode
6ac5504b 3787 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3788
3789 /* Make a place to write the result of the instruction. */
3790 result = target;
3791 if (! (result != 0
3792 && REG_P (result) && GET_MODE (result) == insn_mode
3793 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3794 result = gen_reg_rtx (insn_mode);
3795
3796 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
3797 GEN_INT (MIN (arg1_align, arg2_align)));
3798 }
3799#endif
03fd9d2c 3800#ifdef HAVE_cmpstrnsi
6ac5504b 3801 /* Try to determine at least one length and call cmpstrnsi. */
a0c938f0 3802 if (!insn && HAVE_cmpstrnsi)
6ac5504b 3803 {
3804 tree len;
3805 rtx arg3_rtx;
3806
a0c938f0 3807 enum machine_mode insn_mode
6ac5504b 3808 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
3809 tree len1 = c_strlen (arg1, 1);
3810 tree len2 = c_strlen (arg2, 1);
3811
3812 if (len1)
3813 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3814 if (len2)
3815 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3816
3817 /* If we don't have a constant length for the first, use the length
3818 of the second, if we know it. We don't require a constant for
3819 this case; some cost analysis could be done if both are available
3820 but neither is constant. For now, assume they're equally cheap,
3821 unless one has side effects. If both strings have constant lengths,
3822 use the smaller. */
3823
3824 if (!len1)
3825 len = len2;
3826 else if (!len2)
3827 len = len1;
3828 else if (TREE_SIDE_EFFECTS (len1))
3829 len = len2;
3830 else if (TREE_SIDE_EFFECTS (len2))
3831 len = len1;
3832 else if (TREE_CODE (len1) != INTEGER_CST)
3833 len = len2;
3834 else if (TREE_CODE (len2) != INTEGER_CST)
3835 len = len1;
3836 else if (tree_int_cst_lt (len1, len2))
3837 len = len1;
3838 else
3839 len = len2;
3840
3841 /* If both arguments have side effects, we cannot optimize. */
3842 if (!len || TREE_SIDE_EFFECTS (len))
6b961939 3843 goto do_libcall;
53800dbe 3844
8ec3c5c2 3845 arg3_rtx = expand_normal (len);
902de8ed 3846
6ac5504b 3847 /* Make a place to write the result of the instruction. */
3848 result = target;
3849 if (! (result != 0
3850 && REG_P (result) && GET_MODE (result) == insn_mode
3851 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3852 result = gen_reg_rtx (insn_mode);
53800dbe 3853
6ac5504b 3854 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3855 GEN_INT (MIN (arg1_align, arg2_align)));
3856 }
3857#endif
3f8aefe2 3858
6ac5504b 3859 if (insn)
3860 {
a65c4d64 3861 enum machine_mode mode;
6ac5504b 3862 emit_insn (insn);
3f8aefe2 3863
6ac5504b 3864 /* Return the value in the proper mode for this function. */
3865 mode = TYPE_MODE (TREE_TYPE (exp));
3866 if (GET_MODE (result) == mode)
3867 return result;
3868 if (target == 0)
3869 return convert_to_mode (mode, result, 0);
3870 convert_move (target, result, 0);
3871 return target;
3872 }
902de8ed 3873
6ac5504b 3874 /* Expand the library call ourselves using a stabilized argument
3875 list to avoid re-evaluating the function's arguments twice. */
2694880e 3876#ifdef HAVE_cmpstrnsi
6b961939 3877 do_libcall:
2694880e 3878#endif
6ac5504b 3879 fndecl = get_callee_fndecl (exp);
0568e9c1 3880 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2);
a65c4d64 3881 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
3882 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
6ac5504b 3883 return expand_call (fn, target, target == const0_rtx);
3884 }
7a3f89b5 3885#endif
c2f47e15 3886 return NULL_RTX;
83d79705 3887}
53800dbe 3888
48e1416a 3889/* Expand expression EXP, which is a call to the strncmp builtin. Return
c2f47e15 3890 NULL_RTX if we failed the caller should emit a normal call, otherwise try to get
ed09096d 3891 the result in TARGET, if convenient. */
27d0c333 3892
ed09096d 3893static rtx
a65c4d64 3894expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
3895 ATTRIBUTE_UNUSED enum machine_mode mode)
ed09096d 3896{
a65c4d64 3897 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
389dd41b 3898
c2f47e15 3899 if (!validate_arglist (exp,
3900 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3901 return NULL_RTX;
ed09096d 3902
6e34e617 3903 /* If c_strlen can determine an expression for one of the string
6ac5504b 3904 lengths, and it doesn't have side effects, then emit cmpstrnsi
7a3f89b5 3905 using length MIN(strlen(string)+1, arg3). */
6ac5504b 3906#ifdef HAVE_cmpstrnsi
3907 if (HAVE_cmpstrnsi)
7a3f89b5 3908 {
3909 tree len, len1, len2;
3910 rtx arg1_rtx, arg2_rtx, arg3_rtx;
3911 rtx result, insn;
0b25db21 3912 tree fndecl, fn;
c2f47e15 3913 tree arg1 = CALL_EXPR_ARG (exp, 0);
3914 tree arg2 = CALL_EXPR_ARG (exp, 1);
3915 tree arg3 = CALL_EXPR_ARG (exp, 2);
6f428e8b 3916
957d0361 3917 unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
3918 unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
7a3f89b5 3919 enum machine_mode insn_mode
6ac5504b 3920 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
bf8e3599 3921
681fab1e 3922 len1 = c_strlen (arg1, 1);
3923 len2 = c_strlen (arg2, 1);
7a3f89b5 3924
3925 if (len1)
389dd41b 3926 len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1);
7a3f89b5 3927 if (len2)
389dd41b 3928 len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2);
7a3f89b5 3929
3930 /* If we don't have a constant length for the first, use the length
3931 of the second, if we know it. We don't require a constant for
3932 this case; some cost analysis could be done if both are available
3933 but neither is constant. For now, assume they're equally cheap,
3934 unless one has side effects. If both strings have constant lengths,
3935 use the smaller. */
3936
3937 if (!len1)
3938 len = len2;
3939 else if (!len2)
3940 len = len1;
3941 else if (TREE_SIDE_EFFECTS (len1))
3942 len = len2;
3943 else if (TREE_SIDE_EFFECTS (len2))
3944 len = len1;
3945 else if (TREE_CODE (len1) != INTEGER_CST)
3946 len = len2;
3947 else if (TREE_CODE (len2) != INTEGER_CST)
3948 len = len1;
3949 else if (tree_int_cst_lt (len1, len2))
3950 len = len1;
3951 else
3952 len = len2;
6e34e617 3953
7a3f89b5 3954 /* If both arguments have side effects, we cannot optimize. */
3955 if (!len || TREE_SIDE_EFFECTS (len))
c2f47e15 3956 return NULL_RTX;
bf8e3599 3957
7a3f89b5 3958 /* The actual new length parameter is MIN(len,arg3). */
389dd41b 3959 len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len,
3960 fold_convert_loc (loc, TREE_TYPE (len), arg3));
7a3f89b5 3961
3962 /* If we don't have POINTER_TYPE, call the function. */
3963 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 3964 return NULL_RTX;
7a3f89b5 3965
3966 /* Make a place to write the result of the instruction. */
3967 result = target;
3968 if (! (result != 0
8ad4c111 3969 && REG_P (result) && GET_MODE (result) == insn_mode
7a3f89b5 3970 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3971 result = gen_reg_rtx (insn_mode);
3972
a65c4d64 3973 /* Stabilize the arguments in case gen_cmpstrnsi fails. */
3974 arg1 = builtin_save_expr (arg1);
3975 arg2 = builtin_save_expr (arg2);
3976 len = builtin_save_expr (len);
27d0c333 3977
a65c4d64 3978 arg1_rtx = get_memory_rtx (arg1, len);
3979 arg2_rtx = get_memory_rtx (arg2, len);
3980 arg3_rtx = expand_normal (len);
3981 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3982 GEN_INT (MIN (arg1_align, arg2_align)));
3983 if (insn)
3984 {
3985 emit_insn (insn);
49f0327b 3986
a65c4d64 3987 /* Return the value in the proper mode for this function. */
3988 mode = TYPE_MODE (TREE_TYPE (exp));
3989 if (GET_MODE (result) == mode)
3990 return result;
3991 if (target == 0)
3992 return convert_to_mode (mode, result, 0);
3993 convert_move (target, result, 0);
3994 return target;
3995 }
27d0c333 3996
a65c4d64 3997 /* Expand the library call ourselves using a stabilized argument
3998 list to avoid re-evaluating the function's arguments twice. */
3999 fndecl = get_callee_fndecl (exp);
0568e9c1 4000 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 3,
4001 arg1, arg2, len);
a65c4d64 4002 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
4003 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4004 return expand_call (fn, target, target == const0_rtx);
4005 }
4006#endif
c2f47e15 4007 return NULL_RTX;
49f0327b 4008}
4009
a66c9326 4010/* Expand a call to __builtin_saveregs, generating the result in TARGET,
4011 if that's convenient. */
902de8ed 4012
a66c9326 4013rtx
aecda0d6 4014expand_builtin_saveregs (void)
53800dbe 4015{
a66c9326 4016 rtx val, seq;
53800dbe 4017
4018 /* Don't do __builtin_saveregs more than once in a function.
4019 Save the result of the first call and reuse it. */
4020 if (saveregs_value != 0)
4021 return saveregs_value;
53800dbe 4022
a66c9326 4023 /* When this function is called, it means that registers must be
4024 saved on entry to this function. So we migrate the call to the
4025 first insn of this function. */
4026
4027 start_sequence ();
53800dbe 4028
a66c9326 4029 /* Do whatever the machine needs done in this case. */
45550790 4030 val = targetm.calls.expand_builtin_saveregs ();
53800dbe 4031
a66c9326 4032 seq = get_insns ();
4033 end_sequence ();
53800dbe 4034
a66c9326 4035 saveregs_value = val;
53800dbe 4036
31d3e01c 4037 /* Put the insns after the NOTE that starts the function. If this
4038 is inside a start_sequence, make the outer-level insn chain current, so
a66c9326 4039 the code is placed at the start of the function. */
4040 push_topmost_sequence ();
0ec80471 4041 emit_insn_after (seq, entry_of_function ());
a66c9326 4042 pop_topmost_sequence ();
4043
4044 return val;
53800dbe 4045}
4046
79012a9d 4047/* Expand a call to __builtin_next_arg. */
27d0c333 4048
53800dbe 4049static rtx
79012a9d 4050expand_builtin_next_arg (void)
53800dbe 4051{
79012a9d 4052 /* Checking arguments is already done in fold_builtin_next_arg
4053 that must be called before this function. */
940ddc5c 4054 return expand_binop (ptr_mode, add_optab,
abe32cce 4055 crtl->args.internal_arg_pointer,
4056 crtl->args.arg_offset_rtx,
53800dbe 4057 NULL_RTX, 0, OPTAB_LIB_WIDEN);
4058}
4059
a66c9326 4060/* Make it easier for the backends by protecting the valist argument
4061 from multiple evaluations. */
4062
4063static tree
389dd41b 4064stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
a66c9326 4065{
5f57a8b1 4066 tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
4067
182cf5a9 4068 /* The current way of determining the type of valist is completely
4069 bogus. We should have the information on the va builtin instead. */
4070 if (!vatype)
4071 vatype = targetm.fn_abi_va_list (cfun->decl);
5f57a8b1 4072
4073 if (TREE_CODE (vatype) == ARRAY_TYPE)
a66c9326 4074 {
2d47cc32 4075 if (TREE_SIDE_EFFECTS (valist))
4076 valist = save_expr (valist);
11a61dea 4077
2d47cc32 4078 /* For this case, the backends will be expecting a pointer to
5f57a8b1 4079 vatype, but it's possible we've actually been given an array
4080 (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)).
2d47cc32 4081 So fix it. */
4082 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
8a15c04a 4083 {
5f57a8b1 4084 tree p1 = build_pointer_type (TREE_TYPE (vatype));
389dd41b 4085 valist = build_fold_addr_expr_with_type_loc (loc, valist, p1);
8a15c04a 4086 }
a66c9326 4087 }
11a61dea 4088 else
a66c9326 4089 {
182cf5a9 4090 tree pt = build_pointer_type (vatype);
11a61dea 4091
2d47cc32 4092 if (! needs_lvalue)
4093 {
11a61dea 4094 if (! TREE_SIDE_EFFECTS (valist))
4095 return valist;
bf8e3599 4096
389dd41b 4097 valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist);
a66c9326 4098 TREE_SIDE_EFFECTS (valist) = 1;
a66c9326 4099 }
2d47cc32 4100
11a61dea 4101 if (TREE_SIDE_EFFECTS (valist))
2d47cc32 4102 valist = save_expr (valist);
182cf5a9 4103 valist = fold_build2_loc (loc, MEM_REF,
4104 vatype, valist, build_int_cst (pt, 0));
a66c9326 4105 }
4106
4107 return valist;
4108}
4109
2e15d750 4110/* The "standard" definition of va_list is void*. */
4111
4112tree
4113std_build_builtin_va_list (void)
4114{
4115 return ptr_type_node;
4116}
4117
5f57a8b1 4118/* The "standard" abi va_list is va_list_type_node. */
4119
4120tree
4121std_fn_abi_va_list (tree fndecl ATTRIBUTE_UNUSED)
4122{
4123 return va_list_type_node;
4124}
4125
4126/* The "standard" type of va_list is va_list_type_node. */
4127
4128tree
4129std_canonical_va_list_type (tree type)
4130{
4131 tree wtype, htype;
4132
4133 if (INDIRECT_REF_P (type))
4134 type = TREE_TYPE (type);
4135 else if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE(type)))
4136 type = TREE_TYPE (type);
5f57a8b1 4137 wtype = va_list_type_node;
4138 htype = type;
7b36f9ab 4139 /* Treat structure va_list types. */
4140 if (TREE_CODE (wtype) == RECORD_TYPE && POINTER_TYPE_P (htype))
4141 htype = TREE_TYPE (htype);
4142 else if (TREE_CODE (wtype) == ARRAY_TYPE)
5f57a8b1 4143 {
4144 /* If va_list is an array type, the argument may have decayed
4145 to a pointer type, e.g. by being passed to another function.
4146 In that case, unwrap both types so that we can compare the
4147 underlying records. */
4148 if (TREE_CODE (htype) == ARRAY_TYPE
4149 || POINTER_TYPE_P (htype))
4150 {
4151 wtype = TREE_TYPE (wtype);
4152 htype = TREE_TYPE (htype);
4153 }
4154 }
4155 if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype))
4156 return va_list_type_node;
4157
4158 return NULL_TREE;
4159}
4160
a66c9326 4161/* The "standard" implementation of va_start: just assign `nextarg' to
4162 the variable. */
27d0c333 4163
a66c9326 4164void
aecda0d6 4165std_expand_builtin_va_start (tree valist, rtx nextarg)
a66c9326 4166{
f03c17bc 4167 rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
4168 convert_move (va_r, nextarg, 0);
a66c9326 4169}
4170
c2f47e15 4171/* Expand EXP, a call to __builtin_va_start. */
27d0c333 4172
a66c9326 4173static rtx
c2f47e15 4174expand_builtin_va_start (tree exp)
a66c9326 4175{
4176 rtx nextarg;
c2f47e15 4177 tree valist;
389dd41b 4178 location_t loc = EXPR_LOCATION (exp);
a66c9326 4179
c2f47e15 4180 if (call_expr_nargs (exp) < 2)
cb166087 4181 {
389dd41b 4182 error_at (loc, "too few arguments to function %<va_start%>");
cb166087 4183 return const0_rtx;
4184 }
a66c9326 4185
c2f47e15 4186 if (fold_builtin_next_arg (exp, true))
79012a9d 4187 return const0_rtx;
7c2f0500 4188
79012a9d 4189 nextarg = expand_builtin_next_arg ();
389dd41b 4190 valist = stabilize_va_list_loc (loc, CALL_EXPR_ARG (exp, 0), 1);
a66c9326 4191
8a58ed0a 4192 if (targetm.expand_builtin_va_start)
4193 targetm.expand_builtin_va_start (valist, nextarg);
4194 else
4195 std_expand_builtin_va_start (valist, nextarg);
a66c9326 4196
4197 return const0_rtx;
4198}
4199
a66c9326 4200/* The "standard" implementation of va_arg: read the value from the
4201 current (padded) address and increment by the (padded) size. */
f7c44134 4202
e0eca1fa 4203tree
75a70cf9 4204std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
4205 gimple_seq *post_p)
fcdd3ab3 4206{
52cc2eeb 4207 tree addr, t, type_size, rounded_size, valist_tmp;
b8e8e485 4208 unsigned HOST_WIDE_INT align, boundary;
bef380a4 4209 bool indirect;
52cc2eeb 4210
4211#ifdef ARGS_GROW_DOWNWARD
4212 /* All of the alignment and movement below is for args-grow-up machines.
4213 As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
4214 implement their own specialized gimplify_va_arg_expr routines. */
64db345d 4215 gcc_unreachable ();
52cc2eeb 4216#endif
fcdd3ab3 4217
bef380a4 4218 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
4219 if (indirect)
4220 type = build_pointer_type (type);
4221
52cc2eeb 4222 align = PARM_BOUNDARY / BITS_PER_UNIT;
bd99ba64 4223 boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
c8b779eb 4224
4225 /* When we align parameter on stack for caller, if the parameter
befa808c 4226 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
4227 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
c8b779eb 4228 here with caller. */
befa808c 4229 if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
4230 boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
c8b779eb 4231
4232 boundary /= BITS_PER_UNIT;
fcdd3ab3 4233
52cc2eeb 4234 /* Hoist the valist value into a temporary for the moment. */
ecdeeb37 4235 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
4236
fcdd3ab3 4237 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
4238 requires greater alignment, we must perform dynamic alignment. */
85c1f587 4239 if (boundary > align
4240 && !integer_zerop (TYPE_SIZE (type)))
fcdd3ab3 4241 {
41076ef6 4242 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
2cc66f2a 4243 fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
52cc2eeb 4244 gimplify_and_add (t, pre_p);
4245
41076ef6 4246 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
a0553bff 4247 fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
4248 valist_tmp,
4249 build_int_cst (TREE_TYPE (valist), -boundary)));
ecdeeb37 4250 gimplify_and_add (t, pre_p);
fcdd3ab3 4251 }
c5dc0c32 4252 else
4253 boundary = align;
4254
4255 /* If the actual alignment is less than the alignment of the type,
4256 adjust the type accordingly so that we don't assume strict alignment
f0b5f617 4257 when dereferencing the pointer. */
c5dc0c32 4258 boundary *= BITS_PER_UNIT;
4259 if (boundary < TYPE_ALIGN (type))
4260 {
4261 type = build_variant_type_copy (type);
4262 TYPE_ALIGN (type) = boundary;
4263 }
fcdd3ab3 4264
bcff3604 4265 /* Compute the rounded size of the type. */
52cc2eeb 4266 type_size = size_in_bytes (type);
4267 rounded_size = round_up (type_size, align);
4268
fcdd3ab3 4269 /* Reduce rounded_size so it's sharable with the postqueue. */
4270 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
4271
4272 /* Get AP. */
ecdeeb37 4273 addr = valist_tmp;
52cc2eeb 4274 if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
fcdd3ab3 4275 {
4276 /* Small args are padded downward. */
389dd41b 4277 t = fold_build2_loc (input_location, GT_EXPR, sizetype,
4278 rounded_size, size_int (align));
49d00087 4279 t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
4280 size_binop (MINUS_EXPR, rounded_size, type_size));
2cc66f2a 4281 addr = fold_build_pointer_plus (addr, t);
fcdd3ab3 4282 }
4283
fcdd3ab3 4284 /* Compute new value for AP. */
2cc66f2a 4285 t = fold_build_pointer_plus (valist_tmp, rounded_size);
41076ef6 4286 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
ecdeeb37 4287 gimplify_and_add (t, pre_p);
e0eca1fa 4288
4289 addr = fold_convert (build_pointer_type (type), addr);
fcdd3ab3 4290
bef380a4 4291 if (indirect)
f2462d6c 4292 addr = build_va_arg_indirect_ref (addr);
4293
4294 return build_va_arg_indirect_ref (addr);
4295}
a0930a69 4296
f2462d6c 4297/* Build an indirect-ref expression over the given TREE, which represents a
4298 piece of a va_arg() expansion. */
4299tree
4300build_va_arg_indirect_ref (tree addr)
4301{
5c9d7b33 4302 addr = build_simple_mem_ref_loc (EXPR_LOCATION (addr), addr);
f2462d6c 4303
a0930a69 4304 if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */
4305 mf_mark (addr);
bef380a4 4306
a0930a69 4307 return addr;
433006a9 4308}
4309
fcdd3ab3 4310/* Return a dummy expression of type TYPE in order to keep going after an
4311 error. */
4312
4313static tree
4314dummy_object (tree type)
4315{
535664e3 4316 tree t = build_int_cst (build_pointer_type (type), 0);
377bc54c 4317 return build2 (MEM_REF, type, t, t);
fcdd3ab3 4318}
4319
2799a2b7 4320/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
4321 builtin function, but a very special sort of operator. */
fcdd3ab3 4322
4323enum gimplify_status
75a70cf9 4324gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
fcdd3ab3 4325{
5f57a8b1 4326 tree promoted_type, have_va_type;
fcdd3ab3 4327 tree valist = TREE_OPERAND (*expr_p, 0);
4328 tree type = TREE_TYPE (*expr_p);
4329 tree t;
389dd41b 4330 location_t loc = EXPR_LOCATION (*expr_p);
fcdd3ab3 4331
4332 /* Verify that valist is of the proper type. */
fcdd3ab3 4333 have_va_type = TREE_TYPE (valist);
f43dda35 4334 if (have_va_type == error_mark_node)
4335 return GS_ERROR;
5f57a8b1 4336 have_va_type = targetm.canonical_va_list_type (have_va_type);
f43dda35 4337
5f57a8b1 4338 if (have_va_type == NULL_TREE)
fcdd3ab3 4339 {
e60a6f7b 4340 error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>");
e0eca1fa 4341 return GS_ERROR;
fcdd3ab3 4342 }
4343
4344 /* Generate a diagnostic for requesting data of a type that cannot
4345 be passed through `...' due to type promotion at the call site. */
5f57a8b1 4346 if ((promoted_type = lang_hooks.types.type_promotes_to (type))
fcdd3ab3 4347 != type)
4348 {
4349 static bool gave_help;
a52d5726 4350 bool warned;
fcdd3ab3 4351
4352 /* Unfortunately, this is merely undefined, rather than a constraint
4353 violation, so we cannot make this an error. If this call is never
4354 executed, the program is still strictly conforming. */
e60a6f7b 4355 warned = warning_at (loc, 0,
4356 "%qT is promoted to %qT when passed through %<...%>",
4357 type, promoted_type);
a52d5726 4358 if (!gave_help && warned)
fcdd3ab3 4359 {
4360 gave_help = true;
e60a6f7b 4361 inform (loc, "(so you should pass %qT not %qT to %<va_arg%>)",
4362 promoted_type, type);
fcdd3ab3 4363 }
4364
4365 /* We can, however, treat "undefined" any way we please.
4366 Call abort to encourage the user to fix the program. */
a52d5726 4367 if (warned)
e60a6f7b 4368 inform (loc, "if this code is reached, the program will abort");
ad0e7a06 4369 /* Before the abort, allow the evaluation of the va_list
4370 expression to exit or longjmp. */
4371 gimplify_and_add (valist, pre_p);
389dd41b 4372 t = build_call_expr_loc (loc,
b9a16870 4373 builtin_decl_implicit (BUILT_IN_TRAP), 0);
75a70cf9 4374 gimplify_and_add (t, pre_p);
fcdd3ab3 4375
4376 /* This is dead code, but go ahead and finish so that the
4377 mode of the result comes out right. */
4378 *expr_p = dummy_object (type);
4379 return GS_ALL_DONE;
4380 }
4381 else
4382 {
4383 /* Make it easier for the backends by protecting the valist argument
a0c938f0 4384 from multiple evaluations. */
5f57a8b1 4385 if (TREE_CODE (have_va_type) == ARRAY_TYPE)
e0eca1fa 4386 {
4387 /* For this case, the backends will be expecting a pointer to
5f57a8b1 4388 TREE_TYPE (abi), but it's possible we've
4389 actually been given an array (an actual TARGET_FN_ABI_VA_LIST).
e0eca1fa 4390 So fix it. */
4391 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
4392 {
5f57a8b1 4393 tree p1 = build_pointer_type (TREE_TYPE (have_va_type));
389dd41b 4394 valist = fold_convert_loc (loc, p1,
4395 build_fold_addr_expr_loc (loc, valist));
e0eca1fa 4396 }
75a70cf9 4397
e0eca1fa 4398 gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
4399 }
4400 else
4401 gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
fcdd3ab3 4402
17a6380d 4403 if (!targetm.gimplify_va_arg_expr)
75a70cf9 4404 /* FIXME: Once most targets are converted we should merely
89f18f73 4405 assert this is non-null. */
fcdd3ab3 4406 return GS_ALL_DONE;
4407
17a6380d 4408 *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
fcdd3ab3 4409 return GS_OK;
4410 }
4411}
4412
c2f47e15 4413/* Expand EXP, a call to __builtin_va_end. */
f7c44134 4414
a66c9326 4415static rtx
c2f47e15 4416expand_builtin_va_end (tree exp)
a66c9326 4417{
c2f47e15 4418 tree valist = CALL_EXPR_ARG (exp, 0);
8a15c04a 4419
8a15c04a 4420 /* Evaluate for side effects, if needed. I hate macros that don't
4421 do that. */
4422 if (TREE_SIDE_EFFECTS (valist))
4423 expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
a66c9326 4424
4425 return const0_rtx;
4426}
4427
c2f47e15 4428/* Expand EXP, a call to __builtin_va_copy. We do this as a
a66c9326 4429 builtin rather than just as an assignment in stdarg.h because of the
4430 nastiness of array-type va_list types. */
f7c44134 4431
a66c9326 4432static rtx
c2f47e15 4433expand_builtin_va_copy (tree exp)
a66c9326 4434{
4435 tree dst, src, t;
389dd41b 4436 location_t loc = EXPR_LOCATION (exp);
a66c9326 4437
c2f47e15 4438 dst = CALL_EXPR_ARG (exp, 0);
4439 src = CALL_EXPR_ARG (exp, 1);
a66c9326 4440
389dd41b 4441 dst = stabilize_va_list_loc (loc, dst, 1);
4442 src = stabilize_va_list_loc (loc, src, 0);
a66c9326 4443
5f57a8b1 4444 gcc_assert (cfun != NULL && cfun->decl != NULL_TREE);
4445
4446 if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE)
a66c9326 4447 {
5f57a8b1 4448 t = build2 (MODIFY_EXPR, targetm.fn_abi_va_list (cfun->decl), dst, src);
a66c9326 4449 TREE_SIDE_EFFECTS (t) = 1;
4450 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4451 }
4452 else
4453 {
11a61dea 4454 rtx dstb, srcb, size;
4455
4456 /* Evaluate to pointers. */
4457 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
4458 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
5f57a8b1 4459 size = expand_expr (TYPE_SIZE_UNIT (targetm.fn_abi_va_list (cfun->decl)),
4460 NULL_RTX, VOIDmode, EXPAND_NORMAL);
11a61dea 4461
85d654dd 4462 dstb = convert_memory_address (Pmode, dstb);
4463 srcb = convert_memory_address (Pmode, srcb);
726ec87c 4464
11a61dea 4465 /* "Dereference" to BLKmode memories. */
4466 dstb = gen_rtx_MEM (BLKmode, dstb);
ab6ab77e 4467 set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
5f57a8b1 4468 set_mem_align (dstb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 4469 srcb = gen_rtx_MEM (BLKmode, srcb);
ab6ab77e 4470 set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
5f57a8b1 4471 set_mem_align (srcb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 4472
4473 /* Copy. */
0378dbdc 4474 emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
a66c9326 4475 }
4476
4477 return const0_rtx;
4478}
4479
53800dbe 4480/* Expand a call to one of the builtin functions __builtin_frame_address or
4481 __builtin_return_address. */
27d0c333 4482
53800dbe 4483static rtx
c2f47e15 4484expand_builtin_frame_address (tree fndecl, tree exp)
53800dbe 4485{
53800dbe 4486 /* The argument must be a nonnegative integer constant.
4487 It counts the number of frames to scan up the stack.
4488 The value is the return address saved in that frame. */
c2f47e15 4489 if (call_expr_nargs (exp) == 0)
53800dbe 4490 /* Warning about missing arg was already issued. */
4491 return const0_rtx;
c2f47e15 4492 else if (! host_integerp (CALL_EXPR_ARG (exp, 0), 1))
53800dbe 4493 {
4494 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
07e3a3d2 4495 error ("invalid argument to %<__builtin_frame_address%>");
53800dbe 4496 else
07e3a3d2 4497 error ("invalid argument to %<__builtin_return_address%>");
53800dbe 4498 return const0_rtx;
4499 }
4500 else
4501 {
27d0c333 4502 rtx tem
4503 = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
c2f47e15 4504 tree_low_cst (CALL_EXPR_ARG (exp, 0), 1));
53800dbe 4505
4506 /* Some ports cannot access arbitrary stack frames. */
4507 if (tem == NULL)
4508 {
4509 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
c3ceba8e 4510 warning (0, "unsupported argument to %<__builtin_frame_address%>");
53800dbe 4511 else
c3ceba8e 4512 warning (0, "unsupported argument to %<__builtin_return_address%>");
53800dbe 4513 return const0_rtx;
4514 }
4515
4516 /* For __builtin_frame_address, return what we've got. */
4517 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4518 return tem;
4519
8ad4c111 4520 if (!REG_P (tem)
53800dbe 4521 && ! CONSTANT_P (tem))
99182918 4522 tem = copy_addr_to_reg (tem);
53800dbe 4523 return tem;
4524 }
4525}
4526
990495a7 4527/* Expand EXP, a call to the alloca builtin. Return NULL_RTX if we
5be42b39 4528 failed and the caller should emit a normal call. CANNOT_ACCUMULATE
4529 is the same as for allocate_dynamic_stack_space. */
15c6cf6b 4530
53800dbe 4531static rtx
5be42b39 4532expand_builtin_alloca (tree exp, bool cannot_accumulate)
53800dbe 4533{
4534 rtx op0;
15c6cf6b 4535 rtx result;
581bf1c2 4536 bool valid_arglist;
4537 unsigned int align;
4538 bool alloca_with_align = (DECL_FUNCTION_CODE (get_callee_fndecl (exp))
4539 == BUILT_IN_ALLOCA_WITH_ALIGN);
53800dbe 4540
f883da84 4541 /* Emit normal call if we use mudflap. */
4542 if (flag_mudflap)
c2f47e15 4543 return NULL_RTX;
4ee9c684 4544
581bf1c2 4545 valid_arglist
4546 = (alloca_with_align
4547 ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
4548 : validate_arglist (exp, INTEGER_TYPE, VOID_TYPE));
4549
4550 if (!valid_arglist)
c2f47e15 4551 return NULL_RTX;
53800dbe 4552
4553 /* Compute the argument. */
c2f47e15 4554 op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
53800dbe 4555
581bf1c2 4556 /* Compute the alignment. */
4557 align = (alloca_with_align
4558 ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1))
4559 : BIGGEST_ALIGNMENT);
4560
53800dbe 4561 /* Allocate the desired space. */
581bf1c2 4562 result = allocate_dynamic_stack_space (op0, 0, align, cannot_accumulate);
85d654dd 4563 result = convert_memory_address (ptr_mode, result);
15c6cf6b 4564
4565 return result;
53800dbe 4566}
4567
74bdbe96 4568/* Expand a call to bswap builtin in EXP.
4569 Return NULL_RTX if a normal call should be emitted rather than expanding the
4570 function in-line. If convenient, the result should be placed in TARGET.
4571 SUBTARGET may be used as the target for computing one of EXP's operands. */
42791117 4572
4573static rtx
74bdbe96 4574expand_builtin_bswap (enum machine_mode target_mode, tree exp, rtx target,
4575 rtx subtarget)
42791117 4576{
42791117 4577 tree arg;
4578 rtx op0;
4579
c2f47e15 4580 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4581 return NULL_RTX;
42791117 4582
c2f47e15 4583 arg = CALL_EXPR_ARG (exp, 0);
74bdbe96 4584 op0 = expand_expr (arg,
4585 subtarget && GET_MODE (subtarget) == target_mode
4586 ? subtarget : NULL_RTX,
4587 target_mode, EXPAND_NORMAL);
4588 if (GET_MODE (op0) != target_mode)
4589 op0 = convert_to_mode (target_mode, op0, 1);
42791117 4590
74bdbe96 4591 target = expand_unop (target_mode, bswap_optab, op0, target, 1);
42791117 4592
4593 gcc_assert (target);
4594
74bdbe96 4595 return convert_to_mode (target_mode, target, 1);
42791117 4596}
4597
c2f47e15 4598/* Expand a call to a unary builtin in EXP.
4599 Return NULL_RTX if a normal call should be emitted rather than expanding the
53800dbe 4600 function in-line. If convenient, the result should be placed in TARGET.
4601 SUBTARGET may be used as the target for computing one of EXP's operands. */
15c6cf6b 4602
53800dbe 4603static rtx
c2f47e15 4604expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target,
aecda0d6 4605 rtx subtarget, optab op_optab)
53800dbe 4606{
4607 rtx op0;
c2f47e15 4608
4609 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4610 return NULL_RTX;
53800dbe 4611
4612 /* Compute the argument. */
f97eea22 4613 op0 = expand_expr (CALL_EXPR_ARG (exp, 0),
4614 (subtarget
4615 && (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0)))
4616 == GET_MODE (subtarget))) ? subtarget : NULL_RTX,
1db6d067 4617 VOIDmode, EXPAND_NORMAL);
6a08d0ab 4618 /* Compute op, into TARGET if possible.
53800dbe 4619 Set TARGET to wherever the result comes back. */
c2f47e15 4620 target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
6aaa1f9e 4621 op_optab, op0, target, op_optab != clrsb_optab);
64db345d 4622 gcc_assert (target);
7d3f6cc7 4623
efb070c8 4624 return convert_to_mode (target_mode, target, 0);
53800dbe 4625}
89cfe6e5 4626
48e1416a 4627/* Expand a call to __builtin_expect. We just return our argument
5a74f77e 4628 as the builtin_expect semantic should've been already executed by
4629 tree branch prediction pass. */
89cfe6e5 4630
4631static rtx
c2f47e15 4632expand_builtin_expect (tree exp, rtx target)
89cfe6e5 4633{
1e4adcfc 4634 tree arg;
89cfe6e5 4635
c2f47e15 4636 if (call_expr_nargs (exp) < 2)
89cfe6e5 4637 return const0_rtx;
c2f47e15 4638 arg = CALL_EXPR_ARG (exp, 0);
89cfe6e5 4639
c2f47e15 4640 target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5a74f77e 4641 /* When guessing was done, the hints should be already stripped away. */
07311427 4642 gcc_assert (!flag_guess_branch_prob
852f689e 4643 || optimize == 0 || seen_error ());
89cfe6e5 4644 return target;
4645}
689df48e 4646
fca0886c 4647/* Expand a call to __builtin_assume_aligned. We just return our first
4648 argument as the builtin_assume_aligned semantic should've been already
4649 executed by CCP. */
4650
4651static rtx
4652expand_builtin_assume_aligned (tree exp, rtx target)
4653{
4654 if (call_expr_nargs (exp) < 2)
4655 return const0_rtx;
4656 target = expand_expr (CALL_EXPR_ARG (exp, 0), target, VOIDmode,
4657 EXPAND_NORMAL);
4658 gcc_assert (!TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 1))
4659 && (call_expr_nargs (exp) < 3
4660 || !TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 2))));
4661 return target;
4662}
4663
c22de3f0 4664void
aecda0d6 4665expand_builtin_trap (void)
a0ef1725 4666{
4667#ifdef HAVE_trap
4668 if (HAVE_trap)
4669 emit_insn (gen_trap ());
4670 else
4671#endif
4672 emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
4673 emit_barrier ();
4674}
78a74442 4675
d2b48f0c 4676/* Expand a call to __builtin_unreachable. We do nothing except emit
4677 a barrier saying that control flow will not pass here.
4678
4679 It is the responsibility of the program being compiled to ensure
4680 that control flow does never reach __builtin_unreachable. */
4681static void
4682expand_builtin_unreachable (void)
4683{
4684 emit_barrier ();
4685}
4686
c2f47e15 4687/* Expand EXP, a call to fabs, fabsf or fabsl.
4688 Return NULL_RTX if a normal call should be emitted rather than expanding
78a74442 4689 the function inline. If convenient, the result should be placed
4690 in TARGET. SUBTARGET may be used as the target for computing
4691 the operand. */
4692
4693static rtx
c2f47e15 4694expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
78a74442 4695{
4696 enum machine_mode mode;
4697 tree arg;
4698 rtx op0;
4699
c2f47e15 4700 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
4701 return NULL_RTX;
78a74442 4702
c2f47e15 4703 arg = CALL_EXPR_ARG (exp, 0);
c7f617c2 4704 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
78a74442 4705 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 4706 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
78a74442 4707 return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
4708}
4709
c2f47e15 4710/* Expand EXP, a call to copysign, copysignf, or copysignl.
270436f3 4711 Return NULL is a normal call should be emitted rather than expanding the
4712 function inline. If convenient, the result should be placed in TARGET.
4713 SUBTARGET may be used as the target for computing the operand. */
4714
4715static rtx
c2f47e15 4716expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
270436f3 4717{
4718 rtx op0, op1;
4719 tree arg;
4720
c2f47e15 4721 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
4722 return NULL_RTX;
270436f3 4723
c2f47e15 4724 arg = CALL_EXPR_ARG (exp, 0);
8ec3c5c2 4725 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
270436f3 4726
c2f47e15 4727 arg = CALL_EXPR_ARG (exp, 1);
8ec3c5c2 4728 op1 = expand_normal (arg);
270436f3 4729
4730 return expand_copysign (op0, op1, target);
4731}
4732
19bf118a 4733/* Create a new constant string literal and return a char* pointer to it.
4734 The STRING_CST value is the LEN characters at STR. */
1e8e9920 4735tree
19bf118a 4736build_string_literal (int len, const char *str)
4737{
4738 tree t, elem, index, type;
4739
4740 t = build_string (len, str);
4741 elem = build_type_variant (char_type_node, 1, 0);
40238f64 4742 index = build_index_type (size_int (len - 1));
19bf118a 4743 type = build_array_type (elem, index);
4744 TREE_TYPE (t) = type;
4745 TREE_CONSTANT (t) = 1;
4746 TREE_READONLY (t) = 1;
4747 TREE_STATIC (t) = 1;
4748
19bf118a 4749 type = build_pointer_type (elem);
40238f64 4750 t = build1 (ADDR_EXPR, type,
4751 build4 (ARRAY_REF, elem,
4752 t, integer_zero_node, NULL_TREE, NULL_TREE));
19bf118a 4753 return t;
4754}
4755
ac8fb6db 4756/* Expand a call to __builtin___clear_cache. */
4757
4758static rtx
4759expand_builtin___clear_cache (tree exp ATTRIBUTE_UNUSED)
4760{
4761#ifndef HAVE_clear_cache
4762#ifdef CLEAR_INSN_CACHE
4763 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
4764 does something. Just do the default expansion to a call to
4765 __clear_cache(). */
4766 return NULL_RTX;
4767#else
4768 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
4769 does nothing. There is no need to call it. Do nothing. */
4770 return const0_rtx;
4771#endif /* CLEAR_INSN_CACHE */
4772#else
4773 /* We have a "clear_cache" insn, and it will handle everything. */
4774 tree begin, end;
4775 rtx begin_rtx, end_rtx;
ac8fb6db 4776
4777 /* We must not expand to a library call. If we did, any
4778 fallback library function in libgcc that might contain a call to
4779 __builtin___clear_cache() would recurse infinitely. */
4780 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4781 {
4782 error ("both arguments to %<__builtin___clear_cache%> must be pointers");
4783 return const0_rtx;
4784 }
4785
4786 if (HAVE_clear_cache)
4787 {
8786db1e 4788 struct expand_operand ops[2];
ac8fb6db 4789
4790 begin = CALL_EXPR_ARG (exp, 0);
4791 begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
ac8fb6db 4792
4793 end = CALL_EXPR_ARG (exp, 1);
4794 end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
ac8fb6db 4795
8786db1e 4796 create_address_operand (&ops[0], begin_rtx);
4797 create_address_operand (&ops[1], end_rtx);
4798 if (maybe_expand_insn (CODE_FOR_clear_cache, 2, ops))
4799 return const0_rtx;
ac8fb6db 4800 }
4801 return const0_rtx;
4802#endif /* HAVE_clear_cache */
4803}
4804
4ee9c684 4805/* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
4806
4807static rtx
4808round_trampoline_addr (rtx tramp)
4809{
4810 rtx temp, addend, mask;
4811
4812 /* If we don't need too much alignment, we'll have been guaranteed
4813 proper alignment by get_trampoline_type. */
4814 if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
4815 return tramp;
4816
4817 /* Round address up to desired boundary. */
4818 temp = gen_reg_rtx (Pmode);
4819 addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
4820 mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
4821
4822 temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
4823 temp, 0, OPTAB_LIB_WIDEN);
4824 tramp = expand_simple_binop (Pmode, AND, temp, mask,
4825 temp, 0, OPTAB_LIB_WIDEN);
4826
4827 return tramp;
4828}
4829
4830static rtx
c307f106 4831expand_builtin_init_trampoline (tree exp, bool onstack)
4ee9c684 4832{
4833 tree t_tramp, t_func, t_chain;
82c7907c 4834 rtx m_tramp, r_tramp, r_chain, tmp;
4ee9c684 4835
c2f47e15 4836 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
4ee9c684 4837 POINTER_TYPE, VOID_TYPE))
4838 return NULL_RTX;
4839
c2f47e15 4840 t_tramp = CALL_EXPR_ARG (exp, 0);
4841 t_func = CALL_EXPR_ARG (exp, 1);
4842 t_chain = CALL_EXPR_ARG (exp, 2);
4ee9c684 4843
8ec3c5c2 4844 r_tramp = expand_normal (t_tramp);
82c7907c 4845 m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
4846 MEM_NOTRAP_P (m_tramp) = 1;
4847
c307f106 4848 /* If ONSTACK, the TRAMP argument should be the address of a field
4849 within the local function's FRAME decl. Either way, let's see if
4850 we can fill in the MEM_ATTRs for this memory. */
82c7907c 4851 if (TREE_CODE (t_tramp) == ADDR_EXPR)
4852 set_mem_attributes_minus_bitpos (m_tramp, TREE_OPERAND (t_tramp, 0),
4853 true, 0);
4854
c307f106 4855 /* Creator of a heap trampoline is responsible for making sure the
4856 address is aligned to at least STACK_BOUNDARY. Normally malloc
4857 will ensure this anyhow. */
82c7907c 4858 tmp = round_trampoline_addr (r_tramp);
4859 if (tmp != r_tramp)
4860 {
4861 m_tramp = change_address (m_tramp, BLKmode, tmp);
4862 set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
5b2a69fa 4863 set_mem_size (m_tramp, TRAMPOLINE_SIZE);
82c7907c 4864 }
4865
4866 /* The FUNC argument should be the address of the nested function.
4867 Extract the actual function decl to pass to the hook. */
4868 gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
4869 t_func = TREE_OPERAND (t_func, 0);
4870 gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
4871
8ec3c5c2 4872 r_chain = expand_normal (t_chain);
4ee9c684 4873
4874 /* Generate insns to initialize the trampoline. */
82c7907c 4875 targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
4ee9c684 4876
c307f106 4877 if (onstack)
4878 {
4879 trampolines_created = 1;
8bc8a8f4 4880
c307f106 4881 warning_at (DECL_SOURCE_LOCATION (t_func), OPT_Wtrampolines,
4882 "trampoline generated for nested function %qD", t_func);
4883 }
8bc8a8f4 4884
4ee9c684 4885 return const0_rtx;
4886}
4887
4888static rtx
c2f47e15 4889expand_builtin_adjust_trampoline (tree exp)
4ee9c684 4890{
4891 rtx tramp;
4892
c2f47e15 4893 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
4ee9c684 4894 return NULL_RTX;
4895
c2f47e15 4896 tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
4ee9c684 4897 tramp = round_trampoline_addr (tramp);
82c7907c 4898 if (targetm.calls.trampoline_adjust_address)
4899 tramp = targetm.calls.trampoline_adjust_address (tramp);
4ee9c684 4900
4901 return tramp;
4902}
4903
93f564d6 4904/* Expand the call EXP to the built-in signbit, signbitf or signbitl
4905 function. The function first checks whether the back end provides
4906 an insn to implement signbit for the respective mode. If not, it
4907 checks whether the floating point format of the value is such that
4908 the sign bit can be extracted. If that is not the case, the
4909 function returns NULL_RTX to indicate that a normal call should be
4910 emitted rather than expanding the function in-line. EXP is the
4911 expression that is a call to the builtin function; if convenient,
4912 the result should be placed in TARGET. */
27f261ef 4913static rtx
4914expand_builtin_signbit (tree exp, rtx target)
4915{
4916 const struct real_format *fmt;
4917 enum machine_mode fmode, imode, rmode;
c2f47e15 4918 tree arg;
ca4f1f5b 4919 int word, bitpos;
27eda240 4920 enum insn_code icode;
27f261ef 4921 rtx temp;
389dd41b 4922 location_t loc = EXPR_LOCATION (exp);
27f261ef 4923
c2f47e15 4924 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
4925 return NULL_RTX;
27f261ef 4926
c2f47e15 4927 arg = CALL_EXPR_ARG (exp, 0);
27f261ef 4928 fmode = TYPE_MODE (TREE_TYPE (arg));
4929 rmode = TYPE_MODE (TREE_TYPE (exp));
4930 fmt = REAL_MODE_FORMAT (fmode);
4931
93f564d6 4932 arg = builtin_save_expr (arg);
4933
4934 /* Expand the argument yielding a RTX expression. */
4935 temp = expand_normal (arg);
4936
4937 /* Check if the back end provides an insn that handles signbit for the
4938 argument's mode. */
d6bf3b14 4939 icode = optab_handler (signbit_optab, fmode);
27eda240 4940 if (icode != CODE_FOR_nothing)
93f564d6 4941 {
4e2a2fb4 4942 rtx last = get_last_insn ();
93f564d6 4943 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
4e2a2fb4 4944 if (maybe_emit_unop_insn (icode, target, temp, UNKNOWN))
4945 return target;
4946 delete_insns_since (last);
93f564d6 4947 }
4948
27f261ef 4949 /* For floating point formats without a sign bit, implement signbit
4950 as "ARG < 0.0". */
8d564692 4951 bitpos = fmt->signbit_ro;
ca4f1f5b 4952 if (bitpos < 0)
27f261ef 4953 {
4954 /* But we can't do this if the format supports signed zero. */
4955 if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
c2f47e15 4956 return NULL_RTX;
27f261ef 4957
389dd41b 4958 arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
49d00087 4959 build_real (TREE_TYPE (arg), dconst0));
27f261ef 4960 return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
4961 }
4962
ca4f1f5b 4963 if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
27f261ef 4964 {
ca4f1f5b 4965 imode = int_mode_for_mode (fmode);
4966 if (imode == BLKmode)
c2f47e15 4967 return NULL_RTX;
ca4f1f5b 4968 temp = gen_lowpart (imode, temp);
24fd4260 4969 }
4970 else
4971 {
ca4f1f5b 4972 imode = word_mode;
4973 /* Handle targets with different FP word orders. */
4974 if (FLOAT_WORDS_BIG_ENDIAN)
a0c938f0 4975 word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
ca4f1f5b 4976 else
a0c938f0 4977 word = bitpos / BITS_PER_WORD;
ca4f1f5b 4978 temp = operand_subword_force (temp, word, fmode);
4979 bitpos = bitpos % BITS_PER_WORD;
4980 }
4981
44b0f1d0 4982 /* Force the intermediate word_mode (or narrower) result into a
4983 register. This avoids attempting to create paradoxical SUBREGs
4984 of floating point modes below. */
4985 temp = force_reg (imode, temp);
4986
ca4f1f5b 4987 /* If the bitpos is within the "result mode" lowpart, the operation
4988 can be implement with a single bitwise AND. Otherwise, we need
4989 a right shift and an AND. */
4990
4991 if (bitpos < GET_MODE_BITSIZE (rmode))
4992 {
cf8f0e63 4993 double_int mask = double_int_zero.set_bit (bitpos);
27f261ef 4994
4a46f016 4995 if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
ca4f1f5b 4996 temp = gen_lowpart (rmode, temp);
24fd4260 4997 temp = expand_binop (rmode, and_optab, temp,
3e052aec 4998 immed_double_int_const (mask, rmode),
ca4f1f5b 4999 NULL_RTX, 1, OPTAB_LIB_WIDEN);
27f261ef 5000 }
ca4f1f5b 5001 else
5002 {
5003 /* Perform a logical right shift to place the signbit in the least
a0c938f0 5004 significant bit, then truncate the result to the desired mode
ca4f1f5b 5005 and mask just this bit. */
f5ff0b21 5006 temp = expand_shift (RSHIFT_EXPR, imode, temp, bitpos, NULL_RTX, 1);
ca4f1f5b 5007 temp = gen_lowpart (rmode, temp);
5008 temp = expand_binop (rmode, and_optab, temp, const1_rtx,
5009 NULL_RTX, 1, OPTAB_LIB_WIDEN);
5010 }
5011
27f261ef 5012 return temp;
5013}
73673831 5014
5015/* Expand fork or exec calls. TARGET is the desired target of the
c2f47e15 5016 call. EXP is the call. FN is the
73673831 5017 identificator of the actual function. IGNORE is nonzero if the
5018 value is to be ignored. */
5019
5020static rtx
c2f47e15 5021expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
73673831 5022{
5023 tree id, decl;
5024 tree call;
5025
5026 /* If we are not profiling, just call the function. */
5027 if (!profile_arc_flag)
5028 return NULL_RTX;
5029
5030 /* Otherwise call the wrapper. This should be equivalent for the rest of
5031 compiler, so the code does not diverge, and the wrapper may run the
9c9bad97 5032 code necessary for keeping the profiling sane. */
73673831 5033
5034 switch (DECL_FUNCTION_CODE (fn))
5035 {
5036 case BUILT_IN_FORK:
5037 id = get_identifier ("__gcov_fork");
5038 break;
5039
5040 case BUILT_IN_EXECL:
5041 id = get_identifier ("__gcov_execl");
5042 break;
5043
5044 case BUILT_IN_EXECV:
5045 id = get_identifier ("__gcov_execv");
5046 break;
5047
5048 case BUILT_IN_EXECLP:
5049 id = get_identifier ("__gcov_execlp");
5050 break;
5051
5052 case BUILT_IN_EXECLE:
5053 id = get_identifier ("__gcov_execle");
5054 break;
5055
5056 case BUILT_IN_EXECVP:
5057 id = get_identifier ("__gcov_execvp");
5058 break;
5059
5060 case BUILT_IN_EXECVE:
5061 id = get_identifier ("__gcov_execve");
5062 break;
5063
5064 default:
64db345d 5065 gcc_unreachable ();
73673831 5066 }
5067
e60a6f7b 5068 decl = build_decl (DECL_SOURCE_LOCATION (fn),
5069 FUNCTION_DECL, id, TREE_TYPE (fn));
73673831 5070 DECL_EXTERNAL (decl) = 1;
5071 TREE_PUBLIC (decl) = 1;
5072 DECL_ARTIFICIAL (decl) = 1;
5073 TREE_NOTHROW (decl) = 1;
e82d310b 5074 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
5075 DECL_VISIBILITY_SPECIFIED (decl) = 1;
389dd41b 5076 call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0);
73673831 5077 return expand_call (call, target, ignore);
c2f47e15 5078 }
48e1416a 5079
b6a5fc45 5080
5081\f
3e272de8 5082/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
5083 the pointer in these functions is void*, the tree optimizers may remove
5084 casts. The mode computed in expand_builtin isn't reliable either, due
5085 to __sync_bool_compare_and_swap.
5086
5087 FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
5088 group of builtins. This gives us log2 of the mode size. */
5089
5090static inline enum machine_mode
5091get_builtin_sync_mode (int fcode_diff)
5092{
ad3a13b5 5093 /* The size is not negotiable, so ask not to get BLKmode in return
5094 if the target indicates that a smaller size would be better. */
5095 return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
3e272de8 5096}
5097
041e0215 5098/* Expand the memory expression LOC and return the appropriate memory operand
5099 for the builtin_sync operations. */
5100
5101static rtx
5102get_builtin_sync_mem (tree loc, enum machine_mode mode)
5103{
5104 rtx addr, mem;
5105
7f4d56ad 5106 addr = expand_expr (loc, NULL_RTX, ptr_mode, EXPAND_SUM);
5107 addr = convert_memory_address (Pmode, addr);
041e0215 5108
5109 /* Note that we explicitly do not want any alias information for this
5110 memory, so that we kill all other live memories. Otherwise we don't
5111 satisfy the full barrier semantics of the intrinsic. */
5112 mem = validize_mem (gen_rtx_MEM (mode, addr));
5113
153c3b50 5114 /* The alignment needs to be at least according to that of the mode. */
5115 set_mem_align (mem, MAX (GET_MODE_ALIGNMENT (mode),
957d0361 5116 get_pointer_alignment (loc)));
c94cfd1c 5117 set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
041e0215 5118 MEM_VOLATILE_P (mem) = 1;
5119
5120 return mem;
5121}
5122
1cd6e20d 5123/* Make sure an argument is in the right mode.
5124 EXP is the tree argument.
5125 MODE is the mode it should be in. */
5126
5127static rtx
5128expand_expr_force_mode (tree exp, enum machine_mode mode)
5129{
5130 rtx val;
5131 enum machine_mode old_mode;
5132
5133 val = expand_expr (exp, NULL_RTX, mode, EXPAND_NORMAL);
5134 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5135 of CONST_INTs, where we know the old_mode only from the call argument. */
5136
5137 old_mode = GET_MODE (val);
5138 if (old_mode == VOIDmode)
5139 old_mode = TYPE_MODE (TREE_TYPE (exp));
5140 val = convert_modes (mode, old_mode, val, 1);
5141 return val;
5142}
5143
5144
b6a5fc45 5145/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
c2f47e15 5146 EXP is the CALL_EXPR. CODE is the rtx code
b6a5fc45 5147 that corresponds to the arithmetic or logical operation from the name;
5148 an exception here is that NOT actually means NAND. TARGET is an optional
5149 place for us to store the results; AFTER is true if this is the
1cd6e20d 5150 fetch_and_xxx form. */
b6a5fc45 5151
5152static rtx
c2f47e15 5153expand_builtin_sync_operation (enum machine_mode mode, tree exp,
3e272de8 5154 enum rtx_code code, bool after,
1cd6e20d 5155 rtx target)
b6a5fc45 5156{
041e0215 5157 rtx val, mem;
e60a6f7b 5158 location_t loc = EXPR_LOCATION (exp);
b6a5fc45 5159
cf73e559 5160 if (code == NOT && warn_sync_nand)
5161 {
5162 tree fndecl = get_callee_fndecl (exp);
5163 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
5164
5165 static bool warned_f_a_n, warned_n_a_f;
5166
5167 switch (fcode)
5168 {
2797f13a 5169 case BUILT_IN_SYNC_FETCH_AND_NAND_1:
5170 case BUILT_IN_SYNC_FETCH_AND_NAND_2:
5171 case BUILT_IN_SYNC_FETCH_AND_NAND_4:
5172 case BUILT_IN_SYNC_FETCH_AND_NAND_8:
5173 case BUILT_IN_SYNC_FETCH_AND_NAND_16:
cf73e559 5174 if (warned_f_a_n)
5175 break;
5176
b9a16870 5177 fndecl = builtin_decl_implicit (BUILT_IN_SYNC_FETCH_AND_NAND_N);
e60a6f7b 5178 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
cf73e559 5179 warned_f_a_n = true;
5180 break;
5181
2797f13a 5182 case BUILT_IN_SYNC_NAND_AND_FETCH_1:
5183 case BUILT_IN_SYNC_NAND_AND_FETCH_2:
5184 case BUILT_IN_SYNC_NAND_AND_FETCH_4:
5185 case BUILT_IN_SYNC_NAND_AND_FETCH_8:
5186 case BUILT_IN_SYNC_NAND_AND_FETCH_16:
cf73e559 5187 if (warned_n_a_f)
5188 break;
5189
b9a16870 5190 fndecl = builtin_decl_implicit (BUILT_IN_SYNC_NAND_AND_FETCH_N);
e60a6f7b 5191 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
cf73e559 5192 warned_n_a_f = true;
5193 break;
5194
5195 default:
5196 gcc_unreachable ();
5197 }
5198 }
5199
b6a5fc45 5200 /* Expand the operands. */
c2f47e15 5201 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1cd6e20d 5202 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
b6a5fc45 5203
1cd6e20d 5204 return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SEQ_CST,
5205 after);
b6a5fc45 5206}
5207
5208/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
c2f47e15 5209 intrinsics. EXP is the CALL_EXPR. IS_BOOL is
b6a5fc45 5210 true if this is the boolean form. TARGET is a place for us to store the
5211 results; this is NOT optional if IS_BOOL is true. */
5212
5213static rtx
c2f47e15 5214expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
3e272de8 5215 bool is_bool, rtx target)
b6a5fc45 5216{
041e0215 5217 rtx old_val, new_val, mem;
ba885f6a 5218 rtx *pbool, *poval;
b6a5fc45 5219
5220 /* Expand the operands. */
c2f47e15 5221 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1cd6e20d 5222 old_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5223 new_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
b6a5fc45 5224
ba885f6a 5225 pbool = poval = NULL;
5226 if (target != const0_rtx)
5227 {
5228 if (is_bool)
5229 pbool = &target;
5230 else
5231 poval = &target;
5232 }
5233 if (!expand_atomic_compare_and_swap (pbool, poval, mem, old_val, new_val,
5234 false, MEMMODEL_SEQ_CST,
5235 MEMMODEL_SEQ_CST))
1cd6e20d 5236 return NULL_RTX;
c2f47e15 5237
1cd6e20d 5238 return target;
b6a5fc45 5239}
5240
5241/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
5242 general form is actually an atomic exchange, and some targets only
5243 support a reduced form with the second argument being a constant 1.
48e1416a 5244 EXP is the CALL_EXPR; TARGET is an optional place for us to store
c2f47e15 5245 the results. */
b6a5fc45 5246
5247static rtx
2797f13a 5248expand_builtin_sync_lock_test_and_set (enum machine_mode mode, tree exp,
1cd6e20d 5249 rtx target)
b6a5fc45 5250{
041e0215 5251 rtx val, mem;
b6a5fc45 5252
5253 /* Expand the operands. */
c2f47e15 5254 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1cd6e20d 5255 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5256
7821cde1 5257 return expand_sync_lock_test_and_set (target, mem, val);
1cd6e20d 5258}
5259
5260/* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */
5261
5262static void
5263expand_builtin_sync_lock_release (enum machine_mode mode, tree exp)
5264{
5265 rtx mem;
5266
5267 /* Expand the operands. */
5268 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5269
8808bf16 5270 expand_atomic_store (mem, const0_rtx, MEMMODEL_RELEASE, true);
1cd6e20d 5271}
5272
5273/* Given an integer representing an ``enum memmodel'', verify its
5274 correctness and return the memory model enum. */
5275
5276static enum memmodel
5277get_memmodel (tree exp)
5278{
5279 rtx op;
7f738025 5280 unsigned HOST_WIDE_INT val;
1cd6e20d 5281
5282 /* If the parameter is not a constant, it's a run time value so we'll just
5283 convert it to MEMMODEL_SEQ_CST to avoid annoying runtime checking. */
5284 if (TREE_CODE (exp) != INTEGER_CST)
5285 return MEMMODEL_SEQ_CST;
5286
5287 op = expand_normal (exp);
7f738025 5288
5289 val = INTVAL (op);
5290 if (targetm.memmodel_check)
5291 val = targetm.memmodel_check (val);
5292 else if (val & ~MEMMODEL_MASK)
5293 {
5294 warning (OPT_Winvalid_memory_model,
5295 "Unknown architecture specifier in memory model to builtin.");
5296 return MEMMODEL_SEQ_CST;
5297 }
5298
5299 if ((INTVAL(op) & MEMMODEL_MASK) >= MEMMODEL_LAST)
1cd6e20d 5300 {
5301 warning (OPT_Winvalid_memory_model,
5302 "invalid memory model argument to builtin");
5303 return MEMMODEL_SEQ_CST;
5304 }
7f738025 5305
5306 return (enum memmodel) val;
1cd6e20d 5307}
5308
5309/* Expand the __atomic_exchange intrinsic:
5310 TYPE __atomic_exchange (TYPE *object, TYPE desired, enum memmodel)
5311 EXP is the CALL_EXPR.
5312 TARGET is an optional place for us to store the results. */
5313
5314static rtx
5315expand_builtin_atomic_exchange (enum machine_mode mode, tree exp, rtx target)
5316{
5317 rtx val, mem;
5318 enum memmodel model;
5319
5320 model = get_memmodel (CALL_EXPR_ARG (exp, 2));
7f738025 5321 if ((model & MEMMODEL_MASK) == MEMMODEL_CONSUME)
1cd6e20d 5322 {
5323 error ("invalid memory model for %<__atomic_exchange%>");
5324 return NULL_RTX;
5325 }
5326
5327 if (!flag_inline_atomics)
5328 return NULL_RTX;
5329
5330 /* Expand the operands. */
5331 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5332 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5333
7821cde1 5334 return expand_atomic_exchange (target, mem, val, model);
1cd6e20d 5335}
5336
5337/* Expand the __atomic_compare_exchange intrinsic:
5338 bool __atomic_compare_exchange (TYPE *object, TYPE *expect,
5339 TYPE desired, BOOL weak,
5340 enum memmodel success,
5341 enum memmodel failure)
5342 EXP is the CALL_EXPR.
5343 TARGET is an optional place for us to store the results. */
5344
5345static rtx
5346expand_builtin_atomic_compare_exchange (enum machine_mode mode, tree exp,
5347 rtx target)
5348{
5349 rtx expect, desired, mem, oldval;
5350 enum memmodel success, failure;
5351 tree weak;
5352 bool is_weak;
5353
5354 success = get_memmodel (CALL_EXPR_ARG (exp, 4));
5355 failure = get_memmodel (CALL_EXPR_ARG (exp, 5));
5356
7f738025 5357 if ((failure & MEMMODEL_MASK) == MEMMODEL_RELEASE
5358 || (failure & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
1cd6e20d 5359 {
5360 error ("invalid failure memory model for %<__atomic_compare_exchange%>");
5361 return NULL_RTX;
5362 }
5363
5364 if (failure > success)
5365 {
5366 error ("failure memory model cannot be stronger than success "
5367 "memory model for %<__atomic_compare_exchange%>");
5368 return NULL_RTX;
5369 }
5370
5371 if (!flag_inline_atomics)
5372 return NULL_RTX;
5373
5374 /* Expand the operands. */
5375 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5376
5377 expect = expand_normal (CALL_EXPR_ARG (exp, 1));
5378 expect = convert_memory_address (Pmode, expect);
c401b131 5379 expect = gen_rtx_MEM (mode, expect);
1cd6e20d 5380 desired = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
5381
5382 weak = CALL_EXPR_ARG (exp, 3);
5383 is_weak = false;
5384 if (host_integerp (weak, 0) && tree_low_cst (weak, 0) != 0)
5385 is_weak = true;
5386
c401b131 5387 oldval = expect;
ba885f6a 5388 if (!expand_atomic_compare_and_swap ((target == const0_rtx ? NULL : &target),
5389 &oldval, mem, oldval, desired,
5390 is_weak, success, failure))
1cd6e20d 5391 return NULL_RTX;
5392
c401b131 5393 if (oldval != expect)
5394 emit_move_insn (expect, oldval);
5395
1cd6e20d 5396 return target;
5397}
5398
5399/* Expand the __atomic_load intrinsic:
5400 TYPE __atomic_load (TYPE *object, enum memmodel)
5401 EXP is the CALL_EXPR.
5402 TARGET is an optional place for us to store the results. */
5403
5404static rtx
5405expand_builtin_atomic_load (enum machine_mode mode, tree exp, rtx target)
5406{
5407 rtx mem;
5408 enum memmodel model;
5409
5410 model = get_memmodel (CALL_EXPR_ARG (exp, 1));
7f738025 5411 if ((model & MEMMODEL_MASK) == MEMMODEL_RELEASE
5412 || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
1cd6e20d 5413 {
5414 error ("invalid memory model for %<__atomic_load%>");
5415 return NULL_RTX;
5416 }
5417
5418 if (!flag_inline_atomics)
5419 return NULL_RTX;
5420
5421 /* Expand the operand. */
5422 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5423
5424 return expand_atomic_load (target, mem, model);
5425}
5426
5427
5428/* Expand the __atomic_store intrinsic:
5429 void __atomic_store (TYPE *object, TYPE desired, enum memmodel)
5430 EXP is the CALL_EXPR.
5431 TARGET is an optional place for us to store the results. */
5432
5433static rtx
5434expand_builtin_atomic_store (enum machine_mode mode, tree exp)
5435{
5436 rtx mem, val;
5437 enum memmodel model;
5438
5439 model = get_memmodel (CALL_EXPR_ARG (exp, 2));
7f738025 5440 if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED
5441 && (model & MEMMODEL_MASK) != MEMMODEL_SEQ_CST
5442 && (model & MEMMODEL_MASK) != MEMMODEL_RELEASE)
1cd6e20d 5443 {
5444 error ("invalid memory model for %<__atomic_store%>");
5445 return NULL_RTX;
5446 }
5447
5448 if (!flag_inline_atomics)
5449 return NULL_RTX;
5450
5451 /* Expand the operands. */
5452 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5453 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5454
8808bf16 5455 return expand_atomic_store (mem, val, model, false);
1cd6e20d 5456}
5457
5458/* Expand the __atomic_fetch_XXX intrinsic:
5459 TYPE __atomic_fetch_XXX (TYPE *object, TYPE val, enum memmodel)
5460 EXP is the CALL_EXPR.
5461 TARGET is an optional place for us to store the results.
5462 CODE is the operation, PLUS, MINUS, ADD, XOR, or IOR.
5463 FETCH_AFTER is true if returning the result of the operation.
5464 FETCH_AFTER is false if returning the value before the operation.
5465 IGNORE is true if the result is not used.
5466 EXT_CALL is the correct builtin for an external call if this cannot be
5467 resolved to an instruction sequence. */
5468
5469static rtx
5470expand_builtin_atomic_fetch_op (enum machine_mode mode, tree exp, rtx target,
5471 enum rtx_code code, bool fetch_after,
5472 bool ignore, enum built_in_function ext_call)
5473{
5474 rtx val, mem, ret;
5475 enum memmodel model;
5476 tree fndecl;
5477 tree addr;
5478
5479 model = get_memmodel (CALL_EXPR_ARG (exp, 2));
5480
5481 /* Expand the operands. */
5482 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5483 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5484
5485 /* Only try generating instructions if inlining is turned on. */
5486 if (flag_inline_atomics)
5487 {
5488 ret = expand_atomic_fetch_op (target, mem, val, code, model, fetch_after);
5489 if (ret)
5490 return ret;
5491 }
5492
5493 /* Return if a different routine isn't needed for the library call. */
5494 if (ext_call == BUILT_IN_NONE)
5495 return NULL_RTX;
5496
5497 /* Change the call to the specified function. */
5498 fndecl = get_callee_fndecl (exp);
5499 addr = CALL_EXPR_FN (exp);
5500 STRIP_NOPS (addr);
5501
5502 gcc_assert (TREE_OPERAND (addr, 0) == fndecl);
5503 TREE_OPERAND (addr, 0) = builtin_decl_explicit(ext_call);
5504
5505 /* Expand the call here so we can emit trailing code. */
5506 ret = expand_call (exp, target, ignore);
5507
5508 /* Replace the original function just in case it matters. */
5509 TREE_OPERAND (addr, 0) = fndecl;
5510
5511 /* Then issue the arithmetic correction to return the right result. */
5512 if (!ignore)
c449f851 5513 {
5514 if (code == NOT)
5515 {
5516 ret = expand_simple_binop (mode, AND, ret, val, NULL_RTX, true,
5517 OPTAB_LIB_WIDEN);
5518 ret = expand_simple_unop (mode, NOT, ret, target, true);
5519 }
5520 else
5521 ret = expand_simple_binop (mode, code, ret, val, target, true,
5522 OPTAB_LIB_WIDEN);
5523 }
1cd6e20d 5524 return ret;
5525}
5526
10b744a3 5527
7821cde1 5528#ifndef HAVE_atomic_clear
5529# define HAVE_atomic_clear 0
5530# define gen_atomic_clear(x,y) (gcc_unreachable (), NULL_RTX)
5531#endif
5532
10b744a3 5533/* Expand an atomic clear operation.
5534 void _atomic_clear (BOOL *obj, enum memmodel)
5535 EXP is the call expression. */
5536
5537static rtx
5538expand_builtin_atomic_clear (tree exp)
5539{
5540 enum machine_mode mode;
5541 rtx mem, ret;
5542 enum memmodel model;
5543
5544 mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0);
5545 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5546 model = get_memmodel (CALL_EXPR_ARG (exp, 1));
5547
7f738025 5548 if ((model & MEMMODEL_MASK) == MEMMODEL_ACQUIRE
5549 || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
10b744a3 5550 {
5551 error ("invalid memory model for %<__atomic_store%>");
5552 return const0_rtx;
5553 }
5554
7821cde1 5555 if (HAVE_atomic_clear)
5556 {
5557 emit_insn (gen_atomic_clear (mem, model));
5558 return const0_rtx;
5559 }
5560
10b744a3 5561 /* Try issuing an __atomic_store, and allow fallback to __sync_lock_release.
5562 Failing that, a store is issued by __atomic_store. The only way this can
5563 fail is if the bool type is larger than a word size. Unlikely, but
5564 handle it anyway for completeness. Assume a single threaded model since
5565 there is no atomic support in this case, and no barriers are required. */
5566 ret = expand_atomic_store (mem, const0_rtx, model, true);
5567 if (!ret)
5568 emit_move_insn (mem, const0_rtx);
5569 return const0_rtx;
5570}
5571
5572/* Expand an atomic test_and_set operation.
5573 bool _atomic_test_and_set (BOOL *obj, enum memmodel)
5574 EXP is the call expression. */
5575
5576static rtx
7821cde1 5577expand_builtin_atomic_test_and_set (tree exp, rtx target)
10b744a3 5578{
7821cde1 5579 rtx mem;
10b744a3 5580 enum memmodel model;
5581 enum machine_mode mode;
5582
5583 mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0);
5584 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5585 model = get_memmodel (CALL_EXPR_ARG (exp, 1));
5586
7821cde1 5587 return expand_atomic_test_and_set (target, mem, model);
10b744a3 5588}
5589
5590
1cd6e20d 5591/* Return true if (optional) argument ARG1 of size ARG0 is always lock free on
5592 this architecture. If ARG1 is NULL, use typical alignment for size ARG0. */
5593
5594static tree
5595fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
5596{
5597 int size;
5598 enum machine_mode mode;
5599 unsigned int mode_align, type_align;
5600
5601 if (TREE_CODE (arg0) != INTEGER_CST)
5602 return NULL_TREE;
b6a5fc45 5603
1cd6e20d 5604 size = INTVAL (expand_normal (arg0)) * BITS_PER_UNIT;
5605 mode = mode_for_size (size, MODE_INT, 0);
5606 mode_align = GET_MODE_ALIGNMENT (mode);
5607
5608 if (TREE_CODE (arg1) == INTEGER_CST && INTVAL (expand_normal (arg1)) == 0)
5609 type_align = mode_align;
5610 else
5611 {
5612 tree ttype = TREE_TYPE (arg1);
5613
5614 /* This function is usually invoked and folded immediately by the front
5615 end before anything else has a chance to look at it. The pointer
5616 parameter at this point is usually cast to a void *, so check for that
5617 and look past the cast. */
5618 if (TREE_CODE (arg1) == NOP_EXPR && POINTER_TYPE_P (ttype)
5619 && VOID_TYPE_P (TREE_TYPE (ttype)))
5620 arg1 = TREE_OPERAND (arg1, 0);
5621
5622 ttype = TREE_TYPE (arg1);
5623 gcc_assert (POINTER_TYPE_P (ttype));
5624
5625 /* Get the underlying type of the object. */
5626 ttype = TREE_TYPE (ttype);
5627 type_align = TYPE_ALIGN (ttype);
5628 }
5629
5630 /* If the object has smaller alignment, the the lock free routines cannot
5631 be used. */
5632 if (type_align < mode_align)
06308d2a 5633 return boolean_false_node;
1cd6e20d 5634
5635 /* Check if a compare_and_swap pattern exists for the mode which represents
5636 the required size. The pattern is not allowed to fail, so the existence
5637 of the pattern indicates support is present. */
29139cdc 5638 if (can_compare_and_swap_p (mode, true))
06308d2a 5639 return boolean_true_node;
1cd6e20d 5640 else
06308d2a 5641 return boolean_false_node;
1cd6e20d 5642}
5643
5644/* Return true if the parameters to call EXP represent an object which will
5645 always generate lock free instructions. The first argument represents the
5646 size of the object, and the second parameter is a pointer to the object
5647 itself. If NULL is passed for the object, then the result is based on
5648 typical alignment for an object of the specified size. Otherwise return
5649 false. */
5650
5651static rtx
5652expand_builtin_atomic_always_lock_free (tree exp)
5653{
5654 tree size;
5655 tree arg0 = CALL_EXPR_ARG (exp, 0);
5656 tree arg1 = CALL_EXPR_ARG (exp, 1);
5657
5658 if (TREE_CODE (arg0) != INTEGER_CST)
5659 {
5660 error ("non-constant argument 1 to __atomic_always_lock_free");
5661 return const0_rtx;
5662 }
5663
5664 size = fold_builtin_atomic_always_lock_free (arg0, arg1);
06308d2a 5665 if (size == boolean_true_node)
1cd6e20d 5666 return const1_rtx;
5667 return const0_rtx;
5668}
5669
5670/* Return a one or zero if it can be determined that object ARG1 of size ARG
5671 is lock free on this architecture. */
5672
5673static tree
5674fold_builtin_atomic_is_lock_free (tree arg0, tree arg1)
5675{
5676 if (!flag_inline_atomics)
5677 return NULL_TREE;
5678
5679 /* If it isn't always lock free, don't generate a result. */
06308d2a 5680 if (fold_builtin_atomic_always_lock_free (arg0, arg1) == boolean_true_node)
5681 return boolean_true_node;
1cd6e20d 5682
5683 return NULL_TREE;
5684}
5685
5686/* Return true if the parameters to call EXP represent an object which will
5687 always generate lock free instructions. The first argument represents the
5688 size of the object, and the second parameter is a pointer to the object
5689 itself. If NULL is passed for the object, then the result is based on
5690 typical alignment for an object of the specified size. Otherwise return
5691 NULL*/
5692
5693static rtx
5694expand_builtin_atomic_is_lock_free (tree exp)
5695{
5696 tree size;
5697 tree arg0 = CALL_EXPR_ARG (exp, 0);
5698 tree arg1 = CALL_EXPR_ARG (exp, 1);
5699
5700 if (!INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
5701 {
5702 error ("non-integer argument 1 to __atomic_is_lock_free");
5703 return NULL_RTX;
5704 }
5705
5706 if (!flag_inline_atomics)
5707 return NULL_RTX;
5708
5709 /* If the value is known at compile time, return the RTX for it. */
5710 size = fold_builtin_atomic_is_lock_free (arg0, arg1);
06308d2a 5711 if (size == boolean_true_node)
1cd6e20d 5712 return const1_rtx;
5713
5714 return NULL_RTX;
5715}
5716
1cd6e20d 5717/* Expand the __atomic_thread_fence intrinsic:
5718 void __atomic_thread_fence (enum memmodel)
5719 EXP is the CALL_EXPR. */
5720
5721static void
5722expand_builtin_atomic_thread_fence (tree exp)
5723{
fe54c06b 5724 enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
5725 expand_mem_thread_fence (model);
1cd6e20d 5726}
5727
5728/* Expand the __atomic_signal_fence intrinsic:
5729 void __atomic_signal_fence (enum memmodel)
5730 EXP is the CALL_EXPR. */
5731
5732static void
5733expand_builtin_atomic_signal_fence (tree exp)
5734{
fe54c06b 5735 enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
5736 expand_mem_signal_fence (model);
b6a5fc45 5737}
5738
5739/* Expand the __sync_synchronize intrinsic. */
5740
5741static void
2797f13a 5742expand_builtin_sync_synchronize (void)
b6a5fc45 5743{
fe54c06b 5744 expand_mem_thread_fence (MEMMODEL_SEQ_CST);
b6a5fc45 5745}
5746
badaa04c 5747static rtx
5748expand_builtin_thread_pointer (tree exp, rtx target)
5749{
5750 enum insn_code icode;
5751 if (!validate_arglist (exp, VOID_TYPE))
5752 return const0_rtx;
5753 icode = direct_optab_handler (get_thread_pointer_optab, Pmode);
5754 if (icode != CODE_FOR_nothing)
5755 {
5756 struct expand_operand op;
5757 if (!REG_P (target) || GET_MODE (target) != Pmode)
5758 target = gen_reg_rtx (Pmode);
5759 create_output_operand (&op, target, Pmode);
5760 expand_insn (icode, 1, &op);
5761 return target;
5762 }
5763 error ("__builtin_thread_pointer is not supported on this target");
5764 return const0_rtx;
5765}
5766
5767static void
5768expand_builtin_set_thread_pointer (tree exp)
5769{
5770 enum insn_code icode;
5771 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
5772 return;
5773 icode = direct_optab_handler (set_thread_pointer_optab, Pmode);
5774 if (icode != CODE_FOR_nothing)
5775 {
5776 struct expand_operand op;
5777 rtx val = expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX,
5778 Pmode, EXPAND_NORMAL);
6f343c10 5779 create_input_operand (&op, val, Pmode);
badaa04c 5780 expand_insn (icode, 1, &op);
5781 return;
5782 }
5783 error ("__builtin_set_thread_pointer is not supported on this target");
5784}
5785
53800dbe 5786\f
5787/* Expand an expression EXP that calls a built-in function,
5788 with result going to TARGET if that's convenient
5789 (and in mode MODE if that's convenient).
5790 SUBTARGET may be used as the target for computing one of EXP's operands.
5791 IGNORE is nonzero if the value is to be ignored. */
5792
5793rtx
aecda0d6 5794expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
5795 int ignore)
53800dbe 5796{
c6e6ecb1 5797 tree fndecl = get_callee_fndecl (exp);
53800dbe 5798 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
efb070c8 5799 enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
67fa4078 5800 int flags;
53800dbe 5801
8305149e 5802 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
883b2e73 5803 return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
bf8e3599 5804
53800dbe 5805 /* When not optimizing, generate calls to library functions for a certain
5806 set of builtins. */
cd9ff771 5807 if (!optimize
b6a5fc45 5808 && !called_as_built_in (fndecl)
2c281b15 5809 && fcode != BUILT_IN_ALLOCA
581bf1c2 5810 && fcode != BUILT_IN_ALLOCA_WITH_ALIGN
2c281b15 5811 && fcode != BUILT_IN_FREE)
cd9ff771 5812 return expand_call (exp, target, ignore);
53800dbe 5813
8d6d7930 5814 /* The built-in function expanders test for target == const0_rtx
5815 to determine whether the function's result will be ignored. */
5816 if (ignore)
5817 target = const0_rtx;
5818
5819 /* If the result of a pure or const built-in function is ignored, and
5820 none of its arguments are volatile, we can avoid expanding the
5821 built-in call and just evaluate the arguments for side-effects. */
5822 if (target == const0_rtx
67fa4078 5823 && ((flags = flags_from_decl_or_type (fndecl)) & (ECF_CONST | ECF_PURE))
5824 && !(flags & ECF_LOOPING_CONST_OR_PURE))
8d6d7930 5825 {
5826 bool volatilep = false;
5827 tree arg;
c2f47e15 5828 call_expr_arg_iterator iter;
8d6d7930 5829
c2f47e15 5830 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5831 if (TREE_THIS_VOLATILE (arg))
8d6d7930 5832 {
5833 volatilep = true;
5834 break;
5835 }
5836
5837 if (! volatilep)
5838 {
c2f47e15 5839 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5840 expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
8d6d7930 5841 return const0_rtx;
5842 }
5843 }
5844
53800dbe 5845 switch (fcode)
5846 {
4f35b1fc 5847 CASE_FLT_FN (BUILT_IN_FABS):
c2f47e15 5848 target = expand_builtin_fabs (exp, target, subtarget);
78a74442 5849 if (target)
a0c938f0 5850 return target;
78a74442 5851 break;
5852
4f35b1fc 5853 CASE_FLT_FN (BUILT_IN_COPYSIGN):
c2f47e15 5854 target = expand_builtin_copysign (exp, target, subtarget);
270436f3 5855 if (target)
5856 return target;
5857 break;
5858
7d3f6cc7 5859 /* Just do a normal library call if we were unable to fold
5860 the values. */
4f35b1fc 5861 CASE_FLT_FN (BUILT_IN_CABS):
78a74442 5862 break;
53800dbe 5863
4f35b1fc 5864 CASE_FLT_FN (BUILT_IN_EXP):
5865 CASE_FLT_FN (BUILT_IN_EXP10):
5866 CASE_FLT_FN (BUILT_IN_POW10):
5867 CASE_FLT_FN (BUILT_IN_EXP2):
5868 CASE_FLT_FN (BUILT_IN_EXPM1):
5869 CASE_FLT_FN (BUILT_IN_LOGB):
4f35b1fc 5870 CASE_FLT_FN (BUILT_IN_LOG):
5871 CASE_FLT_FN (BUILT_IN_LOG10):
5872 CASE_FLT_FN (BUILT_IN_LOG2):
5873 CASE_FLT_FN (BUILT_IN_LOG1P):
5874 CASE_FLT_FN (BUILT_IN_TAN):
5875 CASE_FLT_FN (BUILT_IN_ASIN):
5876 CASE_FLT_FN (BUILT_IN_ACOS):
5877 CASE_FLT_FN (BUILT_IN_ATAN):
b3154a1f 5878 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
7f3be425 5879 /* Treat these like sqrt only if unsafe math optimizations are allowed,
5880 because of possible accuracy problems. */
5881 if (! flag_unsafe_math_optimizations)
53800dbe 5882 break;
4f35b1fc 5883 CASE_FLT_FN (BUILT_IN_SQRT):
5884 CASE_FLT_FN (BUILT_IN_FLOOR):
5885 CASE_FLT_FN (BUILT_IN_CEIL):
5886 CASE_FLT_FN (BUILT_IN_TRUNC):
5887 CASE_FLT_FN (BUILT_IN_ROUND):
5888 CASE_FLT_FN (BUILT_IN_NEARBYINT):
5889 CASE_FLT_FN (BUILT_IN_RINT):
53800dbe 5890 target = expand_builtin_mathfn (exp, target, subtarget);
5891 if (target)
5892 return target;
5893 break;
5894
7e0713b1 5895 CASE_FLT_FN (BUILT_IN_FMA):
5896 target = expand_builtin_mathfn_ternary (exp, target, subtarget);
5897 if (target)
5898 return target;
5899 break;
5900
a67a90e5 5901 CASE_FLT_FN (BUILT_IN_ILOGB):
5902 if (! flag_unsafe_math_optimizations)
5903 break;
69b779ea 5904 CASE_FLT_FN (BUILT_IN_ISINF):
cde061c1 5905 CASE_FLT_FN (BUILT_IN_FINITE):
5906 case BUILT_IN_ISFINITE:
8a1a9cb7 5907 case BUILT_IN_ISNORMAL:
f97eea22 5908 target = expand_builtin_interclass_mathfn (exp, target);
a67a90e5 5909 if (target)
5910 return target;
5911 break;
5912
80ff6494 5913 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 5914 CASE_FLT_FN (BUILT_IN_LCEIL):
5915 CASE_FLT_FN (BUILT_IN_LLCEIL):
5916 CASE_FLT_FN (BUILT_IN_LFLOOR):
80ff6494 5917 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 5918 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ff1b14e4 5919 target = expand_builtin_int_roundingfn (exp, target);
ad52b9b7 5920 if (target)
5921 return target;
5922 break;
5923
80ff6494 5924 CASE_FLT_FN (BUILT_IN_IRINT):
7d3afc77 5925 CASE_FLT_FN (BUILT_IN_LRINT):
5926 CASE_FLT_FN (BUILT_IN_LLRINT):
80ff6494 5927 CASE_FLT_FN (BUILT_IN_IROUND):
ef2f1a10 5928 CASE_FLT_FN (BUILT_IN_LROUND):
5929 CASE_FLT_FN (BUILT_IN_LLROUND):
ff1b14e4 5930 target = expand_builtin_int_roundingfn_2 (exp, target);
7d3afc77 5931 if (target)
5932 return target;
5933 break;
5934
4f35b1fc 5935 CASE_FLT_FN (BUILT_IN_POWI):
f97eea22 5936 target = expand_builtin_powi (exp, target);
757c219d 5937 if (target)
5938 return target;
5939 break;
5940
4f35b1fc 5941 CASE_FLT_FN (BUILT_IN_ATAN2):
5942 CASE_FLT_FN (BUILT_IN_LDEXP):
73a954a1 5943 CASE_FLT_FN (BUILT_IN_SCALB):
5944 CASE_FLT_FN (BUILT_IN_SCALBN):
5945 CASE_FLT_FN (BUILT_IN_SCALBLN):
0fd605a5 5946 if (! flag_unsafe_math_optimizations)
5947 break;
ef722005 5948
5949 CASE_FLT_FN (BUILT_IN_FMOD):
5950 CASE_FLT_FN (BUILT_IN_REMAINDER):
5951 CASE_FLT_FN (BUILT_IN_DREM):
0810ff17 5952 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 5953 target = expand_builtin_mathfn_2 (exp, target, subtarget);
5954 if (target)
5955 return target;
5956 break;
5957
d735c391 5958 CASE_FLT_FN (BUILT_IN_CEXPI):
f97eea22 5959 target = expand_builtin_cexpi (exp, target);
d735c391 5960 gcc_assert (target);
5961 return target;
5962
4f35b1fc 5963 CASE_FLT_FN (BUILT_IN_SIN):
5964 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 5965 if (! flag_unsafe_math_optimizations)
5966 break;
5967 target = expand_builtin_mathfn_3 (exp, target, subtarget);
5968 if (target)
5969 return target;
5970 break;
5971
c3147c1a 5972 CASE_FLT_FN (BUILT_IN_SINCOS):
5973 if (! flag_unsafe_math_optimizations)
5974 break;
5975 target = expand_builtin_sincos (exp);
5976 if (target)
5977 return target;
5978 break;
5979
53800dbe 5980 case BUILT_IN_APPLY_ARGS:
5981 return expand_builtin_apply_args ();
5982
5983 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
5984 FUNCTION with a copy of the parameters described by
5985 ARGUMENTS, and ARGSIZE. It returns a block of memory
5986 allocated on the stack into which is stored all the registers
5987 that might possibly be used for returning the result of a
5988 function. ARGUMENTS is the value returned by
5989 __builtin_apply_args. ARGSIZE is the number of bytes of
5990 arguments that must be copied. ??? How should this value be
5991 computed? We'll also need a safe worst case value for varargs
5992 functions. */
5993 case BUILT_IN_APPLY:
c2f47e15 5994 if (!validate_arglist (exp, POINTER_TYPE,
0eb671f7 5995 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
c2f47e15 5996 && !validate_arglist (exp, REFERENCE_TYPE,
0eb671f7 5997 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 5998 return const0_rtx;
5999 else
6000 {
53800dbe 6001 rtx ops[3];
6002
c2f47e15 6003 ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
6004 ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
6005 ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
53800dbe 6006
6007 return expand_builtin_apply (ops[0], ops[1], ops[2]);
6008 }
6009
6010 /* __builtin_return (RESULT) causes the function to return the
6011 value described by RESULT. RESULT is address of the block of
6012 memory returned by __builtin_apply. */
6013 case BUILT_IN_RETURN:
c2f47e15 6014 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
6015 expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
53800dbe 6016 return const0_rtx;
6017
6018 case BUILT_IN_SAVEREGS:
a66c9326 6019 return expand_builtin_saveregs ();
53800dbe 6020
48dc2227 6021 case BUILT_IN_VA_ARG_PACK:
6022 /* All valid uses of __builtin_va_arg_pack () are removed during
6023 inlining. */
b8c23db3 6024 error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
48dc2227 6025 return const0_rtx;
6026
4e1d7ea4 6027 case BUILT_IN_VA_ARG_PACK_LEN:
6028 /* All valid uses of __builtin_va_arg_pack_len () are removed during
6029 inlining. */
b8c23db3 6030 error ("%Kinvalid use of %<__builtin_va_arg_pack_len ()%>", exp);
4e1d7ea4 6031 return const0_rtx;
6032
53800dbe 6033 /* Return the address of the first anonymous stack arg. */
6034 case BUILT_IN_NEXT_ARG:
c2f47e15 6035 if (fold_builtin_next_arg (exp, false))
a0c938f0 6036 return const0_rtx;
79012a9d 6037 return expand_builtin_next_arg ();
53800dbe 6038
ac8fb6db 6039 case BUILT_IN_CLEAR_CACHE:
6040 target = expand_builtin___clear_cache (exp);
6041 if (target)
6042 return target;
6043 break;
6044
53800dbe 6045 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 6046 return expand_builtin_classify_type (exp);
53800dbe 6047
6048 case BUILT_IN_CONSTANT_P:
4ee9c684 6049 return const0_rtx;
53800dbe 6050
6051 case BUILT_IN_FRAME_ADDRESS:
6052 case BUILT_IN_RETURN_ADDRESS:
c2f47e15 6053 return expand_builtin_frame_address (fndecl, exp);
53800dbe 6054
6055 /* Returns the address of the area where the structure is returned.
6056 0 otherwise. */
6057 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
c2f47e15 6058 if (call_expr_nargs (exp) != 0
9342ee68 6059 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
e16ceb8e 6060 || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
9342ee68 6061 return const0_rtx;
53800dbe 6062 else
9342ee68 6063 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
53800dbe 6064
6065 case BUILT_IN_ALLOCA:
581bf1c2 6066 case BUILT_IN_ALLOCA_WITH_ALIGN:
990495a7 6067 /* If the allocation stems from the declaration of a variable-sized
6068 object, it cannot accumulate. */
a882d754 6069 target = expand_builtin_alloca (exp, CALL_ALLOCA_FOR_VAR_P (exp));
53800dbe 6070 if (target)
6071 return target;
6072 break;
6073
4ee9c684 6074 case BUILT_IN_STACK_SAVE:
6075 return expand_stack_save ();
6076
6077 case BUILT_IN_STACK_RESTORE:
c2f47e15 6078 expand_stack_restore (CALL_EXPR_ARG (exp, 0));
4ee9c684 6079 return const0_rtx;
6080
74bdbe96 6081 case BUILT_IN_BSWAP16:
42791117 6082 case BUILT_IN_BSWAP32:
6083 case BUILT_IN_BSWAP64:
74bdbe96 6084 target = expand_builtin_bswap (target_mode, exp, target, subtarget);
42791117 6085 if (target)
6086 return target;
6087 break;
6088
4f35b1fc 6089 CASE_INT_FN (BUILT_IN_FFS):
5053259b 6090 case BUILT_IN_FFSIMAX:
c2f47e15 6091 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6092 subtarget, ffs_optab);
6a08d0ab 6093 if (target)
6094 return target;
6095 break;
6096
4f35b1fc 6097 CASE_INT_FN (BUILT_IN_CLZ):
5053259b 6098 case BUILT_IN_CLZIMAX:
c2f47e15 6099 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6100 subtarget, clz_optab);
6a08d0ab 6101 if (target)
6102 return target;
6103 break;
6104
4f35b1fc 6105 CASE_INT_FN (BUILT_IN_CTZ):
5053259b 6106 case BUILT_IN_CTZIMAX:
c2f47e15 6107 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6108 subtarget, ctz_optab);
6a08d0ab 6109 if (target)
6110 return target;
6111 break;
6112
d8492bd3 6113 CASE_INT_FN (BUILT_IN_CLRSB):
6114 case BUILT_IN_CLRSBIMAX:
6115 target = expand_builtin_unop (target_mode, exp, target,
6116 subtarget, clrsb_optab);
6117 if (target)
6118 return target;
6119 break;
6120
4f35b1fc 6121 CASE_INT_FN (BUILT_IN_POPCOUNT):
5053259b 6122 case BUILT_IN_POPCOUNTIMAX:
c2f47e15 6123 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6124 subtarget, popcount_optab);
6a08d0ab 6125 if (target)
6126 return target;
6127 break;
6128
4f35b1fc 6129 CASE_INT_FN (BUILT_IN_PARITY):
5053259b 6130 case BUILT_IN_PARITYIMAX:
c2f47e15 6131 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6132 subtarget, parity_optab);
53800dbe 6133 if (target)
6134 return target;
6135 break;
6136
6137 case BUILT_IN_STRLEN:
c2f47e15 6138 target = expand_builtin_strlen (exp, target, target_mode);
53800dbe 6139 if (target)
6140 return target;
6141 break;
6142
6143 case BUILT_IN_STRCPY:
a65c4d64 6144 target = expand_builtin_strcpy (exp, target);
53800dbe 6145 if (target)
6146 return target;
6147 break;
bf8e3599 6148
ed09096d 6149 case BUILT_IN_STRNCPY:
a65c4d64 6150 target = expand_builtin_strncpy (exp, target);
ed09096d 6151 if (target)
6152 return target;
6153 break;
bf8e3599 6154
3b824fa6 6155 case BUILT_IN_STPCPY:
dc369150 6156 target = expand_builtin_stpcpy (exp, target, mode);
3b824fa6 6157 if (target)
6158 return target;
6159 break;
6160
53800dbe 6161 case BUILT_IN_MEMCPY:
a65c4d64 6162 target = expand_builtin_memcpy (exp, target);
3b824fa6 6163 if (target)
6164 return target;
6165 break;
6166
6167 case BUILT_IN_MEMPCPY:
c2f47e15 6168 target = expand_builtin_mempcpy (exp, target, mode);
53800dbe 6169 if (target)
6170 return target;
6171 break;
6172
6173 case BUILT_IN_MEMSET:
c2f47e15 6174 target = expand_builtin_memset (exp, target, mode);
53800dbe 6175 if (target)
6176 return target;
6177 break;
6178
ffc83088 6179 case BUILT_IN_BZERO:
0b25db21 6180 target = expand_builtin_bzero (exp);
ffc83088 6181 if (target)
6182 return target;
6183 break;
6184
53800dbe 6185 case BUILT_IN_STRCMP:
a65c4d64 6186 target = expand_builtin_strcmp (exp, target);
53800dbe 6187 if (target)
6188 return target;
6189 break;
6190
ed09096d 6191 case BUILT_IN_STRNCMP:
6192 target = expand_builtin_strncmp (exp, target, mode);
6193 if (target)
6194 return target;
6195 break;
6196
071f1696 6197 case BUILT_IN_BCMP:
53800dbe 6198 case BUILT_IN_MEMCMP:
c2f47e15 6199 target = expand_builtin_memcmp (exp, target, mode);
53800dbe 6200 if (target)
6201 return target;
6202 break;
53800dbe 6203
6204 case BUILT_IN_SETJMP:
2c8a1497 6205 /* This should have been lowered to the builtins below. */
6206 gcc_unreachable ();
6207
6208 case BUILT_IN_SETJMP_SETUP:
6209 /* __builtin_setjmp_setup is passed a pointer to an array of five words
6210 and the receiver label. */
c2f47e15 6211 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2c8a1497 6212 {
c2f47e15 6213 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
2c8a1497 6214 VOIDmode, EXPAND_NORMAL);
c2f47e15 6215 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
2c8a1497 6216 rtx label_r = label_rtx (label);
6217
6218 /* This is copied from the handling of non-local gotos. */
6219 expand_builtin_setjmp_setup (buf_addr, label_r);
6220 nonlocal_goto_handler_labels
6221 = gen_rtx_EXPR_LIST (VOIDmode, label_r,
6222 nonlocal_goto_handler_labels);
6223 /* ??? Do not let expand_label treat us as such since we would
6224 not want to be both on the list of non-local labels and on
6225 the list of forced labels. */
6226 FORCED_LABEL (label) = 0;
6227 return const0_rtx;
6228 }
6229 break;
6230
6231 case BUILT_IN_SETJMP_DISPATCHER:
6232 /* __builtin_setjmp_dispatcher is passed the dispatcher label. */
c2f47e15 6233 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6234 {
c2f47e15 6235 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6236 rtx label_r = label_rtx (label);
6237
6238 /* Remove the dispatcher label from the list of non-local labels
6239 since the receiver labels have been added to it above. */
6240 remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels);
6241 return const0_rtx;
6242 }
6243 break;
6244
6245 case BUILT_IN_SETJMP_RECEIVER:
6246 /* __builtin_setjmp_receiver is passed the receiver label. */
c2f47e15 6247 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6248 {
c2f47e15 6249 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6250 rtx label_r = label_rtx (label);
6251
6252 expand_builtin_setjmp_receiver (label_r);
6253 return const0_rtx;
6254 }
6b7f6858 6255 break;
53800dbe 6256
6257 /* __builtin_longjmp is passed a pointer to an array of five words.
6258 It's similar to the C library longjmp function but works with
6259 __builtin_setjmp above. */
6260 case BUILT_IN_LONGJMP:
c2f47e15 6261 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 6262 {
c2f47e15 6263 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
8ec3c5c2 6264 VOIDmode, EXPAND_NORMAL);
c2f47e15 6265 rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
53800dbe 6266
6267 if (value != const1_rtx)
6268 {
1e5fcbe2 6269 error ("%<__builtin_longjmp%> second argument must be 1");
53800dbe 6270 return const0_rtx;
6271 }
6272
6273 expand_builtin_longjmp (buf_addr, value);
6274 return const0_rtx;
6275 }
2c8a1497 6276 break;
53800dbe 6277
4ee9c684 6278 case BUILT_IN_NONLOCAL_GOTO:
c2f47e15 6279 target = expand_builtin_nonlocal_goto (exp);
4ee9c684 6280 if (target)
6281 return target;
6282 break;
6283
843d08a9 6284 /* This updates the setjmp buffer that is its argument with the value
6285 of the current stack pointer. */
6286 case BUILT_IN_UPDATE_SETJMP_BUF:
c2f47e15 6287 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
843d08a9 6288 {
6289 rtx buf_addr
c2f47e15 6290 = expand_normal (CALL_EXPR_ARG (exp, 0));
843d08a9 6291
6292 expand_builtin_update_setjmp_buf (buf_addr);
6293 return const0_rtx;
6294 }
6295 break;
6296
53800dbe 6297 case BUILT_IN_TRAP:
a0ef1725 6298 expand_builtin_trap ();
53800dbe 6299 return const0_rtx;
6300
d2b48f0c 6301 case BUILT_IN_UNREACHABLE:
6302 expand_builtin_unreachable ();
6303 return const0_rtx;
6304
4f35b1fc 6305 CASE_FLT_FN (BUILT_IN_SIGNBIT):
004e23c4 6306 case BUILT_IN_SIGNBITD32:
6307 case BUILT_IN_SIGNBITD64:
6308 case BUILT_IN_SIGNBITD128:
27f261ef 6309 target = expand_builtin_signbit (exp, target);
6310 if (target)
6311 return target;
6312 break;
6313
53800dbe 6314 /* Various hooks for the DWARF 2 __throw routine. */
6315 case BUILT_IN_UNWIND_INIT:
6316 expand_builtin_unwind_init ();
6317 return const0_rtx;
6318 case BUILT_IN_DWARF_CFA:
6319 return virtual_cfa_rtx;
6320#ifdef DWARF2_UNWIND_INFO
f8f023a5 6321 case BUILT_IN_DWARF_SP_COLUMN:
6322 return expand_builtin_dwarf_sp_column ();
695e919b 6323 case BUILT_IN_INIT_DWARF_REG_SIZES:
c2f47e15 6324 expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
695e919b 6325 return const0_rtx;
53800dbe 6326#endif
6327 case BUILT_IN_FROB_RETURN_ADDR:
c2f47e15 6328 return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6329 case BUILT_IN_EXTRACT_RETURN_ADDR:
c2f47e15 6330 return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6331 case BUILT_IN_EH_RETURN:
c2f47e15 6332 expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
6333 CALL_EXPR_ARG (exp, 1));
53800dbe 6334 return const0_rtx;
df4b504c 6335#ifdef EH_RETURN_DATA_REGNO
6336 case BUILT_IN_EH_RETURN_DATA_REGNO:
c2f47e15 6337 return expand_builtin_eh_return_data_regno (exp);
df4b504c 6338#endif
26093bf4 6339 case BUILT_IN_EXTEND_POINTER:
c2f47e15 6340 return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
e38def9c 6341 case BUILT_IN_EH_POINTER:
6342 return expand_builtin_eh_pointer (exp);
6343 case BUILT_IN_EH_FILTER:
6344 return expand_builtin_eh_filter (exp);
6345 case BUILT_IN_EH_COPY_VALUES:
6346 return expand_builtin_eh_copy_values (exp);
26093bf4 6347
7ccc713a 6348 case BUILT_IN_VA_START:
c2f47e15 6349 return expand_builtin_va_start (exp);
a66c9326 6350 case BUILT_IN_VA_END:
c2f47e15 6351 return expand_builtin_va_end (exp);
a66c9326 6352 case BUILT_IN_VA_COPY:
c2f47e15 6353 return expand_builtin_va_copy (exp);
89cfe6e5 6354 case BUILT_IN_EXPECT:
c2f47e15 6355 return expand_builtin_expect (exp, target);
fca0886c 6356 case BUILT_IN_ASSUME_ALIGNED:
6357 return expand_builtin_assume_aligned (exp, target);
5e3608d8 6358 case BUILT_IN_PREFETCH:
c2f47e15 6359 expand_builtin_prefetch (exp);
5e3608d8 6360 return const0_rtx;
6361
4ee9c684 6362 case BUILT_IN_INIT_TRAMPOLINE:
c307f106 6363 return expand_builtin_init_trampoline (exp, true);
6364 case BUILT_IN_INIT_HEAP_TRAMPOLINE:
6365 return expand_builtin_init_trampoline (exp, false);
4ee9c684 6366 case BUILT_IN_ADJUST_TRAMPOLINE:
c2f47e15 6367 return expand_builtin_adjust_trampoline (exp);
4ee9c684 6368
73673831 6369 case BUILT_IN_FORK:
6370 case BUILT_IN_EXECL:
6371 case BUILT_IN_EXECV:
6372 case BUILT_IN_EXECLP:
6373 case BUILT_IN_EXECLE:
6374 case BUILT_IN_EXECVP:
6375 case BUILT_IN_EXECVE:
c2f47e15 6376 target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
73673831 6377 if (target)
6378 return target;
6379 break;
53800dbe 6380
2797f13a 6381 case BUILT_IN_SYNC_FETCH_AND_ADD_1:
6382 case BUILT_IN_SYNC_FETCH_AND_ADD_2:
6383 case BUILT_IN_SYNC_FETCH_AND_ADD_4:
6384 case BUILT_IN_SYNC_FETCH_AND_ADD_8:
6385 case BUILT_IN_SYNC_FETCH_AND_ADD_16:
6386 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_ADD_1);
1cd6e20d 6387 target = expand_builtin_sync_operation (mode, exp, PLUS, false, target);
b6a5fc45 6388 if (target)
6389 return target;
6390 break;
6391
2797f13a 6392 case BUILT_IN_SYNC_FETCH_AND_SUB_1:
6393 case BUILT_IN_SYNC_FETCH_AND_SUB_2:
6394 case BUILT_IN_SYNC_FETCH_AND_SUB_4:
6395 case BUILT_IN_SYNC_FETCH_AND_SUB_8:
6396 case BUILT_IN_SYNC_FETCH_AND_SUB_16:
6397 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_SUB_1);
1cd6e20d 6398 target = expand_builtin_sync_operation (mode, exp, MINUS, false, target);
b6a5fc45 6399 if (target)
6400 return target;
6401 break;
6402
2797f13a 6403 case BUILT_IN_SYNC_FETCH_AND_OR_1:
6404 case BUILT_IN_SYNC_FETCH_AND_OR_2:
6405 case BUILT_IN_SYNC_FETCH_AND_OR_4:
6406 case BUILT_IN_SYNC_FETCH_AND_OR_8:
6407 case BUILT_IN_SYNC_FETCH_AND_OR_16:
6408 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_OR_1);
1cd6e20d 6409 target = expand_builtin_sync_operation (mode, exp, IOR, false, target);
b6a5fc45 6410 if (target)
6411 return target;
6412 break;
6413
2797f13a 6414 case BUILT_IN_SYNC_FETCH_AND_AND_1:
6415 case BUILT_IN_SYNC_FETCH_AND_AND_2:
6416 case BUILT_IN_SYNC_FETCH_AND_AND_4:
6417 case BUILT_IN_SYNC_FETCH_AND_AND_8:
6418 case BUILT_IN_SYNC_FETCH_AND_AND_16:
6419 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_AND_1);
1cd6e20d 6420 target = expand_builtin_sync_operation (mode, exp, AND, false, target);
b6a5fc45 6421 if (target)
6422 return target;
6423 break;
6424
2797f13a 6425 case BUILT_IN_SYNC_FETCH_AND_XOR_1:
6426 case BUILT_IN_SYNC_FETCH_AND_XOR_2:
6427 case BUILT_IN_SYNC_FETCH_AND_XOR_4:
6428 case BUILT_IN_SYNC_FETCH_AND_XOR_8:
6429 case BUILT_IN_SYNC_FETCH_AND_XOR_16:
6430 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_XOR_1);
1cd6e20d 6431 target = expand_builtin_sync_operation (mode, exp, XOR, false, target);
b6a5fc45 6432 if (target)
6433 return target;
6434 break;
6435
2797f13a 6436 case BUILT_IN_SYNC_FETCH_AND_NAND_1:
6437 case BUILT_IN_SYNC_FETCH_AND_NAND_2:
6438 case BUILT_IN_SYNC_FETCH_AND_NAND_4:
6439 case BUILT_IN_SYNC_FETCH_AND_NAND_8:
6440 case BUILT_IN_SYNC_FETCH_AND_NAND_16:
6441 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_NAND_1);
1cd6e20d 6442 target = expand_builtin_sync_operation (mode, exp, NOT, false, target);
b6a5fc45 6443 if (target)
6444 return target;
6445 break;
6446
2797f13a 6447 case BUILT_IN_SYNC_ADD_AND_FETCH_1:
6448 case BUILT_IN_SYNC_ADD_AND_FETCH_2:
6449 case BUILT_IN_SYNC_ADD_AND_FETCH_4:
6450 case BUILT_IN_SYNC_ADD_AND_FETCH_8:
6451 case BUILT_IN_SYNC_ADD_AND_FETCH_16:
6452 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_ADD_AND_FETCH_1);
1cd6e20d 6453 target = expand_builtin_sync_operation (mode, exp, PLUS, true, target);
b6a5fc45 6454 if (target)
6455 return target;
6456 break;
6457
2797f13a 6458 case BUILT_IN_SYNC_SUB_AND_FETCH_1:
6459 case BUILT_IN_SYNC_SUB_AND_FETCH_2:
6460 case BUILT_IN_SYNC_SUB_AND_FETCH_4:
6461 case BUILT_IN_SYNC_SUB_AND_FETCH_8:
6462 case BUILT_IN_SYNC_SUB_AND_FETCH_16:
6463 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_SUB_AND_FETCH_1);
1cd6e20d 6464 target = expand_builtin_sync_operation (mode, exp, MINUS, true, target);
b6a5fc45 6465 if (target)
6466 return target;
6467 break;
6468
2797f13a 6469 case BUILT_IN_SYNC_OR_AND_FETCH_1:
6470 case BUILT_IN_SYNC_OR_AND_FETCH_2:
6471 case BUILT_IN_SYNC_OR_AND_FETCH_4:
6472 case BUILT_IN_SYNC_OR_AND_FETCH_8:
6473 case BUILT_IN_SYNC_OR_AND_FETCH_16:
6474 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_OR_AND_FETCH_1);
1cd6e20d 6475 target = expand_builtin_sync_operation (mode, exp, IOR, true, target);
b6a5fc45 6476 if (target)
6477 return target;
6478 break;
6479
2797f13a 6480 case BUILT_IN_SYNC_AND_AND_FETCH_1:
6481 case BUILT_IN_SYNC_AND_AND_FETCH_2:
6482 case BUILT_IN_SYNC_AND_AND_FETCH_4:
6483 case BUILT_IN_SYNC_AND_AND_FETCH_8:
6484 case BUILT_IN_SYNC_AND_AND_FETCH_16:
6485 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_AND_AND_FETCH_1);
1cd6e20d 6486 target = expand_builtin_sync_operation (mode, exp, AND, true, target);
b6a5fc45 6487 if (target)
6488 return target;
6489 break;
6490
2797f13a 6491 case BUILT_IN_SYNC_XOR_AND_FETCH_1:
6492 case BUILT_IN_SYNC_XOR_AND_FETCH_2:
6493 case BUILT_IN_SYNC_XOR_AND_FETCH_4:
6494 case BUILT_IN_SYNC_XOR_AND_FETCH_8:
6495 case BUILT_IN_SYNC_XOR_AND_FETCH_16:
6496 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_XOR_AND_FETCH_1);
1cd6e20d 6497 target = expand_builtin_sync_operation (mode, exp, XOR, true, target);
b6a5fc45 6498 if (target)
6499 return target;
6500 break;
6501
2797f13a 6502 case BUILT_IN_SYNC_NAND_AND_FETCH_1:
6503 case BUILT_IN_SYNC_NAND_AND_FETCH_2:
6504 case BUILT_IN_SYNC_NAND_AND_FETCH_4:
6505 case BUILT_IN_SYNC_NAND_AND_FETCH_8:
6506 case BUILT_IN_SYNC_NAND_AND_FETCH_16:
6507 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_NAND_AND_FETCH_1);
1cd6e20d 6508 target = expand_builtin_sync_operation (mode, exp, NOT, true, target);
b6a5fc45 6509 if (target)
6510 return target;
6511 break;
6512
2797f13a 6513 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
6514 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
6515 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
6516 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
6517 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16:
a601d32a 6518 if (mode == VOIDmode)
6519 mode = TYPE_MODE (boolean_type_node);
b6a5fc45 6520 if (!target || !register_operand (target, mode))
6521 target = gen_reg_rtx (mode);
3e272de8 6522
2797f13a 6523 mode = get_builtin_sync_mode
6524 (fcode - BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1);
c2f47e15 6525 target = expand_builtin_compare_and_swap (mode, exp, true, target);
b6a5fc45 6526 if (target)
6527 return target;
6528 break;
6529
2797f13a 6530 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
6531 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
6532 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
6533 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
6534 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
6535 mode = get_builtin_sync_mode
6536 (fcode - BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1);
c2f47e15 6537 target = expand_builtin_compare_and_swap (mode, exp, false, target);
b6a5fc45 6538 if (target)
6539 return target;
6540 break;
6541
2797f13a 6542 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
6543 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
6544 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
6545 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
6546 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16:
6547 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_TEST_AND_SET_1);
6548 target = expand_builtin_sync_lock_test_and_set (mode, exp, target);
b6a5fc45 6549 if (target)
6550 return target;
6551 break;
6552
2797f13a 6553 case BUILT_IN_SYNC_LOCK_RELEASE_1:
6554 case BUILT_IN_SYNC_LOCK_RELEASE_2:
6555 case BUILT_IN_SYNC_LOCK_RELEASE_4:
6556 case BUILT_IN_SYNC_LOCK_RELEASE_8:
6557 case BUILT_IN_SYNC_LOCK_RELEASE_16:
6558 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_RELEASE_1);
6559 expand_builtin_sync_lock_release (mode, exp);
b6a5fc45 6560 return const0_rtx;
6561
2797f13a 6562 case BUILT_IN_SYNC_SYNCHRONIZE:
6563 expand_builtin_sync_synchronize ();
b6a5fc45 6564 return const0_rtx;
6565
1cd6e20d 6566 case BUILT_IN_ATOMIC_EXCHANGE_1:
6567 case BUILT_IN_ATOMIC_EXCHANGE_2:
6568 case BUILT_IN_ATOMIC_EXCHANGE_4:
6569 case BUILT_IN_ATOMIC_EXCHANGE_8:
6570 case BUILT_IN_ATOMIC_EXCHANGE_16:
6571 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_EXCHANGE_1);
6572 target = expand_builtin_atomic_exchange (mode, exp, target);
6573 if (target)
6574 return target;
6575 break;
6576
6577 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1:
6578 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2:
6579 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4:
6580 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8:
6581 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
2c201ad1 6582 {
6583 unsigned int nargs, z;
f1f41a6c 6584 vec<tree, va_gc> *vec;
2c201ad1 6585
6586 mode =
6587 get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1);
6588 target = expand_builtin_atomic_compare_exchange (mode, exp, target);
6589 if (target)
6590 return target;
6591
6592 /* If this is turned into an external library call, the weak parameter
6593 must be dropped to match the expected parameter list. */
6594 nargs = call_expr_nargs (exp);
f1f41a6c 6595 vec_alloc (vec, nargs - 1);
2c201ad1 6596 for (z = 0; z < 3; z++)
f1f41a6c 6597 vec->quick_push (CALL_EXPR_ARG (exp, z));
2c201ad1 6598 /* Skip the boolean weak parameter. */
6599 for (z = 4; z < 6; z++)
f1f41a6c 6600 vec->quick_push (CALL_EXPR_ARG (exp, z));
2c201ad1 6601 exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), vec);
6602 break;
6603 }
1cd6e20d 6604
6605 case BUILT_IN_ATOMIC_LOAD_1:
6606 case BUILT_IN_ATOMIC_LOAD_2:
6607 case BUILT_IN_ATOMIC_LOAD_4:
6608 case BUILT_IN_ATOMIC_LOAD_8:
6609 case BUILT_IN_ATOMIC_LOAD_16:
6610 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_LOAD_1);
6611 target = expand_builtin_atomic_load (mode, exp, target);
6612 if (target)
6613 return target;
6614 break;
6615
6616 case BUILT_IN_ATOMIC_STORE_1:
6617 case BUILT_IN_ATOMIC_STORE_2:
6618 case BUILT_IN_ATOMIC_STORE_4:
6619 case BUILT_IN_ATOMIC_STORE_8:
6620 case BUILT_IN_ATOMIC_STORE_16:
6621 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_STORE_1);
6622 target = expand_builtin_atomic_store (mode, exp);
6623 if (target)
6624 return const0_rtx;
6625 break;
6626
6627 case BUILT_IN_ATOMIC_ADD_FETCH_1:
6628 case BUILT_IN_ATOMIC_ADD_FETCH_2:
6629 case BUILT_IN_ATOMIC_ADD_FETCH_4:
6630 case BUILT_IN_ATOMIC_ADD_FETCH_8:
6631 case BUILT_IN_ATOMIC_ADD_FETCH_16:
6632 {
6633 enum built_in_function lib;
6634 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1);
6635 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_ADD_1 +
6636 (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1));
6637 target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, true,
6638 ignore, lib);
6639 if (target)
6640 return target;
6641 break;
6642 }
6643 case BUILT_IN_ATOMIC_SUB_FETCH_1:
6644 case BUILT_IN_ATOMIC_SUB_FETCH_2:
6645 case BUILT_IN_ATOMIC_SUB_FETCH_4:
6646 case BUILT_IN_ATOMIC_SUB_FETCH_8:
6647 case BUILT_IN_ATOMIC_SUB_FETCH_16:
6648 {
6649 enum built_in_function lib;
6650 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1);
6651 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_SUB_1 +
6652 (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1));
6653 target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, true,
6654 ignore, lib);
6655 if (target)
6656 return target;
6657 break;
6658 }
6659 case BUILT_IN_ATOMIC_AND_FETCH_1:
6660 case BUILT_IN_ATOMIC_AND_FETCH_2:
6661 case BUILT_IN_ATOMIC_AND_FETCH_4:
6662 case BUILT_IN_ATOMIC_AND_FETCH_8:
6663 case BUILT_IN_ATOMIC_AND_FETCH_16:
6664 {
6665 enum built_in_function lib;
6666 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_AND_FETCH_1);
6667 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_AND_1 +
6668 (fcode - BUILT_IN_ATOMIC_AND_FETCH_1));
6669 target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, true,
6670 ignore, lib);
6671 if (target)
6672 return target;
6673 break;
6674 }
6675 case BUILT_IN_ATOMIC_NAND_FETCH_1:
6676 case BUILT_IN_ATOMIC_NAND_FETCH_2:
6677 case BUILT_IN_ATOMIC_NAND_FETCH_4:
6678 case BUILT_IN_ATOMIC_NAND_FETCH_8:
6679 case BUILT_IN_ATOMIC_NAND_FETCH_16:
6680 {
6681 enum built_in_function lib;
6682 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1);
6683 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_NAND_1 +
6684 (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1));
6685 target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, true,
6686 ignore, lib);
6687 if (target)
6688 return target;
6689 break;
6690 }
6691 case BUILT_IN_ATOMIC_XOR_FETCH_1:
6692 case BUILT_IN_ATOMIC_XOR_FETCH_2:
6693 case BUILT_IN_ATOMIC_XOR_FETCH_4:
6694 case BUILT_IN_ATOMIC_XOR_FETCH_8:
6695 case BUILT_IN_ATOMIC_XOR_FETCH_16:
6696 {
6697 enum built_in_function lib;
6698 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1);
6699 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_XOR_1 +
6700 (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1));
6701 target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, true,
6702 ignore, lib);
6703 if (target)
6704 return target;
6705 break;
6706 }
6707 case BUILT_IN_ATOMIC_OR_FETCH_1:
6708 case BUILT_IN_ATOMIC_OR_FETCH_2:
6709 case BUILT_IN_ATOMIC_OR_FETCH_4:
6710 case BUILT_IN_ATOMIC_OR_FETCH_8:
6711 case BUILT_IN_ATOMIC_OR_FETCH_16:
6712 {
6713 enum built_in_function lib;
6714 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_OR_FETCH_1);
6715 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_OR_1 +
6716 (fcode - BUILT_IN_ATOMIC_OR_FETCH_1));
6717 target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, true,
6718 ignore, lib);
6719 if (target)
6720 return target;
6721 break;
6722 }
6723 case BUILT_IN_ATOMIC_FETCH_ADD_1:
6724 case BUILT_IN_ATOMIC_FETCH_ADD_2:
6725 case BUILT_IN_ATOMIC_FETCH_ADD_4:
6726 case BUILT_IN_ATOMIC_FETCH_ADD_8:
6727 case BUILT_IN_ATOMIC_FETCH_ADD_16:
6728 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_ADD_1);
6729 target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, false,
6730 ignore, BUILT_IN_NONE);
6731 if (target)
6732 return target;
6733 break;
6734
6735 case BUILT_IN_ATOMIC_FETCH_SUB_1:
6736 case BUILT_IN_ATOMIC_FETCH_SUB_2:
6737 case BUILT_IN_ATOMIC_FETCH_SUB_4:
6738 case BUILT_IN_ATOMIC_FETCH_SUB_8:
6739 case BUILT_IN_ATOMIC_FETCH_SUB_16:
6740 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_SUB_1);
6741 target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, false,
6742 ignore, BUILT_IN_NONE);
6743 if (target)
6744 return target;
6745 break;
6746
6747 case BUILT_IN_ATOMIC_FETCH_AND_1:
6748 case BUILT_IN_ATOMIC_FETCH_AND_2:
6749 case BUILT_IN_ATOMIC_FETCH_AND_4:
6750 case BUILT_IN_ATOMIC_FETCH_AND_8:
6751 case BUILT_IN_ATOMIC_FETCH_AND_16:
6752 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_AND_1);
6753 target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, false,
6754 ignore, BUILT_IN_NONE);
6755 if (target)
6756 return target;
6757 break;
6758
6759 case BUILT_IN_ATOMIC_FETCH_NAND_1:
6760 case BUILT_IN_ATOMIC_FETCH_NAND_2:
6761 case BUILT_IN_ATOMIC_FETCH_NAND_4:
6762 case BUILT_IN_ATOMIC_FETCH_NAND_8:
6763 case BUILT_IN_ATOMIC_FETCH_NAND_16:
6764 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_NAND_1);
6765 target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, false,
6766 ignore, BUILT_IN_NONE);
6767 if (target)
6768 return target;
6769 break;
6770
6771 case BUILT_IN_ATOMIC_FETCH_XOR_1:
6772 case BUILT_IN_ATOMIC_FETCH_XOR_2:
6773 case BUILT_IN_ATOMIC_FETCH_XOR_4:
6774 case BUILT_IN_ATOMIC_FETCH_XOR_8:
6775 case BUILT_IN_ATOMIC_FETCH_XOR_16:
6776 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_XOR_1);
6777 target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, false,
6778 ignore, BUILT_IN_NONE);
6779 if (target)
6780 return target;
6781 break;
6782
6783 case BUILT_IN_ATOMIC_FETCH_OR_1:
6784 case BUILT_IN_ATOMIC_FETCH_OR_2:
6785 case BUILT_IN_ATOMIC_FETCH_OR_4:
6786 case BUILT_IN_ATOMIC_FETCH_OR_8:
6787 case BUILT_IN_ATOMIC_FETCH_OR_16:
6788 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_OR_1);
6789 target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, false,
6790 ignore, BUILT_IN_NONE);
6791 if (target)
6792 return target;
6793 break;
10b744a3 6794
6795 case BUILT_IN_ATOMIC_TEST_AND_SET:
7821cde1 6796 return expand_builtin_atomic_test_and_set (exp, target);
10b744a3 6797
6798 case BUILT_IN_ATOMIC_CLEAR:
6799 return expand_builtin_atomic_clear (exp);
1cd6e20d 6800
6801 case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
6802 return expand_builtin_atomic_always_lock_free (exp);
6803
6804 case BUILT_IN_ATOMIC_IS_LOCK_FREE:
6805 target = expand_builtin_atomic_is_lock_free (exp);
6806 if (target)
6807 return target;
6808 break;
6809
6810 case BUILT_IN_ATOMIC_THREAD_FENCE:
6811 expand_builtin_atomic_thread_fence (exp);
6812 return const0_rtx;
6813
6814 case BUILT_IN_ATOMIC_SIGNAL_FENCE:
6815 expand_builtin_atomic_signal_fence (exp);
6816 return const0_rtx;
6817
0a39fd54 6818 case BUILT_IN_OBJECT_SIZE:
6819 return expand_builtin_object_size (exp);
6820
6821 case BUILT_IN_MEMCPY_CHK:
6822 case BUILT_IN_MEMPCPY_CHK:
6823 case BUILT_IN_MEMMOVE_CHK:
6824 case BUILT_IN_MEMSET_CHK:
6825 target = expand_builtin_memory_chk (exp, target, mode, fcode);
6826 if (target)
6827 return target;
6828 break;
6829
6830 case BUILT_IN_STRCPY_CHK:
6831 case BUILT_IN_STPCPY_CHK:
6832 case BUILT_IN_STRNCPY_CHK:
1063acde 6833 case BUILT_IN_STPNCPY_CHK:
0a39fd54 6834 case BUILT_IN_STRCAT_CHK:
b356dfef 6835 case BUILT_IN_STRNCAT_CHK:
0a39fd54 6836 case BUILT_IN_SNPRINTF_CHK:
6837 case BUILT_IN_VSNPRINTF_CHK:
6838 maybe_emit_chk_warning (exp, fcode);
6839 break;
6840
6841 case BUILT_IN_SPRINTF_CHK:
6842 case BUILT_IN_VSPRINTF_CHK:
6843 maybe_emit_sprintf_chk_warning (exp, fcode);
6844 break;
6845
2c281b15 6846 case BUILT_IN_FREE:
f74ea1c2 6847 if (warn_free_nonheap_object)
6848 maybe_emit_free_warning (exp);
2c281b15 6849 break;
6850
badaa04c 6851 case BUILT_IN_THREAD_POINTER:
6852 return expand_builtin_thread_pointer (exp, target);
6853
6854 case BUILT_IN_SET_THREAD_POINTER:
6855 expand_builtin_set_thread_pointer (exp);
6856 return const0_rtx;
6857
92482ee0 6858 default: /* just do library call, if unknown builtin */
146c1b4f 6859 break;
53800dbe 6860 }
6861
6862 /* The switch statement above can drop through to cause the function
6863 to be called normally. */
6864 return expand_call (exp, target, ignore);
6865}
650e4c94 6866
805e22b2 6867/* Determine whether a tree node represents a call to a built-in
52203a9d 6868 function. If the tree T is a call to a built-in function with
6869 the right number of arguments of the appropriate types, return
6870 the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
6871 Otherwise the return value is END_BUILTINS. */
aecda0d6 6872
805e22b2 6873enum built_in_function
b7bf20db 6874builtin_mathfn_code (const_tree t)
805e22b2 6875{
b7bf20db 6876 const_tree fndecl, arg, parmlist;
6877 const_tree argtype, parmtype;
6878 const_call_expr_arg_iterator iter;
805e22b2 6879
6880 if (TREE_CODE (t) != CALL_EXPR
c2f47e15 6881 || TREE_CODE (CALL_EXPR_FN (t)) != ADDR_EXPR)
805e22b2 6882 return END_BUILTINS;
6883
c6e6ecb1 6884 fndecl = get_callee_fndecl (t);
6885 if (fndecl == NULL_TREE
52203a9d 6886 || TREE_CODE (fndecl) != FUNCTION_DECL
805e22b2 6887 || ! DECL_BUILT_IN (fndecl)
6888 || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
6889 return END_BUILTINS;
6890
52203a9d 6891 parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
b7bf20db 6892 init_const_call_expr_arg_iterator (t, &iter);
52203a9d 6893 for (; parmlist; parmlist = TREE_CHAIN (parmlist))
e9f80ff5 6894 {
52203a9d 6895 /* If a function doesn't take a variable number of arguments,
6896 the last element in the list will have type `void'. */
6897 parmtype = TREE_VALUE (parmlist);
6898 if (VOID_TYPE_P (parmtype))
6899 {
b7bf20db 6900 if (more_const_call_expr_args_p (&iter))
52203a9d 6901 return END_BUILTINS;
6902 return DECL_FUNCTION_CODE (fndecl);
6903 }
6904
b7bf20db 6905 if (! more_const_call_expr_args_p (&iter))
e9f80ff5 6906 return END_BUILTINS;
48e1416a 6907
b7bf20db 6908 arg = next_const_call_expr_arg (&iter);
c2f47e15 6909 argtype = TREE_TYPE (arg);
52203a9d 6910
6911 if (SCALAR_FLOAT_TYPE_P (parmtype))
6912 {
6913 if (! SCALAR_FLOAT_TYPE_P (argtype))
6914 return END_BUILTINS;
6915 }
6916 else if (COMPLEX_FLOAT_TYPE_P (parmtype))
6917 {
6918 if (! COMPLEX_FLOAT_TYPE_P (argtype))
6919 return END_BUILTINS;
6920 }
6921 else if (POINTER_TYPE_P (parmtype))
6922 {
6923 if (! POINTER_TYPE_P (argtype))
6924 return END_BUILTINS;
6925 }
6926 else if (INTEGRAL_TYPE_P (parmtype))
6927 {
6928 if (! INTEGRAL_TYPE_P (argtype))
6929 return END_BUILTINS;
6930 }
6931 else
e9f80ff5 6932 return END_BUILTINS;
e9f80ff5 6933 }
6934
52203a9d 6935 /* Variable-length argument list. */
805e22b2 6936 return DECL_FUNCTION_CODE (fndecl);
6937}
6938
c2f47e15 6939/* Fold a call to __builtin_constant_p, if we know its argument ARG will
6940 evaluate to a constant. */
650e4c94 6941
6942static tree
c2f47e15 6943fold_builtin_constant_p (tree arg)
650e4c94 6944{
650e4c94 6945 /* We return 1 for a numeric type that's known to be a constant
6946 value at compile-time or for an aggregate type that's a
6947 literal constant. */
c2f47e15 6948 STRIP_NOPS (arg);
650e4c94 6949
6950 /* If we know this is a constant, emit the constant of one. */
c2f47e15 6951 if (CONSTANT_CLASS_P (arg)
6952 || (TREE_CODE (arg) == CONSTRUCTOR
6953 && TREE_CONSTANT (arg)))
650e4c94 6954 return integer_one_node;
c2f47e15 6955 if (TREE_CODE (arg) == ADDR_EXPR)
adcfa3a3 6956 {
c2f47e15 6957 tree op = TREE_OPERAND (arg, 0);
adcfa3a3 6958 if (TREE_CODE (op) == STRING_CST
6959 || (TREE_CODE (op) == ARRAY_REF
6960 && integer_zerop (TREE_OPERAND (op, 1))
6961 && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
6962 return integer_one_node;
6963 }
650e4c94 6964
1fb4300c 6965 /* If this expression has side effects, show we don't know it to be a
6966 constant. Likewise if it's a pointer or aggregate type since in
6967 those case we only want literals, since those are only optimized
f97c71a1 6968 when generating RTL, not later.
6969 And finally, if we are compiling an initializer, not code, we
6970 need to return a definite result now; there's not going to be any
6971 more optimization done. */
c2f47e15 6972 if (TREE_SIDE_EFFECTS (arg)
6973 || AGGREGATE_TYPE_P (TREE_TYPE (arg))
6974 || POINTER_TYPE_P (TREE_TYPE (arg))
47be647d 6975 || cfun == 0
6976 || folding_initializer)
650e4c94 6977 return integer_zero_node;
6978
c2f47e15 6979 return NULL_TREE;
650e4c94 6980}
6981
76f5a783 6982/* Create builtin_expect with PRED and EXPECTED as its arguments and
6983 return it as a truthvalue. */
4ee9c684 6984
6985static tree
389dd41b 6986build_builtin_expect_predicate (location_t loc, tree pred, tree expected)
4ee9c684 6987{
76f5a783 6988 tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
4ee9c684 6989
b9a16870 6990 fn = builtin_decl_explicit (BUILT_IN_EXPECT);
76f5a783 6991 arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
6992 ret_type = TREE_TYPE (TREE_TYPE (fn));
6993 pred_type = TREE_VALUE (arg_types);
6994 expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
6995
389dd41b 6996 pred = fold_convert_loc (loc, pred_type, pred);
6997 expected = fold_convert_loc (loc, expected_type, expected);
6998 call_expr = build_call_expr_loc (loc, fn, 2, pred, expected);
76f5a783 6999
7000 return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
7001 build_int_cst (ret_type, 0));
7002}
7003
7004/* Fold a call to builtin_expect with arguments ARG0 and ARG1. Return
7005 NULL_TREE if no simplification is possible. */
7006
7007static tree
389dd41b 7008fold_builtin_expect (location_t loc, tree arg0, tree arg1)
76f5a783 7009{
083bada9 7010 tree inner, fndecl, inner_arg0;
76f5a783 7011 enum tree_code code;
7012
083bada9 7013 /* Distribute the expected value over short-circuiting operators.
7014 See through the cast from truthvalue_type_node to long. */
7015 inner_arg0 = arg0;
7016 while (TREE_CODE (inner_arg0) == NOP_EXPR
7017 && INTEGRAL_TYPE_P (TREE_TYPE (inner_arg0))
7018 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner_arg0, 0))))
7019 inner_arg0 = TREE_OPERAND (inner_arg0, 0);
7020
76f5a783 7021 /* If this is a builtin_expect within a builtin_expect keep the
7022 inner one. See through a comparison against a constant. It
7023 might have been added to create a thruthvalue. */
083bada9 7024 inner = inner_arg0;
7025
76f5a783 7026 if (COMPARISON_CLASS_P (inner)
7027 && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST)
7028 inner = TREE_OPERAND (inner, 0);
7029
7030 if (TREE_CODE (inner) == CALL_EXPR
7031 && (fndecl = get_callee_fndecl (inner))
7032 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
7033 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT)
7034 return arg0;
7035
083bada9 7036 inner = inner_arg0;
76f5a783 7037 code = TREE_CODE (inner);
7038 if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
7039 {
7040 tree op0 = TREE_OPERAND (inner, 0);
7041 tree op1 = TREE_OPERAND (inner, 1);
7042
389dd41b 7043 op0 = build_builtin_expect_predicate (loc, op0, arg1);
7044 op1 = build_builtin_expect_predicate (loc, op1, arg1);
76f5a783 7045 inner = build2 (code, TREE_TYPE (inner), op0, op1);
7046
389dd41b 7047 return fold_convert_loc (loc, TREE_TYPE (arg0), inner);
76f5a783 7048 }
7049
7050 /* If the argument isn't invariant then there's nothing else we can do. */
083bada9 7051 if (!TREE_CONSTANT (inner_arg0))
c2f47e15 7052 return NULL_TREE;
4ee9c684 7053
76f5a783 7054 /* If we expect that a comparison against the argument will fold to
7055 a constant return the constant. In practice, this means a true
7056 constant or the address of a non-weak symbol. */
083bada9 7057 inner = inner_arg0;
4ee9c684 7058 STRIP_NOPS (inner);
7059 if (TREE_CODE (inner) == ADDR_EXPR)
7060 {
7061 do
7062 {
7063 inner = TREE_OPERAND (inner, 0);
7064 }
7065 while (TREE_CODE (inner) == COMPONENT_REF
7066 || TREE_CODE (inner) == ARRAY_REF);
062b4460 7067 if ((TREE_CODE (inner) == VAR_DECL
7068 || TREE_CODE (inner) == FUNCTION_DECL)
7069 && DECL_WEAK (inner))
c2f47e15 7070 return NULL_TREE;
4ee9c684 7071 }
7072
76f5a783 7073 /* Otherwise, ARG0 already has the proper type for the return value. */
7074 return arg0;
4ee9c684 7075}
7076
c2f47e15 7077/* Fold a call to __builtin_classify_type with argument ARG. */
27d0c333 7078
539a3a92 7079static tree
c2f47e15 7080fold_builtin_classify_type (tree arg)
539a3a92 7081{
c2f47e15 7082 if (arg == 0)
7002a1c8 7083 return build_int_cst (integer_type_node, no_type_class);
539a3a92 7084
7002a1c8 7085 return build_int_cst (integer_type_node, type_to_class (TREE_TYPE (arg)));
539a3a92 7086}
7087
c2f47e15 7088/* Fold a call to __builtin_strlen with argument ARG. */
e6e27594 7089
7090static tree
c7cbde74 7091fold_builtin_strlen (location_t loc, tree type, tree arg)
e6e27594 7092{
c2f47e15 7093 if (!validate_arg (arg, POINTER_TYPE))
e6e27594 7094 return NULL_TREE;
7095 else
7096 {
c2f47e15 7097 tree len = c_strlen (arg, 0);
e6e27594 7098
7099 if (len)
c7cbde74 7100 return fold_convert_loc (loc, type, len);
e6e27594 7101
7102 return NULL_TREE;
7103 }
7104}
7105
92c43e3c 7106/* Fold a call to __builtin_inf or __builtin_huge_val. */
7107
7108static tree
389dd41b 7109fold_builtin_inf (location_t loc, tree type, int warn)
92c43e3c 7110{
aa870c1b 7111 REAL_VALUE_TYPE real;
7112
40f4dbd5 7113 /* __builtin_inff is intended to be usable to define INFINITY on all
7114 targets. If an infinity is not available, INFINITY expands "to a
7115 positive constant of type float that overflows at translation
7116 time", footnote "In this case, using INFINITY will violate the
7117 constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
7118 Thus we pedwarn to ensure this constraint violation is
7119 diagnosed. */
92c43e3c 7120 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
389dd41b 7121 pedwarn (loc, 0, "target format does not support infinity");
92c43e3c 7122
aa870c1b 7123 real_inf (&real);
7124 return build_real (type, real);
92c43e3c 7125}
7126
c2f47e15 7127/* Fold a call to __builtin_nan or __builtin_nans with argument ARG. */
b0db7939 7128
7129static tree
c2f47e15 7130fold_builtin_nan (tree arg, tree type, int quiet)
b0db7939 7131{
7132 REAL_VALUE_TYPE real;
7133 const char *str;
7134
c2f47e15 7135 if (!validate_arg (arg, POINTER_TYPE))
7136 return NULL_TREE;
7137 str = c_getstr (arg);
b0db7939 7138 if (!str)
c2f47e15 7139 return NULL_TREE;
b0db7939 7140
7141 if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
c2f47e15 7142 return NULL_TREE;
b0db7939 7143
7144 return build_real (type, real);
7145}
7146
277f8dd2 7147/* Return true if the floating point expression T has an integer value.
7148 We also allow +Inf, -Inf and NaN to be considered integer values. */
7149
7150static bool
7151integer_valued_real_p (tree t)
7152{
7153 switch (TREE_CODE (t))
7154 {
7155 case FLOAT_EXPR:
7156 return true;
7157
7158 case ABS_EXPR:
7159 case SAVE_EXPR:
277f8dd2 7160 return integer_valued_real_p (TREE_OPERAND (t, 0));
7161
7162 case COMPOUND_EXPR:
41076ef6 7163 case MODIFY_EXPR:
277f8dd2 7164 case BIND_EXPR:
75a70cf9 7165 return integer_valued_real_p (TREE_OPERAND (t, 1));
277f8dd2 7166
7167 case PLUS_EXPR:
7168 case MINUS_EXPR:
7169 case MULT_EXPR:
7170 case MIN_EXPR:
7171 case MAX_EXPR:
7172 return integer_valued_real_p (TREE_OPERAND (t, 0))
7173 && integer_valued_real_p (TREE_OPERAND (t, 1));
7174
7175 case COND_EXPR:
7176 return integer_valued_real_p (TREE_OPERAND (t, 1))
7177 && integer_valued_real_p (TREE_OPERAND (t, 2));
7178
7179 case REAL_CST:
0570334c 7180 return real_isinteger (TREE_REAL_CST_PTR (t), TYPE_MODE (TREE_TYPE (t)));
277f8dd2 7181
7182 case NOP_EXPR:
7183 {
7184 tree type = TREE_TYPE (TREE_OPERAND (t, 0));
7185 if (TREE_CODE (type) == INTEGER_TYPE)
7186 return true;
7187 if (TREE_CODE (type) == REAL_TYPE)
7188 return integer_valued_real_p (TREE_OPERAND (t, 0));
7189 break;
7190 }
7191
7192 case CALL_EXPR:
7193 switch (builtin_mathfn_code (t))
7194 {
4f35b1fc 7195 CASE_FLT_FN (BUILT_IN_CEIL):
7196 CASE_FLT_FN (BUILT_IN_FLOOR):
7197 CASE_FLT_FN (BUILT_IN_NEARBYINT):
7198 CASE_FLT_FN (BUILT_IN_RINT):
7199 CASE_FLT_FN (BUILT_IN_ROUND):
7200 CASE_FLT_FN (BUILT_IN_TRUNC):
277f8dd2 7201 return true;
7202
d4a43a03 7203 CASE_FLT_FN (BUILT_IN_FMIN):
7204 CASE_FLT_FN (BUILT_IN_FMAX):
c2f47e15 7205 return integer_valued_real_p (CALL_EXPR_ARG (t, 0))
7206 && integer_valued_real_p (CALL_EXPR_ARG (t, 1));
d4a43a03 7207
277f8dd2 7208 default:
7209 break;
7210 }
7211 break;
7212
7213 default:
7214 break;
7215 }
7216 return false;
7217}
7218
c2f47e15 7219/* FNDECL is assumed to be a builtin where truncation can be propagated
6528f4f4 7220 across (for instance floor((double)f) == (double)floorf (f).
c2f47e15 7221 Do the transformation for a call with argument ARG. */
277f8dd2 7222
6528f4f4 7223static tree
389dd41b 7224fold_trunc_transparent_mathfn (location_t loc, tree fndecl, tree arg)
6528f4f4 7225{
6528f4f4 7226 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
277f8dd2 7227
c2f47e15 7228 if (!validate_arg (arg, REAL_TYPE))
7229 return NULL_TREE;
6528f4f4 7230
277f8dd2 7231 /* Integer rounding functions are idempotent. */
7232 if (fcode == builtin_mathfn_code (arg))
7233 return arg;
7234
7235 /* If argument is already integer valued, and we don't need to worry
7236 about setting errno, there's no need to perform rounding. */
7237 if (! flag_errno_math && integer_valued_real_p (arg))
7238 return arg;
7239
7240 if (optimize)
6528f4f4 7241 {
277f8dd2 7242 tree arg0 = strip_float_extensions (arg);
2426241c 7243 tree ftype = TREE_TYPE (TREE_TYPE (fndecl));
6528f4f4 7244 tree newtype = TREE_TYPE (arg0);
7245 tree decl;
7246
7247 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7248 && (decl = mathfn_built_in (newtype, fcode)))
389dd41b 7249 return fold_convert_loc (loc, ftype,
7250 build_call_expr_loc (loc, decl, 1,
7251 fold_convert_loc (loc,
7252 newtype,
7253 arg0)));
6528f4f4 7254 }
c2f47e15 7255 return NULL_TREE;
6528f4f4 7256}
7257
c2f47e15 7258/* FNDECL is assumed to be builtin which can narrow the FP type of
7259 the argument, for instance lround((double)f) -> lroundf (f).
7260 Do the transformation for a call with argument ARG. */
9ed65c7f 7261
7262static tree
389dd41b 7263fold_fixed_mathfn (location_t loc, tree fndecl, tree arg)
9ed65c7f 7264{
9ed65c7f 7265 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9ed65c7f 7266
c2f47e15 7267 if (!validate_arg (arg, REAL_TYPE))
7268 return NULL_TREE;
9ed65c7f 7269
7270 /* If argument is already integer valued, and we don't need to worry
7271 about setting errno, there's no need to perform rounding. */
7272 if (! flag_errno_math && integer_valued_real_p (arg))
389dd41b 7273 return fold_build1_loc (loc, FIX_TRUNC_EXPR,
7274 TREE_TYPE (TREE_TYPE (fndecl)), arg);
9ed65c7f 7275
7276 if (optimize)
7277 {
7278 tree ftype = TREE_TYPE (arg);
7279 tree arg0 = strip_float_extensions (arg);
7280 tree newtype = TREE_TYPE (arg0);
7281 tree decl;
7282
7283 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7284 && (decl = mathfn_built_in (newtype, fcode)))
389dd41b 7285 return build_call_expr_loc (loc, decl, 1,
7286 fold_convert_loc (loc, newtype, arg0));
9ed65c7f 7287 }
73a0da56 7288
80ff6494 7289 /* Canonicalize iround (x) to lround (x) on ILP32 targets where
7290 sizeof (int) == sizeof (long). */
7291 if (TYPE_PRECISION (integer_type_node)
7292 == TYPE_PRECISION (long_integer_type_node))
7293 {
7294 tree newfn = NULL_TREE;
7295 switch (fcode)
7296 {
7297 CASE_FLT_FN (BUILT_IN_ICEIL):
7298 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
7299 break;
7300
7301 CASE_FLT_FN (BUILT_IN_IFLOOR):
7302 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
7303 break;
7304
7305 CASE_FLT_FN (BUILT_IN_IROUND):
7306 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
7307 break;
7308
7309 CASE_FLT_FN (BUILT_IN_IRINT):
7310 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
7311 break;
7312
7313 default:
7314 break;
7315 }
7316
7317 if (newfn)
7318 {
7319 tree newcall = build_call_expr_loc (loc, newfn, 1, arg);
7320 return fold_convert_loc (loc,
7321 TREE_TYPE (TREE_TYPE (fndecl)), newcall);
7322 }
7323 }
7324
73a0da56 7325 /* Canonicalize llround (x) to lround (x) on LP64 targets where
7326 sizeof (long long) == sizeof (long). */
7327 if (TYPE_PRECISION (long_long_integer_type_node)
7328 == TYPE_PRECISION (long_integer_type_node))
7329 {
7330 tree newfn = NULL_TREE;
7331 switch (fcode)
7332 {
7333 CASE_FLT_FN (BUILT_IN_LLCEIL):
7334 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
7335 break;
7336
7337 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7338 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
7339 break;
7340
7341 CASE_FLT_FN (BUILT_IN_LLROUND):
7342 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
7343 break;
7344
7345 CASE_FLT_FN (BUILT_IN_LLRINT):
7346 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
7347 break;
7348
7349 default:
7350 break;
7351 }
7352
7353 if (newfn)
7354 {
389dd41b 7355 tree newcall = build_call_expr_loc (loc, newfn, 1, arg);
7356 return fold_convert_loc (loc,
7357 TREE_TYPE (TREE_TYPE (fndecl)), newcall);
73a0da56 7358 }
7359 }
7360
c2f47e15 7361 return NULL_TREE;
9ed65c7f 7362}
7363
c2f47e15 7364/* Fold call to builtin cabs, cabsf or cabsl with argument ARG. TYPE is the
7365 return type. Return NULL_TREE if no simplification can be made. */
c63f4ad3 7366
7367static tree
389dd41b 7368fold_builtin_cabs (location_t loc, tree arg, tree type, tree fndecl)
c63f4ad3 7369{
c2f47e15 7370 tree res;
c63f4ad3 7371
b0ce8887 7372 if (!validate_arg (arg, COMPLEX_TYPE)
c63f4ad3 7373 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
7374 return NULL_TREE;
7375
b4725390 7376 /* Calculate the result when the argument is a constant. */
7377 if (TREE_CODE (arg) == COMPLEX_CST
7378 && (res = do_mpfr_arg2 (TREE_REALPART (arg), TREE_IMAGPART (arg),
7379 type, mpfr_hypot)))
7380 return res;
48e1416a 7381
1af0d139 7382 if (TREE_CODE (arg) == COMPLEX_EXPR)
7383 {
7384 tree real = TREE_OPERAND (arg, 0);
7385 tree imag = TREE_OPERAND (arg, 1);
48e1416a 7386
1af0d139 7387 /* If either part is zero, cabs is fabs of the other. */
7388 if (real_zerop (real))
389dd41b 7389 return fold_build1_loc (loc, ABS_EXPR, type, imag);
1af0d139 7390 if (real_zerop (imag))
389dd41b 7391 return fold_build1_loc (loc, ABS_EXPR, type, real);
1af0d139 7392
7393 /* cabs(x+xi) -> fabs(x)*sqrt(2). */
7394 if (flag_unsafe_math_optimizations
7395 && operand_equal_p (real, imag, OEP_PURE_SAME))
7396 {
2e7ca27b 7397 const REAL_VALUE_TYPE sqrt2_trunc
7910b2fb 7398 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
1af0d139 7399 STRIP_NOPS (real);
389dd41b 7400 return fold_build2_loc (loc, MULT_EXPR, type,
7401 fold_build1_loc (loc, ABS_EXPR, type, real),
2e7ca27b 7402 build_real (type, sqrt2_trunc));
1af0d139 7403 }
7404 }
c63f4ad3 7405
749891b2 7406 /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */
7407 if (TREE_CODE (arg) == NEGATE_EXPR
7408 || TREE_CODE (arg) == CONJ_EXPR)
389dd41b 7409 return build_call_expr_loc (loc, fndecl, 1, TREE_OPERAND (arg, 0));
749891b2 7410
7d3f6cc7 7411 /* Don't do this when optimizing for size. */
7412 if (flag_unsafe_math_optimizations
0bfd8d5c 7413 && optimize && optimize_function_for_speed_p (cfun))
c63f4ad3 7414 {
0da0dbfa 7415 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
c63f4ad3 7416
7417 if (sqrtfn != NULL_TREE)
7418 {
c2f47e15 7419 tree rpart, ipart, result;
c63f4ad3 7420
4ee9c684 7421 arg = builtin_save_expr (arg);
29a6518e 7422
389dd41b 7423 rpart = fold_build1_loc (loc, REALPART_EXPR, type, arg);
7424 ipart = fold_build1_loc (loc, IMAGPART_EXPR, type, arg);
c63f4ad3 7425
4ee9c684 7426 rpart = builtin_save_expr (rpart);
7427 ipart = builtin_save_expr (ipart);
c63f4ad3 7428
389dd41b 7429 result = fold_build2_loc (loc, PLUS_EXPR, type,
7430 fold_build2_loc (loc, MULT_EXPR, type,
49d00087 7431 rpart, rpart),
389dd41b 7432 fold_build2_loc (loc, MULT_EXPR, type,
49d00087 7433 ipart, ipart));
c63f4ad3 7434
389dd41b 7435 return build_call_expr_loc (loc, sqrtfn, 1, result);
c63f4ad3 7436 }
7437 }
7438
7439 return NULL_TREE;
7440}
7441
c2373fdb 7442/* Build a complex (inf +- 0i) for the result of cproj. TYPE is the
7443 complex tree type of the result. If NEG is true, the imaginary
7444 zero is negative. */
7445
7446static tree
7447build_complex_cproj (tree type, bool neg)
7448{
7449 REAL_VALUE_TYPE rinf, rzero = dconst0;
7450
7451 real_inf (&rinf);
7452 rzero.sign = neg;
7453 return build_complex (type, build_real (TREE_TYPE (type), rinf),
7454 build_real (TREE_TYPE (type), rzero));
7455}
7456
7457/* Fold call to builtin cproj, cprojf or cprojl with argument ARG. TYPE is the
7458 return type. Return NULL_TREE if no simplification can be made. */
7459
7460static tree
7461fold_builtin_cproj (location_t loc, tree arg, tree type)
7462{
7463 if (!validate_arg (arg, COMPLEX_TYPE)
7464 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
7465 return NULL_TREE;
7466
7467 /* If there are no infinities, return arg. */
7468 if (! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (type))))
7469 return non_lvalue_loc (loc, arg);
7470
7471 /* Calculate the result when the argument is a constant. */
7472 if (TREE_CODE (arg) == COMPLEX_CST)
7473 {
7474 const REAL_VALUE_TYPE *real = TREE_REAL_CST_PTR (TREE_REALPART (arg));
7475 const REAL_VALUE_TYPE *imag = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
7476
7477 if (real_isinf (real) || real_isinf (imag))
7478 return build_complex_cproj (type, imag->sign);
7479 else
7480 return arg;
7481 }
b4c7e601 7482 else if (TREE_CODE (arg) == COMPLEX_EXPR)
7483 {
7484 tree real = TREE_OPERAND (arg, 0);
7485 tree imag = TREE_OPERAND (arg, 1);
7486
7487 STRIP_NOPS (real);
7488 STRIP_NOPS (imag);
7489
7490 /* If the real part is inf and the imag part is known to be
7491 nonnegative, return (inf + 0i). Remember side-effects are
7492 possible in the imag part. */
7493 if (TREE_CODE (real) == REAL_CST
7494 && real_isinf (TREE_REAL_CST_PTR (real))
7495 && tree_expr_nonnegative_p (imag))
7496 return omit_one_operand_loc (loc, type,
7497 build_complex_cproj (type, false),
7498 arg);
7499
7500 /* If the imag part is inf, return (inf+I*copysign(0,imag)).
7501 Remember side-effects are possible in the real part. */
7502 if (TREE_CODE (imag) == REAL_CST
7503 && real_isinf (TREE_REAL_CST_PTR (imag)))
7504 return
7505 omit_one_operand_loc (loc, type,
7506 build_complex_cproj (type, TREE_REAL_CST_PTR
7507 (imag)->sign), arg);
7508 }
c2373fdb 7509
7510 return NULL_TREE;
7511}
7512
c2f47e15 7513/* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG.
7514 Return NULL_TREE if no simplification can be made. */
e6e27594 7515
7516static tree
389dd41b 7517fold_builtin_sqrt (location_t loc, tree arg, tree type)
e6e27594 7518{
7519
7520 enum built_in_function fcode;
b4e8ab0c 7521 tree res;
c2f47e15 7522
7523 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7524 return NULL_TREE;
7525
b4e8ab0c 7526 /* Calculate the result when the argument is a constant. */
7527 if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
7528 return res;
48e1416a 7529
e6e27594 7530 /* Optimize sqrt(expN(x)) = expN(x*0.5). */
7531 fcode = builtin_mathfn_code (arg);
7532 if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
7533 {
c2f47e15 7534 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
389dd41b 7535 arg = fold_build2_loc (loc, MULT_EXPR, type,
c2f47e15 7536 CALL_EXPR_ARG (arg, 0),
49d00087 7537 build_real (type, dconsthalf));
389dd41b 7538 return build_call_expr_loc (loc, expfn, 1, arg);
e6e27594 7539 }
7540
7541 /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */
7542 if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
7543 {
7544 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7545
7546 if (powfn)
7547 {
c2f47e15 7548 tree arg0 = CALL_EXPR_ARG (arg, 0);
e6e27594 7549 tree tree_root;
7550 /* The inner root was either sqrt or cbrt. */
57510da6 7551 /* This was a conditional expression but it triggered a bug
18381619 7552 in Sun C 5.5. */
ce6cd837 7553 REAL_VALUE_TYPE dconstroot;
7554 if (BUILTIN_SQRT_P (fcode))
7555 dconstroot = dconsthalf;
7556 else
7557 dconstroot = dconst_third ();
e6e27594 7558
7559 /* Adjust for the outer root. */
7560 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7561 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7562 tree_root = build_real (type, dconstroot);
389dd41b 7563 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
e6e27594 7564 }
7565 }
7566
bc33117f 7567 /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
e6e27594 7568 if (flag_unsafe_math_optimizations
7569 && (fcode == BUILT_IN_POW
7570 || fcode == BUILT_IN_POWF
7571 || fcode == BUILT_IN_POWL))
7572 {
c2f47e15 7573 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
7574 tree arg0 = CALL_EXPR_ARG (arg, 0);
7575 tree arg1 = CALL_EXPR_ARG (arg, 1);
bc33117f 7576 tree narg1;
7577 if (!tree_expr_nonnegative_p (arg0))
7578 arg0 = build1 (ABS_EXPR, type, arg0);
389dd41b 7579 narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 7580 build_real (type, dconsthalf));
389dd41b 7581 return build_call_expr_loc (loc, powfn, 2, arg0, narg1);
e6e27594 7582 }
7583
7584 return NULL_TREE;
7585}
7586
c2f47e15 7587/* Fold a builtin function call to cbrt, cbrtf, or cbrtl with argument ARG.
7588 Return NULL_TREE if no simplification can be made. */
7589
e6e27594 7590static tree
389dd41b 7591fold_builtin_cbrt (location_t loc, tree arg, tree type)
e6e27594 7592{
e6e27594 7593 const enum built_in_function fcode = builtin_mathfn_code (arg);
29f4cd78 7594 tree res;
e6e27594 7595
c2f47e15 7596 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7597 return NULL_TREE;
7598
29f4cd78 7599 /* Calculate the result when the argument is a constant. */
7600 if ((res = do_mpfr_arg1 (arg, type, mpfr_cbrt, NULL, NULL, 0)))
7601 return res;
e6e27594 7602
cdfeb715 7603 if (flag_unsafe_math_optimizations)
e6e27594 7604 {
cdfeb715 7605 /* Optimize cbrt(expN(x)) -> expN(x/3). */
7606 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 7607 {
c2f47e15 7608 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7609 const REAL_VALUE_TYPE third_trunc =
7910b2fb 7610 real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 7611 arg = fold_build2_loc (loc, MULT_EXPR, type,
c2f47e15 7612 CALL_EXPR_ARG (arg, 0),
49d00087 7613 build_real (type, third_trunc));
389dd41b 7614 return build_call_expr_loc (loc, expfn, 1, arg);
cdfeb715 7615 }
e6e27594 7616
cdfeb715 7617 /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */
7618 if (BUILTIN_SQRT_P (fcode))
a0c938f0 7619 {
cdfeb715 7620 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
e6e27594 7621
cdfeb715 7622 if (powfn)
7623 {
c2f47e15 7624 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7625 tree tree_root;
7910b2fb 7626 REAL_VALUE_TYPE dconstroot = dconst_third ();
cdfeb715 7627
7628 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7629 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7630 tree_root = build_real (type, dconstroot);
389dd41b 7631 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
cdfeb715 7632 }
e6e27594 7633 }
7634
cdfeb715 7635 /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */
7636 if (BUILTIN_CBRT_P (fcode))
a0c938f0 7637 {
c2f47e15 7638 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7639 if (tree_expr_nonnegative_p (arg0))
7640 {
7641 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7642
7643 if (powfn)
a0c938f0 7644 {
cdfeb715 7645 tree tree_root;
7646 REAL_VALUE_TYPE dconstroot;
a0c938f0 7647
3fa759a9 7648 real_arithmetic (&dconstroot, MULT_EXPR,
7910b2fb 7649 dconst_third_ptr (), dconst_third_ptr ());
cdfeb715 7650 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7651 tree_root = build_real (type, dconstroot);
389dd41b 7652 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
cdfeb715 7653 }
7654 }
7655 }
a0c938f0 7656
cdfeb715 7657 /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */
48e1416a 7658 if (fcode == BUILT_IN_POW
c2f47e15 7659 || fcode == BUILT_IN_POWF
cdfeb715 7660 || fcode == BUILT_IN_POWL)
a0c938f0 7661 {
c2f47e15 7662 tree arg00 = CALL_EXPR_ARG (arg, 0);
7663 tree arg01 = CALL_EXPR_ARG (arg, 1);
cdfeb715 7664 if (tree_expr_nonnegative_p (arg00))
7665 {
c2f47e15 7666 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7667 const REAL_VALUE_TYPE dconstroot
7910b2fb 7668 = real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 7669 tree narg01 = fold_build2_loc (loc, MULT_EXPR, type, arg01,
49d00087 7670 build_real (type, dconstroot));
389dd41b 7671 return build_call_expr_loc (loc, powfn, 2, arg00, narg01);
cdfeb715 7672 }
7673 }
e6e27594 7674 }
7675 return NULL_TREE;
7676}
7677
c2f47e15 7678/* Fold function call to builtin cos, cosf, or cosl with argument ARG.
7679 TYPE is the type of the return value. Return NULL_TREE if no
7680 simplification can be made. */
7681
e6e27594 7682static tree
389dd41b 7683fold_builtin_cos (location_t loc,
7684 tree arg, tree type, tree fndecl)
e6e27594 7685{
e6ab33d8 7686 tree res, narg;
e6e27594 7687
c2f47e15 7688 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7689 return NULL_TREE;
7690
bffb7645 7691 /* Calculate the result when the argument is a constant. */
728bac60 7692 if ((res = do_mpfr_arg1 (arg, type, mpfr_cos, NULL, NULL, 0)))
bffb7645 7693 return res;
48e1416a 7694
e6e27594 7695 /* Optimize cos(-x) into cos (x). */
e6ab33d8 7696 if ((narg = fold_strip_sign_ops (arg)))
389dd41b 7697 return build_call_expr_loc (loc, fndecl, 1, narg);
e6e27594 7698
7699 return NULL_TREE;
7700}
7701
c2f47e15 7702/* Fold function call to builtin cosh, coshf, or coshl with argument ARG.
7703 Return NULL_TREE if no simplification can be made. */
7704
cacdc1af 7705static tree
389dd41b 7706fold_builtin_cosh (location_t loc, tree arg, tree type, tree fndecl)
cacdc1af 7707{
c2f47e15 7708 if (validate_arg (arg, REAL_TYPE))
cacdc1af 7709 {
cacdc1af 7710 tree res, narg;
7711
7712 /* Calculate the result when the argument is a constant. */
7713 if ((res = do_mpfr_arg1 (arg, type, mpfr_cosh, NULL, NULL, 0)))
7714 return res;
48e1416a 7715
cacdc1af 7716 /* Optimize cosh(-x) into cosh (x). */
7717 if ((narg = fold_strip_sign_ops (arg)))
389dd41b 7718 return build_call_expr_loc (loc, fndecl, 1, narg);
cacdc1af 7719 }
48e1416a 7720
cacdc1af 7721 return NULL_TREE;
7722}
7723
239d491a 7724/* Fold function call to builtin ccos (or ccosh if HYPER is TRUE) with
7725 argument ARG. TYPE is the type of the return value. Return
7726 NULL_TREE if no simplification can be made. */
7727
7728static tree
965d0f29 7729fold_builtin_ccos (location_t loc, tree arg, tree type, tree fndecl,
7730 bool hyper)
239d491a 7731{
7732 if (validate_arg (arg, COMPLEX_TYPE)
7733 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
7734 {
7735 tree tmp;
7736
239d491a 7737 /* Calculate the result when the argument is a constant. */
7738 if ((tmp = do_mpc_arg1 (arg, type, (hyper ? mpc_cosh : mpc_cos))))
7739 return tmp;
48e1416a 7740
239d491a 7741 /* Optimize fn(-x) into fn(x). */
7742 if ((tmp = fold_strip_sign_ops (arg)))
389dd41b 7743 return build_call_expr_loc (loc, fndecl, 1, tmp);
239d491a 7744 }
7745
7746 return NULL_TREE;
7747}
7748
c2f47e15 7749/* Fold function call to builtin tan, tanf, or tanl with argument ARG.
7750 Return NULL_TREE if no simplification can be made. */
7751
e6e27594 7752static tree
c2f47e15 7753fold_builtin_tan (tree arg, tree type)
e6e27594 7754{
7755 enum built_in_function fcode;
29f4cd78 7756 tree res;
e6e27594 7757
c2f47e15 7758 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7759 return NULL_TREE;
7760
bffb7645 7761 /* Calculate the result when the argument is a constant. */
728bac60 7762 if ((res = do_mpfr_arg1 (arg, type, mpfr_tan, NULL, NULL, 0)))
bffb7645 7763 return res;
48e1416a 7764
e6e27594 7765 /* Optimize tan(atan(x)) = x. */
7766 fcode = builtin_mathfn_code (arg);
7767 if (flag_unsafe_math_optimizations
7768 && (fcode == BUILT_IN_ATAN
7769 || fcode == BUILT_IN_ATANF
7770 || fcode == BUILT_IN_ATANL))
c2f47e15 7771 return CALL_EXPR_ARG (arg, 0);
e6e27594 7772
7773 return NULL_TREE;
7774}
7775
d735c391 7776/* Fold function call to builtin sincos, sincosf, or sincosl. Return
7777 NULL_TREE if no simplification can be made. */
7778
7779static tree
389dd41b 7780fold_builtin_sincos (location_t loc,
7781 tree arg0, tree arg1, tree arg2)
d735c391 7782{
c2f47e15 7783 tree type;
d735c391 7784 tree res, fn, call;
7785
c2f47e15 7786 if (!validate_arg (arg0, REAL_TYPE)
7787 || !validate_arg (arg1, POINTER_TYPE)
7788 || !validate_arg (arg2, POINTER_TYPE))
d735c391 7789 return NULL_TREE;
7790
d735c391 7791 type = TREE_TYPE (arg0);
d735c391 7792
7793 /* Calculate the result when the argument is a constant. */
7794 if ((res = do_mpfr_sincos (arg0, arg1, arg2)))
7795 return res;
7796
7797 /* Canonicalize sincos to cexpi. */
2a6b4c77 7798 if (!TARGET_C99_FUNCTIONS)
7799 return NULL_TREE;
d735c391 7800 fn = mathfn_built_in (type, BUILT_IN_CEXPI);
7801 if (!fn)
7802 return NULL_TREE;
7803
389dd41b 7804 call = build_call_expr_loc (loc, fn, 1, arg0);
d735c391 7805 call = builtin_save_expr (call);
7806
a75b1c71 7807 return build2 (COMPOUND_EXPR, void_type_node,
d735c391 7808 build2 (MODIFY_EXPR, void_type_node,
389dd41b 7809 build_fold_indirect_ref_loc (loc, arg1),
d735c391 7810 build1 (IMAGPART_EXPR, type, call)),
7811 build2 (MODIFY_EXPR, void_type_node,
389dd41b 7812 build_fold_indirect_ref_loc (loc, arg2),
d735c391 7813 build1 (REALPART_EXPR, type, call)));
7814}
7815
c5bb2c4b 7816/* Fold function call to builtin cexp, cexpf, or cexpl. Return
7817 NULL_TREE if no simplification can be made. */
7818
7819static tree
389dd41b 7820fold_builtin_cexp (location_t loc, tree arg0, tree type)
c5bb2c4b 7821{
c2f47e15 7822 tree rtype;
c5bb2c4b 7823 tree realp, imagp, ifn;
239d491a 7824 tree res;
c5bb2c4b 7825
239d491a 7826 if (!validate_arg (arg0, COMPLEX_TYPE)
b0ce8887 7827 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) != REAL_TYPE)
c5bb2c4b 7828 return NULL_TREE;
7829
239d491a 7830 /* Calculate the result when the argument is a constant. */
7831 if ((res = do_mpc_arg1 (arg0, type, mpc_exp)))
7832 return res;
48e1416a 7833
c5bb2c4b 7834 rtype = TREE_TYPE (TREE_TYPE (arg0));
7835
7836 /* In case we can figure out the real part of arg0 and it is constant zero
7837 fold to cexpi. */
2a6b4c77 7838 if (!TARGET_C99_FUNCTIONS)
7839 return NULL_TREE;
c5bb2c4b 7840 ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI);
7841 if (!ifn)
7842 return NULL_TREE;
7843
389dd41b 7844 if ((realp = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0))
c5bb2c4b 7845 && real_zerop (realp))
7846 {
389dd41b 7847 tree narg = fold_build1_loc (loc, IMAGPART_EXPR, rtype, arg0);
7848 return build_call_expr_loc (loc, ifn, 1, narg);
c5bb2c4b 7849 }
7850
7851 /* In case we can easily decompose real and imaginary parts split cexp
7852 to exp (r) * cexpi (i). */
7853 if (flag_unsafe_math_optimizations
7854 && realp)
7855 {
7856 tree rfn, rcall, icall;
7857
7858 rfn = mathfn_built_in (rtype, BUILT_IN_EXP);
7859 if (!rfn)
7860 return NULL_TREE;
7861
389dd41b 7862 imagp = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
c5bb2c4b 7863 if (!imagp)
7864 return NULL_TREE;
7865
389dd41b 7866 icall = build_call_expr_loc (loc, ifn, 1, imagp);
c5bb2c4b 7867 icall = builtin_save_expr (icall);
389dd41b 7868 rcall = build_call_expr_loc (loc, rfn, 1, realp);
c5bb2c4b 7869 rcall = builtin_save_expr (rcall);
389dd41b 7870 return fold_build2_loc (loc, COMPLEX_EXPR, type,
7871 fold_build2_loc (loc, MULT_EXPR, rtype,
71bf42bb 7872 rcall,
389dd41b 7873 fold_build1_loc (loc, REALPART_EXPR,
7874 rtype, icall)),
7875 fold_build2_loc (loc, MULT_EXPR, rtype,
71bf42bb 7876 rcall,
389dd41b 7877 fold_build1_loc (loc, IMAGPART_EXPR,
7878 rtype, icall)));
c5bb2c4b 7879 }
7880
7881 return NULL_TREE;
7882}
7883
c2f47e15 7884/* Fold function call to builtin trunc, truncf or truncl with argument ARG.
7885 Return NULL_TREE if no simplification can be made. */
277f8dd2 7886
7887static tree
389dd41b 7888fold_builtin_trunc (location_t loc, tree fndecl, tree arg)
277f8dd2 7889{
c2f47e15 7890 if (!validate_arg (arg, REAL_TYPE))
7891 return NULL_TREE;
277f8dd2 7892
7893 /* Optimize trunc of constant value. */
f96bd2bf 7894 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7895 {
7896 REAL_VALUE_TYPE r, x;
2426241c 7897 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7898
7899 x = TREE_REAL_CST (arg);
7900 real_trunc (&r, TYPE_MODE (type), &x);
7901 return build_real (type, r);
7902 }
7903
389dd41b 7904 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7905}
7906
c2f47e15 7907/* Fold function call to builtin floor, floorf or floorl with argument ARG.
7908 Return NULL_TREE if no simplification can be made. */
277f8dd2 7909
7910static tree
389dd41b 7911fold_builtin_floor (location_t loc, tree fndecl, tree arg)
277f8dd2 7912{
c2f47e15 7913 if (!validate_arg (arg, REAL_TYPE))
7914 return NULL_TREE;
277f8dd2 7915
7916 /* Optimize floor of constant value. */
f96bd2bf 7917 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7918 {
7919 REAL_VALUE_TYPE x;
7920
7921 x = TREE_REAL_CST (arg);
7922 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7923 {
2426241c 7924 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7925 REAL_VALUE_TYPE r;
7926
7927 real_floor (&r, TYPE_MODE (type), &x);
7928 return build_real (type, r);
7929 }
7930 }
7931
acc2b92e 7932 /* Fold floor (x) where x is nonnegative to trunc (x). */
7933 if (tree_expr_nonnegative_p (arg))
30fe8286 7934 {
7935 tree truncfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_TRUNC);
7936 if (truncfn)
389dd41b 7937 return build_call_expr_loc (loc, truncfn, 1, arg);
30fe8286 7938 }
acc2b92e 7939
389dd41b 7940 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7941}
7942
c2f47e15 7943/* Fold function call to builtin ceil, ceilf or ceill with argument ARG.
7944 Return NULL_TREE if no simplification can be made. */
277f8dd2 7945
7946static tree
389dd41b 7947fold_builtin_ceil (location_t loc, tree fndecl, tree arg)
277f8dd2 7948{
c2f47e15 7949 if (!validate_arg (arg, REAL_TYPE))
7950 return NULL_TREE;
277f8dd2 7951
7952 /* Optimize ceil of constant value. */
f96bd2bf 7953 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7954 {
7955 REAL_VALUE_TYPE x;
7956
7957 x = TREE_REAL_CST (arg);
7958 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7959 {
2426241c 7960 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7961 REAL_VALUE_TYPE r;
7962
7963 real_ceil (&r, TYPE_MODE (type), &x);
7964 return build_real (type, r);
7965 }
7966 }
7967
389dd41b 7968 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7969}
7970
c2f47e15 7971/* Fold function call to builtin round, roundf or roundl with argument ARG.
7972 Return NULL_TREE if no simplification can be made. */
89ab3887 7973
7974static tree
389dd41b 7975fold_builtin_round (location_t loc, tree fndecl, tree arg)
89ab3887 7976{
c2f47e15 7977 if (!validate_arg (arg, REAL_TYPE))
7978 return NULL_TREE;
89ab3887 7979
34f17811 7980 /* Optimize round of constant value. */
f96bd2bf 7981 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
89ab3887 7982 {
7983 REAL_VALUE_TYPE x;
7984
7985 x = TREE_REAL_CST (arg);
7986 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7987 {
2426241c 7988 tree type = TREE_TYPE (TREE_TYPE (fndecl));
89ab3887 7989 REAL_VALUE_TYPE r;
7990
7991 real_round (&r, TYPE_MODE (type), &x);
7992 return build_real (type, r);
7993 }
7994 }
7995
389dd41b 7996 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
89ab3887 7997}
7998
34f17811 7999/* Fold function call to builtin lround, lroundf or lroundl (or the
c2f47e15 8000 corresponding long long versions) and other rounding functions. ARG
8001 is the argument to the call. Return NULL_TREE if no simplification
8002 can be made. */
34f17811 8003
8004static tree
389dd41b 8005fold_builtin_int_roundingfn (location_t loc, tree fndecl, tree arg)
34f17811 8006{
c2f47e15 8007 if (!validate_arg (arg, REAL_TYPE))
8008 return NULL_TREE;
34f17811 8009
8010 /* Optimize lround of constant value. */
f96bd2bf 8011 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
34f17811 8012 {
8013 const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
8014
776a7bab 8015 if (real_isfinite (&x))
34f17811 8016 {
2426241c 8017 tree itype = TREE_TYPE (TREE_TYPE (fndecl));
ca9b061d 8018 tree ftype = TREE_TYPE (arg);
a6caa15f 8019 double_int val;
34f17811 8020 REAL_VALUE_TYPE r;
8021
ad52b9b7 8022 switch (DECL_FUNCTION_CODE (fndecl))
8023 {
80ff6494 8024 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 8025 CASE_FLT_FN (BUILT_IN_LFLOOR):
8026 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 8027 real_floor (&r, TYPE_MODE (ftype), &x);
8028 break;
8029
80ff6494 8030 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 8031 CASE_FLT_FN (BUILT_IN_LCEIL):
8032 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 8033 real_ceil (&r, TYPE_MODE (ftype), &x);
8034 break;
8035
80ff6494 8036 CASE_FLT_FN (BUILT_IN_IROUND):
4f35b1fc 8037 CASE_FLT_FN (BUILT_IN_LROUND):
8038 CASE_FLT_FN (BUILT_IN_LLROUND):
ad52b9b7 8039 real_round (&r, TYPE_MODE (ftype), &x);
8040 break;
8041
8042 default:
8043 gcc_unreachable ();
8044 }
8045
a6caa15f 8046 real_to_integer2 ((HOST_WIDE_INT *)&val.low, &val.high, &r);
8047 if (double_int_fits_to_tree_p (itype, val))
8048 return double_int_to_tree (itype, val);
34f17811 8049 }
8050 }
8051
acc2b92e 8052 switch (DECL_FUNCTION_CODE (fndecl))
8053 {
8054 CASE_FLT_FN (BUILT_IN_LFLOOR):
8055 CASE_FLT_FN (BUILT_IN_LLFLOOR):
8056 /* Fold lfloor (x) where x is nonnegative to FIX_TRUNC (x). */
8057 if (tree_expr_nonnegative_p (arg))
389dd41b 8058 return fold_build1_loc (loc, FIX_TRUNC_EXPR,
8059 TREE_TYPE (TREE_TYPE (fndecl)), arg);
acc2b92e 8060 break;
8061 default:;
8062 }
8063
389dd41b 8064 return fold_fixed_mathfn (loc, fndecl, arg);
34f17811 8065}
8066
70fb4c07 8067/* Fold function call to builtin ffs, clz, ctz, popcount and parity
c2f47e15 8068 and their long and long long variants (i.e. ffsl and ffsll). ARG is
8069 the argument to the call. Return NULL_TREE if no simplification can
8070 be made. */
70fb4c07 8071
8072static tree
c2f47e15 8073fold_builtin_bitop (tree fndecl, tree arg)
70fb4c07 8074{
c2f47e15 8075 if (!validate_arg (arg, INTEGER_TYPE))
70fb4c07 8076 return NULL_TREE;
8077
8078 /* Optimize for constant argument. */
f96bd2bf 8079 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
70fb4c07 8080 {
8081 HOST_WIDE_INT hi, width, result;
8082 unsigned HOST_WIDE_INT lo;
7c446c95 8083 tree type;
70fb4c07 8084
8085 type = TREE_TYPE (arg);
8086 width = TYPE_PRECISION (type);
8087 lo = TREE_INT_CST_LOW (arg);
8088
8089 /* Clear all the bits that are beyond the type's precision. */
8090 if (width > HOST_BITS_PER_WIDE_INT)
8091 {
8092 hi = TREE_INT_CST_HIGH (arg);
24cd46a7 8093 if (width < HOST_BITS_PER_DOUBLE_INT)
6aaa1f9e 8094 hi &= ~((unsigned HOST_WIDE_INT) (-1)
8095 << (width - HOST_BITS_PER_WIDE_INT));
70fb4c07 8096 }
8097 else
8098 {
8099 hi = 0;
8100 if (width < HOST_BITS_PER_WIDE_INT)
8101 lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
8102 }
8103
8104 switch (DECL_FUNCTION_CODE (fndecl))
8105 {
4f35b1fc 8106 CASE_INT_FN (BUILT_IN_FFS):
70fb4c07 8107 if (lo != 0)
7e8d812e 8108 result = ffs_hwi (lo);
70fb4c07 8109 else if (hi != 0)
7e8d812e 8110 result = HOST_BITS_PER_WIDE_INT + ffs_hwi (hi);
70fb4c07 8111 else
8112 result = 0;
8113 break;
8114
4f35b1fc 8115 CASE_INT_FN (BUILT_IN_CLZ):
70fb4c07 8116 if (hi != 0)
8117 result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
8118 else if (lo != 0)
8119 result = width - floor_log2 (lo) - 1;
8120 else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
8121 result = width;
8122 break;
8123
4f35b1fc 8124 CASE_INT_FN (BUILT_IN_CTZ):
70fb4c07 8125 if (lo != 0)
7e8d812e 8126 result = ctz_hwi (lo);
70fb4c07 8127 else if (hi != 0)
7e8d812e 8128 result = HOST_BITS_PER_WIDE_INT + ctz_hwi (hi);
70fb4c07 8129 else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
8130 result = width;
8131 break;
8132
6aaa1f9e 8133 CASE_INT_FN (BUILT_IN_CLRSB):
8134 if (width > HOST_BITS_PER_WIDE_INT
8135 && (hi & ((unsigned HOST_WIDE_INT) 1
8136 << (width - HOST_BITS_PER_WIDE_INT - 1))) != 0)
8137 {
8138 hi = ~hi & ~((unsigned HOST_WIDE_INT) (-1)
8139 << (width - HOST_BITS_PER_WIDE_INT - 1));
8140 lo = ~lo;
8141 }
8142 else if (width <= HOST_BITS_PER_WIDE_INT
8143 && (lo & ((unsigned HOST_WIDE_INT) 1 << (width - 1))) != 0)
8144 lo = ~lo & ~((unsigned HOST_WIDE_INT) (-1) << (width - 1));
8145 if (hi != 0)
8146 result = width - floor_log2 (hi) - 2 - HOST_BITS_PER_WIDE_INT;
8147 else if (lo != 0)
8148 result = width - floor_log2 (lo) - 2;
8149 else
8150 result = width - 1;
8151 break;
8152
4f35b1fc 8153 CASE_INT_FN (BUILT_IN_POPCOUNT):
70fb4c07 8154 result = 0;
8155 while (lo)
8156 result++, lo &= lo - 1;
8157 while (hi)
7e8d812e 8158 result++, hi &= (unsigned HOST_WIDE_INT) hi - 1;
70fb4c07 8159 break;
8160
4f35b1fc 8161 CASE_INT_FN (BUILT_IN_PARITY):
70fb4c07 8162 result = 0;
8163 while (lo)
8164 result++, lo &= lo - 1;
8165 while (hi)
7e8d812e 8166 result++, hi &= (unsigned HOST_WIDE_INT) hi - 1;
70fb4c07 8167 result &= 1;
8168 break;
8169
8170 default:
64db345d 8171 gcc_unreachable ();
70fb4c07 8172 }
8173
2426241c 8174 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
70fb4c07 8175 }
8176
8177 return NULL_TREE;
8178}
8179
74bdbe96 8180/* Fold function call to builtin_bswap and the short, long and long long
42791117 8181 variants. Return NULL_TREE if no simplification can be made. */
8182static tree
c2f47e15 8183fold_builtin_bswap (tree fndecl, tree arg)
42791117 8184{
c2f47e15 8185 if (! validate_arg (arg, INTEGER_TYPE))
8186 return NULL_TREE;
42791117 8187
8188 /* Optimize constant value. */
f96bd2bf 8189 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
42791117 8190 {
8191 HOST_WIDE_INT hi, width, r_hi = 0;
8192 unsigned HOST_WIDE_INT lo, r_lo = 0;
74bdbe96 8193 tree type = TREE_TYPE (TREE_TYPE (fndecl));
42791117 8194
42791117 8195 width = TYPE_PRECISION (type);
8196 lo = TREE_INT_CST_LOW (arg);
8197 hi = TREE_INT_CST_HIGH (arg);
8198
8199 switch (DECL_FUNCTION_CODE (fndecl))
8200 {
74bdbe96 8201 case BUILT_IN_BSWAP16:
42791117 8202 case BUILT_IN_BSWAP32:
8203 case BUILT_IN_BSWAP64:
8204 {
8205 int s;
8206
8207 for (s = 0; s < width; s += 8)
8208 {
8209 int d = width - s - 8;
8210 unsigned HOST_WIDE_INT byte;
8211
8212 if (s < HOST_BITS_PER_WIDE_INT)
8213 byte = (lo >> s) & 0xff;
8214 else
8215 byte = (hi >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff;
8216
8217 if (d < HOST_BITS_PER_WIDE_INT)
8218 r_lo |= byte << d;
8219 else
8220 r_hi |= byte << (d - HOST_BITS_PER_WIDE_INT);
8221 }
8222 }
8223
8224 break;
8225
8226 default:
8227 gcc_unreachable ();
8228 }
8229
8230 if (width < HOST_BITS_PER_WIDE_INT)
74bdbe96 8231 return build_int_cst (type, r_lo);
42791117 8232 else
74bdbe96 8233 return build_int_cst_wide (type, r_lo, r_hi);
42791117 8234 }
8235
8236 return NULL_TREE;
8237}
c2f47e15 8238
8918c507 8239/* A subroutine of fold_builtin to fold the various logarithmic
29f4cd78 8240 functions. Return NULL_TREE if no simplification can me made.
8241 FUNC is the corresponding MPFR logarithm function. */
8918c507 8242
8243static tree
389dd41b 8244fold_builtin_logarithm (location_t loc, tree fndecl, tree arg,
29f4cd78 8245 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8246{
c2f47e15 8247 if (validate_arg (arg, REAL_TYPE))
8918c507 8248 {
8918c507 8249 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8250 tree res;
8918c507 8251 const enum built_in_function fcode = builtin_mathfn_code (arg);
0862b7e9 8252
29f4cd78 8253 /* Calculate the result when the argument is a constant. */
8254 if ((res = do_mpfr_arg1 (arg, type, func, &dconst0, NULL, false)))
8255 return res;
8256
8918c507 8257 /* Special case, optimize logN(expN(x)) = x. */
8258 if (flag_unsafe_math_optimizations
29f4cd78 8259 && ((func == mpfr_log
8918c507 8260 && (fcode == BUILT_IN_EXP
8261 || fcode == BUILT_IN_EXPF
8262 || fcode == BUILT_IN_EXPL))
29f4cd78 8263 || (func == mpfr_log2
8918c507 8264 && (fcode == BUILT_IN_EXP2
8265 || fcode == BUILT_IN_EXP2F
8266 || fcode == BUILT_IN_EXP2L))
29f4cd78 8267 || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode)))))
389dd41b 8268 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
8918c507 8269
ca273d4a 8270 /* Optimize logN(func()) for various exponential functions. We
a0c938f0 8271 want to determine the value "x" and the power "exponent" in
8272 order to transform logN(x**exponent) into exponent*logN(x). */
8918c507 8273 if (flag_unsafe_math_optimizations)
a0c938f0 8274 {
8918c507 8275 tree exponent = 0, x = 0;
0862b7e9 8276
8918c507 8277 switch (fcode)
8278 {
4f35b1fc 8279 CASE_FLT_FN (BUILT_IN_EXP):
8918c507 8280 /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
48e1416a 8281 x = build_real (type, real_value_truncate (TYPE_MODE (type),
7910b2fb 8282 dconst_e ()));
c2f47e15 8283 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8284 break;
4f35b1fc 8285 CASE_FLT_FN (BUILT_IN_EXP2):
8918c507 8286 /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */
8287 x = build_real (type, dconst2);
c2f47e15 8288 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8289 break;
4f35b1fc 8290 CASE_FLT_FN (BUILT_IN_EXP10):
8291 CASE_FLT_FN (BUILT_IN_POW10):
8918c507 8292 /* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */
3fa759a9 8293 {
8294 REAL_VALUE_TYPE dconst10;
8295 real_from_integer (&dconst10, VOIDmode, 10, 0, 0);
8296 x = build_real (type, dconst10);
8297 }
c2f47e15 8298 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8299 break;
4f35b1fc 8300 CASE_FLT_FN (BUILT_IN_SQRT):
8918c507 8301 /* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */
c2f47e15 8302 x = CALL_EXPR_ARG (arg, 0);
8918c507 8303 exponent = build_real (type, dconsthalf);
8304 break;
4f35b1fc 8305 CASE_FLT_FN (BUILT_IN_CBRT):
8918c507 8306 /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */
c2f47e15 8307 x = CALL_EXPR_ARG (arg, 0);
8918c507 8308 exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
7910b2fb 8309 dconst_third ()));
8918c507 8310 break;
4f35b1fc 8311 CASE_FLT_FN (BUILT_IN_POW):
8918c507 8312 /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x). */
c2f47e15 8313 x = CALL_EXPR_ARG (arg, 0);
8314 exponent = CALL_EXPR_ARG (arg, 1);
8918c507 8315 break;
8316 default:
8317 break;
8318 }
8319
8320 /* Now perform the optimization. */
8321 if (x && exponent)
8322 {
389dd41b 8323 tree logfn = build_call_expr_loc (loc, fndecl, 1, x);
8324 return fold_build2_loc (loc, MULT_EXPR, type, exponent, logfn);
8918c507 8325 }
8326 }
8327 }
8328
c2f47e15 8329 return NULL_TREE;
8918c507 8330}
0862b7e9 8331
f0c477f2 8332/* Fold a builtin function call to hypot, hypotf, or hypotl. Return
8333 NULL_TREE if no simplification can be made. */
8334
8335static tree
389dd41b 8336fold_builtin_hypot (location_t loc, tree fndecl,
8337 tree arg0, tree arg1, tree type)
f0c477f2 8338{
e6ab33d8 8339 tree res, narg0, narg1;
f0c477f2 8340
c2f47e15 8341 if (!validate_arg (arg0, REAL_TYPE)
8342 || !validate_arg (arg1, REAL_TYPE))
f0c477f2 8343 return NULL_TREE;
8344
8345 /* Calculate the result when the argument is a constant. */
8346 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot)))
8347 return res;
48e1416a 8348
6c95f21c 8349 /* If either argument to hypot has a negate or abs, strip that off.
8350 E.g. hypot(-x,fabs(y)) -> hypot(x,y). */
e6ab33d8 8351 narg0 = fold_strip_sign_ops (arg0);
8352 narg1 = fold_strip_sign_ops (arg1);
8353 if (narg0 || narg1)
8354 {
48e1416a 8355 return build_call_expr_loc (loc, fndecl, 2, narg0 ? narg0 : arg0,
c2f47e15 8356 narg1 ? narg1 : arg1);
6c95f21c 8357 }
48e1416a 8358
f0c477f2 8359 /* If either argument is zero, hypot is fabs of the other. */
8360 if (real_zerop (arg0))
389dd41b 8361 return fold_build1_loc (loc, ABS_EXPR, type, arg1);
f0c477f2 8362 else if (real_zerop (arg1))
389dd41b 8363 return fold_build1_loc (loc, ABS_EXPR, type, arg0);
48e1416a 8364
6c95f21c 8365 /* hypot(x,x) -> fabs(x)*sqrt(2). */
8366 if (flag_unsafe_math_optimizations
8367 && operand_equal_p (arg0, arg1, OEP_PURE_SAME))
f0c477f2 8368 {
2e7ca27b 8369 const REAL_VALUE_TYPE sqrt2_trunc
7910b2fb 8370 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
389dd41b 8371 return fold_build2_loc (loc, MULT_EXPR, type,
8372 fold_build1_loc (loc, ABS_EXPR, type, arg0),
2e7ca27b 8373 build_real (type, sqrt2_trunc));
f0c477f2 8374 }
8375
f0c477f2 8376 return NULL_TREE;
8377}
8378
8379
e6e27594 8380/* Fold a builtin function call to pow, powf, or powl. Return
8381 NULL_TREE if no simplification can be made. */
8382static tree
389dd41b 8383fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
e6e27594 8384{
f0c477f2 8385 tree res;
e6e27594 8386
c2f47e15 8387 if (!validate_arg (arg0, REAL_TYPE)
8388 || !validate_arg (arg1, REAL_TYPE))
e6e27594 8389 return NULL_TREE;
8390
f0c477f2 8391 /* Calculate the result when the argument is a constant. */
8392 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_pow)))
8393 return res;
8394
e6e27594 8395 /* Optimize pow(1.0,y) = 1.0. */
8396 if (real_onep (arg0))
389dd41b 8397 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
e6e27594 8398
8399 if (TREE_CODE (arg1) == REAL_CST
f96bd2bf 8400 && !TREE_OVERFLOW (arg1))
e6e27594 8401 {
198d9bbe 8402 REAL_VALUE_TYPE cint;
e6e27594 8403 REAL_VALUE_TYPE c;
198d9bbe 8404 HOST_WIDE_INT n;
8405
e6e27594 8406 c = TREE_REAL_CST (arg1);
8407
8408 /* Optimize pow(x,0.0) = 1.0. */
8409 if (REAL_VALUES_EQUAL (c, dconst0))
389dd41b 8410 return omit_one_operand_loc (loc, type, build_real (type, dconst1),
e6e27594 8411 arg0);
8412
8413 /* Optimize pow(x,1.0) = x. */
8414 if (REAL_VALUES_EQUAL (c, dconst1))
8415 return arg0;
8416
8417 /* Optimize pow(x,-1.0) = 1.0/x. */
8418 if (REAL_VALUES_EQUAL (c, dconstm1))
389dd41b 8419 return fold_build2_loc (loc, RDIV_EXPR, type,
49d00087 8420 build_real (type, dconst1), arg0);
e6e27594 8421
8422 /* Optimize pow(x,0.5) = sqrt(x). */
8423 if (flag_unsafe_math_optimizations
8424 && REAL_VALUES_EQUAL (c, dconsthalf))
8425 {
8426 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
8427
8428 if (sqrtfn != NULL_TREE)
389dd41b 8429 return build_call_expr_loc (loc, sqrtfn, 1, arg0);
e6e27594 8430 }
8431
feb5b3eb 8432 /* Optimize pow(x,1.0/3.0) = cbrt(x). */
8433 if (flag_unsafe_math_optimizations)
8434 {
8435 const REAL_VALUE_TYPE dconstroot
7910b2fb 8436 = real_value_truncate (TYPE_MODE (type), dconst_third ());
feb5b3eb 8437
8438 if (REAL_VALUES_EQUAL (c, dconstroot))
8439 {
8440 tree cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT);
8441 if (cbrtfn != NULL_TREE)
389dd41b 8442 return build_call_expr_loc (loc, cbrtfn, 1, arg0);
feb5b3eb 8443 }
8444 }
8445
198d9bbe 8446 /* Check for an integer exponent. */
8447 n = real_to_integer (&c);
8448 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
8449 if (real_identical (&c, &cint))
e6e27594 8450 {
a2b30b48 8451 /* Attempt to evaluate pow at compile-time, unless this should
8452 raise an exception. */
198d9bbe 8453 if (TREE_CODE (arg0) == REAL_CST
a2b30b48 8454 && !TREE_OVERFLOW (arg0)
8455 && (n > 0
8456 || (!flag_trapping_math && !flag_errno_math)
8457 || !REAL_VALUES_EQUAL (TREE_REAL_CST (arg0), dconst0)))
e6e27594 8458 {
8459 REAL_VALUE_TYPE x;
8460 bool inexact;
8461
8462 x = TREE_REAL_CST (arg0);
8463 inexact = real_powi (&x, TYPE_MODE (type), &x, n);
8464 if (flag_unsafe_math_optimizations || !inexact)
8465 return build_real (type, x);
8466 }
198d9bbe 8467
8468 /* Strip sign ops from even integer powers. */
8469 if ((n & 1) == 0 && flag_unsafe_math_optimizations)
8470 {
8471 tree narg0 = fold_strip_sign_ops (arg0);
8472 if (narg0)
389dd41b 8473 return build_call_expr_loc (loc, fndecl, 2, narg0, arg1);
198d9bbe 8474 }
e6e27594 8475 }
8476 }
8477
cdfeb715 8478 if (flag_unsafe_math_optimizations)
e6e27594 8479 {
cdfeb715 8480 const enum built_in_function fcode = builtin_mathfn_code (arg0);
e6e27594 8481
cdfeb715 8482 /* Optimize pow(expN(x),y) = expN(x*y). */
8483 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 8484 {
c2f47e15 8485 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
8486 tree arg = CALL_EXPR_ARG (arg0, 0);
389dd41b 8487 arg = fold_build2_loc (loc, MULT_EXPR, type, arg, arg1);
8488 return build_call_expr_loc (loc, expfn, 1, arg);
cdfeb715 8489 }
e6e27594 8490
cdfeb715 8491 /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
8492 if (BUILTIN_SQRT_P (fcode))
a0c938f0 8493 {
c2f47e15 8494 tree narg0 = CALL_EXPR_ARG (arg0, 0);
389dd41b 8495 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 8496 build_real (type, dconsthalf));
389dd41b 8497 return build_call_expr_loc (loc, fndecl, 2, narg0, narg1);
cdfeb715 8498 }
8499
8500 /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */
8501 if (BUILTIN_CBRT_P (fcode))
a0c938f0 8502 {
c2f47e15 8503 tree arg = CALL_EXPR_ARG (arg0, 0);
cdfeb715 8504 if (tree_expr_nonnegative_p (arg))
8505 {
8506 const REAL_VALUE_TYPE dconstroot
7910b2fb 8507 = real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 8508 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 8509 build_real (type, dconstroot));
389dd41b 8510 return build_call_expr_loc (loc, fndecl, 2, arg, narg1);
cdfeb715 8511 }
8512 }
a0c938f0 8513
49e436b5 8514 /* Optimize pow(pow(x,y),z) = pow(x,y*z) iff x is nonnegative. */
c2f47e15 8515 if (fcode == BUILT_IN_POW
8516 || fcode == BUILT_IN_POWF
8517 || fcode == BUILT_IN_POWL)
a0c938f0 8518 {
c2f47e15 8519 tree arg00 = CALL_EXPR_ARG (arg0, 0);
49e436b5 8520 if (tree_expr_nonnegative_p (arg00))
8521 {
8522 tree arg01 = CALL_EXPR_ARG (arg0, 1);
8523 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg01, arg1);
8524 return build_call_expr_loc (loc, fndecl, 2, arg00, narg1);
8525 }
cdfeb715 8526 }
e6e27594 8527 }
cdfeb715 8528
e6e27594 8529 return NULL_TREE;
8530}
8531
c2f47e15 8532/* Fold a builtin function call to powi, powif, or powil with argument ARG.
8533 Return NULL_TREE if no simplification can be made. */
b4d0c20c 8534static tree
389dd41b 8535fold_builtin_powi (location_t loc, tree fndecl ATTRIBUTE_UNUSED,
c2f47e15 8536 tree arg0, tree arg1, tree type)
b4d0c20c 8537{
c2f47e15 8538 if (!validate_arg (arg0, REAL_TYPE)
8539 || !validate_arg (arg1, INTEGER_TYPE))
b4d0c20c 8540 return NULL_TREE;
8541
8542 /* Optimize pow(1.0,y) = 1.0. */
8543 if (real_onep (arg0))
389dd41b 8544 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
b4d0c20c 8545
8546 if (host_integerp (arg1, 0))
8547 {
8548 HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
8549
8550 /* Evaluate powi at compile-time. */
8551 if (TREE_CODE (arg0) == REAL_CST
f96bd2bf 8552 && !TREE_OVERFLOW (arg0))
b4d0c20c 8553 {
8554 REAL_VALUE_TYPE x;
8555 x = TREE_REAL_CST (arg0);
8556 real_powi (&x, TYPE_MODE (type), &x, c);
8557 return build_real (type, x);
8558 }
8559
8560 /* Optimize pow(x,0) = 1.0. */
8561 if (c == 0)
389dd41b 8562 return omit_one_operand_loc (loc, type, build_real (type, dconst1),
b4d0c20c 8563 arg0);
8564
8565 /* Optimize pow(x,1) = x. */
8566 if (c == 1)
8567 return arg0;
8568
8569 /* Optimize pow(x,-1) = 1.0/x. */
8570 if (c == -1)
389dd41b 8571 return fold_build2_loc (loc, RDIV_EXPR, type,
49d00087 8572 build_real (type, dconst1), arg0);
b4d0c20c 8573 }
8574
8575 return NULL_TREE;
8576}
8577
8918c507 8578/* A subroutine of fold_builtin to fold the various exponent
c2f47e15 8579 functions. Return NULL_TREE if no simplification can be made.
debf9994 8580 FUNC is the corresponding MPFR exponent function. */
8918c507 8581
8582static tree
389dd41b 8583fold_builtin_exponent (location_t loc, tree fndecl, tree arg,
debf9994 8584 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8585{
c2f47e15 8586 if (validate_arg (arg, REAL_TYPE))
8918c507 8587 {
8918c507 8588 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8589 tree res;
48e1416a 8590
debf9994 8591 /* Calculate the result when the argument is a constant. */
728bac60 8592 if ((res = do_mpfr_arg1 (arg, type, func, NULL, NULL, 0)))
debf9994 8593 return res;
8918c507 8594
8595 /* Optimize expN(logN(x)) = x. */
8596 if (flag_unsafe_math_optimizations)
a0c938f0 8597 {
8918c507 8598 const enum built_in_function fcode = builtin_mathfn_code (arg);
8599
debf9994 8600 if ((func == mpfr_exp
8918c507 8601 && (fcode == BUILT_IN_LOG
8602 || fcode == BUILT_IN_LOGF
8603 || fcode == BUILT_IN_LOGL))
debf9994 8604 || (func == mpfr_exp2
8918c507 8605 && (fcode == BUILT_IN_LOG2
8606 || fcode == BUILT_IN_LOG2F
8607 || fcode == BUILT_IN_LOG2L))
debf9994 8608 || (func == mpfr_exp10
8918c507 8609 && (fcode == BUILT_IN_LOG10
8610 || fcode == BUILT_IN_LOG10F
8611 || fcode == BUILT_IN_LOG10L)))
389dd41b 8612 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
8918c507 8613 }
8614 }
8615
c2f47e15 8616 return NULL_TREE;
8918c507 8617}
8618
e973ffcc 8619/* Return true if VAR is a VAR_DECL or a component thereof. */
8620
8621static bool
8622var_decl_component_p (tree var)
8623{
8624 tree inner = var;
8625 while (handled_component_p (inner))
8626 inner = TREE_OPERAND (inner, 0);
8627 return SSA_VAR_P (inner);
8628}
8629
4f46f2b9 8630/* Fold function call to builtin memset. Return
9c8a1629 8631 NULL_TREE if no simplification can be made. */
8632
8633static tree
389dd41b 8634fold_builtin_memset (location_t loc, tree dest, tree c, tree len,
8635 tree type, bool ignore)
9c8a1629 8636{
45bb3afb 8637 tree var, ret, etype;
4f46f2b9 8638 unsigned HOST_WIDE_INT length, cval;
9c8a1629 8639
c2f47e15 8640 if (! validate_arg (dest, POINTER_TYPE)
8641 || ! validate_arg (c, INTEGER_TYPE)
8642 || ! validate_arg (len, INTEGER_TYPE))
8643 return NULL_TREE;
9c8a1629 8644
4f46f2b9 8645 if (! host_integerp (len, 1))
c2f47e15 8646 return NULL_TREE;
4f46f2b9 8647
9c8a1629 8648 /* If the LEN parameter is zero, return DEST. */
8649 if (integer_zerop (len))
389dd41b 8650 return omit_one_operand_loc (loc, type, dest, c);
9c8a1629 8651
d5d2f74a 8652 if (TREE_CODE (c) != INTEGER_CST || TREE_SIDE_EFFECTS (dest))
c2f47e15 8653 return NULL_TREE;
9c8a1629 8654
4f46f2b9 8655 var = dest;
8656 STRIP_NOPS (var);
8657 if (TREE_CODE (var) != ADDR_EXPR)
c2f47e15 8658 return NULL_TREE;
4f46f2b9 8659
8660 var = TREE_OPERAND (var, 0);
8661 if (TREE_THIS_VOLATILE (var))
c2f47e15 8662 return NULL_TREE;
4f46f2b9 8663
45bb3afb 8664 etype = TREE_TYPE (var);
8665 if (TREE_CODE (etype) == ARRAY_TYPE)
8666 etype = TREE_TYPE (etype);
8667
8668 if (!INTEGRAL_TYPE_P (etype)
8669 && !POINTER_TYPE_P (etype))
c2f47e15 8670 return NULL_TREE;
4f46f2b9 8671
e973ffcc 8672 if (! var_decl_component_p (var))
c2f47e15 8673 return NULL_TREE;
e973ffcc 8674
4f46f2b9 8675 length = tree_low_cst (len, 1);
45bb3afb 8676 if (GET_MODE_SIZE (TYPE_MODE (etype)) != length
957d0361 8677 || get_pointer_alignment (dest) / BITS_PER_UNIT < length)
c2f47e15 8678 return NULL_TREE;
4f46f2b9 8679
8680 if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT)
c2f47e15 8681 return NULL_TREE;
4f46f2b9 8682
8683 if (integer_zerop (c))
8684 cval = 0;
8685 else
8686 {
8687 if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64)
c2f47e15 8688 return NULL_TREE;
4f46f2b9 8689
d5d2f74a 8690 cval = TREE_INT_CST_LOW (c);
4f46f2b9 8691 cval &= 0xff;
8692 cval |= cval << 8;
8693 cval |= cval << 16;
8694 cval |= (cval << 31) << 1;
8695 }
8696
45bb3afb 8697 ret = build_int_cst_type (etype, cval);
389dd41b 8698 var = build_fold_indirect_ref_loc (loc,
8699 fold_convert_loc (loc,
8700 build_pointer_type (etype),
8701 dest));
45bb3afb 8702 ret = build2 (MODIFY_EXPR, etype, var, ret);
4f46f2b9 8703 if (ignore)
8704 return ret;
8705
389dd41b 8706 return omit_one_operand_loc (loc, type, dest, ret);
9c8a1629 8707}
8708
4f46f2b9 8709/* Fold function call to builtin memset. Return
9c8a1629 8710 NULL_TREE if no simplification can be made. */
8711
8712static tree
389dd41b 8713fold_builtin_bzero (location_t loc, tree dest, tree size, bool ignore)
9c8a1629 8714{
c2f47e15 8715 if (! validate_arg (dest, POINTER_TYPE)
8716 || ! validate_arg (size, INTEGER_TYPE))
8717 return NULL_TREE;
9c8a1629 8718
4f46f2b9 8719 if (!ignore)
c2f47e15 8720 return NULL_TREE;
a0c938f0 8721
4f46f2b9 8722 /* New argument list transforming bzero(ptr x, int y) to
8723 memset(ptr x, int 0, size_t y). This is done this way
8724 so that if it isn't expanded inline, we fallback to
8725 calling bzero instead of memset. */
8726
389dd41b 8727 return fold_builtin_memset (loc, dest, integer_zero_node,
a0553bff 8728 fold_convert_loc (loc, size_type_node, size),
c2f47e15 8729 void_type_node, ignore);
9c8a1629 8730}
8731
4f46f2b9 8732/* Fold function call to builtin mem{{,p}cpy,move}. Return
8733 NULL_TREE if no simplification can be made.
8734 If ENDP is 0, return DEST (like memcpy).
8735 If ENDP is 1, return DEST+LEN (like mempcpy).
8736 If ENDP is 2, return DEST+LEN-1 (like stpcpy).
8737 If ENDP is 3, return DEST, additionally *SRC and *DEST may overlap
8738 (memmove). */
9c8a1629 8739
8740static tree
389dd41b 8741fold_builtin_memory_op (location_t loc, tree dest, tree src,
8742 tree len, tree type, bool ignore, int endp)
9c8a1629 8743{
c2f47e15 8744 tree destvar, srcvar, expr;
9c8a1629 8745
c2f47e15 8746 if (! validate_arg (dest, POINTER_TYPE)
8747 || ! validate_arg (src, POINTER_TYPE)
8748 || ! validate_arg (len, INTEGER_TYPE))
8749 return NULL_TREE;
9c8a1629 8750
8751 /* If the LEN parameter is zero, return DEST. */
8752 if (integer_zerop (len))
389dd41b 8753 return omit_one_operand_loc (loc, type, dest, src);
9c8a1629 8754
4f46f2b9 8755 /* If SRC and DEST are the same (and not volatile), return
8756 DEST{,+LEN,+LEN-1}. */
9c8a1629 8757 if (operand_equal_p (src, dest, 0))
4f46f2b9 8758 expr = len;
8759 else
8760 {
5a84fdd6 8761 tree srctype, desttype;
153c3b50 8762 unsigned int src_align, dest_align;
182cf5a9 8763 tree off0;
5383fb56 8764
3b1757a2 8765 if (endp == 3)
8766 {
957d0361 8767 src_align = get_pointer_alignment (src);
8768 dest_align = get_pointer_alignment (dest);
5a84fdd6 8769
48e1416a 8770 /* Both DEST and SRC must be pointer types.
3b1757a2 8771 ??? This is what old code did. Is the testing for pointer types
8772 really mandatory?
8773
8774 If either SRC is readonly or length is 1, we can use memcpy. */
3f95c690 8775 if (!dest_align || !src_align)
8776 return NULL_TREE;
8777 if (readonly_data_expr (src)
8778 || (host_integerp (len, 1)
8779 && (MIN (src_align, dest_align) / BITS_PER_UNIT
12c655b1 8780 >= (unsigned HOST_WIDE_INT) tree_low_cst (len, 1))))
3b1757a2 8781 {
b9a16870 8782 tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
3b1757a2 8783 if (!fn)
c2f47e15 8784 return NULL_TREE;
389dd41b 8785 return build_call_expr_loc (loc, fn, 3, dest, src, len);
3b1757a2 8786 }
3f95c690 8787
8788 /* If *src and *dest can't overlap, optimize into memcpy as well. */
182cf5a9 8789 if (TREE_CODE (src) == ADDR_EXPR
8790 && TREE_CODE (dest) == ADDR_EXPR)
3f95c690 8791 {
f85fb819 8792 tree src_base, dest_base, fn;
8793 HOST_WIDE_INT src_offset = 0, dest_offset = 0;
8794 HOST_WIDE_INT size = -1;
8795 HOST_WIDE_INT maxsize = -1;
8796
182cf5a9 8797 srcvar = TREE_OPERAND (src, 0);
8798 src_base = get_ref_base_and_extent (srcvar, &src_offset,
8799 &size, &maxsize);
8800 destvar = TREE_OPERAND (dest, 0);
8801 dest_base = get_ref_base_and_extent (destvar, &dest_offset,
8802 &size, &maxsize);
f85fb819 8803 if (host_integerp (len, 1))
182cf5a9 8804 maxsize = tree_low_cst (len, 1);
f85fb819 8805 else
8806 maxsize = -1;
182cf5a9 8807 src_offset /= BITS_PER_UNIT;
8808 dest_offset /= BITS_PER_UNIT;
f85fb819 8809 if (SSA_VAR_P (src_base)
8810 && SSA_VAR_P (dest_base))
8811 {
8812 if (operand_equal_p (src_base, dest_base, 0)
8813 && ranges_overlap_p (src_offset, maxsize,
8814 dest_offset, maxsize))
8815 return NULL_TREE;
8816 }
182cf5a9 8817 else if (TREE_CODE (src_base) == MEM_REF
8818 && TREE_CODE (dest_base) == MEM_REF)
f85fb819 8819 {
182cf5a9 8820 double_int off;
f85fb819 8821 if (! operand_equal_p (TREE_OPERAND (src_base, 0),
182cf5a9 8822 TREE_OPERAND (dest_base, 0), 0))
8823 return NULL_TREE;
cf8f0e63 8824 off = mem_ref_offset (src_base) +
8825 double_int::from_shwi (src_offset);
8826 if (!off.fits_shwi ())
182cf5a9 8827 return NULL_TREE;
8828 src_offset = off.low;
cf8f0e63 8829 off = mem_ref_offset (dest_base) +
8830 double_int::from_shwi (dest_offset);
8831 if (!off.fits_shwi ())
182cf5a9 8832 return NULL_TREE;
8833 dest_offset = off.low;
8834 if (ranges_overlap_p (src_offset, maxsize,
8835 dest_offset, maxsize))
f85fb819 8836 return NULL_TREE;
8837 }
8838 else
8839 return NULL_TREE;
8840
b9a16870 8841 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
3f95c690 8842 if (!fn)
8843 return NULL_TREE;
389dd41b 8844 return build_call_expr_loc (loc, fn, 3, dest, src, len);
3f95c690 8845 }
c4222b63 8846
8847 /* If the destination and source do not alias optimize into
8848 memcpy as well. */
8849 if ((is_gimple_min_invariant (dest)
8850 || TREE_CODE (dest) == SSA_NAME)
8851 && (is_gimple_min_invariant (src)
8852 || TREE_CODE (src) == SSA_NAME))
8853 {
8854 ao_ref destr, srcr;
8855 ao_ref_init_from_ptr_and_size (&destr, dest, len);
8856 ao_ref_init_from_ptr_and_size (&srcr, src, len);
8857 if (!refs_may_alias_p_1 (&destr, &srcr, false))
8858 {
8859 tree fn;
b9a16870 8860 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
c4222b63 8861 if (!fn)
8862 return NULL_TREE;
8863 return build_call_expr_loc (loc, fn, 3, dest, src, len);
8864 }
8865 }
8866
c2f47e15 8867 return NULL_TREE;
3b1757a2 8868 }
4f46f2b9 8869
5a84fdd6 8870 if (!host_integerp (len, 0))
c2f47e15 8871 return NULL_TREE;
5a84fdd6 8872 /* FIXME:
8873 This logic lose for arguments like (type *)malloc (sizeof (type)),
8874 since we strip the casts of up to VOID return value from malloc.
8875 Perhaps we ought to inherit type from non-VOID argument here? */
8876 STRIP_NOPS (src);
8877 STRIP_NOPS (dest);
e07c7898 8878 if (!POINTER_TYPE_P (TREE_TYPE (src))
8879 || !POINTER_TYPE_P (TREE_TYPE (dest)))
8880 return NULL_TREE;
45bb3afb 8881 /* As we fold (void *)(p + CST) to (void *)p + CST undo this here. */
8882 if (TREE_CODE (src) == POINTER_PLUS_EXPR)
8883 {
8884 tree tem = TREE_OPERAND (src, 0);
8885 STRIP_NOPS (tem);
8886 if (tem != TREE_OPERAND (src, 0))
8887 src = build1 (NOP_EXPR, TREE_TYPE (tem), src);
8888 }
8889 if (TREE_CODE (dest) == POINTER_PLUS_EXPR)
8890 {
8891 tree tem = TREE_OPERAND (dest, 0);
8892 STRIP_NOPS (tem);
8893 if (tem != TREE_OPERAND (dest, 0))
8894 dest = build1 (NOP_EXPR, TREE_TYPE (tem), dest);
8895 }
5a84fdd6 8896 srctype = TREE_TYPE (TREE_TYPE (src));
e07c7898 8897 if (TREE_CODE (srctype) == ARRAY_TYPE
97d4c6a6 8898 && !tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
45bb3afb 8899 {
8900 srctype = TREE_TYPE (srctype);
8901 STRIP_NOPS (src);
8902 src = build1 (NOP_EXPR, build_pointer_type (srctype), src);
8903 }
5a84fdd6 8904 desttype = TREE_TYPE (TREE_TYPE (dest));
e07c7898 8905 if (TREE_CODE (desttype) == ARRAY_TYPE
97d4c6a6 8906 && !tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
45bb3afb 8907 {
8908 desttype = TREE_TYPE (desttype);
8909 STRIP_NOPS (dest);
8910 dest = build1 (NOP_EXPR, build_pointer_type (desttype), dest);
8911 }
e07c7898 8912 if (TREE_ADDRESSABLE (srctype)
8913 || TREE_ADDRESSABLE (desttype))
c2f47e15 8914 return NULL_TREE;
4f46f2b9 8915
957d0361 8916 src_align = get_pointer_alignment (src);
8917 dest_align = get_pointer_alignment (dest);
153c3b50 8918 if (dest_align < TYPE_ALIGN (desttype)
8919 || src_align < TYPE_ALIGN (srctype))
c2f47e15 8920 return NULL_TREE;
e973ffcc 8921
5a84fdd6 8922 if (!ignore)
8923 dest = builtin_save_expr (dest);
4f46f2b9 8924
182cf5a9 8925 /* Build accesses at offset zero with a ref-all character type. */
8926 off0 = build_int_cst (build_pointer_type_for_mode (char_type_node,
8927 ptr_mode, true), 0);
4f46f2b9 8928
182cf5a9 8929 destvar = dest;
8930 STRIP_NOPS (destvar);
8931 if (TREE_CODE (destvar) == ADDR_EXPR
8932 && var_decl_component_p (TREE_OPERAND (destvar, 0))
8933 && tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
8934 destvar = fold_build2 (MEM_REF, desttype, destvar, off0);
8935 else
8936 destvar = NULL_TREE;
8937
8938 srcvar = src;
8939 STRIP_NOPS (srcvar);
8940 if (TREE_CODE (srcvar) == ADDR_EXPR
8941 && var_decl_component_p (TREE_OPERAND (srcvar, 0))
5b99ff01 8942 && tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
8943 {
8944 if (!destvar
8945 || src_align >= TYPE_ALIGN (desttype))
8946 srcvar = fold_build2 (MEM_REF, destvar ? desttype : srctype,
8947 srcvar, off0);
8948 else if (!STRICT_ALIGNMENT)
8949 {
8950 srctype = build_aligned_type (TYPE_MAIN_VARIANT (desttype),
8951 src_align);
8952 srcvar = fold_build2 (MEM_REF, srctype, srcvar, off0);
8953 }
8954 else
8955 srcvar = NULL_TREE;
8956 }
182cf5a9 8957 else
8958 srcvar = NULL_TREE;
5383fb56 8959
8960 if (srcvar == NULL_TREE && destvar == NULL_TREE)
c2f47e15 8961 return NULL_TREE;
4f46f2b9 8962
5383fb56 8963 if (srcvar == NULL_TREE)
8964 {
182cf5a9 8965 STRIP_NOPS (src);
5b99ff01 8966 if (src_align >= TYPE_ALIGN (desttype))
8967 srcvar = fold_build2 (MEM_REF, desttype, src, off0);
8968 else
8969 {
8970 if (STRICT_ALIGNMENT)
8971 return NULL_TREE;
8972 srctype = build_aligned_type (TYPE_MAIN_VARIANT (desttype),
8973 src_align);
8974 srcvar = fold_build2 (MEM_REF, srctype, src, off0);
8975 }
5383fb56 8976 }
8977 else if (destvar == NULL_TREE)
8978 {
182cf5a9 8979 STRIP_NOPS (dest);
5b99ff01 8980 if (dest_align >= TYPE_ALIGN (srctype))
8981 destvar = fold_build2 (MEM_REF, srctype, dest, off0);
8982 else
8983 {
8984 if (STRICT_ALIGNMENT)
8985 return NULL_TREE;
8986 desttype = build_aligned_type (TYPE_MAIN_VARIANT (srctype),
8987 dest_align);
8988 destvar = fold_build2 (MEM_REF, desttype, dest, off0);
8989 }
5383fb56 8990 }
8991
182cf5a9 8992 expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, srcvar);
4f46f2b9 8993 }
8994
8995 if (ignore)
8996 return expr;
8997
8998 if (endp == 0 || endp == 3)
389dd41b 8999 return omit_one_operand_loc (loc, type, dest, expr);
4f46f2b9 9000
9001 if (expr == len)
c2f47e15 9002 expr = NULL_TREE;
4f46f2b9 9003
9004 if (endp == 2)
389dd41b 9005 len = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (len), len,
4f46f2b9 9006 ssize_int (1));
9007
2cc66f2a 9008 dest = fold_build_pointer_plus_loc (loc, dest, len);
389dd41b 9009 dest = fold_convert_loc (loc, type, dest);
4f46f2b9 9010 if (expr)
389dd41b 9011 dest = omit_one_operand_loc (loc, type, dest, expr);
4f46f2b9 9012 return dest;
9013}
9014
c2f47e15 9015/* Fold function call to builtin strcpy with arguments DEST and SRC.
9016 If LEN is not NULL, it represents the length of the string to be
9017 copied. Return NULL_TREE if no simplification can be made. */
9c8a1629 9018
f0613857 9019tree
389dd41b 9020fold_builtin_strcpy (location_t loc, tree fndecl, tree dest, tree src, tree len)
9c8a1629 9021{
c2f47e15 9022 tree fn;
9c8a1629 9023
c2f47e15 9024 if (!validate_arg (dest, POINTER_TYPE)
9025 || !validate_arg (src, POINTER_TYPE))
9026 return NULL_TREE;
9c8a1629 9027
9028 /* If SRC and DEST are the same (and not volatile), return DEST. */
9029 if (operand_equal_p (src, dest, 0))
389dd41b 9030 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
9c8a1629 9031
0bfd8d5c 9032 if (optimize_function_for_size_p (cfun))
c2f47e15 9033 return NULL_TREE;
f0613857 9034
b9a16870 9035 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
f0613857 9036 if (!fn)
c2f47e15 9037 return NULL_TREE;
f0613857 9038
9039 if (!len)
9040 {
9041 len = c_strlen (src, 1);
9042 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 9043 return NULL_TREE;
f0613857 9044 }
9045
bd6dcc04 9046 len = fold_convert_loc (loc, size_type_node, len);
9047 len = size_binop_loc (loc, PLUS_EXPR, len, build_int_cst (size_type_node, 1));
389dd41b 9048 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
9049 build_call_expr_loc (loc, fn, 3, dest, src, len));
9c8a1629 9050}
9051
a65c4d64 9052/* Fold function call to builtin stpcpy with arguments DEST and SRC.
9053 Return NULL_TREE if no simplification can be made. */
9054
9055static tree
9056fold_builtin_stpcpy (location_t loc, tree fndecl, tree dest, tree src)
9057{
9058 tree fn, len, lenp1, call, type;
9059
9060 if (!validate_arg (dest, POINTER_TYPE)
9061 || !validate_arg (src, POINTER_TYPE))
9062 return NULL_TREE;
9063
9064 len = c_strlen (src, 1);
9065 if (!len
9066 || TREE_CODE (len) != INTEGER_CST)
9067 return NULL_TREE;
9068
9069 if (optimize_function_for_size_p (cfun)
9070 /* If length is zero it's small enough. */
9071 && !integer_zerop (len))
9072 return NULL_TREE;
9073
b9a16870 9074 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
a65c4d64 9075 if (!fn)
9076 return NULL_TREE;
9077
bd6dcc04 9078 lenp1 = size_binop_loc (loc, PLUS_EXPR,
9079 fold_convert_loc (loc, size_type_node, len),
9080 build_int_cst (size_type_node, 1));
a65c4d64 9081 /* We use dest twice in building our expression. Save it from
9082 multiple expansions. */
9083 dest = builtin_save_expr (dest);
9084 call = build_call_expr_loc (loc, fn, 3, dest, src, lenp1);
9085
9086 type = TREE_TYPE (TREE_TYPE (fndecl));
2cc66f2a 9087 dest = fold_build_pointer_plus_loc (loc, dest, len);
a65c4d64 9088 dest = fold_convert_loc (loc, type, dest);
9089 dest = omit_one_operand_loc (loc, type, dest, call);
9090 return dest;
9091}
9092
c2f47e15 9093/* Fold function call to builtin strncpy with arguments DEST, SRC, and LEN.
9094 If SLEN is not NULL, it represents the length of the source string.
9095 Return NULL_TREE if no simplification can be made. */
9c8a1629 9096
f0613857 9097tree
389dd41b 9098fold_builtin_strncpy (location_t loc, tree fndecl, tree dest,
9099 tree src, tree len, tree slen)
9c8a1629 9100{
c2f47e15 9101 tree fn;
9c8a1629 9102
c2f47e15 9103 if (!validate_arg (dest, POINTER_TYPE)
9104 || !validate_arg (src, POINTER_TYPE)
9105 || !validate_arg (len, INTEGER_TYPE))
9106 return NULL_TREE;
9c8a1629 9107
9108 /* If the LEN parameter is zero, return DEST. */
9109 if (integer_zerop (len))
389dd41b 9110 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
9c8a1629 9111
19226313 9112 /* We can't compare slen with len as constants below if len is not a
9113 constant. */
9114 if (len == 0 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 9115 return NULL_TREE;
19226313 9116
f0613857 9117 if (!slen)
9118 slen = c_strlen (src, 1);
9119
9120 /* Now, we must be passed a constant src ptr parameter. */
9121 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
c2f47e15 9122 return NULL_TREE;
f0613857 9123
389dd41b 9124 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
f0613857 9125
9126 /* We do not support simplification of this case, though we do
9127 support it when expanding trees into RTL. */
9128 /* FIXME: generate a call to __builtin_memset. */
9129 if (tree_int_cst_lt (slen, len))
c2f47e15 9130 return NULL_TREE;
f0613857 9131
9132 /* OK transform into builtin memcpy. */
b9a16870 9133 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
f0613857 9134 if (!fn)
c2f47e15 9135 return NULL_TREE;
bd6dcc04 9136
9137 len = fold_convert_loc (loc, size_type_node, len);
389dd41b 9138 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
9139 build_call_expr_loc (loc, fn, 3, dest, src, len));
9c8a1629 9140}
9141
7959b13b 9142/* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the
9143 arguments to the call, and TYPE is its return type.
9144 Return NULL_TREE if no simplification can be made. */
9145
9146static tree
389dd41b 9147fold_builtin_memchr (location_t loc, tree arg1, tree arg2, tree len, tree type)
7959b13b 9148{
9149 if (!validate_arg (arg1, POINTER_TYPE)
9150 || !validate_arg (arg2, INTEGER_TYPE)
9151 || !validate_arg (len, INTEGER_TYPE))
9152 return NULL_TREE;
9153 else
9154 {
9155 const char *p1;
9156
9157 if (TREE_CODE (arg2) != INTEGER_CST
9158 || !host_integerp (len, 1))
9159 return NULL_TREE;
9160
9161 p1 = c_getstr (arg1);
9162 if (p1 && compare_tree_int (len, strlen (p1) + 1) <= 0)
9163 {
9164 char c;
9165 const char *r;
9166 tree tem;
9167
9168 if (target_char_cast (arg2, &c))
9169 return NULL_TREE;
9170
609cab98 9171 r = (const char *) memchr (p1, c, tree_low_cst (len, 1));
7959b13b 9172
9173 if (r == NULL)
9174 return build_int_cst (TREE_TYPE (arg1), 0);
9175
2cc66f2a 9176 tem = fold_build_pointer_plus_hwi_loc (loc, arg1, r - p1);
389dd41b 9177 return fold_convert_loc (loc, type, tem);
7959b13b 9178 }
9179 return NULL_TREE;
9180 }
9181}
9182
c2f47e15 9183/* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
9184 Return NULL_TREE if no simplification can be made. */
9c8a1629 9185
9186static tree
389dd41b 9187fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
9c8a1629 9188{
c4fef134 9189 const char *p1, *p2;
9c8a1629 9190
c2f47e15 9191 if (!validate_arg (arg1, POINTER_TYPE)
9192 || !validate_arg (arg2, POINTER_TYPE)
9193 || !validate_arg (len, INTEGER_TYPE))
9194 return NULL_TREE;
9c8a1629 9195
9196 /* If the LEN parameter is zero, return zero. */
9197 if (integer_zerop (len))
389dd41b 9198 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
c4fef134 9199 arg1, arg2);
9c8a1629 9200
9201 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9202 if (operand_equal_p (arg1, arg2, 0))
389dd41b 9203 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
c4fef134 9204
9205 p1 = c_getstr (arg1);
9206 p2 = c_getstr (arg2);
9207
9208 /* If all arguments are constant, and the value of len is not greater
9209 than the lengths of arg1 and arg2, evaluate at compile-time. */
9210 if (host_integerp (len, 1) && p1 && p2
9211 && compare_tree_int (len, strlen (p1) + 1) <= 0
9212 && compare_tree_int (len, strlen (p2) + 1) <= 0)
9213 {
9214 const int r = memcmp (p1, p2, tree_low_cst (len, 1));
9215
9216 if (r > 0)
9217 return integer_one_node;
9218 else if (r < 0)
9219 return integer_minus_one_node;
9220 else
9221 return integer_zero_node;
9222 }
9223
9224 /* If len parameter is one, return an expression corresponding to
9225 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
9226 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
9227 {
9228 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9229 tree cst_uchar_ptr_node
9230 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9231
389dd41b 9232 tree ind1
9233 = fold_convert_loc (loc, integer_type_node,
9234 build1 (INDIRECT_REF, cst_uchar_node,
9235 fold_convert_loc (loc,
9236 cst_uchar_ptr_node,
c4fef134 9237 arg1)));
389dd41b 9238 tree ind2
9239 = fold_convert_loc (loc, integer_type_node,
9240 build1 (INDIRECT_REF, cst_uchar_node,
9241 fold_convert_loc (loc,
9242 cst_uchar_ptr_node,
c4fef134 9243 arg2)));
389dd41b 9244 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
c4fef134 9245 }
9c8a1629 9246
c2f47e15 9247 return NULL_TREE;
9c8a1629 9248}
9249
c2f47e15 9250/* Fold function call to builtin strcmp with arguments ARG1 and ARG2.
9251 Return NULL_TREE if no simplification can be made. */
9c8a1629 9252
9253static tree
389dd41b 9254fold_builtin_strcmp (location_t loc, tree arg1, tree arg2)
9c8a1629 9255{
9c8a1629 9256 const char *p1, *p2;
9257
c2f47e15 9258 if (!validate_arg (arg1, POINTER_TYPE)
9259 || !validate_arg (arg2, POINTER_TYPE))
9260 return NULL_TREE;
9c8a1629 9261
9262 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9263 if (operand_equal_p (arg1, arg2, 0))
c4fef134 9264 return integer_zero_node;
9c8a1629 9265
9266 p1 = c_getstr (arg1);
9267 p2 = c_getstr (arg2);
9268
9269 if (p1 && p2)
9270 {
9c8a1629 9271 const int i = strcmp (p1, p2);
9272 if (i < 0)
c4fef134 9273 return integer_minus_one_node;
9c8a1629 9274 else if (i > 0)
c4fef134 9275 return integer_one_node;
9c8a1629 9276 else
c4fef134 9277 return integer_zero_node;
9278 }
9279
9280 /* If the second arg is "", return *(const unsigned char*)arg1. */
9281 if (p2 && *p2 == '\0')
9282 {
9283 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9284 tree cst_uchar_ptr_node
9285 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9286
389dd41b 9287 return fold_convert_loc (loc, integer_type_node,
9288 build1 (INDIRECT_REF, cst_uchar_node,
9289 fold_convert_loc (loc,
9290 cst_uchar_ptr_node,
9291 arg1)));
c4fef134 9292 }
9293
9294 /* If the first arg is "", return -*(const unsigned char*)arg2. */
9295 if (p1 && *p1 == '\0')
9296 {
9297 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9298 tree cst_uchar_ptr_node
9299 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9300
389dd41b 9301 tree temp
9302 = fold_convert_loc (loc, integer_type_node,
9303 build1 (INDIRECT_REF, cst_uchar_node,
9304 fold_convert_loc (loc,
9305 cst_uchar_ptr_node,
c4fef134 9306 arg2)));
389dd41b 9307 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp);
9c8a1629 9308 }
9309
c2f47e15 9310 return NULL_TREE;
9c8a1629 9311}
9312
c2f47e15 9313/* Fold function call to builtin strncmp with arguments ARG1, ARG2, and LEN.
9314 Return NULL_TREE if no simplification can be made. */
9c8a1629 9315
9316static tree
389dd41b 9317fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len)
9c8a1629 9318{
9c8a1629 9319 const char *p1, *p2;
9320
c2f47e15 9321 if (!validate_arg (arg1, POINTER_TYPE)
9322 || !validate_arg (arg2, POINTER_TYPE)
9323 || !validate_arg (len, INTEGER_TYPE))
9324 return NULL_TREE;
9c8a1629 9325
9326 /* If the LEN parameter is zero, return zero. */
9327 if (integer_zerop (len))
389dd41b 9328 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
c4fef134 9329 arg1, arg2);
9c8a1629 9330
9331 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9332 if (operand_equal_p (arg1, arg2, 0))
389dd41b 9333 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
9c8a1629 9334
9335 p1 = c_getstr (arg1);
9336 p2 = c_getstr (arg2);
9337
9338 if (host_integerp (len, 1) && p1 && p2)
9339 {
9c8a1629 9340 const int i = strncmp (p1, p2, tree_low_cst (len, 1));
c4fef134 9341 if (i > 0)
9342 return integer_one_node;
9343 else if (i < 0)
9344 return integer_minus_one_node;
9c8a1629 9345 else
c4fef134 9346 return integer_zero_node;
9347 }
9348
9349 /* If the second arg is "", and the length is greater than zero,
9350 return *(const unsigned char*)arg1. */
9351 if (p2 && *p2 == '\0'
9352 && TREE_CODE (len) == INTEGER_CST
9353 && tree_int_cst_sgn (len) == 1)
9354 {
9355 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9356 tree cst_uchar_ptr_node
9357 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9358
389dd41b 9359 return fold_convert_loc (loc, integer_type_node,
9360 build1 (INDIRECT_REF, cst_uchar_node,
9361 fold_convert_loc (loc,
9362 cst_uchar_ptr_node,
9363 arg1)));
c4fef134 9364 }
9365
9366 /* If the first arg is "", and the length is greater than zero,
9367 return -*(const unsigned char*)arg2. */
9368 if (p1 && *p1 == '\0'
9369 && TREE_CODE (len) == INTEGER_CST
9370 && tree_int_cst_sgn (len) == 1)
9371 {
9372 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9373 tree cst_uchar_ptr_node
9374 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9375
389dd41b 9376 tree temp = fold_convert_loc (loc, integer_type_node,
9377 build1 (INDIRECT_REF, cst_uchar_node,
9378 fold_convert_loc (loc,
9379 cst_uchar_ptr_node,
9380 arg2)));
9381 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp);
c4fef134 9382 }
9383
9384 /* If len parameter is one, return an expression corresponding to
9385 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
9386 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
9387 {
9388 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9389 tree cst_uchar_ptr_node
9390 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9391
389dd41b 9392 tree ind1 = fold_convert_loc (loc, integer_type_node,
9393 build1 (INDIRECT_REF, cst_uchar_node,
9394 fold_convert_loc (loc,
9395 cst_uchar_ptr_node,
9396 arg1)));
9397 tree ind2 = 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 arg2)));
9402 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
9c8a1629 9403 }
9404
c2f47e15 9405 return NULL_TREE;
9c8a1629 9406}
9407
c2f47e15 9408/* Fold function call to builtin signbit, signbitf or signbitl with argument
9409 ARG. Return NULL_TREE if no simplification can be made. */
27f261ef 9410
9411static tree
389dd41b 9412fold_builtin_signbit (location_t loc, tree arg, tree type)
27f261ef 9413{
c2f47e15 9414 if (!validate_arg (arg, REAL_TYPE))
27f261ef 9415 return NULL_TREE;
9416
27f261ef 9417 /* If ARG is a compile-time constant, determine the result. */
9418 if (TREE_CODE (arg) == REAL_CST
f96bd2bf 9419 && !TREE_OVERFLOW (arg))
27f261ef 9420 {
9421 REAL_VALUE_TYPE c;
9422
9423 c = TREE_REAL_CST (arg);
385f3f36 9424 return (REAL_VALUE_NEGATIVE (c)
9425 ? build_one_cst (type)
9426 : build_zero_cst (type));
27f261ef 9427 }
9428
9429 /* If ARG is non-negative, the result is always zero. */
9430 if (tree_expr_nonnegative_p (arg))
389dd41b 9431 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
27f261ef 9432
9433 /* If ARG's format doesn't have signed zeros, return "arg < 0.0". */
9434 if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
de67cbb8 9435 return fold_convert (type,
9436 fold_build2_loc (loc, LT_EXPR, boolean_type_node, arg,
9437 build_real (TREE_TYPE (arg), dconst0)));
27f261ef 9438
9439 return NULL_TREE;
9440}
9441
c2f47e15 9442/* Fold function call to builtin copysign, copysignf or copysignl with
9443 arguments ARG1 and ARG2. Return NULL_TREE if no simplification can
9444 be made. */
467214fd 9445
9446static tree
389dd41b 9447fold_builtin_copysign (location_t loc, tree fndecl,
9448 tree arg1, tree arg2, tree type)
467214fd 9449{
c2f47e15 9450 tree tem;
467214fd 9451
c2f47e15 9452 if (!validate_arg (arg1, REAL_TYPE)
9453 || !validate_arg (arg2, REAL_TYPE))
467214fd 9454 return NULL_TREE;
9455
467214fd 9456 /* copysign(X,X) is X. */
9457 if (operand_equal_p (arg1, arg2, 0))
389dd41b 9458 return fold_convert_loc (loc, type, arg1);
467214fd 9459
9460 /* If ARG1 and ARG2 are compile-time constants, determine the result. */
9461 if (TREE_CODE (arg1) == REAL_CST
9462 && TREE_CODE (arg2) == REAL_CST
f96bd2bf 9463 && !TREE_OVERFLOW (arg1)
9464 && !TREE_OVERFLOW (arg2))
467214fd 9465 {
9466 REAL_VALUE_TYPE c1, c2;
9467
9468 c1 = TREE_REAL_CST (arg1);
9469 c2 = TREE_REAL_CST (arg2);
749680e2 9470 /* c1.sign := c2.sign. */
467214fd 9471 real_copysign (&c1, &c2);
9472 return build_real (type, c1);
467214fd 9473 }
9474
9475 /* copysign(X, Y) is fabs(X) when Y is always non-negative.
9476 Remember to evaluate Y for side-effects. */
9477 if (tree_expr_nonnegative_p (arg2))
389dd41b 9478 return omit_one_operand_loc (loc, type,
9479 fold_build1_loc (loc, ABS_EXPR, type, arg1),
467214fd 9480 arg2);
9481
198d9bbe 9482 /* Strip sign changing operations for the first argument. */
9483 tem = fold_strip_sign_ops (arg1);
9484 if (tem)
389dd41b 9485 return build_call_expr_loc (loc, fndecl, 2, tem, arg2);
198d9bbe 9486
467214fd 9487 return NULL_TREE;
9488}
9489
c2f47e15 9490/* Fold a call to builtin isascii with argument ARG. */
d49367d4 9491
9492static tree
389dd41b 9493fold_builtin_isascii (location_t loc, tree arg)
d49367d4 9494{
c2f47e15 9495 if (!validate_arg (arg, INTEGER_TYPE))
9496 return NULL_TREE;
d49367d4 9497 else
9498 {
9499 /* Transform isascii(c) -> ((c & ~0x7f) == 0). */
c90b5d40 9500 arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
7002a1c8 9501 build_int_cst (integer_type_node,
c90b5d40 9502 ~ (unsigned HOST_WIDE_INT) 0x7f));
389dd41b 9503 return fold_build2_loc (loc, EQ_EXPR, integer_type_node,
7002a1c8 9504 arg, integer_zero_node);
d49367d4 9505 }
9506}
9507
c2f47e15 9508/* Fold a call to builtin toascii with argument ARG. */
d49367d4 9509
9510static tree
389dd41b 9511fold_builtin_toascii (location_t loc, tree arg)
d49367d4 9512{
c2f47e15 9513 if (!validate_arg (arg, INTEGER_TYPE))
9514 return NULL_TREE;
48e1416a 9515
c2f47e15 9516 /* Transform toascii(c) -> (c & 0x7f). */
389dd41b 9517 return fold_build2_loc (loc, BIT_AND_EXPR, integer_type_node, arg,
7002a1c8 9518 build_int_cst (integer_type_node, 0x7f));
d49367d4 9519}
9520
c2f47e15 9521/* Fold a call to builtin isdigit with argument ARG. */
df1cf42e 9522
9523static tree
389dd41b 9524fold_builtin_isdigit (location_t loc, tree arg)
df1cf42e 9525{
c2f47e15 9526 if (!validate_arg (arg, INTEGER_TYPE))
9527 return NULL_TREE;
df1cf42e 9528 else
9529 {
9530 /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */
624d37a6 9531 /* According to the C standard, isdigit is unaffected by locale.
9532 However, it definitely is affected by the target character set. */
624d37a6 9533 unsigned HOST_WIDE_INT target_digit0
9534 = lang_hooks.to_target_charset ('0');
9535
9536 if (target_digit0 == 0)
9537 return NULL_TREE;
9538
389dd41b 9539 arg = fold_convert_loc (loc, unsigned_type_node, arg);
c90b5d40 9540 arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg,
9541 build_int_cst (unsigned_type_node, target_digit0));
389dd41b 9542 return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg,
f2532264 9543 build_int_cst (unsigned_type_node, 9));
df1cf42e 9544 }
9545}
27f261ef 9546
c2f47e15 9547/* Fold a call to fabs, fabsf or fabsl with argument ARG. */
d1aade50 9548
9549static tree
389dd41b 9550fold_builtin_fabs (location_t loc, tree arg, tree type)
d1aade50 9551{
c2f47e15 9552 if (!validate_arg (arg, REAL_TYPE))
9553 return NULL_TREE;
d1aade50 9554
389dd41b 9555 arg = fold_convert_loc (loc, type, arg);
d1aade50 9556 if (TREE_CODE (arg) == REAL_CST)
9557 return fold_abs_const (arg, type);
389dd41b 9558 return fold_build1_loc (loc, ABS_EXPR, type, arg);
d1aade50 9559}
9560
c2f47e15 9561/* Fold a call to abs, labs, llabs or imaxabs with argument ARG. */
d1aade50 9562
9563static tree
389dd41b 9564fold_builtin_abs (location_t loc, tree arg, tree type)
d1aade50 9565{
c2f47e15 9566 if (!validate_arg (arg, INTEGER_TYPE))
9567 return NULL_TREE;
d1aade50 9568
389dd41b 9569 arg = fold_convert_loc (loc, type, arg);
d1aade50 9570 if (TREE_CODE (arg) == INTEGER_CST)
9571 return fold_abs_const (arg, type);
389dd41b 9572 return fold_build1_loc (loc, ABS_EXPR, type, arg);
d1aade50 9573}
9574
b9be572e 9575/* Fold a fma operation with arguments ARG[012]. */
9576
9577tree
9578fold_fma (location_t loc ATTRIBUTE_UNUSED,
9579 tree type, tree arg0, tree arg1, tree arg2)
9580{
9581 if (TREE_CODE (arg0) == REAL_CST
9582 && TREE_CODE (arg1) == REAL_CST
9583 && TREE_CODE (arg2) == REAL_CST)
9584 return do_mpfr_arg3 (arg0, arg1, arg2, type, mpfr_fma);
9585
9586 return NULL_TREE;
9587}
9588
9589/* Fold a call to fma, fmaf, or fmal with arguments ARG[012]. */
9590
9591static tree
9592fold_builtin_fma (location_t loc, tree arg0, tree arg1, tree arg2, tree type)
9593{
9594 if (validate_arg (arg0, REAL_TYPE)
9595 && validate_arg(arg1, REAL_TYPE)
9596 && validate_arg(arg2, REAL_TYPE))
9597 {
9598 tree tem = fold_fma (loc, type, arg0, arg1, arg2);
9599 if (tem)
9600 return tem;
9601
9602 /* ??? Only expand to FMA_EXPR if it's directly supported. */
9603 if (optab_handler (fma_optab, TYPE_MODE (type)) != CODE_FOR_nothing)
9604 return fold_build3_loc (loc, FMA_EXPR, type, arg0, arg1, arg2);
9605 }
9606 return NULL_TREE;
9607}
9608
d4a43a03 9609/* Fold a call to builtin fmin or fmax. */
9610
9611static tree
389dd41b 9612fold_builtin_fmin_fmax (location_t loc, tree arg0, tree arg1,
9613 tree type, bool max)
d4a43a03 9614{
c2f47e15 9615 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, REAL_TYPE))
d4a43a03 9616 {
d4a43a03 9617 /* Calculate the result when the argument is a constant. */
9618 tree res = do_mpfr_arg2 (arg0, arg1, type, (max ? mpfr_max : mpfr_min));
9619
9620 if (res)
9621 return res;
9622
61fe3555 9623 /* If either argument is NaN, return the other one. Avoid the
9624 transformation if we get (and honor) a signalling NaN. Using
9625 omit_one_operand() ensures we create a non-lvalue. */
9626 if (TREE_CODE (arg0) == REAL_CST
9627 && real_isnan (&TREE_REAL_CST (arg0))
9628 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
9629 || ! TREE_REAL_CST (arg0).signalling))
389dd41b 9630 return omit_one_operand_loc (loc, type, arg1, arg0);
61fe3555 9631 if (TREE_CODE (arg1) == REAL_CST
9632 && real_isnan (&TREE_REAL_CST (arg1))
9633 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
9634 || ! TREE_REAL_CST (arg1).signalling))
389dd41b 9635 return omit_one_operand_loc (loc, type, arg0, arg1);
61fe3555 9636
d4a43a03 9637 /* Transform fmin/fmax(x,x) -> x. */
9638 if (operand_equal_p (arg0, arg1, OEP_PURE_SAME))
389dd41b 9639 return omit_one_operand_loc (loc, type, arg0, arg1);
48e1416a 9640
d4a43a03 9641 /* Convert fmin/fmax to MIN_EXPR/MAX_EXPR. C99 requires these
9642 functions to return the numeric arg if the other one is NaN.
9643 These tree codes don't honor that, so only transform if
9644 -ffinite-math-only is set. C99 doesn't require -0.0 to be
9645 handled, so we don't have to worry about it either. */
9646 if (flag_finite_math_only)
389dd41b 9647 return fold_build2_loc (loc, (max ? MAX_EXPR : MIN_EXPR), type,
9648 fold_convert_loc (loc, type, arg0),
9649 fold_convert_loc (loc, type, arg1));
d4a43a03 9650 }
9651 return NULL_TREE;
9652}
9653
abe4dcf6 9654/* Fold a call to builtin carg(a+bi) -> atan2(b,a). */
9655
9656static tree
389dd41b 9657fold_builtin_carg (location_t loc, tree arg, tree type)
abe4dcf6 9658{
239d491a 9659 if (validate_arg (arg, COMPLEX_TYPE)
9660 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
abe4dcf6 9661 {
9662 tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
48e1416a 9663
abe4dcf6 9664 if (atan2_fn)
9665 {
c2f47e15 9666 tree new_arg = builtin_save_expr (arg);
389dd41b 9667 tree r_arg = fold_build1_loc (loc, REALPART_EXPR, type, new_arg);
9668 tree i_arg = fold_build1_loc (loc, IMAGPART_EXPR, type, new_arg);
9669 return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg);
abe4dcf6 9670 }
9671 }
48e1416a 9672
abe4dcf6 9673 return NULL_TREE;
9674}
9675
cb2b9385 9676/* Fold a call to builtin logb/ilogb. */
9677
9678static tree
389dd41b 9679fold_builtin_logb (location_t loc, tree arg, tree rettype)
cb2b9385 9680{
9681 if (! validate_arg (arg, REAL_TYPE))
9682 return NULL_TREE;
48e1416a 9683
cb2b9385 9684 STRIP_NOPS (arg);
48e1416a 9685
cb2b9385 9686 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9687 {
9688 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
48e1416a 9689
cb2b9385 9690 switch (value->cl)
9691 {
9692 case rvc_nan:
9693 case rvc_inf:
9694 /* If arg is Inf or NaN and we're logb, return it. */
9695 if (TREE_CODE (rettype) == REAL_TYPE)
389dd41b 9696 return fold_convert_loc (loc, rettype, arg);
cb2b9385 9697 /* Fall through... */
9698 case rvc_zero:
9699 /* Zero may set errno and/or raise an exception for logb, also
9700 for ilogb we don't know FP_ILOGB0. */
9701 return NULL_TREE;
9702 case rvc_normal:
9703 /* For normal numbers, proceed iff radix == 2. In GCC,
9704 normalized significands are in the range [0.5, 1.0). We
9705 want the exponent as if they were [1.0, 2.0) so get the
9706 exponent and subtract 1. */
9707 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
389dd41b 9708 return fold_convert_loc (loc, rettype,
7002a1c8 9709 build_int_cst (integer_type_node,
389dd41b 9710 REAL_EXP (value)-1));
cb2b9385 9711 break;
9712 }
9713 }
48e1416a 9714
cb2b9385 9715 return NULL_TREE;
9716}
9717
9718/* Fold a call to builtin significand, if radix == 2. */
9719
9720static tree
389dd41b 9721fold_builtin_significand (location_t loc, tree arg, tree rettype)
cb2b9385 9722{
9723 if (! validate_arg (arg, REAL_TYPE))
9724 return NULL_TREE;
48e1416a 9725
cb2b9385 9726 STRIP_NOPS (arg);
48e1416a 9727
cb2b9385 9728 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9729 {
9730 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
48e1416a 9731
cb2b9385 9732 switch (value->cl)
9733 {
9734 case rvc_zero:
9735 case rvc_nan:
9736 case rvc_inf:
9737 /* If arg is +-0, +-Inf or +-NaN, then return it. */
389dd41b 9738 return fold_convert_loc (loc, rettype, arg);
cb2b9385 9739 case rvc_normal:
9740 /* For normal numbers, proceed iff radix == 2. */
9741 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
9742 {
9743 REAL_VALUE_TYPE result = *value;
9744 /* In GCC, normalized significands are in the range [0.5,
9745 1.0). We want them to be [1.0, 2.0) so set the
9746 exponent to 1. */
9747 SET_REAL_EXP (&result, 1);
9748 return build_real (rettype, result);
9749 }
9750 break;
9751 }
9752 }
48e1416a 9753
cb2b9385 9754 return NULL_TREE;
9755}
9756
3838b9ae 9757/* Fold a call to builtin frexp, we can assume the base is 2. */
9758
9759static tree
389dd41b 9760fold_builtin_frexp (location_t loc, tree arg0, tree arg1, tree rettype)
3838b9ae 9761{
9762 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9763 return NULL_TREE;
48e1416a 9764
3838b9ae 9765 STRIP_NOPS (arg0);
48e1416a 9766
3838b9ae 9767 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9768 return NULL_TREE;
48e1416a 9769
389dd41b 9770 arg1 = build_fold_indirect_ref_loc (loc, arg1);
3838b9ae 9771
9772 /* Proceed if a valid pointer type was passed in. */
9773 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
9774 {
9775 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9776 tree frac, exp;
48e1416a 9777
3838b9ae 9778 switch (value->cl)
9779 {
9780 case rvc_zero:
9781 /* For +-0, return (*exp = 0, +-0). */
9782 exp = integer_zero_node;
9783 frac = arg0;
9784 break;
9785 case rvc_nan:
9786 case rvc_inf:
9787 /* For +-NaN or +-Inf, *exp is unspecified, return arg0. */
389dd41b 9788 return omit_one_operand_loc (loc, rettype, arg0, arg1);
3838b9ae 9789 case rvc_normal:
9790 {
9791 /* Since the frexp function always expects base 2, and in
9792 GCC normalized significands are already in the range
9793 [0.5, 1.0), we have exactly what frexp wants. */
9794 REAL_VALUE_TYPE frac_rvt = *value;
9795 SET_REAL_EXP (&frac_rvt, 0);
9796 frac = build_real (rettype, frac_rvt);
7002a1c8 9797 exp = build_int_cst (integer_type_node, REAL_EXP (value));
3838b9ae 9798 }
9799 break;
9800 default:
9801 gcc_unreachable ();
9802 }
48e1416a 9803
3838b9ae 9804 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
389dd41b 9805 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, exp);
3838b9ae 9806 TREE_SIDE_EFFECTS (arg1) = 1;
389dd41b 9807 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1, frac);
3838b9ae 9808 }
9809
9810 return NULL_TREE;
9811}
9812
7587301b 9813/* Fold a call to builtin ldexp or scalbn/scalbln. If LDEXP is true
9814 then we can assume the base is two. If it's false, then we have to
9815 check the mode of the TYPE parameter in certain cases. */
9816
9817static tree
389dd41b 9818fold_builtin_load_exponent (location_t loc, tree arg0, tree arg1,
9819 tree type, bool ldexp)
7587301b 9820{
9821 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, INTEGER_TYPE))
9822 {
9823 STRIP_NOPS (arg0);
9824 STRIP_NOPS (arg1);
9825
9826 /* If arg0 is 0, Inf or NaN, or if arg1 is 0, then return arg0. */
9827 if (real_zerop (arg0) || integer_zerop (arg1)
9828 || (TREE_CODE (arg0) == REAL_CST
776a7bab 9829 && !real_isfinite (&TREE_REAL_CST (arg0))))
389dd41b 9830 return omit_one_operand_loc (loc, type, arg0, arg1);
48e1416a 9831
7587301b 9832 /* If both arguments are constant, then try to evaluate it. */
9833 if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2)
9834 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
9835 && host_integerp (arg1, 0))
9836 {
9837 /* Bound the maximum adjustment to twice the range of the
9838 mode's valid exponents. Use abs to ensure the range is
9839 positive as a sanity check. */
48e1416a 9840 const long max_exp_adj = 2 *
7587301b 9841 labs (REAL_MODE_FORMAT (TYPE_MODE (type))->emax
9842 - REAL_MODE_FORMAT (TYPE_MODE (type))->emin);
9843
9844 /* Get the user-requested adjustment. */
9845 const HOST_WIDE_INT req_exp_adj = tree_low_cst (arg1, 0);
48e1416a 9846
7587301b 9847 /* The requested adjustment must be inside this range. This
9848 is a preliminary cap to avoid things like overflow, we
9849 may still fail to compute the result for other reasons. */
9850 if (-max_exp_adj < req_exp_adj && req_exp_adj < max_exp_adj)
9851 {
9852 REAL_VALUE_TYPE initial_result;
48e1416a 9853
7587301b 9854 real_ldexp (&initial_result, &TREE_REAL_CST (arg0), req_exp_adj);
9855
9856 /* Ensure we didn't overflow. */
9857 if (! real_isinf (&initial_result))
9858 {
9859 const REAL_VALUE_TYPE trunc_result
9860 = real_value_truncate (TYPE_MODE (type), initial_result);
48e1416a 9861
7587301b 9862 /* Only proceed if the target mode can hold the
9863 resulting value. */
9864 if (REAL_VALUES_EQUAL (initial_result, trunc_result))
9865 return build_real (type, trunc_result);
9866 }
9867 }
9868 }
9869 }
9870
9871 return NULL_TREE;
9872}
9873
ebf8b4f5 9874/* Fold a call to builtin modf. */
9875
9876static tree
389dd41b 9877fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
ebf8b4f5 9878{
9879 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9880 return NULL_TREE;
48e1416a 9881
ebf8b4f5 9882 STRIP_NOPS (arg0);
48e1416a 9883
ebf8b4f5 9884 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9885 return NULL_TREE;
48e1416a 9886
389dd41b 9887 arg1 = build_fold_indirect_ref_loc (loc, arg1);
ebf8b4f5 9888
9889 /* Proceed if a valid pointer type was passed in. */
9890 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
9891 {
9892 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9893 REAL_VALUE_TYPE trunc, frac;
9894
9895 switch (value->cl)
9896 {
9897 case rvc_nan:
9898 case rvc_zero:
9899 /* For +-NaN or +-0, return (*arg1 = arg0, arg0). */
9900 trunc = frac = *value;
9901 break;
9902 case rvc_inf:
9903 /* For +-Inf, return (*arg1 = arg0, +-0). */
9904 frac = dconst0;
9905 frac.sign = value->sign;
9906 trunc = *value;
9907 break;
9908 case rvc_normal:
9909 /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)). */
9910 real_trunc (&trunc, VOIDmode, value);
9911 real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
9912 /* If the original number was negative and already
9913 integral, then the fractional part is -0.0. */
9914 if (value->sign && frac.cl == rvc_zero)
9915 frac.sign = value->sign;
9916 break;
9917 }
48e1416a 9918
ebf8b4f5 9919 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
389dd41b 9920 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1,
ebf8b4f5 9921 build_real (rettype, trunc));
9922 TREE_SIDE_EFFECTS (arg1) = 1;
389dd41b 9923 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1,
ebf8b4f5 9924 build_real (rettype, frac));
9925 }
48e1416a 9926
ebf8b4f5 9927 return NULL_TREE;
9928}
9929
a65c4d64 9930/* Given a location LOC, an interclass builtin function decl FNDECL
9931 and its single argument ARG, return an folded expression computing
9932 the same, or NULL_TREE if we either couldn't or didn't want to fold
9933 (the latter happen if there's an RTL instruction available). */
9934
9935static tree
9936fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
9937{
9938 enum machine_mode mode;
9939
9940 if (!validate_arg (arg, REAL_TYPE))
9941 return NULL_TREE;
9942
9943 if (interclass_mathfn_icode (arg, fndecl) != CODE_FOR_nothing)
9944 return NULL_TREE;
9945
9946 mode = TYPE_MODE (TREE_TYPE (arg));
9947
9948 /* If there is no optab, try generic code. */
9949 switch (DECL_FUNCTION_CODE (fndecl))
9950 {
9951 tree result;
9952
9953 CASE_FLT_FN (BUILT_IN_ISINF):
9954 {
9955 /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
b9a16870 9956 tree const isgr_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
a65c4d64 9957 tree const type = TREE_TYPE (arg);
9958 REAL_VALUE_TYPE r;
9959 char buf[128];
9960
9961 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9962 real_from_string (&r, buf);
9963 result = build_call_expr (isgr_fn, 2,
9964 fold_build1_loc (loc, ABS_EXPR, type, arg),
9965 build_real (type, r));
9966 return result;
9967 }
9968 CASE_FLT_FN (BUILT_IN_FINITE):
9969 case BUILT_IN_ISFINITE:
9970 {
9971 /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
b9a16870 9972 tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
a65c4d64 9973 tree const type = TREE_TYPE (arg);
9974 REAL_VALUE_TYPE r;
9975 char buf[128];
9976
9977 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9978 real_from_string (&r, buf);
9979 result = build_call_expr (isle_fn, 2,
9980 fold_build1_loc (loc, ABS_EXPR, type, arg),
9981 build_real (type, r));
9982 /*result = fold_build2_loc (loc, UNGT_EXPR,
9983 TREE_TYPE (TREE_TYPE (fndecl)),
9984 fold_build1_loc (loc, ABS_EXPR, type, arg),
9985 build_real (type, r));
9986 result = fold_build1_loc (loc, TRUTH_NOT_EXPR,
9987 TREE_TYPE (TREE_TYPE (fndecl)),
9988 result);*/
9989 return result;
9990 }
9991 case BUILT_IN_ISNORMAL:
9992 {
9993 /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
9994 islessequal(fabs(x),DBL_MAX). */
b9a16870 9995 tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
9996 tree const isge_fn = builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL);
a65c4d64 9997 tree const type = TREE_TYPE (arg);
9998 REAL_VALUE_TYPE rmax, rmin;
9999 char buf[128];
10000
10001 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
10002 real_from_string (&rmax, buf);
10003 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
10004 real_from_string (&rmin, buf);
10005 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
10006 result = build_call_expr (isle_fn, 2, arg,
10007 build_real (type, rmax));
10008 result = fold_build2 (BIT_AND_EXPR, integer_type_node, result,
10009 build_call_expr (isge_fn, 2, arg,
10010 build_real (type, rmin)));
10011 return result;
10012 }
10013 default:
10014 break;
10015 }
10016
10017 return NULL_TREE;
10018}
10019
726069ba 10020/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
c2f47e15 10021 ARG is the argument for the call. */
726069ba 10022
10023static tree
389dd41b 10024fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
726069ba 10025{
726069ba 10026 tree type = TREE_TYPE (TREE_TYPE (fndecl));
726069ba 10027 REAL_VALUE_TYPE r;
10028
c2f47e15 10029 if (!validate_arg (arg, REAL_TYPE))
d43cee80 10030 return NULL_TREE;
726069ba 10031
726069ba 10032 switch (builtin_index)
10033 {
10034 case BUILT_IN_ISINF:
b70bfd00 10035 if (!HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 10036 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
726069ba 10037
10038 if (TREE_CODE (arg) == REAL_CST)
10039 {
10040 r = TREE_REAL_CST (arg);
10041 if (real_isinf (&r))
10042 return real_compare (GT_EXPR, &r, &dconst0)
10043 ? integer_one_node : integer_minus_one_node;
10044 else
10045 return integer_zero_node;
10046 }
10047
10048 return NULL_TREE;
10049
c319d56a 10050 case BUILT_IN_ISINF_SIGN:
10051 {
10052 /* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */
10053 /* In a boolean context, GCC will fold the inner COND_EXPR to
10054 1. So e.g. "if (isinf_sign(x))" would be folded to just
10055 "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
10056 tree signbit_fn = mathfn_built_in_1 (TREE_TYPE (arg), BUILT_IN_SIGNBIT, 0);
b9a16870 10057 tree isinf_fn = builtin_decl_explicit (BUILT_IN_ISINF);
c319d56a 10058 tree tmp = NULL_TREE;
10059
10060 arg = builtin_save_expr (arg);
10061
10062 if (signbit_fn && isinf_fn)
10063 {
389dd41b 10064 tree signbit_call = build_call_expr_loc (loc, signbit_fn, 1, arg);
10065 tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg);
c319d56a 10066
389dd41b 10067 signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
c319d56a 10068 signbit_call, integer_zero_node);
389dd41b 10069 isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
c319d56a 10070 isinf_call, integer_zero_node);
48e1416a 10071
389dd41b 10072 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call,
c319d56a 10073 integer_minus_one_node, integer_one_node);
389dd41b 10074 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
10075 isinf_call, tmp,
c319d56a 10076 integer_zero_node);
10077 }
10078
10079 return tmp;
10080 }
10081
cde061c1 10082 case BUILT_IN_ISFINITE:
b70bfd00 10083 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
10084 && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 10085 return omit_one_operand_loc (loc, type, integer_one_node, arg);
726069ba 10086
10087 if (TREE_CODE (arg) == REAL_CST)
10088 {
10089 r = TREE_REAL_CST (arg);
776a7bab 10090 return real_isfinite (&r) ? integer_one_node : integer_zero_node;
726069ba 10091 }
10092
10093 return NULL_TREE;
10094
10095 case BUILT_IN_ISNAN:
b70bfd00 10096 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 10097 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
726069ba 10098
10099 if (TREE_CODE (arg) == REAL_CST)
10100 {
10101 r = TREE_REAL_CST (arg);
10102 return real_isnan (&r) ? integer_one_node : integer_zero_node;
10103 }
10104
10105 arg = builtin_save_expr (arg);
389dd41b 10106 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
726069ba 10107
10108 default:
64db345d 10109 gcc_unreachable ();
726069ba 10110 }
10111}
10112
19fbe3a4 10113/* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...).
10114 This builtin will generate code to return the appropriate floating
10115 point classification depending on the value of the floating point
10116 number passed in. The possible return values must be supplied as
921b27c0 10117 int arguments to the call in the following order: FP_NAN, FP_INFINITE,
19fbe3a4 10118 FP_NORMAL, FP_SUBNORMAL and FP_ZERO. The ellipses is for exactly
10119 one floating point argument which is "type generic". */
10120
10121static tree
389dd41b 10122fold_builtin_fpclassify (location_t loc, tree exp)
19fbe3a4 10123{
921b27c0 10124 tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
10125 arg, type, res, tmp;
19fbe3a4 10126 enum machine_mode mode;
10127 REAL_VALUE_TYPE r;
10128 char buf[128];
48e1416a 10129
19fbe3a4 10130 /* Verify the required arguments in the original call. */
10131 if (!validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE,
10132 INTEGER_TYPE, INTEGER_TYPE,
10133 INTEGER_TYPE, REAL_TYPE, VOID_TYPE))
10134 return NULL_TREE;
48e1416a 10135
19fbe3a4 10136 fp_nan = CALL_EXPR_ARG (exp, 0);
921b27c0 10137 fp_infinite = CALL_EXPR_ARG (exp, 1);
19fbe3a4 10138 fp_normal = CALL_EXPR_ARG (exp, 2);
10139 fp_subnormal = CALL_EXPR_ARG (exp, 3);
10140 fp_zero = CALL_EXPR_ARG (exp, 4);
10141 arg = CALL_EXPR_ARG (exp, 5);
10142 type = TREE_TYPE (arg);
10143 mode = TYPE_MODE (type);
389dd41b 10144 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
19fbe3a4 10145
48e1416a 10146 /* fpclassify(x) ->
19fbe3a4 10147 isnan(x) ? FP_NAN :
921b27c0 10148 (fabs(x) == Inf ? FP_INFINITE :
19fbe3a4 10149 (fabs(x) >= DBL_MIN ? FP_NORMAL :
10150 (x == 0 ? FP_ZERO : FP_SUBNORMAL))). */
48e1416a 10151
389dd41b 10152 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
19fbe3a4 10153 build_real (type, dconst0));
389dd41b 10154 res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
10155 tmp, fp_zero, fp_subnormal);
19fbe3a4 10156
10157 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
10158 real_from_string (&r, buf);
389dd41b 10159 tmp = fold_build2_loc (loc, GE_EXPR, integer_type_node,
10160 arg, build_real (type, r));
10161 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, fp_normal, res);
48e1416a 10162
19fbe3a4 10163 if (HONOR_INFINITIES (mode))
10164 {
10165 real_inf (&r);
389dd41b 10166 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
19fbe3a4 10167 build_real (type, r));
389dd41b 10168 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
10169 fp_infinite, res);
19fbe3a4 10170 }
10171
10172 if (HONOR_NANS (mode))
10173 {
389dd41b 10174 tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
10175 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, res, fp_nan);
19fbe3a4 10176 }
48e1416a 10177
19fbe3a4 10178 return res;
10179}
10180
9bc9f15f 10181/* Fold a call to an unordered comparison function such as
d5019fe8 10182 __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function
c2f47e15 10183 being called and ARG0 and ARG1 are the arguments for the call.
726069ba 10184 UNORDERED_CODE and ORDERED_CODE are comparison codes that give
10185 the opposite of the desired result. UNORDERED_CODE is used
10186 for modes that can hold NaNs and ORDERED_CODE is used for
10187 the rest. */
9bc9f15f 10188
10189static tree
389dd41b 10190fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
9bc9f15f 10191 enum tree_code unordered_code,
10192 enum tree_code ordered_code)
10193{
859f903a 10194 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9bc9f15f 10195 enum tree_code code;
6978db0d 10196 tree type0, type1;
10197 enum tree_code code0, code1;
10198 tree cmp_type = NULL_TREE;
9bc9f15f 10199
6978db0d 10200 type0 = TREE_TYPE (arg0);
10201 type1 = TREE_TYPE (arg1);
a0c938f0 10202
6978db0d 10203 code0 = TREE_CODE (type0);
10204 code1 = TREE_CODE (type1);
a0c938f0 10205
6978db0d 10206 if (code0 == REAL_TYPE && code1 == REAL_TYPE)
10207 /* Choose the wider of two real types. */
10208 cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
10209 ? type0 : type1;
10210 else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
10211 cmp_type = type0;
10212 else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
10213 cmp_type = type1;
a0c938f0 10214
389dd41b 10215 arg0 = fold_convert_loc (loc, cmp_type, arg0);
10216 arg1 = fold_convert_loc (loc, cmp_type, arg1);
859f903a 10217
10218 if (unordered_code == UNORDERED_EXPR)
10219 {
b70bfd00 10220 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
389dd41b 10221 return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
10222 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
859f903a 10223 }
9bc9f15f 10224
b70bfd00 10225 code = HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
10226 : ordered_code;
389dd41b 10227 return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
10228 fold_build2_loc (loc, code, type, arg0, arg1));
9bc9f15f 10229}
10230
c2f47e15 10231/* Fold a call to built-in function FNDECL with 0 arguments.
10232 IGNORE is true if the result of the function call is ignored. This
10233 function returns NULL_TREE if no simplification was possible. */
650e4c94 10234
4ee9c684 10235static tree
389dd41b 10236fold_builtin_0 (location_t loc, tree fndecl, bool ignore ATTRIBUTE_UNUSED)
650e4c94 10237{
e9f80ff5 10238 tree type = TREE_TYPE (TREE_TYPE (fndecl));
c2f47e15 10239 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
189b3398 10240 switch (fcode)
650e4c94 10241 {
c2f47e15 10242 CASE_FLT_FN (BUILT_IN_INF):
10243 case BUILT_IN_INFD32:
10244 case BUILT_IN_INFD64:
10245 case BUILT_IN_INFD128:
389dd41b 10246 return fold_builtin_inf (loc, type, true);
7c2f0500 10247
c2f47e15 10248 CASE_FLT_FN (BUILT_IN_HUGE_VAL):
389dd41b 10249 return fold_builtin_inf (loc, type, false);
7c2f0500 10250
c2f47e15 10251 case BUILT_IN_CLASSIFY_TYPE:
10252 return fold_builtin_classify_type (NULL_TREE);
7c2f0500 10253
c2f47e15 10254 default:
10255 break;
10256 }
10257 return NULL_TREE;
10258}
7c2f0500 10259
c2f47e15 10260/* Fold a call to built-in function FNDECL with 1 argument, ARG0.
10261 IGNORE is true if the result of the function call is ignored. This
10262 function returns NULL_TREE if no simplification was possible. */
7c2f0500 10263
c2f47e15 10264static tree
389dd41b 10265fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
c2f47e15 10266{
10267 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10268 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10269 switch (fcode)
10270 {
650e4c94 10271 case BUILT_IN_CONSTANT_P:
7c2f0500 10272 {
c2f47e15 10273 tree val = fold_builtin_constant_p (arg0);
7c2f0500 10274
7c2f0500 10275 /* Gimplification will pull the CALL_EXPR for the builtin out of
10276 an if condition. When not optimizing, we'll not CSE it back.
10277 To avoid link error types of regressions, return false now. */
10278 if (!val && !optimize)
10279 val = integer_zero_node;
10280
10281 return val;
10282 }
650e4c94 10283
539a3a92 10284 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 10285 return fold_builtin_classify_type (arg0);
539a3a92 10286
650e4c94 10287 case BUILT_IN_STRLEN:
c7cbde74 10288 return fold_builtin_strlen (loc, type, arg0);
650e4c94 10289
4f35b1fc 10290 CASE_FLT_FN (BUILT_IN_FABS):
389dd41b 10291 return fold_builtin_fabs (loc, arg0, type);
d1aade50 10292
10293 case BUILT_IN_ABS:
10294 case BUILT_IN_LABS:
10295 case BUILT_IN_LLABS:
10296 case BUILT_IN_IMAXABS:
389dd41b 10297 return fold_builtin_abs (loc, arg0, type);
c63f4ad3 10298
4f35b1fc 10299 CASE_FLT_FN (BUILT_IN_CONJ):
239d491a 10300 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10301 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10302 return fold_build1_loc (loc, CONJ_EXPR, type, arg0);
c2f47e15 10303 break;
36d3581d 10304
4f35b1fc 10305 CASE_FLT_FN (BUILT_IN_CREAL):
239d491a 10306 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10307 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10308 return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));;
c2f47e15 10309 break;
36d3581d 10310
4f35b1fc 10311 CASE_FLT_FN (BUILT_IN_CIMAG):
b0ce8887 10312 if (validate_arg (arg0, COMPLEX_TYPE)
10313 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10314 return non_lvalue_loc (loc, fold_build1_loc (loc, IMAGPART_EXPR, type, arg0));
c2f47e15 10315 break;
36d3581d 10316
503733d5 10317 CASE_FLT_FN (BUILT_IN_CCOS):
389dd41b 10318 return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ false);
48e1416a 10319
503733d5 10320 CASE_FLT_FN (BUILT_IN_CCOSH):
389dd41b 10321 return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ true);
48e1416a 10322
c2373fdb 10323 CASE_FLT_FN (BUILT_IN_CPROJ):
10324 return fold_builtin_cproj(loc, arg0, type);
10325
239d491a 10326 CASE_FLT_FN (BUILT_IN_CSIN):
10327 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10328 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10329 return do_mpc_arg1 (arg0, type, mpc_sin);
c2f47e15 10330 break;
48e1416a 10331
239d491a 10332 CASE_FLT_FN (BUILT_IN_CSINH):
10333 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10334 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10335 return do_mpc_arg1 (arg0, type, mpc_sinh);
10336 break;
48e1416a 10337
239d491a 10338 CASE_FLT_FN (BUILT_IN_CTAN):
10339 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10340 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10341 return do_mpc_arg1 (arg0, type, mpc_tan);
10342 break;
48e1416a 10343
239d491a 10344 CASE_FLT_FN (BUILT_IN_CTANH):
10345 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10346 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10347 return do_mpc_arg1 (arg0, type, mpc_tanh);
10348 break;
48e1416a 10349
239d491a 10350 CASE_FLT_FN (BUILT_IN_CLOG):
10351 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10352 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10353 return do_mpc_arg1 (arg0, type, mpc_log);
10354 break;
48e1416a 10355
239d491a 10356 CASE_FLT_FN (BUILT_IN_CSQRT):
10357 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10358 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10359 return do_mpc_arg1 (arg0, type, mpc_sqrt);
10360 break;
48e1416a 10361
0e7e6e7f 10362 CASE_FLT_FN (BUILT_IN_CASIN):
10363 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10364 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10365 return do_mpc_arg1 (arg0, type, mpc_asin);
10366 break;
48e1416a 10367
0e7e6e7f 10368 CASE_FLT_FN (BUILT_IN_CACOS):
10369 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10370 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10371 return do_mpc_arg1 (arg0, type, mpc_acos);
10372 break;
48e1416a 10373
0e7e6e7f 10374 CASE_FLT_FN (BUILT_IN_CATAN):
10375 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10376 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10377 return do_mpc_arg1 (arg0, type, mpc_atan);
10378 break;
48e1416a 10379
0e7e6e7f 10380 CASE_FLT_FN (BUILT_IN_CASINH):
10381 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10382 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10383 return do_mpc_arg1 (arg0, type, mpc_asinh);
10384 break;
48e1416a 10385
0e7e6e7f 10386 CASE_FLT_FN (BUILT_IN_CACOSH):
10387 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10388 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10389 return do_mpc_arg1 (arg0, type, mpc_acosh);
10390 break;
48e1416a 10391
0e7e6e7f 10392 CASE_FLT_FN (BUILT_IN_CATANH):
10393 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10394 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10395 return do_mpc_arg1 (arg0, type, mpc_atanh);
10396 break;
48e1416a 10397
4f35b1fc 10398 CASE_FLT_FN (BUILT_IN_CABS):
389dd41b 10399 return fold_builtin_cabs (loc, arg0, type, fndecl);
c63f4ad3 10400
abe4dcf6 10401 CASE_FLT_FN (BUILT_IN_CARG):
389dd41b 10402 return fold_builtin_carg (loc, arg0, type);
abe4dcf6 10403
4f35b1fc 10404 CASE_FLT_FN (BUILT_IN_SQRT):
389dd41b 10405 return fold_builtin_sqrt (loc, arg0, type);
805e22b2 10406
4f35b1fc 10407 CASE_FLT_FN (BUILT_IN_CBRT):
389dd41b 10408 return fold_builtin_cbrt (loc, arg0, type);
3bc5c41b 10409
728bac60 10410 CASE_FLT_FN (BUILT_IN_ASIN):
c2f47e15 10411 if (validate_arg (arg0, REAL_TYPE))
10412 return do_mpfr_arg1 (arg0, type, mpfr_asin,
728bac60 10413 &dconstm1, &dconst1, true);
10414 break;
10415
10416 CASE_FLT_FN (BUILT_IN_ACOS):
c2f47e15 10417 if (validate_arg (arg0, REAL_TYPE))
10418 return do_mpfr_arg1 (arg0, type, mpfr_acos,
728bac60 10419 &dconstm1, &dconst1, true);
10420 break;
10421
10422 CASE_FLT_FN (BUILT_IN_ATAN):
c2f47e15 10423 if (validate_arg (arg0, REAL_TYPE))
10424 return do_mpfr_arg1 (arg0, type, mpfr_atan, NULL, NULL, 0);
728bac60 10425 break;
10426
10427 CASE_FLT_FN (BUILT_IN_ASINH):
c2f47e15 10428 if (validate_arg (arg0, REAL_TYPE))
10429 return do_mpfr_arg1 (arg0, type, mpfr_asinh, NULL, NULL, 0);
728bac60 10430 break;
10431
10432 CASE_FLT_FN (BUILT_IN_ACOSH):
c2f47e15 10433 if (validate_arg (arg0, REAL_TYPE))
10434 return do_mpfr_arg1 (arg0, type, mpfr_acosh,
728bac60 10435 &dconst1, NULL, true);
10436 break;
10437
10438 CASE_FLT_FN (BUILT_IN_ATANH):
c2f47e15 10439 if (validate_arg (arg0, REAL_TYPE))
10440 return do_mpfr_arg1 (arg0, type, mpfr_atanh,
728bac60 10441 &dconstm1, &dconst1, false);
10442 break;
10443
4f35b1fc 10444 CASE_FLT_FN (BUILT_IN_SIN):
c2f47e15 10445 if (validate_arg (arg0, REAL_TYPE))
10446 return do_mpfr_arg1 (arg0, type, mpfr_sin, NULL, NULL, 0);
728bac60 10447 break;
77e89269 10448
4f35b1fc 10449 CASE_FLT_FN (BUILT_IN_COS):
389dd41b 10450 return fold_builtin_cos (loc, arg0, type, fndecl);
77e89269 10451
728bac60 10452 CASE_FLT_FN (BUILT_IN_TAN):
c2f47e15 10453 return fold_builtin_tan (arg0, type);
d735c391 10454
c5bb2c4b 10455 CASE_FLT_FN (BUILT_IN_CEXP):
389dd41b 10456 return fold_builtin_cexp (loc, arg0, type);
c5bb2c4b 10457
d735c391 10458 CASE_FLT_FN (BUILT_IN_CEXPI):
c2f47e15 10459 if (validate_arg (arg0, REAL_TYPE))
10460 return do_mpfr_sincos (arg0, NULL_TREE, NULL_TREE);
10461 break;
d92f994c 10462
728bac60 10463 CASE_FLT_FN (BUILT_IN_SINH):
c2f47e15 10464 if (validate_arg (arg0, REAL_TYPE))
10465 return do_mpfr_arg1 (arg0, type, mpfr_sinh, NULL, NULL, 0);
728bac60 10466 break;
10467
10468 CASE_FLT_FN (BUILT_IN_COSH):
389dd41b 10469 return fold_builtin_cosh (loc, arg0, type, fndecl);
728bac60 10470
10471 CASE_FLT_FN (BUILT_IN_TANH):
c2f47e15 10472 if (validate_arg (arg0, REAL_TYPE))
10473 return do_mpfr_arg1 (arg0, type, mpfr_tanh, NULL, NULL, 0);
728bac60 10474 break;
10475
29f4cd78 10476 CASE_FLT_FN (BUILT_IN_ERF):
c2f47e15 10477 if (validate_arg (arg0, REAL_TYPE))
10478 return do_mpfr_arg1 (arg0, type, mpfr_erf, NULL, NULL, 0);
29f4cd78 10479 break;
10480
10481 CASE_FLT_FN (BUILT_IN_ERFC):
c2f47e15 10482 if (validate_arg (arg0, REAL_TYPE))
10483 return do_mpfr_arg1 (arg0, type, mpfr_erfc, NULL, NULL, 0);
29f4cd78 10484 break;
10485
32dba52b 10486 CASE_FLT_FN (BUILT_IN_TGAMMA):
c2f47e15 10487 if (validate_arg (arg0, REAL_TYPE))
10488 return do_mpfr_arg1 (arg0, type, mpfr_gamma, NULL, NULL, 0);
32dba52b 10489 break;
48e1416a 10490
4f35b1fc 10491 CASE_FLT_FN (BUILT_IN_EXP):
389dd41b 10492 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp);
467214fd 10493
4f35b1fc 10494 CASE_FLT_FN (BUILT_IN_EXP2):
389dd41b 10495 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp2);
467214fd 10496
4f35b1fc 10497 CASE_FLT_FN (BUILT_IN_EXP10):
10498 CASE_FLT_FN (BUILT_IN_POW10):
389dd41b 10499 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp10);
467214fd 10500
29f4cd78 10501 CASE_FLT_FN (BUILT_IN_EXPM1):
c2f47e15 10502 if (validate_arg (arg0, REAL_TYPE))
10503 return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0);
29f4cd78 10504 break;
48e1416a 10505
4f35b1fc 10506 CASE_FLT_FN (BUILT_IN_LOG):
389dd41b 10507 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log);
467214fd 10508
4f35b1fc 10509 CASE_FLT_FN (BUILT_IN_LOG2):
389dd41b 10510 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log2);
467214fd 10511
4f35b1fc 10512 CASE_FLT_FN (BUILT_IN_LOG10):
389dd41b 10513 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log10);
29f4cd78 10514
10515 CASE_FLT_FN (BUILT_IN_LOG1P):
c2f47e15 10516 if (validate_arg (arg0, REAL_TYPE))
10517 return do_mpfr_arg1 (arg0, type, mpfr_log1p,
29f4cd78 10518 &dconstm1, NULL, false);
10519 break;
805e22b2 10520
65dd1378 10521 CASE_FLT_FN (BUILT_IN_J0):
10522 if (validate_arg (arg0, REAL_TYPE))
10523 return do_mpfr_arg1 (arg0, type, mpfr_j0,
10524 NULL, NULL, 0);
10525 break;
10526
10527 CASE_FLT_FN (BUILT_IN_J1):
10528 if (validate_arg (arg0, REAL_TYPE))
10529 return do_mpfr_arg1 (arg0, type, mpfr_j1,
10530 NULL, NULL, 0);
10531 break;
6ff9eeff 10532
10533 CASE_FLT_FN (BUILT_IN_Y0):
10534 if (validate_arg (arg0, REAL_TYPE))
10535 return do_mpfr_arg1 (arg0, type, mpfr_y0,
10536 &dconst0, NULL, false);
10537 break;
10538
10539 CASE_FLT_FN (BUILT_IN_Y1):
10540 if (validate_arg (arg0, REAL_TYPE))
10541 return do_mpfr_arg1 (arg0, type, mpfr_y1,
10542 &dconst0, NULL, false);
10543 break;
65dd1378 10544
4f35b1fc 10545 CASE_FLT_FN (BUILT_IN_NAN):
c4503c0a 10546 case BUILT_IN_NAND32:
10547 case BUILT_IN_NAND64:
10548 case BUILT_IN_NAND128:
c2f47e15 10549 return fold_builtin_nan (arg0, type, true);
b0db7939 10550
4f35b1fc 10551 CASE_FLT_FN (BUILT_IN_NANS):
c2f47e15 10552 return fold_builtin_nan (arg0, type, false);
b0db7939 10553
4f35b1fc 10554 CASE_FLT_FN (BUILT_IN_FLOOR):
389dd41b 10555 return fold_builtin_floor (loc, fndecl, arg0);
277f8dd2 10556
4f35b1fc 10557 CASE_FLT_FN (BUILT_IN_CEIL):
389dd41b 10558 return fold_builtin_ceil (loc, fndecl, arg0);
277f8dd2 10559
4f35b1fc 10560 CASE_FLT_FN (BUILT_IN_TRUNC):
389dd41b 10561 return fold_builtin_trunc (loc, fndecl, arg0);
277f8dd2 10562
4f35b1fc 10563 CASE_FLT_FN (BUILT_IN_ROUND):
389dd41b 10564 return fold_builtin_round (loc, fndecl, arg0);
89ab3887 10565
4f35b1fc 10566 CASE_FLT_FN (BUILT_IN_NEARBYINT):
10567 CASE_FLT_FN (BUILT_IN_RINT):
389dd41b 10568 return fold_trunc_transparent_mathfn (loc, fndecl, arg0);
6528f4f4 10569
80ff6494 10570 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 10571 CASE_FLT_FN (BUILT_IN_LCEIL):
10572 CASE_FLT_FN (BUILT_IN_LLCEIL):
10573 CASE_FLT_FN (BUILT_IN_LFLOOR):
80ff6494 10574 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 10575 CASE_FLT_FN (BUILT_IN_LLFLOOR):
80ff6494 10576 CASE_FLT_FN (BUILT_IN_IROUND):
a0c938f0 10577 CASE_FLT_FN (BUILT_IN_LROUND):
4f35b1fc 10578 CASE_FLT_FN (BUILT_IN_LLROUND):
389dd41b 10579 return fold_builtin_int_roundingfn (loc, fndecl, arg0);
34f17811 10580
80ff6494 10581 CASE_FLT_FN (BUILT_IN_IRINT):
4f35b1fc 10582 CASE_FLT_FN (BUILT_IN_LRINT):
10583 CASE_FLT_FN (BUILT_IN_LLRINT):
389dd41b 10584 return fold_fixed_mathfn (loc, fndecl, arg0);
9ed65c7f 10585
74bdbe96 10586 case BUILT_IN_BSWAP16:
42791117 10587 case BUILT_IN_BSWAP32:
10588 case BUILT_IN_BSWAP64:
c2f47e15 10589 return fold_builtin_bswap (fndecl, arg0);
42791117 10590
4f35b1fc 10591 CASE_INT_FN (BUILT_IN_FFS):
10592 CASE_INT_FN (BUILT_IN_CLZ):
10593 CASE_INT_FN (BUILT_IN_CTZ):
6aaa1f9e 10594 CASE_INT_FN (BUILT_IN_CLRSB):
4f35b1fc 10595 CASE_INT_FN (BUILT_IN_POPCOUNT):
10596 CASE_INT_FN (BUILT_IN_PARITY):
c2f47e15 10597 return fold_builtin_bitop (fndecl, arg0);
9c8a1629 10598
4f35b1fc 10599 CASE_FLT_FN (BUILT_IN_SIGNBIT):
389dd41b 10600 return fold_builtin_signbit (loc, arg0, type);
27f261ef 10601
cb2b9385 10602 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
389dd41b 10603 return fold_builtin_significand (loc, arg0, type);
cb2b9385 10604
10605 CASE_FLT_FN (BUILT_IN_ILOGB):
10606 CASE_FLT_FN (BUILT_IN_LOGB):
389dd41b 10607 return fold_builtin_logb (loc, arg0, type);
cb2b9385 10608
d49367d4 10609 case BUILT_IN_ISASCII:
389dd41b 10610 return fold_builtin_isascii (loc, arg0);
d49367d4 10611
10612 case BUILT_IN_TOASCII:
389dd41b 10613 return fold_builtin_toascii (loc, arg0);
d49367d4 10614
df1cf42e 10615 case BUILT_IN_ISDIGIT:
389dd41b 10616 return fold_builtin_isdigit (loc, arg0);
467214fd 10617
4f35b1fc 10618 CASE_FLT_FN (BUILT_IN_FINITE):
c4503c0a 10619 case BUILT_IN_FINITED32:
10620 case BUILT_IN_FINITED64:
10621 case BUILT_IN_FINITED128:
cde061c1 10622 case BUILT_IN_ISFINITE:
a65c4d64 10623 {
10624 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISFINITE);
10625 if (ret)
10626 return ret;
10627 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10628 }
726069ba 10629
4f35b1fc 10630 CASE_FLT_FN (BUILT_IN_ISINF):
c4503c0a 10631 case BUILT_IN_ISINFD32:
10632 case BUILT_IN_ISINFD64:
10633 case BUILT_IN_ISINFD128:
a65c4d64 10634 {
10635 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF);
10636 if (ret)
10637 return ret;
10638 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10639 }
10640
10641 case BUILT_IN_ISNORMAL:
10642 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
726069ba 10643
c319d56a 10644 case BUILT_IN_ISINF_SIGN:
389dd41b 10645 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF_SIGN);
c319d56a 10646
4f35b1fc 10647 CASE_FLT_FN (BUILT_IN_ISNAN):
c4503c0a 10648 case BUILT_IN_ISNAND32:
10649 case BUILT_IN_ISNAND64:
10650 case BUILT_IN_ISNAND128:
389dd41b 10651 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
c2f47e15 10652
10653 case BUILT_IN_PRINTF:
10654 case BUILT_IN_PRINTF_UNLOCKED:
10655 case BUILT_IN_VPRINTF:
389dd41b 10656 return fold_builtin_printf (loc, fndecl, arg0, NULL_TREE, ignore, fcode);
c2f47e15 10657
663870fc 10658 case BUILT_IN_FREE:
10659 if (integer_zerop (arg0))
10660 return build_empty_stmt (loc);
10661 break;
10662
c2f47e15 10663 default:
10664 break;
10665 }
10666
10667 return NULL_TREE;
10668
10669}
10670
10671/* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1.
10672 IGNORE is true if the result of the function call is ignored. This
10673 function returns NULL_TREE if no simplification was possible. */
10674
10675static tree
389dd41b 10676fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore)
c2f47e15 10677{
10678 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10679 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10680
10681 switch (fcode)
10682 {
65dd1378 10683 CASE_FLT_FN (BUILT_IN_JN):
10684 if (validate_arg (arg0, INTEGER_TYPE)
10685 && validate_arg (arg1, REAL_TYPE))
10686 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_jn, NULL, 0);
10687 break;
6ff9eeff 10688
10689 CASE_FLT_FN (BUILT_IN_YN):
10690 if (validate_arg (arg0, INTEGER_TYPE)
10691 && validate_arg (arg1, REAL_TYPE))
10692 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_yn,
10693 &dconst0, false);
10694 break;
e5407ca6 10695
10696 CASE_FLT_FN (BUILT_IN_DREM):
10697 CASE_FLT_FN (BUILT_IN_REMAINDER):
10698 if (validate_arg (arg0, REAL_TYPE)
10699 && validate_arg(arg1, REAL_TYPE))
10700 return do_mpfr_arg2 (arg0, arg1, type, mpfr_remainder);
10701 break;
e84da7c1 10702
10703 CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
10704 CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
10705 if (validate_arg (arg0, REAL_TYPE)
10706 && validate_arg(arg1, POINTER_TYPE))
10707 return do_mpfr_lgamma_r (arg0, arg1, type);
10708 break;
c2f47e15 10709
10710 CASE_FLT_FN (BUILT_IN_ATAN2):
10711 if (validate_arg (arg0, REAL_TYPE)
10712 && validate_arg(arg1, REAL_TYPE))
10713 return do_mpfr_arg2 (arg0, arg1, type, mpfr_atan2);
10714 break;
10715
10716 CASE_FLT_FN (BUILT_IN_FDIM):
10717 if (validate_arg (arg0, REAL_TYPE)
10718 && validate_arg(arg1, REAL_TYPE))
10719 return do_mpfr_arg2 (arg0, arg1, type, mpfr_dim);
10720 break;
10721
10722 CASE_FLT_FN (BUILT_IN_HYPOT):
389dd41b 10723 return fold_builtin_hypot (loc, fndecl, arg0, arg1, type);
c2f47e15 10724
c699fab8 10725 CASE_FLT_FN (BUILT_IN_CPOW):
10726 if (validate_arg (arg0, COMPLEX_TYPE)
10727 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
10728 && validate_arg (arg1, COMPLEX_TYPE)
48e1416a 10729 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE)
652d9409 10730 return do_mpc_arg2 (arg0, arg1, type, /*do_nonfinite=*/ 0, mpc_pow);
c699fab8 10731 break;
c699fab8 10732
7587301b 10733 CASE_FLT_FN (BUILT_IN_LDEXP):
389dd41b 10734 return fold_builtin_load_exponent (loc, arg0, arg1, type, /*ldexp=*/true);
7587301b 10735 CASE_FLT_FN (BUILT_IN_SCALBN):
10736 CASE_FLT_FN (BUILT_IN_SCALBLN):
389dd41b 10737 return fold_builtin_load_exponent (loc, arg0, arg1,
10738 type, /*ldexp=*/false);
7587301b 10739
3838b9ae 10740 CASE_FLT_FN (BUILT_IN_FREXP):
389dd41b 10741 return fold_builtin_frexp (loc, arg0, arg1, type);
3838b9ae 10742
ebf8b4f5 10743 CASE_FLT_FN (BUILT_IN_MODF):
389dd41b 10744 return fold_builtin_modf (loc, arg0, arg1, type);
ebf8b4f5 10745
c2f47e15 10746 case BUILT_IN_BZERO:
389dd41b 10747 return fold_builtin_bzero (loc, arg0, arg1, ignore);
c2f47e15 10748
10749 case BUILT_IN_FPUTS:
389dd41b 10750 return fold_builtin_fputs (loc, arg0, arg1, ignore, false, NULL_TREE);
c2f47e15 10751
10752 case BUILT_IN_FPUTS_UNLOCKED:
389dd41b 10753 return fold_builtin_fputs (loc, arg0, arg1, ignore, true, NULL_TREE);
c2f47e15 10754
10755 case BUILT_IN_STRSTR:
389dd41b 10756 return fold_builtin_strstr (loc, arg0, arg1, type);
c2f47e15 10757
10758 case BUILT_IN_STRCAT:
389dd41b 10759 return fold_builtin_strcat (loc, arg0, arg1);
c2f47e15 10760
10761 case BUILT_IN_STRSPN:
389dd41b 10762 return fold_builtin_strspn (loc, arg0, arg1);
c2f47e15 10763
10764 case BUILT_IN_STRCSPN:
389dd41b 10765 return fold_builtin_strcspn (loc, arg0, arg1);
c2f47e15 10766
10767 case BUILT_IN_STRCHR:
10768 case BUILT_IN_INDEX:
389dd41b 10769 return fold_builtin_strchr (loc, arg0, arg1, type);
c2f47e15 10770
10771 case BUILT_IN_STRRCHR:
10772 case BUILT_IN_RINDEX:
389dd41b 10773 return fold_builtin_strrchr (loc, arg0, arg1, type);
c2f47e15 10774
10775 case BUILT_IN_STRCPY:
389dd41b 10776 return fold_builtin_strcpy (loc, fndecl, arg0, arg1, NULL_TREE);
c2f47e15 10777
c8b17b2e 10778 case BUILT_IN_STPCPY:
10779 if (ignore)
10780 {
b9a16870 10781 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
c8b17b2e 10782 if (!fn)
10783 break;
10784
389dd41b 10785 return build_call_expr_loc (loc, fn, 2, arg0, arg1);
c8b17b2e 10786 }
a65c4d64 10787 else
10788 return fold_builtin_stpcpy (loc, fndecl, arg0, arg1);
c8b17b2e 10789 break;
10790
c2f47e15 10791 case BUILT_IN_STRCMP:
389dd41b 10792 return fold_builtin_strcmp (loc, arg0, arg1);
c2f47e15 10793
10794 case BUILT_IN_STRPBRK:
389dd41b 10795 return fold_builtin_strpbrk (loc, arg0, arg1, type);
c2f47e15 10796
10797 case BUILT_IN_EXPECT:
389dd41b 10798 return fold_builtin_expect (loc, arg0, arg1);
c2f47e15 10799
10800 CASE_FLT_FN (BUILT_IN_POW):
389dd41b 10801 return fold_builtin_pow (loc, fndecl, arg0, arg1, type);
c2f47e15 10802
10803 CASE_FLT_FN (BUILT_IN_POWI):
389dd41b 10804 return fold_builtin_powi (loc, fndecl, arg0, arg1, type);
c2f47e15 10805
10806 CASE_FLT_FN (BUILT_IN_COPYSIGN):
389dd41b 10807 return fold_builtin_copysign (loc, fndecl, arg0, arg1, type);
c2f47e15 10808
10809 CASE_FLT_FN (BUILT_IN_FMIN):
389dd41b 10810 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/false);
c2f47e15 10811
10812 CASE_FLT_FN (BUILT_IN_FMAX):
389dd41b 10813 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/true);
726069ba 10814
9bc9f15f 10815 case BUILT_IN_ISGREATER:
389dd41b 10816 return fold_builtin_unordered_cmp (loc, fndecl,
10817 arg0, arg1, UNLE_EXPR, LE_EXPR);
9bc9f15f 10818 case BUILT_IN_ISGREATEREQUAL:
389dd41b 10819 return fold_builtin_unordered_cmp (loc, fndecl,
10820 arg0, arg1, UNLT_EXPR, LT_EXPR);
9bc9f15f 10821 case BUILT_IN_ISLESS:
389dd41b 10822 return fold_builtin_unordered_cmp (loc, fndecl,
10823 arg0, arg1, UNGE_EXPR, GE_EXPR);
9bc9f15f 10824 case BUILT_IN_ISLESSEQUAL:
389dd41b 10825 return fold_builtin_unordered_cmp (loc, fndecl,
10826 arg0, arg1, UNGT_EXPR, GT_EXPR);
9bc9f15f 10827 case BUILT_IN_ISLESSGREATER:
389dd41b 10828 return fold_builtin_unordered_cmp (loc, fndecl,
10829 arg0, arg1, UNEQ_EXPR, EQ_EXPR);
9bc9f15f 10830 case BUILT_IN_ISUNORDERED:
389dd41b 10831 return fold_builtin_unordered_cmp (loc, fndecl,
10832 arg0, arg1, UNORDERED_EXPR,
d5019fe8 10833 NOP_EXPR);
9bc9f15f 10834
7c2f0500 10835 /* We do the folding for va_start in the expander. */
10836 case BUILT_IN_VA_START:
10837 break;
f0613857 10838
c2f47e15 10839 case BUILT_IN_SPRINTF:
389dd41b 10840 return fold_builtin_sprintf (loc, arg0, arg1, NULL_TREE, ignore);
c2f47e15 10841
0a39fd54 10842 case BUILT_IN_OBJECT_SIZE:
c2f47e15 10843 return fold_builtin_object_size (arg0, arg1);
0a39fd54 10844
10845 case BUILT_IN_PRINTF:
10846 case BUILT_IN_PRINTF_UNLOCKED:
10847 case BUILT_IN_VPRINTF:
389dd41b 10848 return fold_builtin_printf (loc, fndecl, arg0, arg1, ignore, fcode);
c2f47e15 10849
0a39fd54 10850 case BUILT_IN_PRINTF_CHK:
10851 case BUILT_IN_VPRINTF_CHK:
c2f47e15 10852 if (!validate_arg (arg0, INTEGER_TYPE)
10853 || TREE_SIDE_EFFECTS (arg0))
10854 return NULL_TREE;
10855 else
389dd41b 10856 return fold_builtin_printf (loc, fndecl,
10857 arg1, NULL_TREE, ignore, fcode);
c2f47e15 10858 break;
0a39fd54 10859
10860 case BUILT_IN_FPRINTF:
10861 case BUILT_IN_FPRINTF_UNLOCKED:
10862 case BUILT_IN_VFPRINTF:
389dd41b 10863 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, NULL_TREE,
c2f47e15 10864 ignore, fcode);
10865
1cd6e20d 10866 case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
10867 return fold_builtin_atomic_always_lock_free (arg0, arg1);
10868
10869 case BUILT_IN_ATOMIC_IS_LOCK_FREE:
10870 return fold_builtin_atomic_is_lock_free (arg0, arg1);
10871
c2f47e15 10872 default:
10873 break;
10874 }
10875 return NULL_TREE;
10876}
10877
10878/* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
10879 and ARG2. IGNORE is true if the result of the function call is ignored.
10880 This function returns NULL_TREE if no simplification was possible. */
10881
10882static tree
389dd41b 10883fold_builtin_3 (location_t loc, tree fndecl,
10884 tree arg0, tree arg1, tree arg2, bool ignore)
c2f47e15 10885{
10886 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10887 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10888 switch (fcode)
10889 {
10890
10891 CASE_FLT_FN (BUILT_IN_SINCOS):
389dd41b 10892 return fold_builtin_sincos (loc, arg0, arg1, arg2);
c2f47e15 10893
10894 CASE_FLT_FN (BUILT_IN_FMA):
b9be572e 10895 return fold_builtin_fma (loc, arg0, arg1, arg2, type);
c2f47e15 10896 break;
10897
e5407ca6 10898 CASE_FLT_FN (BUILT_IN_REMQUO):
10899 if (validate_arg (arg0, REAL_TYPE)
10900 && validate_arg(arg1, REAL_TYPE)
10901 && validate_arg(arg2, POINTER_TYPE))
10902 return do_mpfr_remquo (arg0, arg1, arg2);
10903 break;
e5407ca6 10904
c2f47e15 10905 case BUILT_IN_MEMSET:
389dd41b 10906 return fold_builtin_memset (loc, arg0, arg1, arg2, type, ignore);
c2f47e15 10907
10908 case BUILT_IN_BCOPY:
389dd41b 10909 return fold_builtin_memory_op (loc, arg1, arg0, arg2,
10910 void_type_node, true, /*endp=*/3);
c2f47e15 10911
10912 case BUILT_IN_MEMCPY:
389dd41b 10913 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10914 type, ignore, /*endp=*/0);
c2f47e15 10915
10916 case BUILT_IN_MEMPCPY:
389dd41b 10917 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10918 type, ignore, /*endp=*/1);
c2f47e15 10919
10920 case BUILT_IN_MEMMOVE:
389dd41b 10921 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10922 type, ignore, /*endp=*/3);
c2f47e15 10923
10924 case BUILT_IN_STRNCAT:
389dd41b 10925 return fold_builtin_strncat (loc, arg0, arg1, arg2);
c2f47e15 10926
10927 case BUILT_IN_STRNCPY:
389dd41b 10928 return fold_builtin_strncpy (loc, fndecl, arg0, arg1, arg2, NULL_TREE);
c2f47e15 10929
10930 case BUILT_IN_STRNCMP:
389dd41b 10931 return fold_builtin_strncmp (loc, arg0, arg1, arg2);
c2f47e15 10932
7959b13b 10933 case BUILT_IN_MEMCHR:
389dd41b 10934 return fold_builtin_memchr (loc, arg0, arg1, arg2, type);
7959b13b 10935
c2f47e15 10936 case BUILT_IN_BCMP:
10937 case BUILT_IN_MEMCMP:
389dd41b 10938 return fold_builtin_memcmp (loc, arg0, arg1, arg2);;
c2f47e15 10939
10940 case BUILT_IN_SPRINTF:
389dd41b 10941 return fold_builtin_sprintf (loc, arg0, arg1, arg2, ignore);
c2f47e15 10942
750d7b16 10943 case BUILT_IN_SNPRINTF:
10944 return fold_builtin_snprintf (loc, arg0, arg1, arg2, NULL_TREE, ignore);
10945
c2f47e15 10946 case BUILT_IN_STRCPY_CHK:
10947 case BUILT_IN_STPCPY_CHK:
389dd41b 10948 return fold_builtin_stxcpy_chk (loc, fndecl, arg0, arg1, arg2, NULL_TREE,
c2f47e15 10949 ignore, fcode);
10950
10951 case BUILT_IN_STRCAT_CHK:
389dd41b 10952 return fold_builtin_strcat_chk (loc, fndecl, arg0, arg1, arg2);
c2f47e15 10953
10954 case BUILT_IN_PRINTF_CHK:
10955 case BUILT_IN_VPRINTF_CHK:
10956 if (!validate_arg (arg0, INTEGER_TYPE)
10957 || TREE_SIDE_EFFECTS (arg0))
10958 return NULL_TREE;
10959 else
389dd41b 10960 return fold_builtin_printf (loc, fndecl, arg1, arg2, ignore, fcode);
c2f47e15 10961 break;
10962
10963 case BUILT_IN_FPRINTF:
10964 case BUILT_IN_FPRINTF_UNLOCKED:
10965 case BUILT_IN_VFPRINTF:
389dd41b 10966 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, arg2,
10967 ignore, fcode);
c2f47e15 10968
0a39fd54 10969 case BUILT_IN_FPRINTF_CHK:
10970 case BUILT_IN_VFPRINTF_CHK:
c2f47e15 10971 if (!validate_arg (arg1, INTEGER_TYPE)
10972 || TREE_SIDE_EFFECTS (arg1))
10973 return NULL_TREE;
10974 else
389dd41b 10975 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, NULL_TREE,
c2f47e15 10976 ignore, fcode);
0a39fd54 10977
650e4c94 10978 default:
10979 break;
10980 }
c2f47e15 10981 return NULL_TREE;
10982}
650e4c94 10983
c2f47e15 10984/* Fold a call to built-in function FNDECL with 4 arguments, ARG0, ARG1,
10985 ARG2, and ARG3. IGNORE is true if the result of the function call is
10986 ignored. This function returns NULL_TREE if no simplification was
10987 possible. */
48e1416a 10988
c2f47e15 10989static tree
389dd41b 10990fold_builtin_4 (location_t loc, tree fndecl,
10991 tree arg0, tree arg1, tree arg2, tree arg3, bool ignore)
c2f47e15 10992{
10993 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10994
10995 switch (fcode)
10996 {
10997 case BUILT_IN_MEMCPY_CHK:
10998 case BUILT_IN_MEMPCPY_CHK:
10999 case BUILT_IN_MEMMOVE_CHK:
11000 case BUILT_IN_MEMSET_CHK:
389dd41b 11001 return fold_builtin_memory_chk (loc, fndecl, arg0, arg1, arg2, arg3,
c2f47e15 11002 NULL_TREE, ignore,
11003 DECL_FUNCTION_CODE (fndecl));
11004
11005 case BUILT_IN_STRNCPY_CHK:
1063acde 11006 case BUILT_IN_STPNCPY_CHK:
11007 return fold_builtin_stxncpy_chk (loc, arg0, arg1, arg2, arg3, NULL_TREE,
11008 ignore, fcode);
c2f47e15 11009
11010 case BUILT_IN_STRNCAT_CHK:
389dd41b 11011 return fold_builtin_strncat_chk (loc, fndecl, arg0, arg1, arg2, arg3);
c2f47e15 11012
750d7b16 11013 case BUILT_IN_SNPRINTF:
11014 return fold_builtin_snprintf (loc, arg0, arg1, arg2, arg3, ignore);
11015
c2f47e15 11016 case BUILT_IN_FPRINTF_CHK:
11017 case BUILT_IN_VFPRINTF_CHK:
11018 if (!validate_arg (arg1, INTEGER_TYPE)
11019 || TREE_SIDE_EFFECTS (arg1))
11020 return NULL_TREE;
11021 else
389dd41b 11022 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, arg3,
c2f47e15 11023 ignore, fcode);
11024 break;
11025
11026 default:
11027 break;
11028 }
11029 return NULL_TREE;
11030}
11031
11032/* Fold a call to built-in function FNDECL. ARGS is an array of NARGS
11033 arguments, where NARGS <= 4. IGNORE is true if the result of the
11034 function call is ignored. This function returns NULL_TREE if no
11035 simplification was possible. Note that this only folds builtins with
11036 fixed argument patterns. Foldings that do varargs-to-varargs
11037 transformations, or that match calls with more than 4 arguments,
11038 need to be handled with fold_builtin_varargs instead. */
48e1416a 11039
c2f47e15 11040#define MAX_ARGS_TO_FOLD_BUILTIN 4
48e1416a 11041
c2f47e15 11042static tree
389dd41b 11043fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool ignore)
c2f47e15 11044{
11045 tree ret = NULL_TREE;
a7f5bb2d 11046
c2f47e15 11047 switch (nargs)
11048 {
11049 case 0:
389dd41b 11050 ret = fold_builtin_0 (loc, fndecl, ignore);
c2f47e15 11051 break;
11052 case 1:
389dd41b 11053 ret = fold_builtin_1 (loc, fndecl, args[0], ignore);
c2f47e15 11054 break;
11055 case 2:
389dd41b 11056 ret = fold_builtin_2 (loc, fndecl, args[0], args[1], ignore);
c2f47e15 11057 break;
11058 case 3:
389dd41b 11059 ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2], ignore);
c2f47e15 11060 break;
11061 case 4:
389dd41b 11062 ret = fold_builtin_4 (loc, fndecl, args[0], args[1], args[2], args[3],
c2f47e15 11063 ignore);
11064 break;
11065 default:
11066 break;
11067 }
11068 if (ret)
11069 {
75a70cf9 11070 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
389dd41b 11071 SET_EXPR_LOCATION (ret, loc);
c2f47e15 11072 TREE_NO_WARNING (ret) = 1;
11073 return ret;
11074 }
11075 return NULL_TREE;
11076}
11077
11078/* Builtins with folding operations that operate on "..." arguments
11079 need special handling; we need to store the arguments in a convenient
11080 data structure before attempting any folding. Fortunately there are
11081 only a few builtins that fall into this category. FNDECL is the
11082 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
11083 result of the function call is ignored. */
11084
11085static tree
389dd41b 11086fold_builtin_varargs (location_t loc, tree fndecl, tree exp,
11087 bool ignore ATTRIBUTE_UNUSED)
c2f47e15 11088{
11089 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
11090 tree ret = NULL_TREE;
11091
11092 switch (fcode)
11093 {
11094 case BUILT_IN_SPRINTF_CHK:
11095 case BUILT_IN_VSPRINTF_CHK:
389dd41b 11096 ret = fold_builtin_sprintf_chk (loc, exp, fcode);
c2f47e15 11097 break;
11098
11099 case BUILT_IN_SNPRINTF_CHK:
11100 case BUILT_IN_VSNPRINTF_CHK:
389dd41b 11101 ret = fold_builtin_snprintf_chk (loc, exp, NULL_TREE, fcode);
19fbe3a4 11102 break;
11103
11104 case BUILT_IN_FPCLASSIFY:
389dd41b 11105 ret = fold_builtin_fpclassify (loc, exp);
19fbe3a4 11106 break;
c2f47e15 11107
11108 default:
11109 break;
11110 }
11111 if (ret)
11112 {
11113 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
389dd41b 11114 SET_EXPR_LOCATION (ret, loc);
c2f47e15 11115 TREE_NO_WARNING (ret) = 1;
11116 return ret;
11117 }
11118 return NULL_TREE;
650e4c94 11119}
7e15618b 11120
198622c0 11121/* Return true if FNDECL shouldn't be folded right now.
11122 If a built-in function has an inline attribute always_inline
11123 wrapper, defer folding it after always_inline functions have
11124 been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
11125 might not be performed. */
11126
51d2c51e 11127bool
198622c0 11128avoid_folding_inline_builtin (tree fndecl)
11129{
11130 return (DECL_DECLARED_INLINE_P (fndecl)
11131 && DECL_DISREGARD_INLINE_LIMITS (fndecl)
11132 && cfun
11133 && !cfun->always_inline_functions_inlined
11134 && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)));
11135}
11136
4ee9c684 11137/* A wrapper function for builtin folding that prevents warnings for
491e04ef 11138 "statement without effect" and the like, caused by removing the
4ee9c684 11139 call node earlier than the warning is generated. */
11140
11141tree
389dd41b 11142fold_call_expr (location_t loc, tree exp, bool ignore)
4ee9c684 11143{
c2f47e15 11144 tree ret = NULL_TREE;
11145 tree fndecl = get_callee_fndecl (exp);
11146 if (fndecl
11147 && TREE_CODE (fndecl) == FUNCTION_DECL
48dc2227 11148 && DECL_BUILT_IN (fndecl)
11149 /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
11150 yet. Defer folding until we see all the arguments
11151 (after inlining). */
11152 && !CALL_EXPR_VA_ARG_PACK (exp))
11153 {
11154 int nargs = call_expr_nargs (exp);
11155
11156 /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
11157 instead last argument is __builtin_va_arg_pack (). Defer folding
11158 even in that case, until arguments are finalized. */
11159 if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
11160 {
11161 tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1));
11162 if (fndecl2
11163 && TREE_CODE (fndecl2) == FUNCTION_DECL
11164 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
11165 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
11166 return NULL_TREE;
11167 }
11168
198622c0 11169 if (avoid_folding_inline_builtin (fndecl))
11170 return NULL_TREE;
11171
c2f47e15 11172 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
97d67146 11173 return targetm.fold_builtin (fndecl, call_expr_nargs (exp),
11174 CALL_EXPR_ARGP (exp), ignore);
c2f47e15 11175 else
11176 {
c2f47e15 11177 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
11178 {
11179 tree *args = CALL_EXPR_ARGP (exp);
389dd41b 11180 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
c2f47e15 11181 }
11182 if (!ret)
389dd41b 11183 ret = fold_builtin_varargs (loc, fndecl, exp, ignore);
c2f47e15 11184 if (ret)
389dd41b 11185 return ret;
c2f47e15 11186 }
4ee9c684 11187 }
c2f47e15 11188 return NULL_TREE;
11189}
48e1416a 11190
c2f47e15 11191/* Conveniently construct a function call expression. FNDECL names the
414c3a2c 11192 function to be called and N arguments are passed in the array
11193 ARGARRAY. */
48e1416a 11194
c2f47e15 11195tree
414c3a2c 11196build_call_expr_loc_array (location_t loc, tree fndecl, int n, tree *argarray)
c2f47e15 11197{
11198 tree fntype = TREE_TYPE (fndecl);
11199 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
414c3a2c 11200
389dd41b 11201 return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray);
c2f47e15 11202}
11203
414c3a2c 11204/* Conveniently construct a function call expression. FNDECL names the
11205 function to be called and the arguments are passed in the vector
11206 VEC. */
11207
11208tree
f1f41a6c 11209build_call_expr_loc_vec (location_t loc, tree fndecl, vec<tree, va_gc> *vec)
414c3a2c 11210{
f1f41a6c 11211 return build_call_expr_loc_array (loc, fndecl, vec_safe_length (vec),
11212 vec_safe_address (vec));
414c3a2c 11213}
11214
11215
c2f47e15 11216/* Conveniently construct a function call expression. FNDECL names the
11217 function to be called, N is the number of arguments, and the "..."
11218 parameters are the argument expressions. */
48e1416a 11219
c2f47e15 11220tree
389dd41b 11221build_call_expr_loc (location_t loc, tree fndecl, int n, ...)
c2f47e15 11222{
11223 va_list ap;
414c3a2c 11224 tree *argarray = XALLOCAVEC (tree, n);
d01f58f9 11225 int i;
c2f47e15 11226
11227 va_start (ap, n);
d01f58f9 11228 for (i = 0; i < n; i++)
11229 argarray[i] = va_arg (ap, tree);
c2f47e15 11230 va_end (ap);
414c3a2c 11231 return build_call_expr_loc_array (loc, fndecl, n, argarray);
4ee9c684 11232}
11233
0568e9c1 11234/* Like build_call_expr_loc (UNKNOWN_LOCATION, ...). Duplicated because
11235 varargs macros aren't supported by all bootstrap compilers. */
11236
11237tree
11238build_call_expr (tree fndecl, int n, ...)
11239{
11240 va_list ap;
414c3a2c 11241 tree *argarray = XALLOCAVEC (tree, n);
0568e9c1 11242 int i;
11243
11244 va_start (ap, n);
11245 for (i = 0; i < n; i++)
11246 argarray[i] = va_arg (ap, tree);
11247 va_end (ap);
414c3a2c 11248 return build_call_expr_loc_array (UNKNOWN_LOCATION, fndecl, n, argarray);
0568e9c1 11249}
11250
c2f47e15 11251/* Construct a CALL_EXPR with type TYPE with FN as the function expression.
d01f58f9 11252 N arguments are passed in the array ARGARRAY. */
805e22b2 11253
11254tree
389dd41b 11255fold_builtin_call_array (location_t loc, tree type,
d01f58f9 11256 tree fn,
11257 int n,
11258 tree *argarray)
7e15618b 11259{
c2f47e15 11260 tree ret = NULL_TREE;
c2f47e15 11261 tree exp;
11262
11263 if (TREE_CODE (fn) == ADDR_EXPR)
11264 {
11265 tree fndecl = TREE_OPERAND (fn, 0);
11266 if (TREE_CODE (fndecl) == FUNCTION_DECL
11267 && DECL_BUILT_IN (fndecl))
11268 {
48dc2227 11269 /* If last argument is __builtin_va_arg_pack (), arguments to this
11270 function are not finalized yet. Defer folding until they are. */
11271 if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
11272 {
11273 tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
11274 if (fndecl2
11275 && TREE_CODE (fndecl2) == FUNCTION_DECL
11276 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
11277 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
389dd41b 11278 return build_call_array_loc (loc, type, fn, n, argarray);
48dc2227 11279 }
198622c0 11280 if (avoid_folding_inline_builtin (fndecl))
389dd41b 11281 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 11282 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
11283 {
97d67146 11284 ret = targetm.fold_builtin (fndecl, n, argarray, false);
11285 if (ret)
11286 return ret;
11287
389dd41b 11288 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 11289 }
11290 else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
11291 {
11292 /* First try the transformations that don't require consing up
11293 an exp. */
389dd41b 11294 ret = fold_builtin_n (loc, fndecl, argarray, n, false);
c2f47e15 11295 if (ret)
11296 return ret;
11297 }
11298
11299 /* If we got this far, we need to build an exp. */
389dd41b 11300 exp = build_call_array_loc (loc, type, fn, n, argarray);
11301 ret = fold_builtin_varargs (loc, fndecl, exp, false);
c2f47e15 11302 return ret ? ret : exp;
11303 }
11304 }
11305
389dd41b 11306 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 11307}
11308
af1409ad 11309/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
11310 list ARGS along with N new arguments in NEWARGS. SKIP is the number
11311 of arguments in ARGS to be omitted. OLDNARGS is the number of
11312 elements in ARGS. */
c2f47e15 11313
11314static tree
af1409ad 11315rewrite_call_expr_valist (location_t loc, int oldnargs, tree *args,
11316 int skip, tree fndecl, int n, va_list newargs)
c2f47e15 11317{
c2f47e15 11318 int nargs = oldnargs - skip + n;
c2f47e15 11319 tree *buffer;
11320
11321 if (n > 0)
11322 {
11323 int i, j;
7e15618b 11324
364c0c59 11325 buffer = XALLOCAVEC (tree, nargs);
c2f47e15 11326 for (i = 0; i < n; i++)
af1409ad 11327 buffer[i] = va_arg (newargs, tree);
c2f47e15 11328 for (j = skip; j < oldnargs; j++, i++)
af1409ad 11329 buffer[i] = args[j];
c2f47e15 11330 }
48e1416a 11331 else
af1409ad 11332 buffer = args + skip;
11333
11334 return build_call_expr_loc_array (loc, fndecl, nargs, buffer);
11335}
11336
11337/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
11338 list ARGS along with N new arguments specified as the "..."
11339 parameters. SKIP is the number of arguments in ARGS to be omitted.
11340 OLDNARGS is the number of elements in ARGS. */
11341
11342static tree
11343rewrite_call_expr_array (location_t loc, int oldnargs, tree *args,
11344 int skip, tree fndecl, int n, ...)
11345{
11346 va_list ap;
11347 tree t;
11348
11349 va_start (ap, n);
11350 t = rewrite_call_expr_valist (loc, oldnargs, args, skip, fndecl, n, ap);
11351 va_end (ap);
11352
11353 return t;
11354}
11355
11356/* Construct a new CALL_EXPR using the tail of the argument list of EXP
11357 along with N new arguments specified as the "..." parameters. SKIP
11358 is the number of arguments in EXP to be omitted. This function is used
11359 to do varargs-to-varargs transformations. */
11360
11361static tree
11362rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...)
11363{
11364 va_list ap;
11365 tree t;
11366
11367 va_start (ap, n);
11368 t = rewrite_call_expr_valist (loc, call_expr_nargs (exp),
11369 CALL_EXPR_ARGP (exp), skip, fndecl, n, ap);
11370 va_end (ap);
c2f47e15 11371
af1409ad 11372 return t;
c2f47e15 11373}
11374
11375/* Validate a single argument ARG against a tree code CODE representing
11376 a type. */
48e1416a 11377
c2f47e15 11378static bool
b7bf20db 11379validate_arg (const_tree arg, enum tree_code code)
c2f47e15 11380{
11381 if (!arg)
11382 return false;
11383 else if (code == POINTER_TYPE)
11384 return POINTER_TYPE_P (TREE_TYPE (arg));
c7f617c2 11385 else if (code == INTEGER_TYPE)
11386 return INTEGRAL_TYPE_P (TREE_TYPE (arg));
c2f47e15 11387 return code == TREE_CODE (TREE_TYPE (arg));
7e15618b 11388}
0eb671f7 11389
75a70cf9 11390/* This function validates the types of a function call argument list
11391 against a specified list of tree_codes. If the last specifier is a 0,
11392 that represents an ellipses, otherwise the last specifier must be a
11393 VOID_TYPE.
11394
11395 This is the GIMPLE version of validate_arglist. Eventually we want to
11396 completely convert builtins.c to work from GIMPLEs and the tree based
11397 validate_arglist will then be removed. */
11398
11399bool
11400validate_gimple_arglist (const_gimple call, ...)
11401{
11402 enum tree_code code;
11403 bool res = 0;
11404 va_list ap;
11405 const_tree arg;
11406 size_t i;
11407
11408 va_start (ap, call);
11409 i = 0;
11410
11411 do
11412 {
d62e827b 11413 code = (enum tree_code) va_arg (ap, int);
75a70cf9 11414 switch (code)
11415 {
11416 case 0:
11417 /* This signifies an ellipses, any further arguments are all ok. */
11418 res = true;
11419 goto end;
11420 case VOID_TYPE:
11421 /* This signifies an endlink, if no arguments remain, return
11422 true, otherwise return false. */
11423 res = (i == gimple_call_num_args (call));
11424 goto end;
11425 default:
11426 /* If no parameters remain or the parameter's code does not
11427 match the specified code, return false. Otherwise continue
11428 checking any remaining arguments. */
11429 arg = gimple_call_arg (call, i++);
11430 if (!validate_arg (arg, code))
11431 goto end;
11432 break;
11433 }
11434 }
11435 while (1);
11436
11437 /* We need gotos here since we can only have one VA_CLOSE in a
11438 function. */
11439 end: ;
11440 va_end (ap);
11441
11442 return res;
11443}
11444
0eb671f7 11445/* This function validates the types of a function call argument list
c2f47e15 11446 against a specified list of tree_codes. If the last specifier is a 0,
11447 that represents an ellipses, otherwise the last specifier must be a
11448 VOID_TYPE. */
27d0c333 11449
c2f47e15 11450bool
b7bf20db 11451validate_arglist (const_tree callexpr, ...)
0eb671f7 11452{
0eb671f7 11453 enum tree_code code;
c2f47e15 11454 bool res = 0;
ee582a61 11455 va_list ap;
b7bf20db 11456 const_call_expr_arg_iterator iter;
11457 const_tree arg;
aecda0d6 11458
c2f47e15 11459 va_start (ap, callexpr);
b7bf20db 11460 init_const_call_expr_arg_iterator (callexpr, &iter);
0eb671f7 11461
f0ce3b1f 11462 do
0eb671f7 11463 {
d62e827b 11464 code = (enum tree_code) va_arg (ap, int);
f0ce3b1f 11465 switch (code)
11466 {
11467 case 0:
11468 /* This signifies an ellipses, any further arguments are all ok. */
c2f47e15 11469 res = true;
f0ce3b1f 11470 goto end;
11471 case VOID_TYPE:
11472 /* This signifies an endlink, if no arguments remain, return
11473 true, otherwise return false. */
b7bf20db 11474 res = !more_const_call_expr_args_p (&iter);
f0ce3b1f 11475 goto end;
11476 default:
11477 /* If no parameters remain or the parameter's code does not
11478 match the specified code, return false. Otherwise continue
11479 checking any remaining arguments. */
b7bf20db 11480 arg = next_const_call_expr_arg (&iter);
c2f47e15 11481 if (!validate_arg (arg, code))
f0ce3b1f 11482 goto end;
11483 break;
11484 }
0eb671f7 11485 }
f0ce3b1f 11486 while (1);
0903457a 11487
11488 /* We need gotos here since we can only have one VA_CLOSE in a
11489 function. */
11490 end: ;
ee582a61 11491 va_end (ap);
0903457a 11492
11493 return res;
0eb671f7 11494}
fc2a2dcb 11495
fc2a2dcb 11496/* Default target-specific builtin expander that does nothing. */
11497
11498rtx
aecda0d6 11499default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
11500 rtx target ATTRIBUTE_UNUSED,
11501 rtx subtarget ATTRIBUTE_UNUSED,
11502 enum machine_mode mode ATTRIBUTE_UNUSED,
11503 int ignore ATTRIBUTE_UNUSED)
fc2a2dcb 11504{
11505 return NULL_RTX;
11506}
c7926a82 11507
01537105 11508/* Returns true is EXP represents data that would potentially reside
11509 in a readonly section. */
11510
11511static bool
11512readonly_data_expr (tree exp)
11513{
11514 STRIP_NOPS (exp);
11515
9ff0637e 11516 if (TREE_CODE (exp) != ADDR_EXPR)
11517 return false;
11518
11519 exp = get_base_address (TREE_OPERAND (exp, 0));
11520 if (!exp)
11521 return false;
11522
11523 /* Make sure we call decl_readonly_section only for trees it
11524 can handle (since it returns true for everything it doesn't
11525 understand). */
491e04ef 11526 if (TREE_CODE (exp) == STRING_CST
9ff0637e 11527 || TREE_CODE (exp) == CONSTRUCTOR
11528 || (TREE_CODE (exp) == VAR_DECL && TREE_STATIC (exp)))
11529 return decl_readonly_section (exp, 0);
01537105 11530 else
11531 return false;
11532}
4ee9c684 11533
c2f47e15 11534/* Simplify a call to the strstr builtin. S1 and S2 are the arguments
11535 to the call, and TYPE is its return type.
4ee9c684 11536
c2f47e15 11537 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11538 simplified form of the call as a tree.
11539
11540 The simplified form may be a constant or other expression which
11541 computes the same value, but in a more efficient manner (including
11542 calls to other builtin functions).
11543
11544 The call may contain arguments which need to be evaluated, but
11545 which are not useful to determine the result of the call. In
11546 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11547 COMPOUND_EXPR will be an argument which must be evaluated.
11548 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11549 COMPOUND_EXPR in the chain will contain the tree for the simplified
11550 form of the builtin function call. */
11551
11552static tree
389dd41b 11553fold_builtin_strstr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11554{
c2f47e15 11555 if (!validate_arg (s1, POINTER_TYPE)
11556 || !validate_arg (s2, POINTER_TYPE))
11557 return NULL_TREE;
4ee9c684 11558 else
11559 {
4ee9c684 11560 tree fn;
11561 const char *p1, *p2;
11562
11563 p2 = c_getstr (s2);
11564 if (p2 == NULL)
c2f47e15 11565 return NULL_TREE;
4ee9c684 11566
11567 p1 = c_getstr (s1);
11568 if (p1 != NULL)
11569 {
11570 const char *r = strstr (p1, p2);
daa1d5f5 11571 tree tem;
4ee9c684 11572
4ee9c684 11573 if (r == NULL)
779b4c41 11574 return build_int_cst (TREE_TYPE (s1), 0);
c0c67e38 11575
11576 /* Return an offset into the constant string argument. */
2cc66f2a 11577 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11578 return fold_convert_loc (loc, type, tem);
4ee9c684 11579 }
11580
7efa231c 11581 /* The argument is const char *, and the result is char *, so we need
11582 a type conversion here to avoid a warning. */
4ee9c684 11583 if (p2[0] == '\0')
389dd41b 11584 return fold_convert_loc (loc, type, s1);
4ee9c684 11585
11586 if (p2[1] != '\0')
c2f47e15 11587 return NULL_TREE;
4ee9c684 11588
b9a16870 11589 fn = builtin_decl_implicit (BUILT_IN_STRCHR);
4ee9c684 11590 if (!fn)
c2f47e15 11591 return NULL_TREE;
4ee9c684 11592
11593 /* New argument list transforming strstr(s1, s2) to
11594 strchr(s1, s2[0]). */
7002a1c8 11595 return build_call_expr_loc (loc, fn, 2, s1,
11596 build_int_cst (integer_type_node, p2[0]));
4ee9c684 11597 }
11598}
11599
c2f47e15 11600/* Simplify a call to the strchr builtin. S1 and S2 are the arguments to
11601 the call, and TYPE is its return type.
4ee9c684 11602
c2f47e15 11603 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11604 simplified form of the call as a tree.
11605
11606 The simplified form may be a constant or other expression which
11607 computes the same value, but in a more efficient manner (including
11608 calls to other builtin functions).
11609
11610 The call may contain arguments which need to be evaluated, but
11611 which are not useful to determine the result of the call. In
11612 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11613 COMPOUND_EXPR will be an argument which must be evaluated.
11614 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11615 COMPOUND_EXPR in the chain will contain the tree for the simplified
11616 form of the builtin function call. */
11617
11618static tree
389dd41b 11619fold_builtin_strchr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11620{
c2f47e15 11621 if (!validate_arg (s1, POINTER_TYPE)
11622 || !validate_arg (s2, INTEGER_TYPE))
11623 return NULL_TREE;
4ee9c684 11624 else
11625 {
4ee9c684 11626 const char *p1;
11627
11628 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 11629 return NULL_TREE;
4ee9c684 11630
11631 p1 = c_getstr (s1);
11632 if (p1 != NULL)
11633 {
11634 char c;
11635 const char *r;
daa1d5f5 11636 tree tem;
4ee9c684 11637
11638 if (target_char_cast (s2, &c))
c2f47e15 11639 return NULL_TREE;
4ee9c684 11640
11641 r = strchr (p1, c);
11642
11643 if (r == NULL)
779b4c41 11644 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11645
11646 /* Return an offset into the constant string argument. */
2cc66f2a 11647 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11648 return fold_convert_loc (loc, type, tem);
4ee9c684 11649 }
c2f47e15 11650 return NULL_TREE;
4ee9c684 11651 }
11652}
11653
c2f47e15 11654/* Simplify a call to the strrchr builtin. S1 and S2 are the arguments to
11655 the call, and TYPE is its return type.
4ee9c684 11656
c2f47e15 11657 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11658 simplified form of the call as a tree.
11659
11660 The simplified form may be a constant or other expression which
11661 computes the same value, but in a more efficient manner (including
11662 calls to other builtin functions).
11663
11664 The call may contain arguments which need to be evaluated, but
11665 which are not useful to determine the result of the call. In
11666 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11667 COMPOUND_EXPR will be an argument which must be evaluated.
11668 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11669 COMPOUND_EXPR in the chain will contain the tree for the simplified
11670 form of the builtin function call. */
11671
11672static tree
389dd41b 11673fold_builtin_strrchr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11674{
c2f47e15 11675 if (!validate_arg (s1, POINTER_TYPE)
11676 || !validate_arg (s2, INTEGER_TYPE))
11677 return NULL_TREE;
4ee9c684 11678 else
11679 {
4ee9c684 11680 tree fn;
11681 const char *p1;
11682
11683 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 11684 return NULL_TREE;
4ee9c684 11685
11686 p1 = c_getstr (s1);
11687 if (p1 != NULL)
11688 {
11689 char c;
11690 const char *r;
daa1d5f5 11691 tree tem;
4ee9c684 11692
11693 if (target_char_cast (s2, &c))
c2f47e15 11694 return NULL_TREE;
4ee9c684 11695
11696 r = strrchr (p1, c);
11697
11698 if (r == NULL)
779b4c41 11699 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11700
11701 /* Return an offset into the constant string argument. */
2cc66f2a 11702 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11703 return fold_convert_loc (loc, type, tem);
4ee9c684 11704 }
11705
11706 if (! integer_zerop (s2))
c2f47e15 11707 return NULL_TREE;
4ee9c684 11708
b9a16870 11709 fn = builtin_decl_implicit (BUILT_IN_STRCHR);
4ee9c684 11710 if (!fn)
c2f47e15 11711 return NULL_TREE;
4ee9c684 11712
11713 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
389dd41b 11714 return build_call_expr_loc (loc, fn, 2, s1, s2);
4ee9c684 11715 }
11716}
11717
c2f47e15 11718/* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments
11719 to the call, and TYPE is its return type.
4ee9c684 11720
c2f47e15 11721 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11722 simplified form of the call as a tree.
11723
11724 The simplified form may be a constant or other expression which
11725 computes the same value, but in a more efficient manner (including
11726 calls to other builtin functions).
11727
11728 The call may contain arguments which need to be evaluated, but
11729 which are not useful to determine the result of the call. In
11730 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11731 COMPOUND_EXPR will be an argument which must be evaluated.
11732 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11733 COMPOUND_EXPR in the chain will contain the tree for the simplified
11734 form of the builtin function call. */
11735
11736static tree
389dd41b 11737fold_builtin_strpbrk (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11738{
c2f47e15 11739 if (!validate_arg (s1, POINTER_TYPE)
11740 || !validate_arg (s2, POINTER_TYPE))
11741 return NULL_TREE;
4ee9c684 11742 else
11743 {
4ee9c684 11744 tree fn;
11745 const char *p1, *p2;
11746
11747 p2 = c_getstr (s2);
11748 if (p2 == NULL)
c2f47e15 11749 return NULL_TREE;
4ee9c684 11750
11751 p1 = c_getstr (s1);
11752 if (p1 != NULL)
11753 {
11754 const char *r = strpbrk (p1, p2);
daa1d5f5 11755 tree tem;
4ee9c684 11756
11757 if (r == NULL)
779b4c41 11758 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11759
11760 /* Return an offset into the constant string argument. */
2cc66f2a 11761 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11762 return fold_convert_loc (loc, type, tem);
4ee9c684 11763 }
11764
11765 if (p2[0] == '\0')
05abc81b 11766 /* strpbrk(x, "") == NULL.
11767 Evaluate and ignore s1 in case it had side-effects. */
389dd41b 11768 return omit_one_operand_loc (loc, TREE_TYPE (s1), integer_zero_node, s1);
4ee9c684 11769
11770 if (p2[1] != '\0')
c2f47e15 11771 return NULL_TREE; /* Really call strpbrk. */
4ee9c684 11772
b9a16870 11773 fn = builtin_decl_implicit (BUILT_IN_STRCHR);
4ee9c684 11774 if (!fn)
c2f47e15 11775 return NULL_TREE;
4ee9c684 11776
11777 /* New argument list transforming strpbrk(s1, s2) to
11778 strchr(s1, s2[0]). */
7002a1c8 11779 return build_call_expr_loc (loc, fn, 2, s1,
11780 build_int_cst (integer_type_node, p2[0]));
4ee9c684 11781 }
11782}
11783
c2f47e15 11784/* Simplify a call to the strcat builtin. DST and SRC are the arguments
11785 to the call.
4ee9c684 11786
c2f47e15 11787 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11788 simplified form of the call as a tree.
11789
11790 The simplified form may be a constant or other expression which
11791 computes the same value, but in a more efficient manner (including
11792 calls to other builtin functions).
11793
11794 The call may contain arguments which need to be evaluated, but
11795 which are not useful to determine the result of the call. In
11796 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11797 COMPOUND_EXPR will be an argument which must be evaluated.
11798 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11799 COMPOUND_EXPR in the chain will contain the tree for the simplified
11800 form of the builtin function call. */
11801
11802static tree
389dd41b 11803fold_builtin_strcat (location_t loc ATTRIBUTE_UNUSED, tree dst, tree src)
4ee9c684 11804{
c2f47e15 11805 if (!validate_arg (dst, POINTER_TYPE)
11806 || !validate_arg (src, POINTER_TYPE))
11807 return NULL_TREE;
4ee9c684 11808 else
11809 {
4ee9c684 11810 const char *p = c_getstr (src);
11811
11812 /* If the string length is zero, return the dst parameter. */
11813 if (p && *p == '\0')
11814 return dst;
11815
a65c4d64 11816 if (optimize_insn_for_speed_p ())
11817 {
11818 /* See if we can store by pieces into (dst + strlen(dst)). */
11819 tree newdst, call;
b9a16870 11820 tree strlen_fn = builtin_decl_implicit (BUILT_IN_STRLEN);
11821 tree strcpy_fn = builtin_decl_implicit (BUILT_IN_STRCPY);
a65c4d64 11822
11823 if (!strlen_fn || !strcpy_fn)
11824 return NULL_TREE;
11825
11826 /* If we don't have a movstr we don't want to emit an strcpy
11827 call. We have to do that if the length of the source string
11828 isn't computable (in that case we can use memcpy probably
48e1416a 11829 later expanding to a sequence of mov instructions). If we
a65c4d64 11830 have movstr instructions we can emit strcpy calls. */
11831 if (!HAVE_movstr)
11832 {
11833 tree len = c_strlen (src, 1);
11834 if (! len || TREE_SIDE_EFFECTS (len))
11835 return NULL_TREE;
11836 }
11837
11838 /* Stabilize the argument list. */
11839 dst = builtin_save_expr (dst);
11840
11841 /* Create strlen (dst). */
11842 newdst = build_call_expr_loc (loc, strlen_fn, 1, dst);
11843 /* Create (dst p+ strlen (dst)). */
11844
2cc66f2a 11845 newdst = fold_build_pointer_plus_loc (loc, dst, newdst);
a65c4d64 11846 newdst = builtin_save_expr (newdst);
11847
11848 call = build_call_expr_loc (loc, strcpy_fn, 2, newdst, src);
11849 return build2 (COMPOUND_EXPR, TREE_TYPE (dst), call, dst);
11850 }
c2f47e15 11851 return NULL_TREE;
4ee9c684 11852 }
11853}
11854
c2f47e15 11855/* Simplify a call to the strncat builtin. DST, SRC, and LEN are the
11856 arguments to the call.
4ee9c684 11857
c2f47e15 11858 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11859 simplified form of the call as a tree.
11860
11861 The simplified form may be a constant or other expression which
11862 computes the same value, but in a more efficient manner (including
11863 calls to other builtin functions).
11864
11865 The call may contain arguments which need to be evaluated, but
11866 which are not useful to determine the result of the call. In
11867 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11868 COMPOUND_EXPR will be an argument which must be evaluated.
11869 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11870 COMPOUND_EXPR in the chain will contain the tree for the simplified
11871 form of the builtin function call. */
11872
11873static tree
389dd41b 11874fold_builtin_strncat (location_t loc, tree dst, tree src, tree len)
4ee9c684 11875{
c2f47e15 11876 if (!validate_arg (dst, POINTER_TYPE)
11877 || !validate_arg (src, POINTER_TYPE)
11878 || !validate_arg (len, INTEGER_TYPE))
11879 return NULL_TREE;
4ee9c684 11880 else
11881 {
4ee9c684 11882 const char *p = c_getstr (src);
11883
11884 /* If the requested length is zero, or the src parameter string
0a39fd54 11885 length is zero, return the dst parameter. */
4ee9c684 11886 if (integer_zerop (len) || (p && *p == '\0'))
389dd41b 11887 return omit_two_operands_loc (loc, TREE_TYPE (dst), dst, src, len);
4ee9c684 11888
11889 /* If the requested len is greater than or equal to the string
a0c938f0 11890 length, call strcat. */
4ee9c684 11891 if (TREE_CODE (len) == INTEGER_CST && p
11892 && compare_tree_int (len, strlen (p)) >= 0)
11893 {
b9a16870 11894 tree fn = builtin_decl_implicit (BUILT_IN_STRCAT);
4ee9c684 11895
11896 /* If the replacement _DECL isn't initialized, don't do the
11897 transformation. */
11898 if (!fn)
c2f47e15 11899 return NULL_TREE;
4ee9c684 11900
389dd41b 11901 return build_call_expr_loc (loc, fn, 2, dst, src);
4ee9c684 11902 }
c2f47e15 11903 return NULL_TREE;
4ee9c684 11904 }
11905}
11906
c2f47e15 11907/* Simplify a call to the strspn builtin. S1 and S2 are the arguments
11908 to the call.
4ee9c684 11909
c2f47e15 11910 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11911 simplified form of the call as a tree.
11912
11913 The simplified form may be a constant or other expression which
11914 computes the same value, but in a more efficient manner (including
11915 calls to other builtin functions).
11916
11917 The call may contain arguments which need to be evaluated, but
11918 which are not useful to determine the result of the call. In
11919 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11920 COMPOUND_EXPR will be an argument which must be evaluated.
11921 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11922 COMPOUND_EXPR in the chain will contain the tree for the simplified
11923 form of the builtin function call. */
11924
11925static tree
389dd41b 11926fold_builtin_strspn (location_t loc, tree s1, tree s2)
4ee9c684 11927{
c2f47e15 11928 if (!validate_arg (s1, POINTER_TYPE)
11929 || !validate_arg (s2, POINTER_TYPE))
11930 return NULL_TREE;
4ee9c684 11931 else
11932 {
4ee9c684 11933 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11934
11935 /* If both arguments are constants, evaluate at compile-time. */
11936 if (p1 && p2)
11937 {
11938 const size_t r = strspn (p1, p2);
547b938d 11939 return build_int_cst (size_type_node, r);
4ee9c684 11940 }
11941
c2f47e15 11942 /* If either argument is "", return NULL_TREE. */
4ee9c684 11943 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9bc9f15f 11944 /* Evaluate and ignore both arguments in case either one has
11945 side-effects. */
389dd41b 11946 return omit_two_operands_loc (loc, size_type_node, size_zero_node,
9bc9f15f 11947 s1, s2);
c2f47e15 11948 return NULL_TREE;
4ee9c684 11949 }
11950}
11951
c2f47e15 11952/* Simplify a call to the strcspn builtin. S1 and S2 are the arguments
11953 to the call.
4ee9c684 11954
c2f47e15 11955 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11956 simplified form of the call as a tree.
11957
11958 The simplified form may be a constant or other expression which
11959 computes the same value, but in a more efficient manner (including
11960 calls to other builtin functions).
11961
11962 The call may contain arguments which need to be evaluated, but
11963 which are not useful to determine the result of the call. In
11964 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11965 COMPOUND_EXPR will be an argument which must be evaluated.
11966 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11967 COMPOUND_EXPR in the chain will contain the tree for the simplified
11968 form of the builtin function call. */
11969
11970static tree
389dd41b 11971fold_builtin_strcspn (location_t loc, tree s1, tree s2)
4ee9c684 11972{
c2f47e15 11973 if (!validate_arg (s1, POINTER_TYPE)
11974 || !validate_arg (s2, POINTER_TYPE))
11975 return NULL_TREE;
4ee9c684 11976 else
11977 {
4ee9c684 11978 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11979
11980 /* If both arguments are constants, evaluate at compile-time. */
11981 if (p1 && p2)
11982 {
11983 const size_t r = strcspn (p1, p2);
547b938d 11984 return build_int_cst (size_type_node, r);
4ee9c684 11985 }
11986
c2f47e15 11987 /* If the first argument is "", return NULL_TREE. */
4ee9c684 11988 if (p1 && *p1 == '\0')
11989 {
11990 /* Evaluate and ignore argument s2 in case it has
11991 side-effects. */
389dd41b 11992 return omit_one_operand_loc (loc, size_type_node,
39761420 11993 size_zero_node, s2);
4ee9c684 11994 }
11995
11996 /* If the second argument is "", return __builtin_strlen(s1). */
11997 if (p2 && *p2 == '\0')
11998 {
b9a16870 11999 tree fn = builtin_decl_implicit (BUILT_IN_STRLEN);
4ee9c684 12000
12001 /* If the replacement _DECL isn't initialized, don't do the
12002 transformation. */
12003 if (!fn)
c2f47e15 12004 return NULL_TREE;
4ee9c684 12005
389dd41b 12006 return build_call_expr_loc (loc, fn, 1, s1);
4ee9c684 12007 }
c2f47e15 12008 return NULL_TREE;
4ee9c684 12009 }
12010}
12011
c2f47e15 12012/* Fold a call to the fputs builtin. ARG0 and ARG1 are the arguments
12013 to the call. IGNORE is true if the value returned
f0613857 12014 by the builtin will be ignored. UNLOCKED is true is true if this
12015 actually a call to fputs_unlocked. If LEN in non-NULL, it represents
12016 the known length of the string. Return NULL_TREE if no simplification
12017 was possible. */
4ee9c684 12018
12019tree
389dd41b 12020fold_builtin_fputs (location_t loc, tree arg0, tree arg1,
12021 bool ignore, bool unlocked, tree len)
4ee9c684 12022{
6d77ed92 12023 /* If we're using an unlocked function, assume the other unlocked
12024 functions exist explicitly. */
b9a16870 12025 tree const fn_fputc = (unlocked
12026 ? builtin_decl_explicit (BUILT_IN_FPUTC_UNLOCKED)
12027 : builtin_decl_implicit (BUILT_IN_FPUTC));
12028 tree const fn_fwrite = (unlocked
12029 ? builtin_decl_explicit (BUILT_IN_FWRITE_UNLOCKED)
12030 : builtin_decl_implicit (BUILT_IN_FWRITE));
4ee9c684 12031
c403edd4 12032 /* If the return value is used, don't do the transformation. */
12033 if (!ignore)
c2f47e15 12034 return NULL_TREE;
4ee9c684 12035
12036 /* Verify the arguments in the original call. */
c2f47e15 12037 if (!validate_arg (arg0, POINTER_TYPE)
12038 || !validate_arg (arg1, POINTER_TYPE))
12039 return NULL_TREE;
4ee9c684 12040
f0613857 12041 if (! len)
c2f47e15 12042 len = c_strlen (arg0, 0);
4ee9c684 12043
12044 /* Get the length of the string passed to fputs. If the length
12045 can't be determined, punt. */
12046 if (!len
12047 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 12048 return NULL_TREE;
4ee9c684 12049
12050 switch (compare_tree_int (len, 1))
12051 {
12052 case -1: /* length is 0, delete the call entirely . */
389dd41b 12053 return omit_one_operand_loc (loc, integer_type_node,
12054 integer_zero_node, arg1);;
05abc81b 12055
4ee9c684 12056 case 0: /* length is 1, call fputc. */
12057 {
c2f47e15 12058 const char *p = c_getstr (arg0);
4ee9c684 12059
12060 if (p != NULL)
12061 {
c2f47e15 12062 if (fn_fputc)
389dd41b 12063 return build_call_expr_loc (loc, fn_fputc, 2,
7002a1c8 12064 build_int_cst
12065 (integer_type_node, p[0]), arg1);
c2f47e15 12066 else
12067 return NULL_TREE;
4ee9c684 12068 }
12069 }
12070 /* FALLTHROUGH */
12071 case 1: /* length is greater than 1, call fwrite. */
12072 {
0bed3869 12073 /* If optimizing for size keep fputs. */
0bfd8d5c 12074 if (optimize_function_for_size_p (cfun))
c2f47e15 12075 return NULL_TREE;
4ee9c684 12076 /* New argument list transforming fputs(string, stream) to
12077 fwrite(string, 1, len, stream). */
c2f47e15 12078 if (fn_fwrite)
389dd41b 12079 return build_call_expr_loc (loc, fn_fwrite, 4, arg0,
12080 size_one_node, len, arg1);
c2f47e15 12081 else
12082 return NULL_TREE;
4ee9c684 12083 }
12084 default:
64db345d 12085 gcc_unreachable ();
4ee9c684 12086 }
c2f47e15 12087 return NULL_TREE;
4ee9c684 12088}
12089
c2f47e15 12090/* Fold the next_arg or va_start call EXP. Returns true if there was an error
743b0c6a 12091 produced. False otherwise. This is done so that we don't output the error
12092 or warning twice or three times. */
75a70cf9 12093
743b0c6a 12094bool
c2f47e15 12095fold_builtin_next_arg (tree exp, bool va_start_p)
4ee9c684 12096{
12097 tree fntype = TREE_TYPE (current_function_decl);
c2f47e15 12098 int nargs = call_expr_nargs (exp);
12099 tree arg;
d98fd4a4 12100 /* There is good chance the current input_location points inside the
12101 definition of the va_start macro (perhaps on the token for
12102 builtin) in a system header, so warnings will not be emitted.
12103 Use the location in real source code. */
12104 source_location current_location =
12105 linemap_unwind_to_first_non_reserved_loc (line_table, input_location,
12106 NULL);
4ee9c684 12107
257d99c3 12108 if (!stdarg_p (fntype))
743b0c6a 12109 {
12110 error ("%<va_start%> used in function with fixed args");
12111 return true;
12112 }
c2f47e15 12113
12114 if (va_start_p)
79012a9d 12115 {
c2f47e15 12116 if (va_start_p && (nargs != 2))
12117 {
12118 error ("wrong number of arguments to function %<va_start%>");
12119 return true;
12120 }
12121 arg = CALL_EXPR_ARG (exp, 1);
79012a9d 12122 }
12123 /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
12124 when we checked the arguments and if needed issued a warning. */
c2f47e15 12125 else
4ee9c684 12126 {
c2f47e15 12127 if (nargs == 0)
12128 {
12129 /* Evidently an out of date version of <stdarg.h>; can't validate
12130 va_start's second argument, but can still work as intended. */
d98fd4a4 12131 warning_at (current_location,
7edb1062 12132 OPT_Wvarargs,
12133 "%<__builtin_next_arg%> called without an argument");
c2f47e15 12134 return true;
12135 }
12136 else if (nargs > 1)
a0c938f0 12137 {
c2f47e15 12138 error ("wrong number of arguments to function %<__builtin_next_arg%>");
a0c938f0 12139 return true;
12140 }
c2f47e15 12141 arg = CALL_EXPR_ARG (exp, 0);
12142 }
12143
a8dd994c 12144 if (TREE_CODE (arg) == SSA_NAME)
12145 arg = SSA_NAME_VAR (arg);
12146
c2f47e15 12147 /* We destructively modify the call to be __builtin_va_start (ap, 0)
48e1416a 12148 or __builtin_next_arg (0) the first time we see it, after checking
c2f47e15 12149 the arguments and if needed issuing a warning. */
12150 if (!integer_zerop (arg))
12151 {
12152 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
79012a9d 12153
4ee9c684 12154 /* Strip off all nops for the sake of the comparison. This
12155 is not quite the same as STRIP_NOPS. It does more.
12156 We must also strip off INDIRECT_EXPR for C++ reference
12157 parameters. */
72dd6141 12158 while (CONVERT_EXPR_P (arg)
4ee9c684 12159 || TREE_CODE (arg) == INDIRECT_REF)
12160 arg = TREE_OPERAND (arg, 0);
12161 if (arg != last_parm)
a0c938f0 12162 {
b08cf617 12163 /* FIXME: Sometimes with the tree optimizers we can get the
12164 not the last argument even though the user used the last
12165 argument. We just warn and set the arg to be the last
12166 argument so that we will get wrong-code because of
12167 it. */
d98fd4a4 12168 warning_at (current_location,
7edb1062 12169 OPT_Wvarargs,
d98fd4a4 12170 "second parameter of %<va_start%> not last named argument");
743b0c6a 12171 }
24158ad7 12172
12173 /* Undefined by C99 7.15.1.4p4 (va_start):
12174 "If the parameter parmN is declared with the register storage
12175 class, with a function or array type, or with a type that is
12176 not compatible with the type that results after application of
12177 the default argument promotions, the behavior is undefined."
12178 */
12179 else if (DECL_REGISTER (arg))
d98fd4a4 12180 {
12181 warning_at (current_location,
7edb1062 12182 OPT_Wvarargs,
d98fd4a4 12183 "undefined behaviour when second parameter of "
12184 "%<va_start%> is declared with %<register%> storage");
12185 }
24158ad7 12186
79012a9d 12187 /* We want to verify the second parameter just once before the tree
a0c938f0 12188 optimizers are run and then avoid keeping it in the tree,
12189 as otherwise we could warn even for correct code like:
12190 void foo (int i, ...)
12191 { va_list ap; i++; va_start (ap, i); va_end (ap); } */
c2f47e15 12192 if (va_start_p)
12193 CALL_EXPR_ARG (exp, 1) = integer_zero_node;
12194 else
12195 CALL_EXPR_ARG (exp, 0) = integer_zero_node;
743b0c6a 12196 }
12197 return false;
4ee9c684 12198}
12199
12200
c2f47e15 12201/* Simplify a call to the sprintf builtin with arguments DEST, FMT, and ORIG.
12202 ORIG may be null if this is a 2-argument call. We don't attempt to
12203 simplify calls with more than 3 arguments.
4ee9c684 12204
c2f47e15 12205 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 12206 simplified form of the call as a tree. If IGNORED is true, it means that
12207 the caller does not use the returned value of the function. */
12208
12209static tree
389dd41b 12210fold_builtin_sprintf (location_t loc, tree dest, tree fmt,
12211 tree orig, int ignored)
4ee9c684 12212{
c2f47e15 12213 tree call, retval;
4ee9c684 12214 const char *fmt_str = NULL;
12215
12216 /* Verify the required arguments in the original call. We deal with two
12217 types of sprintf() calls: 'sprintf (str, fmt)' and
12218 'sprintf (dest, "%s", orig)'. */
c2f47e15 12219 if (!validate_arg (dest, POINTER_TYPE)
12220 || !validate_arg (fmt, POINTER_TYPE))
12221 return NULL_TREE;
12222 if (orig && !validate_arg (orig, POINTER_TYPE))
4ee9c684 12223 return NULL_TREE;
4ee9c684 12224
12225 /* Check whether the format is a literal string constant. */
12226 fmt_str = c_getstr (fmt);
12227 if (fmt_str == NULL)
12228 return NULL_TREE;
12229
12230 call = NULL_TREE;
12231 retval = NULL_TREE;
12232
d4473c84 12233 if (!init_target_chars ())
c2f47e15 12234 return NULL_TREE;
99eabcc1 12235
4ee9c684 12236 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 12237 if (strchr (fmt_str, target_percent) == NULL)
4ee9c684 12238 {
b9a16870 12239 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
4ee9c684 12240
12241 if (!fn)
12242 return NULL_TREE;
12243
72dfb3f2 12244 /* Don't optimize sprintf (buf, "abc", ptr++). */
c2f47e15 12245 if (orig)
72dfb3f2 12246 return NULL_TREE;
12247
4ee9c684 12248 /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
12249 'format' is known to contain no % formats. */
389dd41b 12250 call = build_call_expr_loc (loc, fn, 2, dest, fmt);
4ee9c684 12251 if (!ignored)
7002a1c8 12252 retval = build_int_cst (integer_type_node, strlen (fmt_str));
4ee9c684 12253 }
12254
12255 /* If the format is "%s", use strcpy if the result isn't used. */
99eabcc1 12256 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
4ee9c684 12257 {
c2f47e15 12258 tree fn;
b9a16870 12259 fn = builtin_decl_implicit (BUILT_IN_STRCPY);
4ee9c684 12260
12261 if (!fn)
12262 return NULL_TREE;
12263
72dfb3f2 12264 /* Don't crash on sprintf (str1, "%s"). */
c2f47e15 12265 if (!orig)
72dfb3f2 12266 return NULL_TREE;
12267
4ee9c684 12268 /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2). */
4ee9c684 12269 if (!ignored)
12270 {
12271 retval = c_strlen (orig, 1);
12272 if (!retval || TREE_CODE (retval) != INTEGER_CST)
12273 return NULL_TREE;
12274 }
389dd41b 12275 call = build_call_expr_loc (loc, fn, 2, dest, orig);
4ee9c684 12276 }
12277
12278 if (call && retval)
12279 {
389dd41b 12280 retval = fold_convert_loc
b9a16870 12281 (loc, TREE_TYPE (TREE_TYPE (builtin_decl_implicit (BUILT_IN_SPRINTF))),
4ee9c684 12282 retval);
05abc81b 12283 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
4ee9c684 12284 }
12285 else
12286 return call;
12287}
0a39fd54 12288
750d7b16 12289/* Simplify a call to the snprintf builtin with arguments DEST, DESTSIZE,
12290 FMT, and ORIG. ORIG may be null if this is a 3-argument call. We don't
12291 attempt to simplify calls with more than 4 arguments.
12292
12293 Return NULL_TREE if no simplification was possible, otherwise return the
12294 simplified form of the call as a tree. If IGNORED is true, it means that
12295 the caller does not use the returned value of the function. */
12296
12297static tree
12298fold_builtin_snprintf (location_t loc, tree dest, tree destsize, tree fmt,
12299 tree orig, int ignored)
12300{
12301 tree call, retval;
12302 const char *fmt_str = NULL;
12303 unsigned HOST_WIDE_INT destlen;
12304
12305 /* Verify the required arguments in the original call. We deal with two
12306 types of snprintf() calls: 'snprintf (str, cst, fmt)' and
12307 'snprintf (dest, cst, "%s", orig)'. */
12308 if (!validate_arg (dest, POINTER_TYPE)
12309 || !validate_arg (destsize, INTEGER_TYPE)
12310 || !validate_arg (fmt, POINTER_TYPE))
12311 return NULL_TREE;
12312 if (orig && !validate_arg (orig, POINTER_TYPE))
12313 return NULL_TREE;
12314
12315 if (!host_integerp (destsize, 1))
12316 return NULL_TREE;
12317
12318 /* Check whether the format is a literal string constant. */
12319 fmt_str = c_getstr (fmt);
12320 if (fmt_str == NULL)
12321 return NULL_TREE;
12322
12323 call = NULL_TREE;
12324 retval = NULL_TREE;
12325
12326 if (!init_target_chars ())
12327 return NULL_TREE;
12328
12329 destlen = tree_low_cst (destsize, 1);
12330
12331 /* If the format doesn't contain % args or %%, use strcpy. */
12332 if (strchr (fmt_str, target_percent) == NULL)
12333 {
b9a16870 12334 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
750d7b16 12335 size_t len = strlen (fmt_str);
12336
12337 /* Don't optimize snprintf (buf, 4, "abc", ptr++). */
12338 if (orig)
12339 return NULL_TREE;
12340
12341 /* We could expand this as
12342 memcpy (str, fmt, cst - 1); str[cst - 1] = '\0';
12343 or to
12344 memcpy (str, fmt_with_nul_at_cstm1, cst);
12345 but in the former case that might increase code size
12346 and in the latter case grow .rodata section too much.
12347 So punt for now. */
12348 if (len >= destlen)
12349 return NULL_TREE;
12350
12351 if (!fn)
12352 return NULL_TREE;
12353
12354 /* Convert snprintf (str, cst, fmt) into strcpy (str, fmt) when
12355 'format' is known to contain no % formats and
12356 strlen (fmt) < cst. */
12357 call = build_call_expr_loc (loc, fn, 2, dest, fmt);
12358
12359 if (!ignored)
7002a1c8 12360 retval = build_int_cst (integer_type_node, strlen (fmt_str));
750d7b16 12361 }
12362
12363 /* If the format is "%s", use strcpy if the result isn't used. */
12364 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
12365 {
b9a16870 12366 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
750d7b16 12367 unsigned HOST_WIDE_INT origlen;
12368
12369 /* Don't crash on snprintf (str1, cst, "%s"). */
12370 if (!orig)
12371 return NULL_TREE;
12372
12373 retval = c_strlen (orig, 1);
12374 if (!retval || !host_integerp (retval, 1))
12375 return NULL_TREE;
12376
12377 origlen = tree_low_cst (retval, 1);
12378 /* We could expand this as
12379 memcpy (str1, str2, cst - 1); str1[cst - 1] = '\0';
12380 or to
12381 memcpy (str1, str2_with_nul_at_cstm1, cst);
12382 but in the former case that might increase code size
12383 and in the latter case grow .rodata section too much.
12384 So punt for now. */
12385 if (origlen >= destlen)
12386 return NULL_TREE;
12387
12388 /* Convert snprintf (str1, cst, "%s", str2) into
12389 strcpy (str1, str2) if strlen (str2) < cst. */
12390 if (!fn)
12391 return NULL_TREE;
12392
12393 call = build_call_expr_loc (loc, fn, 2, dest, orig);
12394
12395 if (ignored)
12396 retval = NULL_TREE;
12397 }
12398
12399 if (call && retval)
12400 {
b9a16870 12401 tree fn = builtin_decl_explicit (BUILT_IN_SNPRINTF);
1914d98e 12402 retval = fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fn)), retval);
750d7b16 12403 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
12404 }
12405 else
12406 return call;
12407}
12408
c2f47e15 12409/* Expand a call EXP to __builtin_object_size. */
0a39fd54 12410
12411rtx
12412expand_builtin_object_size (tree exp)
12413{
12414 tree ost;
12415 int object_size_type;
12416 tree fndecl = get_callee_fndecl (exp);
0a39fd54 12417
c2f47e15 12418 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
0a39fd54 12419 {
b8c23db3 12420 error ("%Kfirst argument of %D must be a pointer, second integer constant",
12421 exp, fndecl);
0a39fd54 12422 expand_builtin_trap ();
12423 return const0_rtx;
12424 }
12425
c2f47e15 12426 ost = CALL_EXPR_ARG (exp, 1);
0a39fd54 12427 STRIP_NOPS (ost);
12428
12429 if (TREE_CODE (ost) != INTEGER_CST
12430 || tree_int_cst_sgn (ost) < 0
12431 || compare_tree_int (ost, 3) > 0)
12432 {
b8c23db3 12433 error ("%Klast argument of %D is not integer constant between 0 and 3",
12434 exp, fndecl);
0a39fd54 12435 expand_builtin_trap ();
12436 return const0_rtx;
12437 }
12438
12439 object_size_type = tree_low_cst (ost, 0);
12440
12441 return object_size_type < 2 ? constm1_rtx : const0_rtx;
12442}
12443
12444/* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
12445 FCODE is the BUILT_IN_* to use.
c2f47e15 12446 Return NULL_RTX if we failed; the caller should emit a normal call,
0a39fd54 12447 otherwise try to get the result in TARGET, if convenient (and in
12448 mode MODE if that's convenient). */
12449
12450static rtx
12451expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
12452 enum built_in_function fcode)
12453{
0a39fd54 12454 tree dest, src, len, size;
12455
c2f47e15 12456 if (!validate_arglist (exp,
0a39fd54 12457 POINTER_TYPE,
12458 fcode == BUILT_IN_MEMSET_CHK
12459 ? INTEGER_TYPE : POINTER_TYPE,
12460 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
c2f47e15 12461 return NULL_RTX;
0a39fd54 12462
c2f47e15 12463 dest = CALL_EXPR_ARG (exp, 0);
12464 src = CALL_EXPR_ARG (exp, 1);
12465 len = CALL_EXPR_ARG (exp, 2);
12466 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 12467
12468 if (! host_integerp (size, 1))
c2f47e15 12469 return NULL_RTX;
0a39fd54 12470
12471 if (host_integerp (len, 1) || integer_all_onesp (size))
12472 {
12473 tree fn;
12474
12475 if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
12476 {
b430e8d9 12477 warning_at (tree_nonartificial_location (exp),
12478 0, "%Kcall to %D will always overflow destination buffer",
12479 exp, get_callee_fndecl (exp));
c2f47e15 12480 return NULL_RTX;
0a39fd54 12481 }
12482
0a39fd54 12483 fn = NULL_TREE;
12484 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
12485 mem{cpy,pcpy,move,set} is available. */
12486 switch (fcode)
12487 {
12488 case BUILT_IN_MEMCPY_CHK:
b9a16870 12489 fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
0a39fd54 12490 break;
12491 case BUILT_IN_MEMPCPY_CHK:
b9a16870 12492 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
0a39fd54 12493 break;
12494 case BUILT_IN_MEMMOVE_CHK:
b9a16870 12495 fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
0a39fd54 12496 break;
12497 case BUILT_IN_MEMSET_CHK:
b9a16870 12498 fn = builtin_decl_explicit (BUILT_IN_MEMSET);
0a39fd54 12499 break;
12500 default:
12501 break;
12502 }
12503
12504 if (! fn)
c2f47e15 12505 return NULL_RTX;
0a39fd54 12506
0568e9c1 12507 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 3, dest, src, len);
a65c4d64 12508 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
12509 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0a39fd54 12510 return expand_expr (fn, target, mode, EXPAND_NORMAL);
12511 }
12512 else if (fcode == BUILT_IN_MEMSET_CHK)
c2f47e15 12513 return NULL_RTX;
0a39fd54 12514 else
12515 {
957d0361 12516 unsigned int dest_align = get_pointer_alignment (dest);
0a39fd54 12517
12518 /* If DEST is not a pointer type, call the normal function. */
12519 if (dest_align == 0)
c2f47e15 12520 return NULL_RTX;
0a39fd54 12521
12522 /* If SRC and DEST are the same (and not volatile), do nothing. */
12523 if (operand_equal_p (src, dest, 0))
12524 {
12525 tree expr;
12526
12527 if (fcode != BUILT_IN_MEMPCPY_CHK)
12528 {
12529 /* Evaluate and ignore LEN in case it has side-effects. */
12530 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
12531 return expand_expr (dest, target, mode, EXPAND_NORMAL);
12532 }
12533
2cc66f2a 12534 expr = fold_build_pointer_plus (dest, len);
0a39fd54 12535 return expand_expr (expr, target, mode, EXPAND_NORMAL);
12536 }
12537
12538 /* __memmove_chk special case. */
12539 if (fcode == BUILT_IN_MEMMOVE_CHK)
12540 {
957d0361 12541 unsigned int src_align = get_pointer_alignment (src);
0a39fd54 12542
12543 if (src_align == 0)
c2f47e15 12544 return NULL_RTX;
0a39fd54 12545
12546 /* If src is categorized for a readonly section we can use
12547 normal __memcpy_chk. */
12548 if (readonly_data_expr (src))
12549 {
b9a16870 12550 tree fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
0a39fd54 12551 if (!fn)
c2f47e15 12552 return NULL_RTX;
0568e9c1 12553 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 4,
12554 dest, src, len, size);
a65c4d64 12555 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
12556 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0a39fd54 12557 return expand_expr (fn, target, mode, EXPAND_NORMAL);
12558 }
12559 }
c2f47e15 12560 return NULL_RTX;
0a39fd54 12561 }
12562}
12563
12564/* Emit warning if a buffer overflow is detected at compile time. */
12565
12566static void
12567maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
12568{
c2f47e15 12569 int is_strlen = 0;
0a39fd54 12570 tree len, size;
b430e8d9 12571 location_t loc = tree_nonartificial_location (exp);
0a39fd54 12572
12573 switch (fcode)
12574 {
12575 case BUILT_IN_STRCPY_CHK:
12576 case BUILT_IN_STPCPY_CHK:
12577 /* For __strcat_chk the warning will be emitted only if overflowing
12578 by at least strlen (dest) + 1 bytes. */
12579 case BUILT_IN_STRCAT_CHK:
c2f47e15 12580 len = CALL_EXPR_ARG (exp, 1);
12581 size = CALL_EXPR_ARG (exp, 2);
0a39fd54 12582 is_strlen = 1;
12583 break;
b356dfef 12584 case BUILT_IN_STRNCAT_CHK:
0a39fd54 12585 case BUILT_IN_STRNCPY_CHK:
1063acde 12586 case BUILT_IN_STPNCPY_CHK:
c2f47e15 12587 len = CALL_EXPR_ARG (exp, 2);
12588 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 12589 break;
12590 case BUILT_IN_SNPRINTF_CHK:
12591 case BUILT_IN_VSNPRINTF_CHK:
c2f47e15 12592 len = CALL_EXPR_ARG (exp, 1);
12593 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 12594 break;
12595 default:
12596 gcc_unreachable ();
12597 }
12598
0a39fd54 12599 if (!len || !size)
12600 return;
12601
0a39fd54 12602 if (! host_integerp (size, 1) || integer_all_onesp (size))
12603 return;
12604
12605 if (is_strlen)
12606 {
12607 len = c_strlen (len, 1);
12608 if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
12609 return;
12610 }
b356dfef 12611 else if (fcode == BUILT_IN_STRNCAT_CHK)
12612 {
c2f47e15 12613 tree src = CALL_EXPR_ARG (exp, 1);
b356dfef 12614 if (! src || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
12615 return;
12616 src = c_strlen (src, 1);
12617 if (! src || ! host_integerp (src, 1))
12618 {
b430e8d9 12619 warning_at (loc, 0, "%Kcall to %D might overflow destination buffer",
12620 exp, get_callee_fndecl (exp));
b356dfef 12621 return;
12622 }
12623 else if (tree_int_cst_lt (src, size))
12624 return;
12625 }
0a39fd54 12626 else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
12627 return;
12628
b430e8d9 12629 warning_at (loc, 0, "%Kcall to %D will always overflow destination buffer",
12630 exp, get_callee_fndecl (exp));
0a39fd54 12631}
12632
12633/* Emit warning if a buffer overflow is detected at compile time
12634 in __sprintf_chk/__vsprintf_chk calls. */
12635
12636static void
12637maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
12638{
1e4adcfc 12639 tree size, len, fmt;
0a39fd54 12640 const char *fmt_str;
c2f47e15 12641 int nargs = call_expr_nargs (exp);
0a39fd54 12642
12643 /* Verify the required arguments in the original call. */
48e1416a 12644
c2f47e15 12645 if (nargs < 4)
0a39fd54 12646 return;
c2f47e15 12647 size = CALL_EXPR_ARG (exp, 2);
12648 fmt = CALL_EXPR_ARG (exp, 3);
0a39fd54 12649
12650 if (! host_integerp (size, 1) || integer_all_onesp (size))
12651 return;
12652
12653 /* Check whether the format is a literal string constant. */
12654 fmt_str = c_getstr (fmt);
12655 if (fmt_str == NULL)
12656 return;
12657
d4473c84 12658 if (!init_target_chars ())
99eabcc1 12659 return;
12660
0a39fd54 12661 /* If the format doesn't contain % args or %%, we know its size. */
99eabcc1 12662 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 12663 len = build_int_cstu (size_type_node, strlen (fmt_str));
12664 /* If the format is "%s" and first ... argument is a string literal,
12665 we know it too. */
c2f47e15 12666 else if (fcode == BUILT_IN_SPRINTF_CHK
12667 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12668 {
12669 tree arg;
12670
c2f47e15 12671 if (nargs < 5)
0a39fd54 12672 return;
c2f47e15 12673 arg = CALL_EXPR_ARG (exp, 4);
0a39fd54 12674 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
12675 return;
12676
12677 len = c_strlen (arg, 1);
12678 if (!len || ! host_integerp (len, 1))
12679 return;
12680 }
12681 else
12682 return;
12683
12684 if (! tree_int_cst_lt (len, size))
b430e8d9 12685 warning_at (tree_nonartificial_location (exp),
12686 0, "%Kcall to %D will always overflow destination buffer",
12687 exp, get_callee_fndecl (exp));
0a39fd54 12688}
12689
2c281b15 12690/* Emit warning if a free is called with address of a variable. */
12691
12692static void
12693maybe_emit_free_warning (tree exp)
12694{
12695 tree arg = CALL_EXPR_ARG (exp, 0);
12696
12697 STRIP_NOPS (arg);
12698 if (TREE_CODE (arg) != ADDR_EXPR)
12699 return;
12700
12701 arg = get_base_address (TREE_OPERAND (arg, 0));
182cf5a9 12702 if (arg == NULL || INDIRECT_REF_P (arg) || TREE_CODE (arg) == MEM_REF)
2c281b15 12703 return;
12704
12705 if (SSA_VAR_P (arg))
f74ea1c2 12706 warning_at (tree_nonartificial_location (exp), OPT_Wfree_nonheap_object,
12707 "%Kattempt to free a non-heap object %qD", exp, arg);
2c281b15 12708 else
f74ea1c2 12709 warning_at (tree_nonartificial_location (exp), OPT_Wfree_nonheap_object,
12710 "%Kattempt to free a non-heap object", exp);
2c281b15 12711}
12712
c2f47e15 12713/* Fold a call to __builtin_object_size with arguments PTR and OST,
12714 if possible. */
0a39fd54 12715
12716tree
c2f47e15 12717fold_builtin_object_size (tree ptr, tree ost)
0a39fd54 12718{
a6caa15f 12719 unsigned HOST_WIDE_INT bytes;
0a39fd54 12720 int object_size_type;
12721
c2f47e15 12722 if (!validate_arg (ptr, POINTER_TYPE)
12723 || !validate_arg (ost, INTEGER_TYPE))
12724 return NULL_TREE;
0a39fd54 12725
0a39fd54 12726 STRIP_NOPS (ost);
12727
12728 if (TREE_CODE (ost) != INTEGER_CST
12729 || tree_int_cst_sgn (ost) < 0
12730 || compare_tree_int (ost, 3) > 0)
c2f47e15 12731 return NULL_TREE;
0a39fd54 12732
12733 object_size_type = tree_low_cst (ost, 0);
12734
12735 /* __builtin_object_size doesn't evaluate side-effects in its arguments;
12736 if there are any side-effects, it returns (size_t) -1 for types 0 and 1
12737 and (size_t) 0 for types 2 and 3. */
12738 if (TREE_SIDE_EFFECTS (ptr))
697bbc3f 12739 return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
0a39fd54 12740
12741 if (TREE_CODE (ptr) == ADDR_EXPR)
a6caa15f 12742 {
12743 bytes = compute_builtin_object_size (ptr, object_size_type);
12744 if (double_int_fits_to_tree_p (size_type_node,
cf8f0e63 12745 double_int::from_uhwi (bytes)))
a6caa15f 12746 return build_int_cstu (size_type_node, bytes);
12747 }
0a39fd54 12748 else if (TREE_CODE (ptr) == SSA_NAME)
12749 {
0a39fd54 12750 /* If object size is not known yet, delay folding until
12751 later. Maybe subsequent passes will help determining
12752 it. */
12753 bytes = compute_builtin_object_size (ptr, object_size_type);
a6caa15f 12754 if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2 ? -1 : 0)
12755 && double_int_fits_to_tree_p (size_type_node,
cf8f0e63 12756 double_int::from_uhwi (bytes)))
a6caa15f 12757 return build_int_cstu (size_type_node, bytes);
0a39fd54 12758 }
12759
a6caa15f 12760 return NULL_TREE;
0a39fd54 12761}
12762
12763/* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
c2f47e15 12764 DEST, SRC, LEN, and SIZE are the arguments to the call.
0a39fd54 12765 IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_*
12766 code of the builtin. If MAXLEN is not NULL, it is maximum length
12767 passed as third argument. */
12768
12769tree
389dd41b 12770fold_builtin_memory_chk (location_t loc, tree fndecl,
c2f47e15 12771 tree dest, tree src, tree len, tree size,
12772 tree maxlen, bool ignore,
0a39fd54 12773 enum built_in_function fcode)
12774{
c2f47e15 12775 tree fn;
0a39fd54 12776
c2f47e15 12777 if (!validate_arg (dest, POINTER_TYPE)
12778 || !validate_arg (src,
12779 (fcode == BUILT_IN_MEMSET_CHK
12780 ? INTEGER_TYPE : POINTER_TYPE))
12781 || !validate_arg (len, INTEGER_TYPE)
12782 || !validate_arg (size, INTEGER_TYPE))
12783 return NULL_TREE;
0a39fd54 12784
12785 /* If SRC and DEST are the same (and not volatile), return DEST
12786 (resp. DEST+LEN for __mempcpy_chk). */
12787 if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
12788 {
12789 if (fcode != BUILT_IN_MEMPCPY_CHK)
389dd41b 12790 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
12791 dest, len);
0a39fd54 12792 else
12793 {
2cc66f2a 12794 tree temp = fold_build_pointer_plus_loc (loc, dest, len);
389dd41b 12795 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), temp);
0a39fd54 12796 }
12797 }
12798
12799 if (! host_integerp (size, 1))
c2f47e15 12800 return NULL_TREE;
0a39fd54 12801
12802 if (! integer_all_onesp (size))
12803 {
12804 if (! host_integerp (len, 1))
12805 {
12806 /* If LEN is not constant, try MAXLEN too.
12807 For MAXLEN only allow optimizing into non-_ocs function
12808 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12809 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
12810 {
12811 if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
12812 {
12813 /* (void) __mempcpy_chk () can be optimized into
12814 (void) __memcpy_chk (). */
b9a16870 12815 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
0a39fd54 12816 if (!fn)
c2f47e15 12817 return NULL_TREE;
0a39fd54 12818
389dd41b 12819 return build_call_expr_loc (loc, fn, 4, dest, src, len, size);
0a39fd54 12820 }
c2f47e15 12821 return NULL_TREE;
0a39fd54 12822 }
0a39fd54 12823 }
ad89623c 12824 else
12825 maxlen = len;
0a39fd54 12826
ad89623c 12827 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12828 return NULL_TREE;
0a39fd54 12829 }
12830
0a39fd54 12831 fn = NULL_TREE;
12832 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
12833 mem{cpy,pcpy,move,set} is available. */
12834 switch (fcode)
12835 {
12836 case BUILT_IN_MEMCPY_CHK:
b9a16870 12837 fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
0a39fd54 12838 break;
12839 case BUILT_IN_MEMPCPY_CHK:
b9a16870 12840 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
0a39fd54 12841 break;
12842 case BUILT_IN_MEMMOVE_CHK:
b9a16870 12843 fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
0a39fd54 12844 break;
12845 case BUILT_IN_MEMSET_CHK:
b9a16870 12846 fn = builtin_decl_explicit (BUILT_IN_MEMSET);
0a39fd54 12847 break;
12848 default:
12849 break;
12850 }
12851
12852 if (!fn)
c2f47e15 12853 return NULL_TREE;
0a39fd54 12854
389dd41b 12855 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12856}
12857
12858/* Fold a call to the __st[rp]cpy_chk builtin.
c2f47e15 12859 DEST, SRC, and SIZE are the arguments to the call.
12860 IGNORE is true if return value can be ignored. FCODE is the BUILT_IN_*
0a39fd54 12861 code of the builtin. If MAXLEN is not NULL, it is maximum length of
12862 strings passed as second argument. */
12863
12864tree
389dd41b 12865fold_builtin_stxcpy_chk (location_t loc, tree fndecl, tree dest,
12866 tree src, tree size,
c2f47e15 12867 tree maxlen, bool ignore,
0a39fd54 12868 enum built_in_function fcode)
12869{
c2f47e15 12870 tree len, fn;
0a39fd54 12871
c2f47e15 12872 if (!validate_arg (dest, POINTER_TYPE)
12873 || !validate_arg (src, POINTER_TYPE)
12874 || !validate_arg (size, INTEGER_TYPE))
12875 return NULL_TREE;
0a39fd54 12876
12877 /* If SRC and DEST are the same (and not volatile), return DEST. */
12878 if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
389dd41b 12879 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
a0c938f0 12880
0a39fd54 12881 if (! host_integerp (size, 1))
c2f47e15 12882 return NULL_TREE;
0a39fd54 12883
12884 if (! integer_all_onesp (size))
12885 {
12886 len = c_strlen (src, 1);
12887 if (! len || ! host_integerp (len, 1))
12888 {
12889 /* If LEN is not constant, try MAXLEN too.
12890 For MAXLEN only allow optimizing into non-_ocs function
12891 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12892 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
12893 {
12894 if (fcode == BUILT_IN_STPCPY_CHK)
12895 {
12896 if (! ignore)
c2f47e15 12897 return NULL_TREE;
0a39fd54 12898
12899 /* If return value of __stpcpy_chk is ignored,
12900 optimize into __strcpy_chk. */
b9a16870 12901 fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
0a39fd54 12902 if (!fn)
c2f47e15 12903 return NULL_TREE;
0a39fd54 12904
389dd41b 12905 return build_call_expr_loc (loc, fn, 3, dest, src, size);
0a39fd54 12906 }
12907
12908 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 12909 return NULL_TREE;
0a39fd54 12910
12911 /* If c_strlen returned something, but not a constant,
12912 transform __strcpy_chk into __memcpy_chk. */
b9a16870 12913 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
0a39fd54 12914 if (!fn)
c2f47e15 12915 return NULL_TREE;
0a39fd54 12916
bd6dcc04 12917 len = fold_convert_loc (loc, size_type_node, len);
12918 len = size_binop_loc (loc, PLUS_EXPR, len,
12919 build_int_cst (size_type_node, 1));
389dd41b 12920 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
12921 build_call_expr_loc (loc, fn, 4,
12922 dest, src, len, size));
0a39fd54 12923 }
0a39fd54 12924 }
ad89623c 12925 else
12926 maxlen = len;
12927
12928 if (! tree_int_cst_lt (maxlen, size))
c2f47e15 12929 return NULL_TREE;
0a39fd54 12930 }
12931
0a39fd54 12932 /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available. */
b9a16870 12933 fn = builtin_decl_explicit (fcode == BUILT_IN_STPCPY_CHK
12934 ? BUILT_IN_STPCPY : BUILT_IN_STRCPY);
0a39fd54 12935 if (!fn)
c2f47e15 12936 return NULL_TREE;
0a39fd54 12937
389dd41b 12938 return build_call_expr_loc (loc, fn, 2, dest, src);
0a39fd54 12939}
12940
1063acde 12941/* Fold a call to the __st{r,p}ncpy_chk builtin. DEST, SRC, LEN, and SIZE
c2f47e15 12942 are the arguments to the call. If MAXLEN is not NULL, it is maximum
1063acde 12943 length passed as third argument. IGNORE is true if return value can be
12944 ignored. FCODE is the BUILT_IN_* code of the builtin. */
0a39fd54 12945
12946tree
1063acde 12947fold_builtin_stxncpy_chk (location_t loc, tree dest, tree src,
12948 tree len, tree size, tree maxlen, bool ignore,
12949 enum built_in_function fcode)
0a39fd54 12950{
c2f47e15 12951 tree fn;
0a39fd54 12952
c2f47e15 12953 if (!validate_arg (dest, POINTER_TYPE)
12954 || !validate_arg (src, POINTER_TYPE)
12955 || !validate_arg (len, INTEGER_TYPE)
12956 || !validate_arg (size, INTEGER_TYPE))
12957 return NULL_TREE;
0a39fd54 12958
1063acde 12959 if (fcode == BUILT_IN_STPNCPY_CHK && ignore)
12960 {
12961 /* If return value of __stpncpy_chk is ignored,
12962 optimize into __strncpy_chk. */
12963 fn = builtin_decl_explicit (BUILT_IN_STRNCPY_CHK);
12964 if (fn)
12965 return build_call_expr_loc (loc, fn, 4, dest, src, len, size);
12966 }
12967
0a39fd54 12968 if (! host_integerp (size, 1))
c2f47e15 12969 return NULL_TREE;
0a39fd54 12970
12971 if (! integer_all_onesp (size))
12972 {
12973 if (! host_integerp (len, 1))
12974 {
12975 /* If LEN is not constant, try MAXLEN too.
12976 For MAXLEN only allow optimizing into non-_ocs function
12977 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12978 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 12979 return NULL_TREE;
0a39fd54 12980 }
ad89623c 12981 else
12982 maxlen = len;
0a39fd54 12983
ad89623c 12984 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12985 return NULL_TREE;
0a39fd54 12986 }
12987
1063acde 12988 /* If __builtin_st{r,p}ncpy_chk is used, assume st{r,p}ncpy is available. */
12989 fn = builtin_decl_explicit (fcode == BUILT_IN_STPNCPY_CHK
12990 ? BUILT_IN_STPNCPY : BUILT_IN_STRNCPY);
0a39fd54 12991 if (!fn)
c2f47e15 12992 return NULL_TREE;
0a39fd54 12993
389dd41b 12994 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12995}
12996
c2f47e15 12997/* Fold a call to the __strcat_chk builtin FNDECL. DEST, SRC, and SIZE
12998 are the arguments to the call. */
0a39fd54 12999
13000static tree
389dd41b 13001fold_builtin_strcat_chk (location_t loc, tree fndecl, tree dest,
13002 tree src, tree size)
0a39fd54 13003{
c2f47e15 13004 tree fn;
0a39fd54 13005 const char *p;
13006
c2f47e15 13007 if (!validate_arg (dest, POINTER_TYPE)
13008 || !validate_arg (src, POINTER_TYPE)
13009 || !validate_arg (size, INTEGER_TYPE))
13010 return NULL_TREE;
0a39fd54 13011
13012 p = c_getstr (src);
13013 /* If the SRC parameter is "", return DEST. */
13014 if (p && *p == '\0')
389dd41b 13015 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
0a39fd54 13016
13017 if (! host_integerp (size, 1) || ! integer_all_onesp (size))
c2f47e15 13018 return NULL_TREE;
0a39fd54 13019
13020 /* If __builtin_strcat_chk is used, assume strcat is available. */
b9a16870 13021 fn = builtin_decl_explicit (BUILT_IN_STRCAT);
0a39fd54 13022 if (!fn)
c2f47e15 13023 return NULL_TREE;
0a39fd54 13024
389dd41b 13025 return build_call_expr_loc (loc, fn, 2, dest, src);
0a39fd54 13026}
13027
c2f47e15 13028/* Fold a call to the __strncat_chk builtin with arguments DEST, SRC,
13029 LEN, and SIZE. */
0a39fd54 13030
13031static tree
389dd41b 13032fold_builtin_strncat_chk (location_t loc, tree fndecl,
c2f47e15 13033 tree dest, tree src, tree len, tree size)
0a39fd54 13034{
c2f47e15 13035 tree fn;
0a39fd54 13036 const char *p;
13037
c2f47e15 13038 if (!validate_arg (dest, POINTER_TYPE)
13039 || !validate_arg (src, POINTER_TYPE)
13040 || !validate_arg (size, INTEGER_TYPE)
13041 || !validate_arg (size, INTEGER_TYPE))
13042 return NULL_TREE;
0a39fd54 13043
13044 p = c_getstr (src);
13045 /* If the SRC parameter is "" or if LEN is 0, return DEST. */
13046 if (p && *p == '\0')
389dd41b 13047 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
0a39fd54 13048 else if (integer_zerop (len))
389dd41b 13049 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
0a39fd54 13050
13051 if (! host_integerp (size, 1))
c2f47e15 13052 return NULL_TREE;
0a39fd54 13053
13054 if (! integer_all_onesp (size))
13055 {
13056 tree src_len = c_strlen (src, 1);
13057 if (src_len
13058 && host_integerp (src_len, 1)
13059 && host_integerp (len, 1)
13060 && ! tree_int_cst_lt (len, src_len))
13061 {
13062 /* If LEN >= strlen (SRC), optimize into __strcat_chk. */
b9a16870 13063 fn = builtin_decl_explicit (BUILT_IN_STRCAT_CHK);
0a39fd54 13064 if (!fn)
c2f47e15 13065 return NULL_TREE;
0a39fd54 13066
389dd41b 13067 return build_call_expr_loc (loc, fn, 3, dest, src, size);
0a39fd54 13068 }
c2f47e15 13069 return NULL_TREE;
0a39fd54 13070 }
13071
0a39fd54 13072 /* If __builtin_strncat_chk is used, assume strncat is available. */
b9a16870 13073 fn = builtin_decl_explicit (BUILT_IN_STRNCAT);
0a39fd54 13074 if (!fn)
c2f47e15 13075 return NULL_TREE;
0a39fd54 13076
389dd41b 13077 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 13078}
13079
af1409ad 13080/* Fold a call EXP to __{,v}sprintf_chk having NARGS passed as ARGS.
13081 Return NULL_TREE if a normal call should be emitted rather than
13082 expanding the function inline. FCODE is either BUILT_IN_SPRINTF_CHK
13083 or BUILT_IN_VSPRINTF_CHK. */
0a39fd54 13084
13085static tree
af1409ad 13086fold_builtin_sprintf_chk_1 (location_t loc, int nargs, tree *args,
13087 enum built_in_function fcode)
0a39fd54 13088{
13089 tree dest, size, len, fn, fmt, flag;
13090 const char *fmt_str;
13091
13092 /* Verify the required arguments in the original call. */
c2f47e15 13093 if (nargs < 4)
13094 return NULL_TREE;
af1409ad 13095 dest = args[0];
c2f47e15 13096 if (!validate_arg (dest, POINTER_TYPE))
13097 return NULL_TREE;
af1409ad 13098 flag = args[1];
c2f47e15 13099 if (!validate_arg (flag, INTEGER_TYPE))
13100 return NULL_TREE;
af1409ad 13101 size = args[2];
c2f47e15 13102 if (!validate_arg (size, INTEGER_TYPE))
13103 return NULL_TREE;
af1409ad 13104 fmt = args[3];
c2f47e15 13105 if (!validate_arg (fmt, POINTER_TYPE))
13106 return NULL_TREE;
0a39fd54 13107
13108 if (! host_integerp (size, 1))
c2f47e15 13109 return NULL_TREE;
0a39fd54 13110
13111 len = NULL_TREE;
13112
d4473c84 13113 if (!init_target_chars ())
c2f47e15 13114 return NULL_TREE;
99eabcc1 13115
0a39fd54 13116 /* Check whether the format is a literal string constant. */
13117 fmt_str = c_getstr (fmt);
13118 if (fmt_str != NULL)
13119 {
13120 /* If the format doesn't contain % args or %%, we know the size. */
99eabcc1 13121 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 13122 {
c2f47e15 13123 if (fcode != BUILT_IN_SPRINTF_CHK || nargs == 4)
0a39fd54 13124 len = build_int_cstu (size_type_node, strlen (fmt_str));
13125 }
13126 /* If the format is "%s" and first ... argument is a string literal,
13127 we know the size too. */
c2f47e15 13128 else if (fcode == BUILT_IN_SPRINTF_CHK
13129 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 13130 {
13131 tree arg;
13132
c2f47e15 13133 if (nargs == 5)
0a39fd54 13134 {
af1409ad 13135 arg = args[4];
c2f47e15 13136 if (validate_arg (arg, POINTER_TYPE))
0a39fd54 13137 {
13138 len = c_strlen (arg, 1);
13139 if (! len || ! host_integerp (len, 1))
13140 len = NULL_TREE;
13141 }
13142 }
13143 }
13144 }
13145
13146 if (! integer_all_onesp (size))
13147 {
13148 if (! len || ! tree_int_cst_lt (len, size))
c2f47e15 13149 return NULL_TREE;
0a39fd54 13150 }
13151
13152 /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
13153 or if format doesn't contain % chars or is "%s". */
13154 if (! integer_zerop (flag))
13155 {
13156 if (fmt_str == NULL)
c2f47e15 13157 return NULL_TREE;
13158 if (strchr (fmt_str, target_percent) != NULL
13159 && strcmp (fmt_str, target_percent_s))
13160 return NULL_TREE;
0a39fd54 13161 }
13162
0a39fd54 13163 /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
b9a16870 13164 fn = builtin_decl_explicit (fcode == BUILT_IN_VSPRINTF_CHK
13165 ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF);
0a39fd54 13166 if (!fn)
c2f47e15 13167 return NULL_TREE;
0a39fd54 13168
af1409ad 13169 return rewrite_call_expr_array (loc, nargs, args, 4, fn, 2, dest, fmt);
0a39fd54 13170}
13171
af1409ad 13172/* Fold a call EXP to __{,v}sprintf_chk. Return NULL_TREE if
0a39fd54 13173 a normal call should be emitted rather than expanding the function
af1409ad 13174 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
13175
13176static tree
13177fold_builtin_sprintf_chk (location_t loc, tree exp,
13178 enum built_in_function fcode)
13179{
13180 return fold_builtin_sprintf_chk_1 (loc, call_expr_nargs (exp),
13181 CALL_EXPR_ARGP (exp), fcode);
13182}
13183
13184/* Fold a call EXP to {,v}snprintf having NARGS passed as ARGS. Return
13185 NULL_TREE if a normal call should be emitted rather than expanding
13186 the function inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
0a39fd54 13187 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
13188 passed as second argument. */
13189
af1409ad 13190static tree
13191fold_builtin_snprintf_chk_1 (location_t loc, int nargs, tree *args,
13192 tree maxlen, enum built_in_function fcode)
0a39fd54 13193{
13194 tree dest, size, len, fn, fmt, flag;
13195 const char *fmt_str;
13196
13197 /* Verify the required arguments in the original call. */
af1409ad 13198 if (nargs < 5)
c2f47e15 13199 return NULL_TREE;
af1409ad 13200 dest = args[0];
c2f47e15 13201 if (!validate_arg (dest, POINTER_TYPE))
13202 return NULL_TREE;
af1409ad 13203 len = args[1];
c2f47e15 13204 if (!validate_arg (len, INTEGER_TYPE))
13205 return NULL_TREE;
af1409ad 13206 flag = args[2];
c2f47e15 13207 if (!validate_arg (flag, INTEGER_TYPE))
13208 return NULL_TREE;
af1409ad 13209 size = args[3];
c2f47e15 13210 if (!validate_arg (size, INTEGER_TYPE))
13211 return NULL_TREE;
af1409ad 13212 fmt = args[4];
c2f47e15 13213 if (!validate_arg (fmt, POINTER_TYPE))
13214 return NULL_TREE;
0a39fd54 13215
13216 if (! host_integerp (size, 1))
c2f47e15 13217 return NULL_TREE;
0a39fd54 13218
13219 if (! integer_all_onesp (size))
13220 {
13221 if (! host_integerp (len, 1))
13222 {
13223 /* If LEN is not constant, try MAXLEN too.
13224 For MAXLEN only allow optimizing into non-_ocs function
13225 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
13226 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 13227 return NULL_TREE;
0a39fd54 13228 }
ad89623c 13229 else
13230 maxlen = len;
0a39fd54 13231
ad89623c 13232 if (tree_int_cst_lt (size, maxlen))
c2f47e15 13233 return NULL_TREE;
0a39fd54 13234 }
13235
d4473c84 13236 if (!init_target_chars ())
c2f47e15 13237 return NULL_TREE;
99eabcc1 13238
0a39fd54 13239 /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
13240 or if format doesn't contain % chars or is "%s". */
13241 if (! integer_zerop (flag))
13242 {
13243 fmt_str = c_getstr (fmt);
13244 if (fmt_str == NULL)
c2f47e15 13245 return NULL_TREE;
13246 if (strchr (fmt_str, target_percent) != NULL
13247 && strcmp (fmt_str, target_percent_s))
13248 return NULL_TREE;
0a39fd54 13249 }
13250
0a39fd54 13251 /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
13252 available. */
b9a16870 13253 fn = builtin_decl_explicit (fcode == BUILT_IN_VSNPRINTF_CHK
13254 ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF);
0a39fd54 13255 if (!fn)
c2f47e15 13256 return NULL_TREE;
0a39fd54 13257
af1409ad 13258 return rewrite_call_expr_array (loc, nargs, args, 5, fn, 3, dest, len, fmt);
13259}
13260
13261/* Fold a call EXP to {,v}snprintf. Return NULL_TREE if
13262 a normal call should be emitted rather than expanding the function
13263 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
13264 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
13265 passed as second argument. */
13266
13267tree
13268fold_builtin_snprintf_chk (location_t loc, tree exp, tree maxlen,
13269 enum built_in_function fcode)
13270{
13271 return fold_builtin_snprintf_chk_1 (loc, call_expr_nargs (exp),
13272 CALL_EXPR_ARGP (exp), maxlen, fcode);
0a39fd54 13273}
13274
13275/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 13276 FMT and ARG are the arguments to the call; we don't fold cases with
13277 more than 2 arguments, and ARG may be null if this is a 1-argument case.
0a39fd54 13278
c2f47e15 13279 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 13280 simplified form of the call as a tree. FCODE is the BUILT_IN_*
13281 code of the function to be simplified. */
13282
13283static tree
389dd41b 13284fold_builtin_printf (location_t loc, tree fndecl, tree fmt,
13285 tree arg, bool ignore,
0a39fd54 13286 enum built_in_function fcode)
13287{
c2f47e15 13288 tree fn_putchar, fn_puts, newarg, call = NULL_TREE;
0a39fd54 13289 const char *fmt_str = NULL;
13290
13291 /* If the return value is used, don't do the transformation. */
13292 if (! ignore)
c2f47e15 13293 return NULL_TREE;
0a39fd54 13294
13295 /* Verify the required arguments in the original call. */
c2f47e15 13296 if (!validate_arg (fmt, POINTER_TYPE))
13297 return NULL_TREE;
0a39fd54 13298
13299 /* Check whether the format is a literal string constant. */
13300 fmt_str = c_getstr (fmt);
13301 if (fmt_str == NULL)
13302 return NULL_TREE;
13303
13304 if (fcode == BUILT_IN_PRINTF_UNLOCKED)
13305 {
6d77ed92 13306 /* If we're using an unlocked function, assume the other
13307 unlocked functions exist explicitly. */
b9a16870 13308 fn_putchar = builtin_decl_explicit (BUILT_IN_PUTCHAR_UNLOCKED);
13309 fn_puts = builtin_decl_explicit (BUILT_IN_PUTS_UNLOCKED);
0a39fd54 13310 }
13311 else
13312 {
b9a16870 13313 fn_putchar = builtin_decl_implicit (BUILT_IN_PUTCHAR);
13314 fn_puts = builtin_decl_implicit (BUILT_IN_PUTS);
0a39fd54 13315 }
13316
d4473c84 13317 if (!init_target_chars ())
c2f47e15 13318 return NULL_TREE;
a0c938f0 13319
c2f47e15 13320 if (strcmp (fmt_str, target_percent_s) == 0
13321 || strchr (fmt_str, target_percent) == NULL)
0a39fd54 13322 {
13323 const char *str;
13324
99eabcc1 13325 if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 13326 {
13327 if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 13328 return NULL_TREE;
0a39fd54 13329
c2f47e15 13330 if (!arg || !validate_arg (arg, POINTER_TYPE))
13331 return NULL_TREE;
0a39fd54 13332
c2f47e15 13333 str = c_getstr (arg);
0a39fd54 13334 if (str == NULL)
c2f47e15 13335 return NULL_TREE;
0a39fd54 13336 }
13337 else
13338 {
13339 /* The format specifier doesn't contain any '%' characters. */
13340 if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
c2f47e15 13341 && arg)
13342 return NULL_TREE;
0a39fd54 13343 str = fmt_str;
13344 }
13345
13346 /* If the string was "", printf does nothing. */
13347 if (str[0] == '\0')
13348 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
13349
13350 /* If the string has length of 1, call putchar. */
13351 if (str[1] == '\0')
13352 {
13353 /* Given printf("c"), (where c is any one character,)
13354 convert "c"[0] to an int and pass that to the replacement
13355 function. */
7002a1c8 13356 newarg = build_int_cst (integer_type_node, str[0]);
c2f47e15 13357 if (fn_putchar)
389dd41b 13358 call = build_call_expr_loc (loc, fn_putchar, 1, newarg);
0a39fd54 13359 }
13360 else
13361 {
13362 /* If the string was "string\n", call puts("string"). */
13363 size_t len = strlen (str);
663dbd5e 13364 if ((unsigned char)str[len - 1] == target_newline
13365 && (size_t) (int) len == len
13366 && (int) len > 0)
0a39fd54 13367 {
663dbd5e 13368 char *newstr;
13369 tree offset_node, string_cst;
13370
0a39fd54 13371 /* Create a NUL-terminated string that's one char shorter
13372 than the original, stripping off the trailing '\n'. */
663dbd5e 13373 newarg = build_string_literal (len, str);
13374 string_cst = string_constant (newarg, &offset_node);
13375 gcc_checking_assert (string_cst
13376 && (TREE_STRING_LENGTH (string_cst)
13377 == (int) len)
13378 && integer_zerop (offset_node)
13379 && (unsigned char)
13380 TREE_STRING_POINTER (string_cst)[len - 1]
13381 == target_newline);
13382 /* build_string_literal creates a new STRING_CST,
13383 modify it in place to avoid double copying. */
13384 newstr = CONST_CAST (char *, TREE_STRING_POINTER (string_cst));
13385 newstr[len - 1] = '\0';
c2f47e15 13386 if (fn_puts)
389dd41b 13387 call = build_call_expr_loc (loc, fn_puts, 1, newarg);
0a39fd54 13388 }
13389 else
13390 /* We'd like to arrange to call fputs(string,stdout) here,
13391 but we need stdout and don't have a way to get it yet. */
c2f47e15 13392 return NULL_TREE;
0a39fd54 13393 }
13394 }
13395
13396 /* The other optimizations can be done only on the non-va_list variants. */
13397 else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 13398 return NULL_TREE;
0a39fd54 13399
13400 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
99eabcc1 13401 else if (strcmp (fmt_str, target_percent_s_newline) == 0)
0a39fd54 13402 {
c2f47e15 13403 if (!arg || !validate_arg (arg, POINTER_TYPE))
13404 return NULL_TREE;
13405 if (fn_puts)
389dd41b 13406 call = build_call_expr_loc (loc, fn_puts, 1, arg);
0a39fd54 13407 }
13408
13409 /* If the format specifier was "%c", call __builtin_putchar(arg). */
99eabcc1 13410 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 13411 {
c2f47e15 13412 if (!arg || !validate_arg (arg, INTEGER_TYPE))
13413 return NULL_TREE;
13414 if (fn_putchar)
389dd41b 13415 call = build_call_expr_loc (loc, fn_putchar, 1, arg);
0a39fd54 13416 }
13417
c2f47e15 13418 if (!call)
13419 return NULL_TREE;
0a39fd54 13420
389dd41b 13421 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
0a39fd54 13422}
13423
13424/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 13425 FP, FMT, and ARG are the arguments to the call. We don't fold calls with
13426 more than 3 arguments, and ARG may be null in the 2-argument case.
0a39fd54 13427
c2f47e15 13428 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 13429 simplified form of the call as a tree. FCODE is the BUILT_IN_*
13430 code of the function to be simplified. */
13431
13432static tree
389dd41b 13433fold_builtin_fprintf (location_t loc, tree fndecl, tree fp,
13434 tree fmt, tree arg, bool ignore,
0a39fd54 13435 enum built_in_function fcode)
13436{
c2f47e15 13437 tree fn_fputc, fn_fputs, call = NULL_TREE;
0a39fd54 13438 const char *fmt_str = NULL;
13439
13440 /* If the return value is used, don't do the transformation. */
13441 if (! ignore)
c2f47e15 13442 return NULL_TREE;
0a39fd54 13443
13444 /* Verify the required arguments in the original call. */
c2f47e15 13445 if (!validate_arg (fp, POINTER_TYPE))
13446 return NULL_TREE;
13447 if (!validate_arg (fmt, POINTER_TYPE))
13448 return NULL_TREE;
0a39fd54 13449
13450 /* Check whether the format is a literal string constant. */
13451 fmt_str = c_getstr (fmt);
13452 if (fmt_str == NULL)
13453 return NULL_TREE;
13454
13455 if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
13456 {
6d77ed92 13457 /* If we're using an unlocked function, assume the other
13458 unlocked functions exist explicitly. */
b9a16870 13459 fn_fputc = builtin_decl_explicit (BUILT_IN_FPUTC_UNLOCKED);
13460 fn_fputs = builtin_decl_explicit (BUILT_IN_FPUTS_UNLOCKED);
0a39fd54 13461 }
13462 else
13463 {
b9a16870 13464 fn_fputc = builtin_decl_implicit (BUILT_IN_FPUTC);
13465 fn_fputs = builtin_decl_implicit (BUILT_IN_FPUTS);
0a39fd54 13466 }
13467
d4473c84 13468 if (!init_target_chars ())
c2f47e15 13469 return NULL_TREE;
a0c938f0 13470
0a39fd54 13471 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 13472 if (strchr (fmt_str, target_percent) == NULL)
0a39fd54 13473 {
13474 if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
c2f47e15 13475 && arg)
13476 return NULL_TREE;
0a39fd54 13477
13478 /* If the format specifier was "", fprintf does nothing. */
13479 if (fmt_str[0] == '\0')
13480 {
13481 /* If FP has side-effects, just wait until gimplification is
13482 done. */
13483 if (TREE_SIDE_EFFECTS (fp))
c2f47e15 13484 return NULL_TREE;
0a39fd54 13485
13486 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
13487 }
13488
13489 /* When "string" doesn't contain %, replace all cases of
13490 fprintf (fp, string) with fputs (string, fp). The fputs
13491 builtin will take care of special cases like length == 1. */
c2f47e15 13492 if (fn_fputs)
389dd41b 13493 call = build_call_expr_loc (loc, fn_fputs, 2, fmt, fp);
0a39fd54 13494 }
13495
13496 /* The other optimizations can be done only on the non-va_list variants. */
13497 else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
c2f47e15 13498 return NULL_TREE;
0a39fd54 13499
13500 /* If the format specifier was "%s", call __builtin_fputs (arg, fp). */
99eabcc1 13501 else if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 13502 {
c2f47e15 13503 if (!arg || !validate_arg (arg, POINTER_TYPE))
13504 return NULL_TREE;
13505 if (fn_fputs)
389dd41b 13506 call = build_call_expr_loc (loc, fn_fputs, 2, arg, fp);
0a39fd54 13507 }
13508
13509 /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */
99eabcc1 13510 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 13511 {
c2f47e15 13512 if (!arg || !validate_arg (arg, INTEGER_TYPE))
13513 return NULL_TREE;
13514 if (fn_fputc)
389dd41b 13515 call = build_call_expr_loc (loc, fn_fputc, 2, arg, fp);
0a39fd54 13516 }
13517
c2f47e15 13518 if (!call)
13519 return NULL_TREE;
389dd41b 13520 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
0a39fd54 13521}
99eabcc1 13522
13523/* Initialize format string characters in the target charset. */
13524
13525static bool
13526init_target_chars (void)
13527{
13528 static bool init;
13529 if (!init)
13530 {
13531 target_newline = lang_hooks.to_target_charset ('\n');
13532 target_percent = lang_hooks.to_target_charset ('%');
13533 target_c = lang_hooks.to_target_charset ('c');
13534 target_s = lang_hooks.to_target_charset ('s');
13535 if (target_newline == 0 || target_percent == 0 || target_c == 0
13536 || target_s == 0)
13537 return false;
13538
13539 target_percent_c[0] = target_percent;
13540 target_percent_c[1] = target_c;
13541 target_percent_c[2] = '\0';
13542
13543 target_percent_s[0] = target_percent;
13544 target_percent_s[1] = target_s;
13545 target_percent_s[2] = '\0';
13546
13547 target_percent_s_newline[0] = target_percent;
13548 target_percent_s_newline[1] = target_s;
13549 target_percent_s_newline[2] = target_newline;
13550 target_percent_s_newline[3] = '\0';
a0c938f0 13551
99eabcc1 13552 init = true;
13553 }
13554 return true;
13555}
bffb7645 13556
f0c477f2 13557/* Helper function for do_mpfr_arg*(). Ensure M is a normal number
13558 and no overflow/underflow occurred. INEXACT is true if M was not
fa7637bd 13559 exactly calculated. TYPE is the tree type for the result. This
f0c477f2 13560 function assumes that you cleared the MPFR flags and then
13561 calculated M to see if anything subsequently set a flag prior to
13562 entering this function. Return NULL_TREE if any checks fail. */
13563
13564static tree
d4473c84 13565do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
f0c477f2 13566{
13567 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
13568 overflow/underflow occurred. If -frounding-math, proceed iff the
13569 result of calling FUNC was exact. */
d4473c84 13570 if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
f0c477f2 13571 && (!flag_rounding_math || !inexact))
13572 {
13573 REAL_VALUE_TYPE rr;
13574
66fa16e6 13575 real_from_mpfr (&rr, m, type, GMP_RNDN);
f0c477f2 13576 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
13577 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
13578 but the mpft_t is not, then we underflowed in the
13579 conversion. */
776a7bab 13580 if (real_isfinite (&rr)
f0c477f2 13581 && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
13582 {
13583 REAL_VALUE_TYPE rmode;
13584
13585 real_convert (&rmode, TYPE_MODE (type), &rr);
13586 /* Proceed iff the specified mode can hold the value. */
13587 if (real_identical (&rmode, &rr))
13588 return build_real (type, rmode);
13589 }
13590 }
13591 return NULL_TREE;
13592}
13593
239d491a 13594/* Helper function for do_mpc_arg*(). Ensure M is a normal complex
13595 number and no overflow/underflow occurred. INEXACT is true if M
13596 was not exactly calculated. TYPE is the tree type for the result.
13597 This function assumes that you cleared the MPFR flags and then
13598 calculated M to see if anything subsequently set a flag prior to
652d9409 13599 entering this function. Return NULL_TREE if any checks fail, if
13600 FORCE_CONVERT is true, then bypass the checks. */
239d491a 13601
13602static tree
652d9409 13603do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert)
239d491a 13604{
13605 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
13606 overflow/underflow occurred. If -frounding-math, proceed iff the
13607 result of calling FUNC was exact. */
652d9409 13608 if (force_convert
13609 || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m))
13610 && !mpfr_overflow_p () && !mpfr_underflow_p ()
13611 && (!flag_rounding_math || !inexact)))
239d491a 13612 {
13613 REAL_VALUE_TYPE re, im;
13614
b0e7c4d4 13615 real_from_mpfr (&re, mpc_realref (m), TREE_TYPE (type), GMP_RNDN);
13616 real_from_mpfr (&im, mpc_imagref (m), TREE_TYPE (type), GMP_RNDN);
239d491a 13617 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
13618 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
13619 but the mpft_t is not, then we underflowed in the
13620 conversion. */
652d9409 13621 if (force_convert
13622 || (real_isfinite (&re) && real_isfinite (&im)
13623 && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0)
13624 && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0)))
239d491a 13625 {
13626 REAL_VALUE_TYPE re_mode, im_mode;
13627
13628 real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re);
13629 real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im);
13630 /* Proceed iff the specified mode can hold the value. */
652d9409 13631 if (force_convert
13632 || (real_identical (&re_mode, &re)
13633 && real_identical (&im_mode, &im)))
239d491a 13634 return build_complex (type, build_real (TREE_TYPE (type), re_mode),
13635 build_real (TREE_TYPE (type), im_mode));
13636 }
13637 }
13638 return NULL_TREE;
13639}
239d491a 13640
bffb7645 13641/* If argument ARG is a REAL_CST, call the one-argument mpfr function
13642 FUNC on it and return the resulting value as a tree with type TYPE.
728bac60 13643 If MIN and/or MAX are not NULL, then the supplied ARG must be
13644 within those bounds. If INCLUSIVE is true, then MIN/MAX are
13645 acceptable values, otherwise they are not. The mpfr precision is
13646 set to the precision of TYPE. We assume that function FUNC returns
13647 zero if the result could be calculated exactly within the requested
13648 precision. */
bffb7645 13649
13650static tree
728bac60 13651do_mpfr_arg1 (tree arg, tree type, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
13652 const REAL_VALUE_TYPE *min, const REAL_VALUE_TYPE *max,
13653 bool inclusive)
bffb7645 13654{
13655 tree result = NULL_TREE;
48e1416a 13656
bffb7645 13657 STRIP_NOPS (arg);
13658
bd7d6fa4 13659 /* To proceed, MPFR must exactly represent the target floating point
13660 format, which only happens when the target base equals two. */
13661 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13662 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
bffb7645 13663 {
f0c477f2 13664 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
bffb7645 13665
776a7bab 13666 if (real_isfinite (ra)
f0c477f2 13667 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min))
13668 && (!max || real_compare (inclusive ? LE_EXPR: LT_EXPR , ra, max)))
bffb7645 13669 {
e2eb2b7f 13670 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13671 const int prec = fmt->p;
13672 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
debf9994 13673 int inexact;
bffb7645 13674 mpfr_t m;
13675
13676 mpfr_init2 (m, prec);
66fa16e6 13677 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 13678 mpfr_clear_flags ();
e2eb2b7f 13679 inexact = func (m, m, rnd);
f0c477f2 13680 result = do_mpfr_ckconv (m, type, inexact);
bffb7645 13681 mpfr_clear (m);
13682 }
13683 }
48e1416a 13684
bffb7645 13685 return result;
13686}
f0c477f2 13687
13688/* If argument ARG is a REAL_CST, call the two-argument mpfr function
13689 FUNC on it and return the resulting value as a tree with type TYPE.
13690 The mpfr precision is set to the precision of TYPE. We assume that
13691 function FUNC returns zero if the result could be calculated
13692 exactly within the requested precision. */
13693
13694static tree
13695do_mpfr_arg2 (tree arg1, tree arg2, tree type,
13696 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
13697{
13698 tree result = NULL_TREE;
48e1416a 13699
f0c477f2 13700 STRIP_NOPS (arg1);
13701 STRIP_NOPS (arg2);
13702
bd7d6fa4 13703 /* To proceed, MPFR must exactly represent the target floating point
13704 format, which only happens when the target base equals two. */
13705 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13706 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
13707 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
f0c477f2 13708 {
13709 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
13710 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
13711
776a7bab 13712 if (real_isfinite (ra1) && real_isfinite (ra2))
f0c477f2 13713 {
e2eb2b7f 13714 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13715 const int prec = fmt->p;
13716 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
f0c477f2 13717 int inexact;
13718 mpfr_t m1, m2;
13719
13720 mpfr_inits2 (prec, m1, m2, NULL);
66fa16e6 13721 mpfr_from_real (m1, ra1, GMP_RNDN);
13722 mpfr_from_real (m2, ra2, GMP_RNDN);
d4473c84 13723 mpfr_clear_flags ();
e2eb2b7f 13724 inexact = func (m1, m1, m2, rnd);
f0c477f2 13725 result = do_mpfr_ckconv (m1, type, inexact);
13726 mpfr_clears (m1, m2, NULL);
13727 }
13728 }
48e1416a 13729
f0c477f2 13730 return result;
13731}
d92f994c 13732
9917422b 13733/* If argument ARG is a REAL_CST, call the three-argument mpfr function
13734 FUNC on it and return the resulting value as a tree with type TYPE.
13735 The mpfr precision is set to the precision of TYPE. We assume that
13736 function FUNC returns zero if the result could be calculated
13737 exactly within the requested precision. */
13738
13739static tree
13740do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type,
13741 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
13742{
13743 tree result = NULL_TREE;
48e1416a 13744
9917422b 13745 STRIP_NOPS (arg1);
13746 STRIP_NOPS (arg2);
13747 STRIP_NOPS (arg3);
13748
bd7d6fa4 13749 /* To proceed, MPFR must exactly represent the target floating point
13750 format, which only happens when the target base equals two. */
13751 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13752 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
13753 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2)
13754 && TREE_CODE (arg3) == REAL_CST && !TREE_OVERFLOW (arg3))
9917422b 13755 {
13756 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
13757 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
13758 const REAL_VALUE_TYPE *const ra3 = &TREE_REAL_CST (arg3);
13759
776a7bab 13760 if (real_isfinite (ra1) && real_isfinite (ra2) && real_isfinite (ra3))
9917422b 13761 {
e2eb2b7f 13762 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13763 const int prec = fmt->p;
13764 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
9917422b 13765 int inexact;
13766 mpfr_t m1, m2, m3;
13767
13768 mpfr_inits2 (prec, m1, m2, m3, NULL);
66fa16e6 13769 mpfr_from_real (m1, ra1, GMP_RNDN);
13770 mpfr_from_real (m2, ra2, GMP_RNDN);
13771 mpfr_from_real (m3, ra3, GMP_RNDN);
d4473c84 13772 mpfr_clear_flags ();
e2eb2b7f 13773 inexact = func (m1, m1, m2, m3, rnd);
9917422b 13774 result = do_mpfr_ckconv (m1, type, inexact);
13775 mpfr_clears (m1, m2, m3, NULL);
13776 }
13777 }
48e1416a 13778
9917422b 13779 return result;
13780}
13781
d92f994c 13782/* If argument ARG is a REAL_CST, call mpfr_sin_cos() on it and set
13783 the pointers *(ARG_SINP) and *(ARG_COSP) to the resulting values.
d735c391 13784 If ARG_SINP and ARG_COSP are NULL then the result is returned
13785 as a complex value.
d92f994c 13786 The type is taken from the type of ARG and is used for setting the
13787 precision of the calculation and results. */
13788
13789static tree
13790do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp)
13791{
bd7d6fa4 13792 tree const type = TREE_TYPE (arg);
d92f994c 13793 tree result = NULL_TREE;
48e1416a 13794
d92f994c 13795 STRIP_NOPS (arg);
48e1416a 13796
bd7d6fa4 13797 /* To proceed, MPFR must exactly represent the target floating point
13798 format, which only happens when the target base equals two. */
13799 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13800 && TREE_CODE (arg) == REAL_CST
13801 && !TREE_OVERFLOW (arg))
d92f994c 13802 {
13803 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
13804
776a7bab 13805 if (real_isfinite (ra))
d92f994c 13806 {
e2eb2b7f 13807 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13808 const int prec = fmt->p;
13809 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
d92f994c 13810 tree result_s, result_c;
13811 int inexact;
13812 mpfr_t m, ms, mc;
13813
13814 mpfr_inits2 (prec, m, ms, mc, NULL);
66fa16e6 13815 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 13816 mpfr_clear_flags ();
e2eb2b7f 13817 inexact = mpfr_sin_cos (ms, mc, m, rnd);
d92f994c 13818 result_s = do_mpfr_ckconv (ms, type, inexact);
13819 result_c = do_mpfr_ckconv (mc, type, inexact);
13820 mpfr_clears (m, ms, mc, NULL);
13821 if (result_s && result_c)
13822 {
d735c391 13823 /* If we are to return in a complex value do so. */
13824 if (!arg_sinp && !arg_cosp)
13825 return build_complex (build_complex_type (type),
13826 result_c, result_s);
13827
d92f994c 13828 /* Dereference the sin/cos pointer arguments. */
13829 arg_sinp = build_fold_indirect_ref (arg_sinp);
13830 arg_cosp = build_fold_indirect_ref (arg_cosp);
13831 /* Proceed if valid pointer type were passed in. */
13832 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_sinp)) == TYPE_MAIN_VARIANT (type)
13833 && TYPE_MAIN_VARIANT (TREE_TYPE (arg_cosp)) == TYPE_MAIN_VARIANT (type))
13834 {
13835 /* Set the values. */
41076ef6 13836 result_s = fold_build2 (MODIFY_EXPR, type, arg_sinp,
35cc02b5 13837 result_s);
d92f994c 13838 TREE_SIDE_EFFECTS (result_s) = 1;
41076ef6 13839 result_c = fold_build2 (MODIFY_EXPR, type, arg_cosp,
35cc02b5 13840 result_c);
d92f994c 13841 TREE_SIDE_EFFECTS (result_c) = 1;
13842 /* Combine the assignments into a compound expr. */
13843 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13844 result_s, result_c));
13845 }
13846 }
13847 }
13848 }
13849 return result;
13850}
65dd1378 13851
65dd1378 13852/* If argument ARG1 is an INTEGER_CST and ARG2 is a REAL_CST, call the
13853 two-argument mpfr order N Bessel function FUNC on them and return
13854 the resulting value as a tree with type TYPE. The mpfr precision
13855 is set to the precision of TYPE. We assume that function FUNC
13856 returns zero if the result could be calculated exactly within the
13857 requested precision. */
13858static tree
13859do_mpfr_bessel_n (tree arg1, tree arg2, tree type,
13860 int (*func)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
13861 const REAL_VALUE_TYPE *min, bool inclusive)
13862{
13863 tree result = NULL_TREE;
13864
13865 STRIP_NOPS (arg1);
13866 STRIP_NOPS (arg2);
13867
13868 /* To proceed, MPFR must exactly represent the target floating point
13869 format, which only happens when the target base equals two. */
13870 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13871 && host_integerp (arg1, 0)
13872 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
13873 {
13874 const HOST_WIDE_INT n = tree_low_cst(arg1, 0);
13875 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg2);
13876
13877 if (n == (long)n
776a7bab 13878 && real_isfinite (ra)
65dd1378 13879 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min)))
13880 {
e2eb2b7f 13881 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13882 const int prec = fmt->p;
13883 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
65dd1378 13884 int inexact;
13885 mpfr_t m;
13886
13887 mpfr_init2 (m, prec);
13888 mpfr_from_real (m, ra, GMP_RNDN);
13889 mpfr_clear_flags ();
e2eb2b7f 13890 inexact = func (m, n, m, rnd);
65dd1378 13891 result = do_mpfr_ckconv (m, type, inexact);
13892 mpfr_clear (m);
13893 }
13894 }
48e1416a 13895
65dd1378 13896 return result;
13897}
e5407ca6 13898
13899/* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
13900 the pointer *(ARG_QUO) and return the result. The type is taken
13901 from the type of ARG0 and is used for setting the precision of the
13902 calculation and results. */
13903
13904static tree
13905do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
13906{
13907 tree const type = TREE_TYPE (arg0);
13908 tree result = NULL_TREE;
48e1416a 13909
e5407ca6 13910 STRIP_NOPS (arg0);
13911 STRIP_NOPS (arg1);
48e1416a 13912
e5407ca6 13913 /* To proceed, MPFR must exactly represent the target floating point
13914 format, which only happens when the target base equals two. */
13915 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13916 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
13917 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
13918 {
13919 const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
13920 const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
13921
776a7bab 13922 if (real_isfinite (ra0) && real_isfinite (ra1))
e5407ca6 13923 {
e2eb2b7f 13924 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13925 const int prec = fmt->p;
13926 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
e5407ca6 13927 tree result_rem;
13928 long integer_quo;
13929 mpfr_t m0, m1;
13930
13931 mpfr_inits2 (prec, m0, m1, NULL);
13932 mpfr_from_real (m0, ra0, GMP_RNDN);
13933 mpfr_from_real (m1, ra1, GMP_RNDN);
13934 mpfr_clear_flags ();
e2eb2b7f 13935 mpfr_remquo (m0, &integer_quo, m0, m1, rnd);
e5407ca6 13936 /* Remquo is independent of the rounding mode, so pass
13937 inexact=0 to do_mpfr_ckconv(). */
13938 result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
13939 mpfr_clears (m0, m1, NULL);
13940 if (result_rem)
13941 {
13942 /* MPFR calculates quo in the host's long so it may
13943 return more bits in quo than the target int can hold
13944 if sizeof(host long) > sizeof(target int). This can
13945 happen even for native compilers in LP64 mode. In
13946 these cases, modulo the quo value with the largest
13947 number that the target int can hold while leaving one
13948 bit for the sign. */
13949 if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
13950 integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
13951
13952 /* Dereference the quo pointer argument. */
13953 arg_quo = build_fold_indirect_ref (arg_quo);
13954 /* Proceed iff a valid pointer type was passed in. */
13955 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
13956 {
13957 /* Set the value. */
7002a1c8 13958 tree result_quo
13959 = fold_build2 (MODIFY_EXPR, TREE_TYPE (arg_quo), arg_quo,
13960 build_int_cst (TREE_TYPE (arg_quo),
13961 integer_quo));
e5407ca6 13962 TREE_SIDE_EFFECTS (result_quo) = 1;
13963 /* Combine the quo assignment with the rem. */
13964 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13965 result_quo, result_rem));
13966 }
13967 }
13968 }
13969 }
13970 return result;
13971}
e84da7c1 13972
13973/* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
13974 resulting value as a tree with type TYPE. The mpfr precision is
13975 set to the precision of TYPE. We assume that this mpfr function
13976 returns zero if the result could be calculated exactly within the
13977 requested precision. In addition, the integer pointer represented
13978 by ARG_SG will be dereferenced and set to the appropriate signgam
13979 (-1,1) value. */
13980
13981static tree
13982do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
13983{
13984 tree result = NULL_TREE;
13985
13986 STRIP_NOPS (arg);
48e1416a 13987
e84da7c1 13988 /* To proceed, MPFR must exactly represent the target floating point
13989 format, which only happens when the target base equals two. Also
13990 verify ARG is a constant and that ARG_SG is an int pointer. */
13991 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13992 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
13993 && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
13994 && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
13995 {
13996 const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
13997
13998 /* In addition to NaN and Inf, the argument cannot be zero or a
13999 negative integer. */
776a7bab 14000 if (real_isfinite (ra)
e84da7c1 14001 && ra->cl != rvc_zero
14002 && !(real_isneg(ra) && real_isinteger(ra, TYPE_MODE (type))))
14003 {
e2eb2b7f 14004 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
14005 const int prec = fmt->p;
14006 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
e84da7c1 14007 int inexact, sg;
14008 mpfr_t m;
14009 tree result_lg;
14010
14011 mpfr_init2 (m, prec);
14012 mpfr_from_real (m, ra, GMP_RNDN);
14013 mpfr_clear_flags ();
e2eb2b7f 14014 inexact = mpfr_lgamma (m, &sg, m, rnd);
e84da7c1 14015 result_lg = do_mpfr_ckconv (m, type, inexact);
14016 mpfr_clear (m);
14017 if (result_lg)
14018 {
14019 tree result_sg;
14020
14021 /* Dereference the arg_sg pointer argument. */
14022 arg_sg = build_fold_indirect_ref (arg_sg);
14023 /* Assign the signgam value into *arg_sg. */
14024 result_sg = fold_build2 (MODIFY_EXPR,
14025 TREE_TYPE (arg_sg), arg_sg,
7002a1c8 14026 build_int_cst (TREE_TYPE (arg_sg), sg));
e84da7c1 14027 TREE_SIDE_EFFECTS (result_sg) = 1;
14028 /* Combine the signgam assignment with the lgamma result. */
14029 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
14030 result_sg, result_lg));
14031 }
14032 }
14033 }
14034
14035 return result;
14036}
75a70cf9 14037
239d491a 14038/* If argument ARG is a COMPLEX_CST, call the one-argument mpc
14039 function FUNC on it and return the resulting value as a tree with
14040 type TYPE. The mpfr precision is set to the precision of TYPE. We
14041 assume that function FUNC returns zero if the result could be
14042 calculated exactly within the requested precision. */
14043
14044static tree
14045do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t))
14046{
14047 tree result = NULL_TREE;
48e1416a 14048
239d491a 14049 STRIP_NOPS (arg);
14050
14051 /* To proceed, MPFR must exactly represent the target floating point
14052 format, which only happens when the target base equals two. */
14053 if (TREE_CODE (arg) == COMPLEX_CST && !TREE_OVERFLOW (arg)
14054 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE
14055 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))))->b == 2)
14056 {
14057 const REAL_VALUE_TYPE *const re = TREE_REAL_CST_PTR (TREE_REALPART (arg));
14058 const REAL_VALUE_TYPE *const im = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
14059
14060 if (real_isfinite (re) && real_isfinite (im))
14061 {
14062 const struct real_format *const fmt =
14063 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
14064 const int prec = fmt->p;
14065 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
44d89feb 14066 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
239d491a 14067 int inexact;
14068 mpc_t m;
48e1416a 14069
239d491a 14070 mpc_init2 (m, prec);
c3cfad90 14071 mpfr_from_real (mpc_realref(m), re, rnd);
14072 mpfr_from_real (mpc_imagref(m), im, rnd);
239d491a 14073 mpfr_clear_flags ();
44d89feb 14074 inexact = func (m, m, crnd);
652d9409 14075 result = do_mpc_ckconv (m, type, inexact, /*force_convert=*/ 0);
239d491a 14076 mpc_clear (m);
14077 }
14078 }
14079
14080 return result;
14081}
c699fab8 14082
14083/* If arguments ARG0 and ARG1 are a COMPLEX_CST, call the two-argument
14084 mpc function FUNC on it and return the resulting value as a tree
14085 with type TYPE. The mpfr precision is set to the precision of
14086 TYPE. We assume that function FUNC returns zero if the result
652d9409 14087 could be calculated exactly within the requested precision. If
14088 DO_NONFINITE is true, then fold expressions containing Inf or NaN
14089 in the arguments and/or results. */
c699fab8 14090
63e89698 14091tree
652d9409 14092do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
c699fab8 14093 int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
14094{
14095 tree result = NULL_TREE;
48e1416a 14096
c699fab8 14097 STRIP_NOPS (arg0);
14098 STRIP_NOPS (arg1);
14099
14100 /* To proceed, MPFR must exactly represent the target floating point
14101 format, which only happens when the target base equals two. */
14102 if (TREE_CODE (arg0) == COMPLEX_CST && !TREE_OVERFLOW (arg0)
14103 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
14104 && TREE_CODE (arg1) == COMPLEX_CST && !TREE_OVERFLOW (arg1)
14105 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE
14106 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))))->b == 2)
14107 {
14108 const REAL_VALUE_TYPE *const re0 = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
14109 const REAL_VALUE_TYPE *const im0 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
14110 const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1));
14111 const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1));
14112
652d9409 14113 if (do_nonfinite
14114 || (real_isfinite (re0) && real_isfinite (im0)
14115 && real_isfinite (re1) && real_isfinite (im1)))
c699fab8 14116 {
14117 const struct real_format *const fmt =
14118 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
14119 const int prec = fmt->p;
14120 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
14121 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
14122 int inexact;
14123 mpc_t m0, m1;
48e1416a 14124
c699fab8 14125 mpc_init2 (m0, prec);
14126 mpc_init2 (m1, prec);
14127 mpfr_from_real (mpc_realref(m0), re0, rnd);
14128 mpfr_from_real (mpc_imagref(m0), im0, rnd);
14129 mpfr_from_real (mpc_realref(m1), re1, rnd);
14130 mpfr_from_real (mpc_imagref(m1), im1, rnd);
14131 mpfr_clear_flags ();
14132 inexact = func (m0, m0, m1, crnd);
652d9409 14133 result = do_mpc_ckconv (m0, type, inexact, do_nonfinite);
c699fab8 14134 mpc_clear (m0);
14135 mpc_clear (m1);
14136 }
14137 }
14138
14139 return result;
14140}
239d491a 14141
75a70cf9 14142/* Fold a call STMT to __{,v}sprintf_chk. Return NULL_TREE if
14143 a normal call should be emitted rather than expanding the function
14144 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
14145
14146static tree
14147gimple_fold_builtin_sprintf_chk (gimple stmt, enum built_in_function fcode)
14148{
75a70cf9 14149 int nargs = gimple_call_num_args (stmt);
14150
af1409ad 14151 return fold_builtin_sprintf_chk_1 (gimple_location (stmt), nargs,
14152 (nargs > 0
14153 ? gimple_call_arg_ptr (stmt, 0)
14154 : &error_mark_node), fcode);
75a70cf9 14155}
14156
14157/* Fold a call STMT to {,v}snprintf. Return NULL_TREE if
14158 a normal call should be emitted rather than expanding the function
14159 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
14160 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
14161 passed as second argument. */
14162
14163tree
14164gimple_fold_builtin_snprintf_chk (gimple stmt, tree maxlen,
14165 enum built_in_function fcode)
14166{
af1409ad 14167 int nargs = gimple_call_num_args (stmt);
75a70cf9 14168
af1409ad 14169 return fold_builtin_snprintf_chk_1 (gimple_location (stmt), nargs,
14170 (nargs > 0
14171 ? gimple_call_arg_ptr (stmt, 0)
14172 : &error_mark_node), maxlen, fcode);
75a70cf9 14173}
14174
14175/* Builtins with folding operations that operate on "..." arguments
14176 need special handling; we need to store the arguments in a convenient
14177 data structure before attempting any folding. Fortunately there are
14178 only a few builtins that fall into this category. FNDECL is the
14179 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
14180 result of the function call is ignored. */
14181
14182static tree
389dd41b 14183gimple_fold_builtin_varargs (tree fndecl, gimple stmt,
14184 bool ignore ATTRIBUTE_UNUSED)
75a70cf9 14185{
14186 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
14187 tree ret = NULL_TREE;
14188
14189 switch (fcode)
14190 {
14191 case BUILT_IN_SPRINTF_CHK:
14192 case BUILT_IN_VSPRINTF_CHK:
14193 ret = gimple_fold_builtin_sprintf_chk (stmt, fcode);
14194 break;
14195
14196 case BUILT_IN_SNPRINTF_CHK:
14197 case BUILT_IN_VSNPRINTF_CHK:
14198 ret = gimple_fold_builtin_snprintf_chk (stmt, NULL_TREE, fcode);
14199
14200 default:
14201 break;
14202 }
14203 if (ret)
14204 {
14205 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
14206 TREE_NO_WARNING (ret) = 1;
14207 return ret;
14208 }
14209 return NULL_TREE;
14210}
14211
14212/* A wrapper function for builtin folding that prevents warnings for
14213 "statement without effect" and the like, caused by removing the
14214 call node earlier than the warning is generated. */
14215
14216tree
14217fold_call_stmt (gimple stmt, bool ignore)
14218{
14219 tree ret = NULL_TREE;
14220 tree fndecl = gimple_call_fndecl (stmt);
389dd41b 14221 location_t loc = gimple_location (stmt);
75a70cf9 14222 if (fndecl
14223 && TREE_CODE (fndecl) == FUNCTION_DECL
14224 && DECL_BUILT_IN (fndecl)
14225 && !gimple_call_va_arg_pack_p (stmt))
14226 {
14227 int nargs = gimple_call_num_args (stmt);
9845fb99 14228 tree *args = (nargs > 0
14229 ? gimple_call_arg_ptr (stmt, 0)
14230 : &error_mark_node);
75a70cf9 14231
198622c0 14232 if (avoid_folding_inline_builtin (fndecl))
14233 return NULL_TREE;
75a70cf9 14234 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
14235 {
9845fb99 14236 return targetm.fold_builtin (fndecl, nargs, args, ignore);
75a70cf9 14237 }
14238 else
14239 {
14240 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
9845fb99 14241 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
75a70cf9 14242 if (!ret)
14243 ret = gimple_fold_builtin_varargs (fndecl, stmt, ignore);
14244 if (ret)
14245 {
14246 /* Propagate location information from original call to
14247 expansion of builtin. Otherwise things like
14248 maybe_emit_chk_warning, that operate on the expansion
14249 of a builtin, will use the wrong location information. */
14250 if (gimple_has_location (stmt))
14251 {
14252 tree realret = ret;
14253 if (TREE_CODE (ret) == NOP_EXPR)
14254 realret = TREE_OPERAND (ret, 0);
14255 if (CAN_HAVE_LOCATION_P (realret)
14256 && !EXPR_HAS_LOCATION (realret))
389dd41b 14257 SET_EXPR_LOCATION (realret, loc);
75a70cf9 14258 return realret;
14259 }
14260 return ret;
14261 }
14262 }
14263 }
14264 return NULL_TREE;
14265}
7bfefa9d 14266
b9a16870 14267/* Look up the function in builtin_decl that corresponds to DECL
7bfefa9d 14268 and set ASMSPEC as its user assembler name. DECL must be a
14269 function decl that declares a builtin. */
14270
14271void
14272set_builtin_user_assembler_name (tree decl, const char *asmspec)
14273{
14274 tree builtin;
14275 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
14276 && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
14277 && asmspec != 0);
14278
b9a16870 14279 builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
4d8e0d6d 14280 set_user_assembler_name (builtin, asmspec);
7bfefa9d 14281 switch (DECL_FUNCTION_CODE (decl))
14282 {
14283 case BUILT_IN_MEMCPY:
14284 init_block_move_fn (asmspec);
14285 memcpy_libfunc = set_user_assembler_libfunc ("memcpy", asmspec);
14286 break;
14287 case BUILT_IN_MEMSET:
14288 init_block_clear_fn (asmspec);
14289 memset_libfunc = set_user_assembler_libfunc ("memset", asmspec);
14290 break;
14291 case BUILT_IN_MEMMOVE:
14292 memmove_libfunc = set_user_assembler_libfunc ("memmove", asmspec);
14293 break;
14294 case BUILT_IN_MEMCMP:
14295 memcmp_libfunc = set_user_assembler_libfunc ("memcmp", asmspec);
14296 break;
14297 case BUILT_IN_ABORT:
14298 abort_libfunc = set_user_assembler_libfunc ("abort", asmspec);
14299 break;
5a80a58b 14300 case BUILT_IN_FFS:
14301 if (INT_TYPE_SIZE < BITS_PER_WORD)
14302 {
14303 set_user_assembler_libfunc ("ffs", asmspec);
14304 set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE,
14305 MODE_INT, 0), "ffs");
14306 }
14307 break;
7bfefa9d 14308 default:
14309 break;
14310 }
14311}
a6b74a67 14312
14313/* Return true if DECL is a builtin that expands to a constant or similarly
14314 simple code. */
14315bool
14316is_simple_builtin (tree decl)
14317{
14318 if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
14319 switch (DECL_FUNCTION_CODE (decl))
14320 {
14321 /* Builtins that expand to constants. */
14322 case BUILT_IN_CONSTANT_P:
14323 case BUILT_IN_EXPECT:
14324 case BUILT_IN_OBJECT_SIZE:
14325 case BUILT_IN_UNREACHABLE:
14326 /* Simple register moves or loads from stack. */
fca0886c 14327 case BUILT_IN_ASSUME_ALIGNED:
a6b74a67 14328 case BUILT_IN_RETURN_ADDRESS:
14329 case BUILT_IN_EXTRACT_RETURN_ADDR:
14330 case BUILT_IN_FROB_RETURN_ADDR:
14331 case BUILT_IN_RETURN:
14332 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
14333 case BUILT_IN_FRAME_ADDRESS:
14334 case BUILT_IN_VA_END:
14335 case BUILT_IN_STACK_SAVE:
14336 case BUILT_IN_STACK_RESTORE:
14337 /* Exception state returns or moves registers around. */
14338 case BUILT_IN_EH_FILTER:
14339 case BUILT_IN_EH_POINTER:
14340 case BUILT_IN_EH_COPY_VALUES:
14341 return true;
14342
14343 default:
14344 return false;
14345 }
14346
14347 return false;
14348}
14349
14350/* Return true if DECL is a builtin that is not expensive, i.e., they are
14351 most probably expanded inline into reasonably simple code. This is a
14352 superset of is_simple_builtin. */
14353bool
14354is_inexpensive_builtin (tree decl)
14355{
14356 if (!decl)
14357 return false;
14358 else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_MD)
14359 return true;
14360 else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
14361 switch (DECL_FUNCTION_CODE (decl))
14362 {
14363 case BUILT_IN_ABS:
14364 case BUILT_IN_ALLOCA:
581bf1c2 14365 case BUILT_IN_ALLOCA_WITH_ALIGN:
74bdbe96 14366 case BUILT_IN_BSWAP16:
a6b74a67 14367 case BUILT_IN_BSWAP32:
14368 case BUILT_IN_BSWAP64:
14369 case BUILT_IN_CLZ:
14370 case BUILT_IN_CLZIMAX:
14371 case BUILT_IN_CLZL:
14372 case BUILT_IN_CLZLL:
14373 case BUILT_IN_CTZ:
14374 case BUILT_IN_CTZIMAX:
14375 case BUILT_IN_CTZL:
14376 case BUILT_IN_CTZLL:
14377 case BUILT_IN_FFS:
14378 case BUILT_IN_FFSIMAX:
14379 case BUILT_IN_FFSL:
14380 case BUILT_IN_FFSLL:
14381 case BUILT_IN_IMAXABS:
14382 case BUILT_IN_FINITE:
14383 case BUILT_IN_FINITEF:
14384 case BUILT_IN_FINITEL:
14385 case BUILT_IN_FINITED32:
14386 case BUILT_IN_FINITED64:
14387 case BUILT_IN_FINITED128:
14388 case BUILT_IN_FPCLASSIFY:
14389 case BUILT_IN_ISFINITE:
14390 case BUILT_IN_ISINF_SIGN:
14391 case BUILT_IN_ISINF:
14392 case BUILT_IN_ISINFF:
14393 case BUILT_IN_ISINFL:
14394 case BUILT_IN_ISINFD32:
14395 case BUILT_IN_ISINFD64:
14396 case BUILT_IN_ISINFD128:
14397 case BUILT_IN_ISNAN:
14398 case BUILT_IN_ISNANF:
14399 case BUILT_IN_ISNANL:
14400 case BUILT_IN_ISNAND32:
14401 case BUILT_IN_ISNAND64:
14402 case BUILT_IN_ISNAND128:
14403 case BUILT_IN_ISNORMAL:
14404 case BUILT_IN_ISGREATER:
14405 case BUILT_IN_ISGREATEREQUAL:
14406 case BUILT_IN_ISLESS:
14407 case BUILT_IN_ISLESSEQUAL:
14408 case BUILT_IN_ISLESSGREATER:
14409 case BUILT_IN_ISUNORDERED:
14410 case BUILT_IN_VA_ARG_PACK:
14411 case BUILT_IN_VA_ARG_PACK_LEN:
14412 case BUILT_IN_VA_COPY:
14413 case BUILT_IN_TRAP:
14414 case BUILT_IN_SAVEREGS:
14415 case BUILT_IN_POPCOUNTL:
14416 case BUILT_IN_POPCOUNTLL:
14417 case BUILT_IN_POPCOUNTIMAX:
14418 case BUILT_IN_POPCOUNT:
14419 case BUILT_IN_PARITYL:
14420 case BUILT_IN_PARITYLL:
14421 case BUILT_IN_PARITYIMAX:
14422 case BUILT_IN_PARITY:
14423 case BUILT_IN_LABS:
14424 case BUILT_IN_LLABS:
14425 case BUILT_IN_PREFETCH:
14426 return true;
14427
14428 default:
14429 return is_simple_builtin (decl);
14430 }
14431
14432 return false;
14433}