]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/builtins.c
Fix g++.dg/tls/thread_local* on Solaris 9
[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
e12b44a3 954 happen immediately, not later. Similarly, we must block
955 (frame-related) register values to be used across this code. */
3072d30e 956 emit_insn (gen_blockage ());
6b7f6858 957}
53800dbe 958
53800dbe 959/* __builtin_longjmp is passed a pointer to an array of five words (not
960 all will be used on all machines). It operates similarly to the C
961 library function of the same name, but is more efficient. Much of
2c8a1497 962 the code below is copied from the handling of non-local gotos. */
53800dbe 963
c626df3d 964static void
aecda0d6 965expand_builtin_longjmp (rtx buf_addr, rtx value)
53800dbe 966{
4712c7d6 967 rtx fp, lab, stack, insn, last;
53800dbe 968 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
969
48e1416a 970 /* DRAP is needed for stack realign if longjmp is expanded to current
27a7a23a 971 function */
972 if (SUPPORTS_STACK_ALIGNMENT)
973 crtl->need_drap = true;
974
f7c44134 975 if (setjmp_alias_set == -1)
976 setjmp_alias_set = new_alias_set ();
977
85d654dd 978 buf_addr = convert_memory_address (Pmode, buf_addr);
479e4d5e 979
53800dbe 980 buf_addr = force_reg (Pmode, buf_addr);
981
82c7907c 982 /* We require that the user must pass a second argument of 1, because
983 that is what builtin_setjmp will return. */
64db345d 984 gcc_assert (value == const1_rtx);
53800dbe 985
4712c7d6 986 last = get_last_insn ();
53800dbe 987#ifdef HAVE_builtin_longjmp
988 if (HAVE_builtin_longjmp)
989 emit_insn (gen_builtin_longjmp (buf_addr));
990 else
991#endif
992 {
993 fp = gen_rtx_MEM (Pmode, buf_addr);
29c05e22 994 lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
53800dbe 995 GET_MODE_SIZE (Pmode)));
996
29c05e22 997 stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, buf_addr,
53800dbe 998 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 999 set_mem_alias_set (fp, setjmp_alias_set);
1000 set_mem_alias_set (lab, setjmp_alias_set);
1001 set_mem_alias_set (stack, setjmp_alias_set);
53800dbe 1002
1003 /* Pick up FP, label, and SP from the block and jump. This code is
1004 from expand_goto in stmt.c; see there for detailed comments. */
03fd9d2c 1005#ifdef HAVE_nonlocal_goto
53800dbe 1006 if (HAVE_nonlocal_goto)
1007 /* We have to pass a value to the nonlocal_goto pattern that will
1008 get copied into the static_chain pointer, but it does not matter
1009 what that value is, because builtin_setjmp does not use it. */
28d202a8 1010 emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
53800dbe 1011 else
1012#endif
1013 {
1014 lab = copy_to_reg (lab);
1015
18b42941 1016 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
1017 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
2a871ad1 1018
53800dbe 1019 emit_move_insn (hard_frame_pointer_rtx, fp);
e9c97615 1020 emit_stack_restore (SAVE_NONLOCAL, stack);
53800dbe 1021
18b42941 1022 emit_use (hard_frame_pointer_rtx);
1023 emit_use (stack_pointer_rtx);
53800dbe 1024 emit_indirect_jump (lab);
1025 }
1026 }
615166bb 1027
1028 /* Search backwards and mark the jump insn as a non-local goto.
1029 Note that this precludes the use of __builtin_longjmp to a
1030 __builtin_setjmp target in the same function. However, we've
1031 already cautioned the user that these functions are for
1032 internal exception handling use only. */
449c0509 1033 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
1034 {
64db345d 1035 gcc_assert (insn != last);
7d3f6cc7 1036
6d7dc5b9 1037 if (JUMP_P (insn))
449c0509 1038 {
a1ddb869 1039 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
449c0509 1040 break;
1041 }
6d7dc5b9 1042 else if (CALL_P (insn))
9342ee68 1043 break;
449c0509 1044 }
53800dbe 1045}
1046
4ee9c684 1047/* Expand a call to __builtin_nonlocal_goto. We're passed the target label
1048 and the address of the save area. */
1049
1050static rtx
c2f47e15 1051expand_builtin_nonlocal_goto (tree exp)
4ee9c684 1052{
1053 tree t_label, t_save_area;
1054 rtx r_label, r_save_area, r_fp, r_sp, insn;
1055
c2f47e15 1056 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4ee9c684 1057 return NULL_RTX;
1058
c2f47e15 1059 t_label = CALL_EXPR_ARG (exp, 0);
1060 t_save_area = CALL_EXPR_ARG (exp, 1);
4ee9c684 1061
8ec3c5c2 1062 r_label = expand_normal (t_label);
3dce56cc 1063 r_label = convert_memory_address (Pmode, r_label);
8ec3c5c2 1064 r_save_area = expand_normal (t_save_area);
3dce56cc 1065 r_save_area = convert_memory_address (Pmode, r_save_area);
d1ff492e 1066 /* Copy the address of the save location to a register just in case it was
1067 based on the frame pointer. */
51adbc8a 1068 r_save_area = copy_to_reg (r_save_area);
4ee9c684 1069 r_fp = gen_rtx_MEM (Pmode, r_save_area);
1070 r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
29c05e22 1071 plus_constant (Pmode, r_save_area,
1072 GET_MODE_SIZE (Pmode)));
4ee9c684 1073
18d50ae6 1074 crtl->has_nonlocal_goto = 1;
4ee9c684 1075
03fd9d2c 1076#ifdef HAVE_nonlocal_goto
4ee9c684 1077 /* ??? We no longer need to pass the static chain value, afaik. */
1078 if (HAVE_nonlocal_goto)
1079 emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
1080 else
1081#endif
1082 {
1083 r_label = copy_to_reg (r_label);
1084
18b42941 1085 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
1086 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
491e04ef 1087
d1ff492e 1088 /* Restore frame pointer for containing function. */
4ee9c684 1089 emit_move_insn (hard_frame_pointer_rtx, r_fp);
e9c97615 1090 emit_stack_restore (SAVE_NONLOCAL, r_sp);
491e04ef 1091
4ee9c684 1092 /* USE of hard_frame_pointer_rtx added for consistency;
1093 not clear if really needed. */
18b42941 1094 emit_use (hard_frame_pointer_rtx);
1095 emit_use (stack_pointer_rtx);
ad0d0af8 1096
1097 /* If the architecture is using a GP register, we must
1098 conservatively assume that the target function makes use of it.
1099 The prologue of functions with nonlocal gotos must therefore
1100 initialize the GP register to the appropriate value, and we
1101 must then make sure that this value is live at the point
1102 of the jump. (Note that this doesn't necessarily apply
1103 to targets with a nonlocal_goto pattern; they are free
1104 to implement it in their own way. Note also that this is
1105 a no-op if the GP register is a global invariant.) */
1106 if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
1107 && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
18b42941 1108 emit_use (pic_offset_table_rtx);
ad0d0af8 1109
4ee9c684 1110 emit_indirect_jump (r_label);
1111 }
491e04ef 1112
4ee9c684 1113 /* Search backwards to the jump insn and mark it as a
1114 non-local goto. */
1115 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
1116 {
6d7dc5b9 1117 if (JUMP_P (insn))
4ee9c684 1118 {
a1ddb869 1119 add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx);
4ee9c684 1120 break;
1121 }
6d7dc5b9 1122 else if (CALL_P (insn))
4ee9c684 1123 break;
1124 }
1125
1126 return const0_rtx;
1127}
1128
843d08a9 1129/* __builtin_update_setjmp_buf is passed a pointer to an array of five words
1130 (not all will be used on all machines) that was passed to __builtin_setjmp.
1131 It updates the stack pointer in that block to correspond to the current
1132 stack pointer. */
1133
1134static void
1135expand_builtin_update_setjmp_buf (rtx buf_addr)
1136{
d1ff492e 1137 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
1138 rtx stack_save
843d08a9 1139 = gen_rtx_MEM (sa_mode,
1140 memory_address
1141 (sa_mode,
29c05e22 1142 plus_constant (Pmode, buf_addr,
1143 2 * GET_MODE_SIZE (Pmode))));
843d08a9 1144
e9c97615 1145 emit_stack_save (SAVE_NONLOCAL, &stack_save);
843d08a9 1146}
1147
5e3608d8 1148/* Expand a call to __builtin_prefetch. For a target that does not support
1149 data prefetch, evaluate the memory address argument in case it has side
1150 effects. */
1151
1152static void
c2f47e15 1153expand_builtin_prefetch (tree exp)
5e3608d8 1154{
1155 tree arg0, arg1, arg2;
c2f47e15 1156 int nargs;
5e3608d8 1157 rtx op0, op1, op2;
1158
c2f47e15 1159 if (!validate_arglist (exp, POINTER_TYPE, 0))
26a5cadb 1160 return;
1161
c2f47e15 1162 arg0 = CALL_EXPR_ARG (exp, 0);
1163
26a5cadb 1164 /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
1165 zero (read) and argument 2 (locality) defaults to 3 (high degree of
1166 locality). */
c2f47e15 1167 nargs = call_expr_nargs (exp);
1168 if (nargs > 1)
1169 arg1 = CALL_EXPR_ARG (exp, 1);
26a5cadb 1170 else
c2f47e15 1171 arg1 = integer_zero_node;
1172 if (nargs > 2)
1173 arg2 = CALL_EXPR_ARG (exp, 2);
1174 else
2512209b 1175 arg2 = integer_three_node;
5e3608d8 1176
1177 /* Argument 0 is an address. */
1178 op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
1179
1180 /* Argument 1 (read/write flag) must be a compile-time constant int. */
1181 if (TREE_CODE (arg1) != INTEGER_CST)
1182 {
07e3a3d2 1183 error ("second argument to %<__builtin_prefetch%> must be a constant");
9342ee68 1184 arg1 = integer_zero_node;
5e3608d8 1185 }
8ec3c5c2 1186 op1 = expand_normal (arg1);
5e3608d8 1187 /* Argument 1 must be either zero or one. */
1188 if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
1189 {
c3ceba8e 1190 warning (0, "invalid second argument to %<__builtin_prefetch%>;"
07e3a3d2 1191 " using zero");
5e3608d8 1192 op1 = const0_rtx;
1193 }
1194
1195 /* Argument 2 (locality) must be a compile-time constant int. */
1196 if (TREE_CODE (arg2) != INTEGER_CST)
1197 {
07e3a3d2 1198 error ("third argument to %<__builtin_prefetch%> must be a constant");
5e3608d8 1199 arg2 = integer_zero_node;
1200 }
8ec3c5c2 1201 op2 = expand_normal (arg2);
5e3608d8 1202 /* Argument 2 must be 0, 1, 2, or 3. */
1203 if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
1204 {
c3ceba8e 1205 warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
5e3608d8 1206 op2 = const0_rtx;
1207 }
1208
1209#ifdef HAVE_prefetch
1210 if (HAVE_prefetch)
1211 {
8786db1e 1212 struct expand_operand ops[3];
1213
1214 create_address_operand (&ops[0], op0);
1215 create_integer_operand (&ops[1], INTVAL (op1));
1216 create_integer_operand (&ops[2], INTVAL (op2));
1217 if (maybe_expand_insn (CODE_FOR_prefetch, 3, ops))
1218 return;
5e3608d8 1219 }
5e3608d8 1220#endif
0a534ba7 1221
f0ce3b1f 1222 /* Don't do anything with direct references to volatile memory, but
1223 generate code to handle other side effects. */
e16ceb8e 1224 if (!MEM_P (op0) && side_effects_p (op0))
f0ce3b1f 1225 emit_insn (op0);
5e3608d8 1226}
1227
f7c44134 1228/* Get a MEM rtx for expression EXP which is the address of an operand
d8ae1baa 1229 to be used in a string instruction (cmpstrsi, movmemsi, ..). LEN is
1230 the maximum length of the block of memory that might be accessed or
1231 NULL if unknown. */
f7c44134 1232
53800dbe 1233static rtx
d8ae1baa 1234get_memory_rtx (tree exp, tree len)
53800dbe 1235{
ad0a178f 1236 tree orig_exp = exp;
1237 rtx addr, mem;
ad0a178f 1238
1239 /* When EXP is not resolved SAVE_EXPR, MEM_ATTRS can be still derived
1240 from its expression, for expr->a.b only <variable>.a.b is recorded. */
1241 if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp))
1242 exp = TREE_OPERAND (exp, 0);
1243
1244 addr = expand_expr (orig_exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
1245 mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
2a631e19 1246
f7c44134 1247 /* Get an expression we can use to find the attributes to assign to MEM.
5dd3f78f 1248 First remove any nops. */
72dd6141 1249 while (CONVERT_EXPR_P (exp)
f7c44134 1250 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
1251 exp = TREE_OPERAND (exp, 0);
1252
5dd3f78f 1253 /* Build a MEM_REF representing the whole accessed area as a byte blob,
1254 (as builtin stringops may alias with anything). */
1255 exp = fold_build2 (MEM_REF,
1256 build_array_type (char_type_node,
1257 build_range_type (sizetype,
1258 size_one_node, len)),
1259 exp, build_int_cst (ptr_type_node, 0));
1260
1261 /* If the MEM_REF has no acceptable address, try to get the base object
1262 from the original address we got, and build an all-aliasing
1263 unknown-sized access to that one. */
1264 if (is_gimple_mem_ref_addr (TREE_OPERAND (exp, 0)))
1265 set_mem_attributes (mem, exp, 0);
1266 else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
1267 && (exp = get_base_address (TREE_OPERAND (TREE_OPERAND (exp, 0),
1268 0))))
eec8e941 1269 {
5dd3f78f 1270 exp = build_fold_addr_expr (exp);
1271 exp = fold_build2 (MEM_REF,
1272 build_array_type (char_type_node,
1273 build_range_type (sizetype,
1274 size_zero_node,
1275 NULL)),
1276 exp, build_int_cst (ptr_type_node, 0));
a1a25d19 1277 set_mem_attributes (mem, exp, 0);
eec8e941 1278 }
5dd3f78f 1279 set_mem_alias_set (mem, 0);
53800dbe 1280 return mem;
1281}
1282\f
1283/* Built-in functions to perform an untyped call and return. */
1284
3b9c3a16 1285#define apply_args_mode \
1286 (this_target_builtins->x_apply_args_mode)
1287#define apply_result_mode \
1288 (this_target_builtins->x_apply_result_mode)
53800dbe 1289
53800dbe 1290/* Return the size required for the block returned by __builtin_apply_args,
1291 and initialize apply_args_mode. */
1292
1293static int
aecda0d6 1294apply_args_size (void)
53800dbe 1295{
1296 static int size = -1;
58e9ce8f 1297 int align;
1298 unsigned int regno;
53800dbe 1299 enum machine_mode mode;
1300
1301 /* The values computed by this function never change. */
1302 if (size < 0)
1303 {
1304 /* The first value is the incoming arg-pointer. */
1305 size = GET_MODE_SIZE (Pmode);
1306
1307 /* The second value is the structure value address unless this is
1308 passed as an "invisible" first argument. */
6812c89e 1309 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1310 size += GET_MODE_SIZE (Pmode);
1311
1312 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1313 if (FUNCTION_ARG_REGNO_P (regno))
1314 {
4bac51c9 1315 mode = targetm.calls.get_raw_arg_mode (regno);
0862b7e9 1316
64db345d 1317 gcc_assert (mode != VOIDmode);
53800dbe 1318
1319 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1320 if (size % align != 0)
1321 size = CEIL (size, align) * align;
53800dbe 1322 size += GET_MODE_SIZE (mode);
1323 apply_args_mode[regno] = mode;
1324 }
1325 else
1326 {
1327 apply_args_mode[regno] = VOIDmode;
53800dbe 1328 }
1329 }
1330 return size;
1331}
1332
1333/* Return the size required for the block returned by __builtin_apply,
1334 and initialize apply_result_mode. */
1335
1336static int
aecda0d6 1337apply_result_size (void)
53800dbe 1338{
1339 static int size = -1;
1340 int align, regno;
1341 enum machine_mode mode;
1342
1343 /* The values computed by this function never change. */
1344 if (size < 0)
1345 {
1346 size = 0;
1347
1348 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
e1ce1485 1349 if (targetm.calls.function_value_regno_p (regno))
53800dbe 1350 {
4bac51c9 1351 mode = targetm.calls.get_raw_result_mode (regno);
0862b7e9 1352
64db345d 1353 gcc_assert (mode != VOIDmode);
53800dbe 1354
1355 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1356 if (size % align != 0)
1357 size = CEIL (size, align) * align;
1358 size += GET_MODE_SIZE (mode);
1359 apply_result_mode[regno] = mode;
1360 }
1361 else
1362 apply_result_mode[regno] = VOIDmode;
1363
1364 /* Allow targets that use untyped_call and untyped_return to override
1365 the size so that machine-specific information can be stored here. */
1366#ifdef APPLY_RESULT_SIZE
1367 size = APPLY_RESULT_SIZE;
1368#endif
1369 }
1370 return size;
1371}
1372
1373#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1374/* Create a vector describing the result block RESULT. If SAVEP is true,
1375 the result block is used to save the values; otherwise it is used to
1376 restore the values. */
1377
1378static rtx
aecda0d6 1379result_vector (int savep, rtx result)
53800dbe 1380{
1381 int regno, size, align, nelts;
1382 enum machine_mode mode;
1383 rtx reg, mem;
364c0c59 1384 rtx *savevec = XALLOCAVEC (rtx, FIRST_PSEUDO_REGISTER);
bf8e3599 1385
53800dbe 1386 size = nelts = 0;
1387 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1388 if ((mode = apply_result_mode[regno]) != VOIDmode)
1389 {
1390 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1391 if (size % align != 0)
1392 size = CEIL (size, align) * align;
1393 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
e513d163 1394 mem = adjust_address (result, mode, size);
53800dbe 1395 savevec[nelts++] = (savep
1396 ? gen_rtx_SET (VOIDmode, mem, reg)
1397 : gen_rtx_SET (VOIDmode, reg, mem));
1398 size += GET_MODE_SIZE (mode);
1399 }
1400 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1401}
1402#endif /* HAVE_untyped_call or HAVE_untyped_return */
1403
1404/* Save the state required to perform an untyped call with the same
1405 arguments as were passed to the current function. */
1406
1407static rtx
aecda0d6 1408expand_builtin_apply_args_1 (void)
53800dbe 1409{
1c7e61a7 1410 rtx registers, tem;
53800dbe 1411 int size, align, regno;
1412 enum machine_mode mode;
6812c89e 1413 rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
53800dbe 1414
1415 /* Create a block where the arg-pointer, structure value address,
1416 and argument registers can be saved. */
1417 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1418
1419 /* Walk past the arg-pointer and structure value address. */
1420 size = GET_MODE_SIZE (Pmode);
6812c89e 1421 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
53800dbe 1422 size += GET_MODE_SIZE (Pmode);
1423
1424 /* Save each register used in calling a function to the block. */
1425 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1426 if ((mode = apply_args_mode[regno]) != VOIDmode)
1427 {
53800dbe 1428 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1429 if (size % align != 0)
1430 size = CEIL (size, align) * align;
1431
1432 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1433
e513d163 1434 emit_move_insn (adjust_address (registers, mode, size), tem);
53800dbe 1435 size += GET_MODE_SIZE (mode);
1436 }
1437
1438 /* Save the arg pointer to the block. */
27a7a23a 1439 tem = copy_to_reg (crtl->args.internal_arg_pointer);
f083a92b 1440#ifdef STACK_GROWS_DOWNWARD
1c7e61a7 1441 /* We need the pointer as the caller actually passed them to us, not
9d4b544c 1442 as we might have pretended they were passed. Make sure it's a valid
1443 operand, as emit_move_insn isn't expected to handle a PLUS. */
1444 tem
29c05e22 1445 = force_operand (plus_constant (Pmode, tem, crtl->args.pretend_args_size),
9d4b544c 1446 NULL_RTX);
1c7e61a7 1447#endif
1448 emit_move_insn (adjust_address (registers, Pmode, 0), tem);
0862b7e9 1449
53800dbe 1450 size = GET_MODE_SIZE (Pmode);
1451
1452 /* Save the structure value address unless this is passed as an
1453 "invisible" first argument. */
45550790 1454 if (struct_incoming_value)
53800dbe 1455 {
e513d163 1456 emit_move_insn (adjust_address (registers, Pmode, size),
45550790 1457 copy_to_reg (struct_incoming_value));
53800dbe 1458 size += GET_MODE_SIZE (Pmode);
1459 }
1460
1461 /* Return the address of the block. */
1462 return copy_addr_to_reg (XEXP (registers, 0));
1463}
1464
1465/* __builtin_apply_args returns block of memory allocated on
1466 the stack into which is stored the arg pointer, structure
1467 value address, static chain, and all the registers that might
1468 possibly be used in performing a function call. The code is
1469 moved to the start of the function so the incoming values are
1470 saved. */
27d0c333 1471
53800dbe 1472static rtx
aecda0d6 1473expand_builtin_apply_args (void)
53800dbe 1474{
1475 /* Don't do __builtin_apply_args more than once in a function.
1476 Save the result of the first call and reuse it. */
1477 if (apply_args_value != 0)
1478 return apply_args_value;
1479 {
1480 /* When this function is called, it means that registers must be
1481 saved on entry to this function. So we migrate the
1482 call to the first insn of this function. */
1483 rtx temp;
1484 rtx seq;
1485
1486 start_sequence ();
1487 temp = expand_builtin_apply_args_1 ();
1488 seq = get_insns ();
1489 end_sequence ();
1490
1491 apply_args_value = temp;
1492
31d3e01c 1493 /* Put the insns after the NOTE that starts the function.
1494 If this is inside a start_sequence, make the outer-level insn
53800dbe 1495 chain current, so the code is placed at the start of the
0ef1a651 1496 function. If internal_arg_pointer is a non-virtual pseudo,
1497 it needs to be placed after the function that initializes
1498 that pseudo. */
53800dbe 1499 push_topmost_sequence ();
0ef1a651 1500 if (REG_P (crtl->args.internal_arg_pointer)
1501 && REGNO (crtl->args.internal_arg_pointer) > LAST_VIRTUAL_REGISTER)
1502 emit_insn_before (seq, parm_birth_insn);
1503 else
1504 emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
53800dbe 1505 pop_topmost_sequence ();
1506 return temp;
1507 }
1508}
1509
1510/* Perform an untyped call and save the state required to perform an
1511 untyped return of whatever value was returned by the given function. */
1512
1513static rtx
aecda0d6 1514expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
53800dbe 1515{
1516 int size, align, regno;
1517 enum machine_mode mode;
2a631e19 1518 rtx incoming_args, result, reg, dest, src, call_insn;
53800dbe 1519 rtx old_stack_level = 0;
1520 rtx call_fusage = 0;
6812c89e 1521 rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
53800dbe 1522
85d654dd 1523 arguments = convert_memory_address (Pmode, arguments);
726ec87c 1524
53800dbe 1525 /* Create a block where the return registers can be saved. */
1526 result = assign_stack_local (BLKmode, apply_result_size (), -1);
1527
53800dbe 1528 /* Fetch the arg pointer from the ARGUMENTS block. */
1529 incoming_args = gen_reg_rtx (Pmode);
726ec87c 1530 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
53800dbe 1531#ifndef STACK_GROWS_DOWNWARD
ad99e708 1532 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1533 incoming_args, 0, OPTAB_LIB_WIDEN);
53800dbe 1534#endif
1535
04a46d40 1536 /* Push a new argument block and copy the arguments. Do not allow
1537 the (potential) memcpy call below to interfere with our stack
1538 manipulations. */
53800dbe 1539 do_pending_stack_adjust ();
04a46d40 1540 NO_DEFER_POP;
53800dbe 1541
2358393e 1542 /* Save the stack with nonlocal if available. */
53800dbe 1543#ifdef HAVE_save_stack_nonlocal
1544 if (HAVE_save_stack_nonlocal)
e9c97615 1545 emit_stack_save (SAVE_NONLOCAL, &old_stack_level);
53800dbe 1546 else
1547#endif
e9c97615 1548 emit_stack_save (SAVE_BLOCK, &old_stack_level);
53800dbe 1549
59647703 1550 /* Allocate a block of memory onto the stack and copy the memory
990495a7 1551 arguments to the outgoing arguments address. We can pass TRUE
1552 as the 4th argument because we just saved the stack pointer
1553 and will restore it right after the call. */
5be42b39 1554 allocate_dynamic_stack_space (argsize, 0, BIGGEST_ALIGNMENT, true);
27a7a23a 1555
1556 /* Set DRAP flag to true, even though allocate_dynamic_stack_space
1557 may have already set current_function_calls_alloca to true.
1558 current_function_calls_alloca won't be set if argsize is zero,
1559 so we have to guarantee need_drap is true here. */
1560 if (SUPPORTS_STACK_ALIGNMENT)
1561 crtl->need_drap = true;
1562
59647703 1563 dest = virtual_outgoing_args_rtx;
1564#ifndef STACK_GROWS_DOWNWARD
971ba038 1565 if (CONST_INT_P (argsize))
29c05e22 1566 dest = plus_constant (Pmode, dest, -INTVAL (argsize));
59647703 1567 else
1568 dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1569#endif
2a631e19 1570 dest = gen_rtx_MEM (BLKmode, dest);
1571 set_mem_align (dest, PARM_BOUNDARY);
1572 src = gen_rtx_MEM (BLKmode, incoming_args);
1573 set_mem_align (src, PARM_BOUNDARY);
0378dbdc 1574 emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
53800dbe 1575
1576 /* Refer to the argument block. */
1577 apply_args_size ();
1578 arguments = gen_rtx_MEM (BLKmode, arguments);
2a631e19 1579 set_mem_align (arguments, PARM_BOUNDARY);
53800dbe 1580
1581 /* Walk past the arg-pointer and structure value address. */
1582 size = GET_MODE_SIZE (Pmode);
45550790 1583 if (struct_value)
53800dbe 1584 size += GET_MODE_SIZE (Pmode);
1585
1586 /* Restore each of the registers previously saved. Make USE insns
1587 for each of these registers for use in making the call. */
1588 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1589 if ((mode = apply_args_mode[regno]) != VOIDmode)
1590 {
1591 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1592 if (size % align != 0)
1593 size = CEIL (size, align) * align;
1594 reg = gen_rtx_REG (mode, regno);
e513d163 1595 emit_move_insn (reg, adjust_address (arguments, mode, size));
53800dbe 1596 use_reg (&call_fusage, reg);
1597 size += GET_MODE_SIZE (mode);
1598 }
1599
1600 /* Restore the structure value address unless this is passed as an
1601 "invisible" first argument. */
1602 size = GET_MODE_SIZE (Pmode);
45550790 1603 if (struct_value)
53800dbe 1604 {
1605 rtx value = gen_reg_rtx (Pmode);
e513d163 1606 emit_move_insn (value, adjust_address (arguments, Pmode, size));
45550790 1607 emit_move_insn (struct_value, value);
8ad4c111 1608 if (REG_P (struct_value))
45550790 1609 use_reg (&call_fusage, struct_value);
53800dbe 1610 size += GET_MODE_SIZE (Pmode);
1611 }
1612
1613 /* All arguments and registers used for the call are set up by now! */
82c7907c 1614 function = prepare_call_address (NULL, function, NULL, &call_fusage, 0, 0);
53800dbe 1615
1616 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1617 and we don't want to load it into a register as an optimization,
1618 because prepare_call_address already did it if it should be done. */
1619 if (GET_CODE (function) != SYMBOL_REF)
1620 function = memory_address (FUNCTION_MODE, function);
1621
1622 /* Generate the actual call instruction and save the return value. */
1623#ifdef HAVE_untyped_call
1624 if (HAVE_untyped_call)
1625 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1626 result, result_vector (1, result)));
1627 else
1628#endif
1629#ifdef HAVE_call_value
1630 if (HAVE_call_value)
1631 {
1632 rtx valreg = 0;
1633
1634 /* Locate the unique return register. It is not possible to
1635 express a call that sets more than one return register using
1636 call_value; use untyped_call for that. In fact, untyped_call
1637 only needs to save the return registers in the given block. */
1638 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1639 if ((mode = apply_result_mode[regno]) != VOIDmode)
1640 {
64db345d 1641 gcc_assert (!valreg); /* HAVE_untyped_call required. */
7d3f6cc7 1642
53800dbe 1643 valreg = gen_rtx_REG (mode, regno);
1644 }
1645
2ed6c343 1646 emit_call_insn (GEN_CALL_VALUE (valreg,
53800dbe 1647 gen_rtx_MEM (FUNCTION_MODE, function),
1648 const0_rtx, NULL_RTX, const0_rtx));
1649
e513d163 1650 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
53800dbe 1651 }
1652 else
1653#endif
64db345d 1654 gcc_unreachable ();
53800dbe 1655
d5f9786f 1656 /* Find the CALL insn we just emitted, and attach the register usage
1657 information. */
1658 call_insn = last_call_insn ();
1659 add_function_usage_to (call_insn, call_fusage);
53800dbe 1660
1661 /* Restore the stack. */
1662#ifdef HAVE_save_stack_nonlocal
1663 if (HAVE_save_stack_nonlocal)
e9c97615 1664 emit_stack_restore (SAVE_NONLOCAL, old_stack_level);
53800dbe 1665 else
1666#endif
e9c97615 1667 emit_stack_restore (SAVE_BLOCK, old_stack_level);
4bb7c660 1668 fixup_args_size_notes (call_insn, get_last_insn(), 0);
53800dbe 1669
04a46d40 1670 OK_DEFER_POP;
1671
53800dbe 1672 /* Return the address of the result block. */
85d654dd 1673 result = copy_addr_to_reg (XEXP (result, 0));
1674 return convert_memory_address (ptr_mode, result);
53800dbe 1675}
1676
1677/* Perform an untyped return. */
1678
1679static void
aecda0d6 1680expand_builtin_return (rtx result)
53800dbe 1681{
1682 int size, align, regno;
1683 enum machine_mode mode;
1684 rtx reg;
1685 rtx call_fusage = 0;
1686
85d654dd 1687 result = convert_memory_address (Pmode, result);
726ec87c 1688
53800dbe 1689 apply_result_size ();
1690 result = gen_rtx_MEM (BLKmode, result);
1691
1692#ifdef HAVE_untyped_return
1693 if (HAVE_untyped_return)
1694 {
1695 emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1696 emit_barrier ();
1697 return;
1698 }
1699#endif
1700
1701 /* Restore the return value and note that each value is used. */
1702 size = 0;
1703 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1704 if ((mode = apply_result_mode[regno]) != VOIDmode)
1705 {
1706 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1707 if (size % align != 0)
1708 size = CEIL (size, align) * align;
1709 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
e513d163 1710 emit_move_insn (reg, adjust_address (result, mode, size));
53800dbe 1711
1712 push_to_sequence (call_fusage);
18b42941 1713 emit_use (reg);
53800dbe 1714 call_fusage = get_insns ();
1715 end_sequence ();
1716 size += GET_MODE_SIZE (mode);
1717 }
1718
1719 /* Put the USE insns before the return. */
31d3e01c 1720 emit_insn (call_fusage);
53800dbe 1721
1722 /* Return whatever values was restored by jumping directly to the end
1723 of the function. */
62380d2d 1724 expand_naked_return ();
53800dbe 1725}
1726
539a3a92 1727/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
27d0c333 1728
539a3a92 1729static enum type_class
aecda0d6 1730type_to_class (tree type)
539a3a92 1731{
1732 switch (TREE_CODE (type))
1733 {
1734 case VOID_TYPE: return void_type_class;
1735 case INTEGER_TYPE: return integer_type_class;
539a3a92 1736 case ENUMERAL_TYPE: return enumeral_type_class;
1737 case BOOLEAN_TYPE: return boolean_type_class;
1738 case POINTER_TYPE: return pointer_type_class;
1739 case REFERENCE_TYPE: return reference_type_class;
1740 case OFFSET_TYPE: return offset_type_class;
1741 case REAL_TYPE: return real_type_class;
1742 case COMPLEX_TYPE: return complex_type_class;
1743 case FUNCTION_TYPE: return function_type_class;
1744 case METHOD_TYPE: return method_type_class;
1745 case RECORD_TYPE: return record_type_class;
1746 case UNION_TYPE:
1747 case QUAL_UNION_TYPE: return union_type_class;
1748 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1749 ? string_type_class : array_type_class);
539a3a92 1750 case LANG_TYPE: return lang_type_class;
1751 default: return no_type_class;
1752 }
1753}
bf8e3599 1754
c2f47e15 1755/* Expand a call EXP to __builtin_classify_type. */
27d0c333 1756
53800dbe 1757static rtx
c2f47e15 1758expand_builtin_classify_type (tree exp)
53800dbe 1759{
c2f47e15 1760 if (call_expr_nargs (exp))
1761 return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG (exp, 0))));
53800dbe 1762 return GEN_INT (no_type_class);
1763}
1764
07976da7 1765/* This helper macro, meant to be used in mathfn_built_in below,
1766 determines which among a set of three builtin math functions is
1767 appropriate for a given type mode. The `F' and `L' cases are
1768 automatically generated from the `double' case. */
1769#define CASE_MATHFN(BUILT_IN_MATHFN) \
1770 case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1771 fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1772 fcodel = BUILT_IN_MATHFN##L ; break;
cd2656b0 1773/* Similar to above, but appends _R after any F/L suffix. */
1774#define CASE_MATHFN_REENT(BUILT_IN_MATHFN) \
1775 case BUILT_IN_MATHFN##_R: case BUILT_IN_MATHFN##F_R: case BUILT_IN_MATHFN##L_R: \
1776 fcode = BUILT_IN_MATHFN##_R; fcodef = BUILT_IN_MATHFN##F_R ; \
1777 fcodel = BUILT_IN_MATHFN##L_R ; break;
07976da7 1778
b9a16870 1779/* Return mathematic function equivalent to FN but operating directly on TYPE,
1780 if available. If IMPLICIT is true use the implicit builtin declaration,
1781 otherwise use the explicit declaration. If we can't do the conversion,
1782 return zero. */
c319d56a 1783
1784static tree
b9a16870 1785mathfn_built_in_1 (tree type, enum built_in_function fn, bool implicit_p)
0a68165a 1786{
b9a16870 1787 enum built_in_function fcode, fcodef, fcodel, fcode2;
07976da7 1788
1789 switch (fn)
1790 {
746114e8 1791 CASE_MATHFN (BUILT_IN_ACOS)
1792 CASE_MATHFN (BUILT_IN_ACOSH)
1793 CASE_MATHFN (BUILT_IN_ASIN)
1794 CASE_MATHFN (BUILT_IN_ASINH)
07976da7 1795 CASE_MATHFN (BUILT_IN_ATAN)
746114e8 1796 CASE_MATHFN (BUILT_IN_ATAN2)
1797 CASE_MATHFN (BUILT_IN_ATANH)
1798 CASE_MATHFN (BUILT_IN_CBRT)
07976da7 1799 CASE_MATHFN (BUILT_IN_CEIL)
d735c391 1800 CASE_MATHFN (BUILT_IN_CEXPI)
746114e8 1801 CASE_MATHFN (BUILT_IN_COPYSIGN)
07976da7 1802 CASE_MATHFN (BUILT_IN_COS)
746114e8 1803 CASE_MATHFN (BUILT_IN_COSH)
1804 CASE_MATHFN (BUILT_IN_DREM)
1805 CASE_MATHFN (BUILT_IN_ERF)
1806 CASE_MATHFN (BUILT_IN_ERFC)
07976da7 1807 CASE_MATHFN (BUILT_IN_EXP)
746114e8 1808 CASE_MATHFN (BUILT_IN_EXP10)
1809 CASE_MATHFN (BUILT_IN_EXP2)
1810 CASE_MATHFN (BUILT_IN_EXPM1)
1811 CASE_MATHFN (BUILT_IN_FABS)
1812 CASE_MATHFN (BUILT_IN_FDIM)
07976da7 1813 CASE_MATHFN (BUILT_IN_FLOOR)
746114e8 1814 CASE_MATHFN (BUILT_IN_FMA)
1815 CASE_MATHFN (BUILT_IN_FMAX)
1816 CASE_MATHFN (BUILT_IN_FMIN)
1817 CASE_MATHFN (BUILT_IN_FMOD)
1818 CASE_MATHFN (BUILT_IN_FREXP)
1819 CASE_MATHFN (BUILT_IN_GAMMA)
cd2656b0 1820 CASE_MATHFN_REENT (BUILT_IN_GAMMA) /* GAMMA_R */
746114e8 1821 CASE_MATHFN (BUILT_IN_HUGE_VAL)
1822 CASE_MATHFN (BUILT_IN_HYPOT)
1823 CASE_MATHFN (BUILT_IN_ILOGB)
80ff6494 1824 CASE_MATHFN (BUILT_IN_ICEIL)
1825 CASE_MATHFN (BUILT_IN_IFLOOR)
746114e8 1826 CASE_MATHFN (BUILT_IN_INF)
80ff6494 1827 CASE_MATHFN (BUILT_IN_IRINT)
1828 CASE_MATHFN (BUILT_IN_IROUND)
69b779ea 1829 CASE_MATHFN (BUILT_IN_ISINF)
746114e8 1830 CASE_MATHFN (BUILT_IN_J0)
1831 CASE_MATHFN (BUILT_IN_J1)
1832 CASE_MATHFN (BUILT_IN_JN)
ac148751 1833 CASE_MATHFN (BUILT_IN_LCEIL)
746114e8 1834 CASE_MATHFN (BUILT_IN_LDEXP)
ad52b9b7 1835 CASE_MATHFN (BUILT_IN_LFLOOR)
746114e8 1836 CASE_MATHFN (BUILT_IN_LGAMMA)
cd2656b0 1837 CASE_MATHFN_REENT (BUILT_IN_LGAMMA) /* LGAMMA_R */
ac148751 1838 CASE_MATHFN (BUILT_IN_LLCEIL)
ad52b9b7 1839 CASE_MATHFN (BUILT_IN_LLFLOOR)
746114e8 1840 CASE_MATHFN (BUILT_IN_LLRINT)
1841 CASE_MATHFN (BUILT_IN_LLROUND)
07976da7 1842 CASE_MATHFN (BUILT_IN_LOG)
746114e8 1843 CASE_MATHFN (BUILT_IN_LOG10)
1844 CASE_MATHFN (BUILT_IN_LOG1P)
1845 CASE_MATHFN (BUILT_IN_LOG2)
1846 CASE_MATHFN (BUILT_IN_LOGB)
1847 CASE_MATHFN (BUILT_IN_LRINT)
1848 CASE_MATHFN (BUILT_IN_LROUND)
1849 CASE_MATHFN (BUILT_IN_MODF)
1850 CASE_MATHFN (BUILT_IN_NAN)
1851 CASE_MATHFN (BUILT_IN_NANS)
07976da7 1852 CASE_MATHFN (BUILT_IN_NEARBYINT)
746114e8 1853 CASE_MATHFN (BUILT_IN_NEXTAFTER)
1854 CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1855 CASE_MATHFN (BUILT_IN_POW)
757c219d 1856 CASE_MATHFN (BUILT_IN_POWI)
746114e8 1857 CASE_MATHFN (BUILT_IN_POW10)
1858 CASE_MATHFN (BUILT_IN_REMAINDER)
1859 CASE_MATHFN (BUILT_IN_REMQUO)
1860 CASE_MATHFN (BUILT_IN_RINT)
07976da7 1861 CASE_MATHFN (BUILT_IN_ROUND)
746114e8 1862 CASE_MATHFN (BUILT_IN_SCALB)
1863 CASE_MATHFN (BUILT_IN_SCALBLN)
1864 CASE_MATHFN (BUILT_IN_SCALBN)
c319d56a 1865 CASE_MATHFN (BUILT_IN_SIGNBIT)
746114e8 1866 CASE_MATHFN (BUILT_IN_SIGNIFICAND)
07976da7 1867 CASE_MATHFN (BUILT_IN_SIN)
746114e8 1868 CASE_MATHFN (BUILT_IN_SINCOS)
1869 CASE_MATHFN (BUILT_IN_SINH)
07976da7 1870 CASE_MATHFN (BUILT_IN_SQRT)
1871 CASE_MATHFN (BUILT_IN_TAN)
746114e8 1872 CASE_MATHFN (BUILT_IN_TANH)
1873 CASE_MATHFN (BUILT_IN_TGAMMA)
07976da7 1874 CASE_MATHFN (BUILT_IN_TRUNC)
746114e8 1875 CASE_MATHFN (BUILT_IN_Y0)
1876 CASE_MATHFN (BUILT_IN_Y1)
1877 CASE_MATHFN (BUILT_IN_YN)
07976da7 1878
0a68165a 1879 default:
c2f47e15 1880 return NULL_TREE;
0a68165a 1881 }
07976da7 1882
96b9f485 1883 if (TYPE_MAIN_VARIANT (type) == double_type_node)
b9a16870 1884 fcode2 = fcode;
96b9f485 1885 else if (TYPE_MAIN_VARIANT (type) == float_type_node)
b9a16870 1886 fcode2 = fcodef;
96b9f485 1887 else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
b9a16870 1888 fcode2 = fcodel;
07976da7 1889 else
c2f47e15 1890 return NULL_TREE;
b9a16870 1891
1892 if (implicit_p && !builtin_decl_implicit_p (fcode2))
1893 return NULL_TREE;
1894
1895 return builtin_decl_explicit (fcode2);
0a68165a 1896}
1897
c319d56a 1898/* Like mathfn_built_in_1(), but always use the implicit array. */
1899
1900tree
1901mathfn_built_in (tree type, enum built_in_function fn)
1902{
1903 return mathfn_built_in_1 (type, fn, /*implicit=*/ 1);
1904}
1905
0fd605a5 1906/* If errno must be maintained, expand the RTL to check if the result,
1907 TARGET, of a built-in function call, EXP, is NaN, and if so set
1908 errno to EDOM. */
1909
1910static void
aecda0d6 1911expand_errno_check (tree exp, rtx target)
0fd605a5 1912{
7f05340e 1913 rtx lab = gen_label_rtx ();
0fd605a5 1914
7f05340e 1915 /* Test the result; if it is NaN, set errno=EDOM because
1916 the argument was not in the domain. */
3fcf767f 1917 do_compare_rtx_and_jump (target, target, EQ, 0, GET_MODE (target),
79ab74cc 1918 NULL_RTX, NULL_RTX, lab,
1919 /* The jump is very likely. */
1920 REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1));
0fd605a5 1921
1922#ifdef TARGET_EDOM
7f05340e 1923 /* If this built-in doesn't throw an exception, set errno directly. */
c2f47e15 1924 if (TREE_NOTHROW (TREE_OPERAND (CALL_EXPR_FN (exp), 0)))
7f05340e 1925 {
0fd605a5 1926#ifdef GEN_ERRNO_RTX
7f05340e 1927 rtx errno_rtx = GEN_ERRNO_RTX;
0fd605a5 1928#else
7f05340e 1929 rtx errno_rtx
0fd605a5 1930 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1931#endif
7f05340e 1932 emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
0fd605a5 1933 emit_label (lab);
7f05340e 1934 return;
0fd605a5 1935 }
7f05340e 1936#endif
1937
08491912 1938 /* Make sure the library call isn't expanded as a tail call. */
1939 CALL_EXPR_TAILCALL (exp) = 0;
1940
7f05340e 1941 /* We can't set errno=EDOM directly; let the library call do it.
1942 Pop the arguments right away in case the call gets deleted. */
1943 NO_DEFER_POP;
1944 expand_call (exp, target, 0);
1945 OK_DEFER_POP;
1946 emit_label (lab);
0fd605a5 1947}
1948
6b43bae4 1949/* Expand a call to one of the builtin math functions (sqrt, exp, or log).
c2f47e15 1950 Return NULL_RTX if a normal call should be emitted rather than expanding
1951 the function in-line. EXP is the expression that is a call to the builtin
53800dbe 1952 function; if convenient, the result should be placed in TARGET.
1953 SUBTARGET may be used as the target for computing one of EXP's operands. */
27d0c333 1954
53800dbe 1955static rtx
aecda0d6 1956expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
53800dbe 1957{
bf8e3599 1958 optab builtin_optab;
1e4adcfc 1959 rtx op0, insns;
c6e6ecb1 1960 tree fndecl = get_callee_fndecl (exp);
7f05340e 1961 enum machine_mode mode;
528ee710 1962 bool errno_set = false;
abfea505 1963 tree arg;
53800dbe 1964
c2f47e15 1965 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
1966 return NULL_RTX;
53800dbe 1967
c2f47e15 1968 arg = CALL_EXPR_ARG (exp, 0);
53800dbe 1969
1970 switch (DECL_FUNCTION_CODE (fndecl))
1971 {
4f35b1fc 1972 CASE_FLT_FN (BUILT_IN_SQRT):
7f05340e 1973 errno_set = ! tree_expr_nonnegative_p (arg);
1974 builtin_optab = sqrt_optab;
1975 break;
4f35b1fc 1976 CASE_FLT_FN (BUILT_IN_EXP):
528ee710 1977 errno_set = true; builtin_optab = exp_optab; break;
4f35b1fc 1978 CASE_FLT_FN (BUILT_IN_EXP10):
1979 CASE_FLT_FN (BUILT_IN_POW10):
750ef9f5 1980 errno_set = true; builtin_optab = exp10_optab; break;
4f35b1fc 1981 CASE_FLT_FN (BUILT_IN_EXP2):
750ef9f5 1982 errno_set = true; builtin_optab = exp2_optab; break;
4f35b1fc 1983 CASE_FLT_FN (BUILT_IN_EXPM1):
a6b4eed2 1984 errno_set = true; builtin_optab = expm1_optab; break;
4f35b1fc 1985 CASE_FLT_FN (BUILT_IN_LOGB):
4efbc641 1986 errno_set = true; builtin_optab = logb_optab; break;
4f35b1fc 1987 CASE_FLT_FN (BUILT_IN_LOG):
528ee710 1988 errno_set = true; builtin_optab = log_optab; break;
4f35b1fc 1989 CASE_FLT_FN (BUILT_IN_LOG10):
d3cd9bde 1990 errno_set = true; builtin_optab = log10_optab; break;
4f35b1fc 1991 CASE_FLT_FN (BUILT_IN_LOG2):
d3cd9bde 1992 errno_set = true; builtin_optab = log2_optab; break;
4f35b1fc 1993 CASE_FLT_FN (BUILT_IN_LOG1P):
f474cd93 1994 errno_set = true; builtin_optab = log1p_optab; break;
4f35b1fc 1995 CASE_FLT_FN (BUILT_IN_ASIN):
8de2f465 1996 builtin_optab = asin_optab; break;
4f35b1fc 1997 CASE_FLT_FN (BUILT_IN_ACOS):
8de2f465 1998 builtin_optab = acos_optab; break;
4f35b1fc 1999 CASE_FLT_FN (BUILT_IN_TAN):
528ee710 2000 builtin_optab = tan_optab; break;
4f35b1fc 2001 CASE_FLT_FN (BUILT_IN_ATAN):
528ee710 2002 builtin_optab = atan_optab; break;
4f35b1fc 2003 CASE_FLT_FN (BUILT_IN_FLOOR):
528ee710 2004 builtin_optab = floor_optab; break;
4f35b1fc 2005 CASE_FLT_FN (BUILT_IN_CEIL):
528ee710 2006 builtin_optab = ceil_optab; break;
4f35b1fc 2007 CASE_FLT_FN (BUILT_IN_TRUNC):
a7cc195f 2008 builtin_optab = btrunc_optab; break;
4f35b1fc 2009 CASE_FLT_FN (BUILT_IN_ROUND):
528ee710 2010 builtin_optab = round_optab; break;
4f35b1fc 2011 CASE_FLT_FN (BUILT_IN_NEARBYINT):
0ddf4ad9 2012 builtin_optab = nearbyint_optab;
2013 if (flag_trapping_math)
2014 break;
2015 /* Else fallthrough and expand as rint. */
4f35b1fc 2016 CASE_FLT_FN (BUILT_IN_RINT):
aef94a0f 2017 builtin_optab = rint_optab; break;
b3154a1f 2018 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
2019 builtin_optab = significand_optab; break;
42721db0 2020 default:
64db345d 2021 gcc_unreachable ();
53800dbe 2022 }
2023
7f05340e 2024 /* Make a suitable register to place result in. */
2025 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2026
7f05340e 2027 if (! flag_errno_math || ! HONOR_NANS (mode))
2028 errno_set = false;
2029
bd421108 2030 /* Before working hard, check whether the instruction is available. */
f2aca212 2031 if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing
2032 && (!errno_set || !optimize_insn_for_size_p ()))
68e6cb9d 2033 {
de2e453e 2034 rtx result = gen_reg_rtx (mode);
7f05340e 2035
bd421108 2036 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2037 need to expand the argument again. This way, we will not perform
2038 side-effects more the once. */
abfea505 2039 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7f05340e 2040
1db6d067 2041 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
7f05340e 2042
bd421108 2043 start_sequence ();
53800dbe 2044
de2e453e 2045 /* Compute into RESULT.
2046 Set RESULT to wherever the result comes back. */
2047 result = expand_unop (mode, builtin_optab, op0, result, 0);
bd421108 2048
de2e453e 2049 if (result != 0)
bd421108 2050 {
2051 if (errno_set)
de2e453e 2052 expand_errno_check (exp, result);
bd421108 2053
2054 /* Output the entire sequence. */
2055 insns = get_insns ();
2056 end_sequence ();
2057 emit_insn (insns);
de2e453e 2058 return result;
bd421108 2059 }
2060
2061 /* If we were unable to expand via the builtin, stop the sequence
2062 (without outputting the insns) and call to the library function
2063 with the stabilized argument list. */
53800dbe 2064 end_sequence ();
53800dbe 2065 }
2066
1e5b92fa 2067 return expand_call (exp, target, target == const0_rtx);
0fd605a5 2068}
2069
2070/* Expand a call to the builtin binary math functions (pow and atan2).
c2f47e15 2071 Return NULL_RTX if a normal call should be emitted rather than expanding the
0fd605a5 2072 function in-line. EXP is the expression that is a call to the builtin
2073 function; if convenient, the result should be placed in TARGET.
2074 SUBTARGET may be used as the target for computing one of EXP's
2075 operands. */
2076
2077static rtx
aecda0d6 2078expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
0fd605a5 2079{
2080 optab builtin_optab;
de2e453e 2081 rtx op0, op1, insns, result;
4737caf2 2082 int op1_type = REAL_TYPE;
c6e6ecb1 2083 tree fndecl = get_callee_fndecl (exp);
abfea505 2084 tree arg0, arg1;
7f05340e 2085 enum machine_mode mode;
0fd605a5 2086 bool errno_set = true;
0fd605a5 2087
73a954a1 2088 switch (DECL_FUNCTION_CODE (fndecl))
2089 {
2090 CASE_FLT_FN (BUILT_IN_SCALBN):
2091 CASE_FLT_FN (BUILT_IN_SCALBLN):
2092 CASE_FLT_FN (BUILT_IN_LDEXP):
2093 op1_type = INTEGER_TYPE;
2094 default:
2095 break;
2096 }
4737caf2 2097
c2f47e15 2098 if (!validate_arglist (exp, REAL_TYPE, op1_type, VOID_TYPE))
2099 return NULL_RTX;
0fd605a5 2100
c2f47e15 2101 arg0 = CALL_EXPR_ARG (exp, 0);
2102 arg1 = CALL_EXPR_ARG (exp, 1);
0fd605a5 2103
0fd605a5 2104 switch (DECL_FUNCTION_CODE (fndecl))
2105 {
4f35b1fc 2106 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 2107 builtin_optab = pow_optab; break;
4f35b1fc 2108 CASE_FLT_FN (BUILT_IN_ATAN2):
0fd605a5 2109 builtin_optab = atan2_optab; break;
73a954a1 2110 CASE_FLT_FN (BUILT_IN_SCALB):
2111 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2112 return 0;
2113 builtin_optab = scalb_optab; break;
2114 CASE_FLT_FN (BUILT_IN_SCALBN):
2115 CASE_FLT_FN (BUILT_IN_SCALBLN):
2116 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2)
2117 return 0;
2118 /* Fall through... */
4f35b1fc 2119 CASE_FLT_FN (BUILT_IN_LDEXP):
4737caf2 2120 builtin_optab = ldexp_optab; break;
4f35b1fc 2121 CASE_FLT_FN (BUILT_IN_FMOD):
80ed5c06 2122 builtin_optab = fmod_optab; break;
ef722005 2123 CASE_FLT_FN (BUILT_IN_REMAINDER):
4f35b1fc 2124 CASE_FLT_FN (BUILT_IN_DREM):
ef722005 2125 builtin_optab = remainder_optab; break;
0fd605a5 2126 default:
64db345d 2127 gcc_unreachable ();
0fd605a5 2128 }
2129
7f05340e 2130 /* Make a suitable register to place result in. */
2131 mode = TYPE_MODE (TREE_TYPE (exp));
fc4eef90 2132
2133 /* Before working hard, check whether the instruction is available. */
d6bf3b14 2134 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
c2f47e15 2135 return NULL_RTX;
fc4eef90 2136
de2e453e 2137 result = gen_reg_rtx (mode);
7f05340e 2138
2139 if (! flag_errno_math || ! HONOR_NANS (mode))
2140 errno_set = false;
2141
f2aca212 2142 if (errno_set && optimize_insn_for_size_p ())
2143 return 0;
2144
4ee9c684 2145 /* Always stabilize the argument list. */
abfea505 2146 CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
2147 CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
7f05340e 2148
8ec3c5c2 2149 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2150 op1 = expand_normal (arg1);
7f05340e 2151
7f05340e 2152 start_sequence ();
2153
de2e453e 2154 /* Compute into RESULT.
2155 Set RESULT to wherever the result comes back. */
2156 result = expand_binop (mode, builtin_optab, op0, op1,
2157 result, 0, OPTAB_DIRECT);
53800dbe 2158
68e6cb9d 2159 /* If we were unable to expand via the builtin, stop the sequence
2160 (without outputting the insns) and call to the library function
2161 with the stabilized argument list. */
de2e453e 2162 if (result == 0)
0fd605a5 2163 {
2164 end_sequence ();
68e6cb9d 2165 return expand_call (exp, target, target == const0_rtx);
53800dbe 2166 }
2167
a4356fb9 2168 if (errno_set)
de2e453e 2169 expand_errno_check (exp, result);
0fd605a5 2170
53800dbe 2171 /* Output the entire sequence. */
2172 insns = get_insns ();
2173 end_sequence ();
31d3e01c 2174 emit_insn (insns);
bf8e3599 2175
de2e453e 2176 return result;
53800dbe 2177}
2178
7e0713b1 2179/* Expand a call to the builtin trinary math functions (fma).
2180 Return NULL_RTX if a normal call should be emitted rather than expanding the
2181 function in-line. EXP is the expression that is a call to the builtin
2182 function; if convenient, the result should be placed in TARGET.
2183 SUBTARGET may be used as the target for computing one of EXP's
2184 operands. */
2185
2186static rtx
2187expand_builtin_mathfn_ternary (tree exp, rtx target, rtx subtarget)
2188{
2189 optab builtin_optab;
de2e453e 2190 rtx op0, op1, op2, insns, result;
7e0713b1 2191 tree fndecl = get_callee_fndecl (exp);
2192 tree arg0, arg1, arg2;
2193 enum machine_mode mode;
2194
2195 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2196 return NULL_RTX;
2197
2198 arg0 = CALL_EXPR_ARG (exp, 0);
2199 arg1 = CALL_EXPR_ARG (exp, 1);
2200 arg2 = CALL_EXPR_ARG (exp, 2);
2201
2202 switch (DECL_FUNCTION_CODE (fndecl))
2203 {
2204 CASE_FLT_FN (BUILT_IN_FMA):
2205 builtin_optab = fma_optab; break;
2206 default:
2207 gcc_unreachable ();
2208 }
2209
2210 /* Make a suitable register to place result in. */
2211 mode = TYPE_MODE (TREE_TYPE (exp));
2212
2213 /* Before working hard, check whether the instruction is available. */
2214 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
2215 return NULL_RTX;
2216
de2e453e 2217 result = gen_reg_rtx (mode);
7e0713b1 2218
2219 /* Always stabilize the argument list. */
2220 CALL_EXPR_ARG (exp, 0) = arg0 = builtin_save_expr (arg0);
2221 CALL_EXPR_ARG (exp, 1) = arg1 = builtin_save_expr (arg1);
2222 CALL_EXPR_ARG (exp, 2) = arg2 = builtin_save_expr (arg2);
2223
2224 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2225 op1 = expand_normal (arg1);
2226 op2 = expand_normal (arg2);
2227
2228 start_sequence ();
2229
de2e453e 2230 /* Compute into RESULT.
2231 Set RESULT to wherever the result comes back. */
2232 result = expand_ternary_op (mode, builtin_optab, op0, op1, op2,
2233 result, 0);
7e0713b1 2234
2235 /* If we were unable to expand via the builtin, stop the sequence
2236 (without outputting the insns) and call to the library function
2237 with the stabilized argument list. */
de2e453e 2238 if (result == 0)
7e0713b1 2239 {
2240 end_sequence ();
2241 return expand_call (exp, target, target == const0_rtx);
2242 }
2243
2244 /* Output the entire sequence. */
2245 insns = get_insns ();
2246 end_sequence ();
2247 emit_insn (insns);
2248
de2e453e 2249 return result;
7e0713b1 2250}
2251
6b43bae4 2252/* Expand a call to the builtin sin and cos math functions.
c2f47e15 2253 Return NULL_RTX if a normal call should be emitted rather than expanding the
6b43bae4 2254 function in-line. EXP is the expression that is a call to the builtin
2255 function; if convenient, the result should be placed in TARGET.
2256 SUBTARGET may be used as the target for computing one of EXP's
2257 operands. */
2258
2259static rtx
2260expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
2261{
2262 optab builtin_optab;
7511b819 2263 rtx op0, insns;
6b43bae4 2264 tree fndecl = get_callee_fndecl (exp);
6b43bae4 2265 enum machine_mode mode;
abfea505 2266 tree arg;
6b43bae4 2267
c2f47e15 2268 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2269 return NULL_RTX;
6b43bae4 2270
c2f47e15 2271 arg = CALL_EXPR_ARG (exp, 0);
6b43bae4 2272
2273 switch (DECL_FUNCTION_CODE (fndecl))
2274 {
4f35b1fc 2275 CASE_FLT_FN (BUILT_IN_SIN):
2276 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2277 builtin_optab = sincos_optab; break;
2278 default:
64db345d 2279 gcc_unreachable ();
6b43bae4 2280 }
2281
2282 /* Make a suitable register to place result in. */
2283 mode = TYPE_MODE (TREE_TYPE (exp));
2284
6b43bae4 2285 /* Check if sincos insn is available, otherwise fallback
0bed3869 2286 to sin or cos insn. */
d6bf3b14 2287 if (optab_handler (builtin_optab, mode) == CODE_FOR_nothing)
6b43bae4 2288 switch (DECL_FUNCTION_CODE (fndecl))
2289 {
4f35b1fc 2290 CASE_FLT_FN (BUILT_IN_SIN):
6b43bae4 2291 builtin_optab = sin_optab; break;
4f35b1fc 2292 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 2293 builtin_optab = cos_optab; break;
2294 default:
64db345d 2295 gcc_unreachable ();
6b43bae4 2296 }
6b43bae4 2297
2298 /* Before working hard, check whether the instruction is available. */
d6bf3b14 2299 if (optab_handler (builtin_optab, mode) != CODE_FOR_nothing)
6b43bae4 2300 {
de2e453e 2301 rtx result = gen_reg_rtx (mode);
6b43bae4 2302
2303 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2304 need to expand the argument again. This way, we will not perform
2305 side-effects more the once. */
abfea505 2306 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
6b43bae4 2307
1db6d067 2308 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
6b43bae4 2309
6b43bae4 2310 start_sequence ();
2311
de2e453e 2312 /* Compute into RESULT.
2313 Set RESULT to wherever the result comes back. */
6b43bae4 2314 if (builtin_optab == sincos_optab)
2315 {
de2e453e 2316 int ok;
7d3f6cc7 2317
6b43bae4 2318 switch (DECL_FUNCTION_CODE (fndecl))
2319 {
4f35b1fc 2320 CASE_FLT_FN (BUILT_IN_SIN):
de2e453e 2321 ok = expand_twoval_unop (builtin_optab, op0, 0, result, 0);
6b43bae4 2322 break;
4f35b1fc 2323 CASE_FLT_FN (BUILT_IN_COS):
de2e453e 2324 ok = expand_twoval_unop (builtin_optab, op0, result, 0, 0);
6b43bae4 2325 break;
2326 default:
64db345d 2327 gcc_unreachable ();
6b43bae4 2328 }
de2e453e 2329 gcc_assert (ok);
6b43bae4 2330 }
2331 else
de2e453e 2332 result = expand_unop (mode, builtin_optab, op0, result, 0);
6b43bae4 2333
de2e453e 2334 if (result != 0)
6b43bae4 2335 {
6b43bae4 2336 /* Output the entire sequence. */
2337 insns = get_insns ();
2338 end_sequence ();
2339 emit_insn (insns);
de2e453e 2340 return result;
6b43bae4 2341 }
2342
2343 /* If we were unable to expand via the builtin, stop the sequence
2344 (without outputting the insns) and call to the library function
2345 with the stabilized argument list. */
2346 end_sequence ();
2347 }
2348
de2e453e 2349 return expand_call (exp, target, target == const0_rtx);
6b43bae4 2350}
2351
a65c4d64 2352/* Given an interclass math builtin decl FNDECL and it's argument ARG
2353 return an RTL instruction code that implements the functionality.
2354 If that isn't possible or available return CODE_FOR_nothing. */
a67a90e5 2355
a65c4d64 2356static enum insn_code
2357interclass_mathfn_icode (tree arg, tree fndecl)
a67a90e5 2358{
a65c4d64 2359 bool errno_set = false;
6cdd383a 2360 optab builtin_optab = unknown_optab;
a67a90e5 2361 enum machine_mode mode;
a67a90e5 2362
2363 switch (DECL_FUNCTION_CODE (fndecl))
2364 {
2365 CASE_FLT_FN (BUILT_IN_ILOGB):
2366 errno_set = true; builtin_optab = ilogb_optab; break;
69b779ea 2367 CASE_FLT_FN (BUILT_IN_ISINF):
2368 builtin_optab = isinf_optab; break;
8a1a9cb7 2369 case BUILT_IN_ISNORMAL:
cde061c1 2370 case BUILT_IN_ISFINITE:
2371 CASE_FLT_FN (BUILT_IN_FINITE):
a65c4d64 2372 case BUILT_IN_FINITED32:
2373 case BUILT_IN_FINITED64:
2374 case BUILT_IN_FINITED128:
2375 case BUILT_IN_ISINFD32:
2376 case BUILT_IN_ISINFD64:
2377 case BUILT_IN_ISINFD128:
cde061c1 2378 /* These builtins have no optabs (yet). */
2379 break;
a67a90e5 2380 default:
2381 gcc_unreachable ();
2382 }
2383
2384 /* There's no easy way to detect the case we need to set EDOM. */
2385 if (flag_errno_math && errno_set)
a65c4d64 2386 return CODE_FOR_nothing;
a67a90e5 2387
2388 /* Optab mode depends on the mode of the input argument. */
2389 mode = TYPE_MODE (TREE_TYPE (arg));
2390
cde061c1 2391 if (builtin_optab)
d6bf3b14 2392 return optab_handler (builtin_optab, mode);
a65c4d64 2393 return CODE_FOR_nothing;
2394}
2395
2396/* Expand a call to one of the builtin math functions that operate on
2397 floating point argument and output an integer result (ilogb, isinf,
2398 isnan, etc).
2399 Return 0 if a normal call should be emitted rather than expanding the
2400 function in-line. EXP is the expression that is a call to the builtin
f97eea22 2401 function; if convenient, the result should be placed in TARGET. */
a65c4d64 2402
2403static rtx
f97eea22 2404expand_builtin_interclass_mathfn (tree exp, rtx target)
a65c4d64 2405{
2406 enum insn_code icode = CODE_FOR_nothing;
2407 rtx op0;
2408 tree fndecl = get_callee_fndecl (exp);
2409 enum machine_mode mode;
2410 tree arg;
2411
2412 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2413 return NULL_RTX;
2414
2415 arg = CALL_EXPR_ARG (exp, 0);
2416 icode = interclass_mathfn_icode (arg, fndecl);
2417 mode = TYPE_MODE (TREE_TYPE (arg));
2418
a67a90e5 2419 if (icode != CODE_FOR_nothing)
2420 {
8786db1e 2421 struct expand_operand ops[1];
4e2a2fb4 2422 rtx last = get_last_insn ();
2423 tree orig_arg = arg;
a67a90e5 2424
2425 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2426 need to expand the argument again. This way, we will not perform
2427 side-effects more the once. */
abfea505 2428 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
a67a90e5 2429
f97eea22 2430 op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
a67a90e5 2431
2432 if (mode != GET_MODE (op0))
2433 op0 = convert_to_mode (mode, op0, 0);
2434
8786db1e 2435 create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
2436 if (maybe_legitimize_operands (icode, 0, 1, ops)
2437 && maybe_emit_unop_insn (icode, ops[0].value, op0, UNKNOWN))
2438 return ops[0].value;
2439
4e2a2fb4 2440 delete_insns_since (last);
2441 CALL_EXPR_ARG (exp, 0) = orig_arg;
a67a90e5 2442 }
2443
a65c4d64 2444 return NULL_RTX;
a67a90e5 2445}
2446
c3147c1a 2447/* Expand a call to the builtin sincos math function.
c2f47e15 2448 Return NULL_RTX if a normal call should be emitted rather than expanding the
c3147c1a 2449 function in-line. EXP is the expression that is a call to the builtin
2450 function. */
2451
2452static rtx
2453expand_builtin_sincos (tree exp)
2454{
2455 rtx op0, op1, op2, target1, target2;
c3147c1a 2456 enum machine_mode mode;
2457 tree arg, sinp, cosp;
2458 int result;
389dd41b 2459 location_t loc = EXPR_LOCATION (exp);
be5575b2 2460 tree alias_type, alias_off;
c3147c1a 2461
c2f47e15 2462 if (!validate_arglist (exp, REAL_TYPE,
2463 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2464 return NULL_RTX;
c3147c1a 2465
c2f47e15 2466 arg = CALL_EXPR_ARG (exp, 0);
2467 sinp = CALL_EXPR_ARG (exp, 1);
2468 cosp = CALL_EXPR_ARG (exp, 2);
c3147c1a 2469
2470 /* Make a suitable register to place result in. */
2471 mode = TYPE_MODE (TREE_TYPE (arg));
2472
2473 /* Check if sincos insn is available, otherwise emit the call. */
d6bf3b14 2474 if (optab_handler (sincos_optab, mode) == CODE_FOR_nothing)
c3147c1a 2475 return NULL_RTX;
2476
2477 target1 = gen_reg_rtx (mode);
2478 target2 = gen_reg_rtx (mode);
2479
8ec3c5c2 2480 op0 = expand_normal (arg);
be5575b2 2481 alias_type = build_pointer_type_for_mode (TREE_TYPE (arg), ptr_mode, true);
2482 alias_off = build_int_cst (alias_type, 0);
2483 op1 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
2484 sinp, alias_off));
2485 op2 = expand_normal (fold_build2_loc (loc, MEM_REF, TREE_TYPE (arg),
2486 cosp, alias_off));
c3147c1a 2487
2488 /* Compute into target1 and target2.
2489 Set TARGET to wherever the result comes back. */
2490 result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
2491 gcc_assert (result);
2492
2493 /* Move target1 and target2 to the memory locations indicated
2494 by op1 and op2. */
2495 emit_move_insn (op1, target1);
2496 emit_move_insn (op2, target2);
2497
2498 return const0_rtx;
2499}
2500
d735c391 2501/* Expand a call to the internal cexpi builtin to the sincos math function.
2502 EXP is the expression that is a call to the builtin function; if convenient,
f97eea22 2503 the result should be placed in TARGET. */
d735c391 2504
2505static rtx
f97eea22 2506expand_builtin_cexpi (tree exp, rtx target)
d735c391 2507{
2508 tree fndecl = get_callee_fndecl (exp);
d735c391 2509 tree arg, type;
c2f47e15 2510 enum machine_mode mode;
d735c391 2511 rtx op0, op1, op2;
389dd41b 2512 location_t loc = EXPR_LOCATION (exp);
d735c391 2513
c2f47e15 2514 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2515 return NULL_RTX;
d735c391 2516
c2f47e15 2517 arg = CALL_EXPR_ARG (exp, 0);
d735c391 2518 type = TREE_TYPE (arg);
2519 mode = TYPE_MODE (TREE_TYPE (arg));
2520
2521 /* Try expanding via a sincos optab, fall back to emitting a libcall
18b8d8ae 2522 to sincos or cexp. We are sure we have sincos or cexp because cexpi
2523 is only generated from sincos, cexp or if we have either of them. */
d6bf3b14 2524 if (optab_handler (sincos_optab, mode) != CODE_FOR_nothing)
d735c391 2525 {
2526 op1 = gen_reg_rtx (mode);
2527 op2 = gen_reg_rtx (mode);
2528
f97eea22 2529 op0 = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
d735c391 2530
2531 /* Compute into op1 and op2. */
2532 expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
2533 }
18b8d8ae 2534 else if (TARGET_HAS_SINCOS)
d735c391 2535 {
c2f47e15 2536 tree call, fn = NULL_TREE;
d735c391 2537 tree top1, top2;
2538 rtx op1a, op2a;
2539
2540 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
b9a16870 2541 fn = builtin_decl_explicit (BUILT_IN_SINCOSF);
d735c391 2542 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
b9a16870 2543 fn = builtin_decl_explicit (BUILT_IN_SINCOS);
d735c391 2544 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
b9a16870 2545 fn = builtin_decl_explicit (BUILT_IN_SINCOSL);
c2f47e15 2546 else
2547 gcc_unreachable ();
48e1416a 2548
0ab48139 2549 op1 = assign_temp (TREE_TYPE (arg), 1, 1);
2550 op2 = assign_temp (TREE_TYPE (arg), 1, 1);
99182918 2551 op1a = copy_addr_to_reg (XEXP (op1, 0));
2552 op2a = copy_addr_to_reg (XEXP (op2, 0));
d735c391 2553 top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
2554 top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
2555
d735c391 2556 /* Make sure not to fold the sincos call again. */
2557 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
c2f47e15 2558 expand_normal (build_call_nary (TREE_TYPE (TREE_TYPE (fn)),
2559 call, 3, arg, top1, top2));
d735c391 2560 }
18b8d8ae 2561 else
2562 {
0ecbc158 2563 tree call, fn = NULL_TREE, narg;
18b8d8ae 2564 tree ctype = build_complex_type (type);
2565
0ecbc158 2566 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
b9a16870 2567 fn = builtin_decl_explicit (BUILT_IN_CEXPF);
0ecbc158 2568 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
b9a16870 2569 fn = builtin_decl_explicit (BUILT_IN_CEXP);
0ecbc158 2570 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
b9a16870 2571 fn = builtin_decl_explicit (BUILT_IN_CEXPL);
c2f47e15 2572 else
2573 gcc_unreachable ();
fc0dfa6e 2574
2575 /* If we don't have a decl for cexp create one. This is the
2576 friendliest fallback if the user calls __builtin_cexpi
2577 without full target C99 function support. */
2578 if (fn == NULL_TREE)
2579 {
2580 tree fntype;
2581 const char *name = NULL;
2582
2583 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
2584 name = "cexpf";
2585 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
2586 name = "cexp";
2587 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
2588 name = "cexpl";
2589
2590 fntype = build_function_type_list (ctype, ctype, NULL_TREE);
2591 fn = build_fn_decl (name, fntype);
2592 }
2593
389dd41b 2594 narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype,
18b8d8ae 2595 build_real (type, dconst0), arg);
2596
2597 /* Make sure not to fold the cexp call again. */
2598 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
48e1416a 2599 return expand_expr (build_call_nary (ctype, call, 1, narg),
1db6d067 2600 target, VOIDmode, EXPAND_NORMAL);
18b8d8ae 2601 }
d735c391 2602
2603 /* Now build the proper return type. */
2604 return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
2605 make_tree (TREE_TYPE (arg), op2),
2606 make_tree (TREE_TYPE (arg), op1)),
1db6d067 2607 target, VOIDmode, EXPAND_NORMAL);
d735c391 2608}
2609
a65c4d64 2610/* Conveniently construct a function call expression. FNDECL names the
2611 function to be called, N is the number of arguments, and the "..."
2612 parameters are the argument expressions. Unlike build_call_exr
2613 this doesn't fold the call, hence it will always return a CALL_EXPR. */
2614
2615static tree
2616build_call_nofold_loc (location_t loc, tree fndecl, int n, ...)
2617{
2618 va_list ap;
2619 tree fntype = TREE_TYPE (fndecl);
2620 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
2621
2622 va_start (ap, n);
2623 fn = build_call_valist (TREE_TYPE (fntype), fn, n, ap);
2624 va_end (ap);
2625 SET_EXPR_LOCATION (fn, loc);
2626 return fn;
2627}
a65c4d64 2628
7d3afc77 2629/* Expand a call to one of the builtin rounding functions gcc defines
2630 as an extension (lfloor and lceil). As these are gcc extensions we
2631 do not need to worry about setting errno to EDOM.
ad52b9b7 2632 If expanding via optab fails, lower expression to (int)(floor(x)).
2633 EXP is the expression that is a call to the builtin function;
ff1b14e4 2634 if convenient, the result should be placed in TARGET. */
ad52b9b7 2635
2636static rtx
ff1b14e4 2637expand_builtin_int_roundingfn (tree exp, rtx target)
ad52b9b7 2638{
9c42dd28 2639 convert_optab builtin_optab;
ad52b9b7 2640 rtx op0, insns, tmp;
2641 tree fndecl = get_callee_fndecl (exp);
ad52b9b7 2642 enum built_in_function fallback_fn;
2643 tree fallback_fndecl;
2644 enum machine_mode mode;
4de0924f 2645 tree arg;
ad52b9b7 2646
c2f47e15 2647 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
ad52b9b7 2648 gcc_unreachable ();
2649
c2f47e15 2650 arg = CALL_EXPR_ARG (exp, 0);
ad52b9b7 2651
2652 switch (DECL_FUNCTION_CODE (fndecl))
2653 {
80ff6494 2654 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 2655 CASE_FLT_FN (BUILT_IN_LCEIL):
2656 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 2657 builtin_optab = lceil_optab;
2658 fallback_fn = BUILT_IN_CEIL;
2659 break;
2660
80ff6494 2661 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 2662 CASE_FLT_FN (BUILT_IN_LFLOOR):
2663 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 2664 builtin_optab = lfloor_optab;
2665 fallback_fn = BUILT_IN_FLOOR;
2666 break;
2667
2668 default:
2669 gcc_unreachable ();
2670 }
2671
2672 /* Make a suitable register to place result in. */
2673 mode = TYPE_MODE (TREE_TYPE (exp));
2674
9c42dd28 2675 target = gen_reg_rtx (mode);
ad52b9b7 2676
9c42dd28 2677 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2678 need to expand the argument again. This way, we will not perform
2679 side-effects more the once. */
abfea505 2680 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
ad52b9b7 2681
ff1b14e4 2682 op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
ad52b9b7 2683
9c42dd28 2684 start_sequence ();
ad52b9b7 2685
9c42dd28 2686 /* Compute into TARGET. */
2687 if (expand_sfix_optab (target, op0, builtin_optab))
2688 {
2689 /* Output the entire sequence. */
2690 insns = get_insns ();
ad52b9b7 2691 end_sequence ();
9c42dd28 2692 emit_insn (insns);
2693 return target;
ad52b9b7 2694 }
2695
9c42dd28 2696 /* If we were unable to expand via the builtin, stop the sequence
2697 (without outputting the insns). */
2698 end_sequence ();
2699
ad52b9b7 2700 /* Fall back to floating point rounding optab. */
2701 fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
fc0dfa6e 2702
2703 /* For non-C99 targets we may end up without a fallback fndecl here
2704 if the user called __builtin_lfloor directly. In this case emit
2705 a call to the floor/ceil variants nevertheless. This should result
2706 in the best user experience for not full C99 targets. */
2707 if (fallback_fndecl == NULL_TREE)
2708 {
2709 tree fntype;
2710 const char *name = NULL;
2711
2712 switch (DECL_FUNCTION_CODE (fndecl))
2713 {
80ff6494 2714 case BUILT_IN_ICEIL:
fc0dfa6e 2715 case BUILT_IN_LCEIL:
2716 case BUILT_IN_LLCEIL:
2717 name = "ceil";
2718 break;
80ff6494 2719 case BUILT_IN_ICEILF:
fc0dfa6e 2720 case BUILT_IN_LCEILF:
2721 case BUILT_IN_LLCEILF:
2722 name = "ceilf";
2723 break;
80ff6494 2724 case BUILT_IN_ICEILL:
fc0dfa6e 2725 case BUILT_IN_LCEILL:
2726 case BUILT_IN_LLCEILL:
2727 name = "ceill";
2728 break;
80ff6494 2729 case BUILT_IN_IFLOOR:
fc0dfa6e 2730 case BUILT_IN_LFLOOR:
2731 case BUILT_IN_LLFLOOR:
2732 name = "floor";
2733 break;
80ff6494 2734 case BUILT_IN_IFLOORF:
fc0dfa6e 2735 case BUILT_IN_LFLOORF:
2736 case BUILT_IN_LLFLOORF:
2737 name = "floorf";
2738 break;
80ff6494 2739 case BUILT_IN_IFLOORL:
fc0dfa6e 2740 case BUILT_IN_LFLOORL:
2741 case BUILT_IN_LLFLOORL:
2742 name = "floorl";
2743 break;
2744 default:
2745 gcc_unreachable ();
2746 }
2747
2748 fntype = build_function_type_list (TREE_TYPE (arg),
2749 TREE_TYPE (arg), NULL_TREE);
2750 fallback_fndecl = build_fn_decl (name, fntype);
2751 }
2752
0568e9c1 2753 exp = build_call_nofold_loc (EXPR_LOCATION (exp), fallback_fndecl, 1, arg);
ad52b9b7 2754
d4c690af 2755 tmp = expand_normal (exp);
933eb13a 2756 tmp = maybe_emit_group_store (tmp, TREE_TYPE (exp));
ad52b9b7 2757
2758 /* Truncate the result of floating point optab to integer
2759 via expand_fix (). */
2760 target = gen_reg_rtx (mode);
2761 expand_fix (target, tmp, 0);
2762
2763 return target;
2764}
2765
7d3afc77 2766/* Expand a call to one of the builtin math functions doing integer
2767 conversion (lrint).
2768 Return 0 if a normal call should be emitted rather than expanding the
2769 function in-line. EXP is the expression that is a call to the builtin
ff1b14e4 2770 function; if convenient, the result should be placed in TARGET. */
7d3afc77 2771
2772static rtx
ff1b14e4 2773expand_builtin_int_roundingfn_2 (tree exp, rtx target)
7d3afc77 2774{
5f51ee59 2775 convert_optab builtin_optab;
7d3afc77 2776 rtx op0, insns;
2777 tree fndecl = get_callee_fndecl (exp);
4de0924f 2778 tree arg;
c2f47e15 2779 enum machine_mode mode;
e951f9a4 2780 enum built_in_function fallback_fn = BUILT_IN_NONE;
7d3afc77 2781
c2f47e15 2782 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
2783 gcc_unreachable ();
48e1416a 2784
c2f47e15 2785 arg = CALL_EXPR_ARG (exp, 0);
7d3afc77 2786
2787 switch (DECL_FUNCTION_CODE (fndecl))
2788 {
80ff6494 2789 CASE_FLT_FN (BUILT_IN_IRINT):
e951f9a4 2790 fallback_fn = BUILT_IN_LRINT;
2791 /* FALLTHRU */
7d3afc77 2792 CASE_FLT_FN (BUILT_IN_LRINT):
2793 CASE_FLT_FN (BUILT_IN_LLRINT):
e951f9a4 2794 builtin_optab = lrint_optab;
2795 break;
80ff6494 2796
2797 CASE_FLT_FN (BUILT_IN_IROUND):
e951f9a4 2798 fallback_fn = BUILT_IN_LROUND;
2799 /* FALLTHRU */
ef2f1a10 2800 CASE_FLT_FN (BUILT_IN_LROUND):
2801 CASE_FLT_FN (BUILT_IN_LLROUND):
e951f9a4 2802 builtin_optab = lround_optab;
2803 break;
80ff6494 2804
7d3afc77 2805 default:
2806 gcc_unreachable ();
2807 }
2808
e951f9a4 2809 /* There's no easy way to detect the case we need to set EDOM. */
2810 if (flag_errno_math && fallback_fn == BUILT_IN_NONE)
2811 return NULL_RTX;
2812
7d3afc77 2813 /* Make a suitable register to place result in. */
2814 mode = TYPE_MODE (TREE_TYPE (exp));
2815
e951f9a4 2816 /* There's no easy way to detect the case we need to set EDOM. */
2817 if (!flag_errno_math)
2818 {
de2e453e 2819 rtx result = gen_reg_rtx (mode);
7d3afc77 2820
e951f9a4 2821 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2822 need to expand the argument again. This way, we will not perform
2823 side-effects more the once. */
2824 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
7d3afc77 2825
e951f9a4 2826 op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);
7d3afc77 2827
e951f9a4 2828 start_sequence ();
7d3afc77 2829
de2e453e 2830 if (expand_sfix_optab (result, op0, builtin_optab))
e951f9a4 2831 {
2832 /* Output the entire sequence. */
2833 insns = get_insns ();
2834 end_sequence ();
2835 emit_insn (insns);
de2e453e 2836 return result;
e951f9a4 2837 }
2838
2839 /* If we were unable to expand via the builtin, stop the sequence
2840 (without outputting the insns) and call to the library function
2841 with the stabilized argument list. */
7d3afc77 2842 end_sequence ();
2843 }
2844
e951f9a4 2845 if (fallback_fn != BUILT_IN_NONE)
2846 {
2847 /* Fall back to rounding to long int. Use implicit_p 0 - for non-C99
2848 targets, (int) round (x) should never be transformed into
2849 BUILT_IN_IROUND and if __builtin_iround is called directly, emit
2850 a call to lround in the hope that the target provides at least some
2851 C99 functions. This should result in the best user experience for
2852 not full C99 targets. */
2853 tree fallback_fndecl = mathfn_built_in_1 (TREE_TYPE (arg),
2854 fallback_fn, 0);
2855
2856 exp = build_call_nofold_loc (EXPR_LOCATION (exp),
2857 fallback_fndecl, 1, arg);
2858
2859 target = expand_call (exp, NULL_RTX, target == const0_rtx);
933eb13a 2860 target = maybe_emit_group_store (target, TREE_TYPE (exp));
e951f9a4 2861 return convert_to_mode (mode, target, 0);
2862 }
5f51ee59 2863
de2e453e 2864 return expand_call (exp, target, target == const0_rtx);
7d3afc77 2865}
2866
c2f47e15 2867/* Expand a call to the powi built-in mathematical function. Return NULL_RTX if
757c219d 2868 a normal call should be emitted rather than expanding the function
2869 in-line. EXP is the expression that is a call to the builtin
2870 function; if convenient, the result should be placed in TARGET. */
2871
2872static rtx
f97eea22 2873expand_builtin_powi (tree exp, rtx target)
757c219d 2874{
757c219d 2875 tree arg0, arg1;
2876 rtx op0, op1;
2877 enum machine_mode mode;
d0405f40 2878 enum machine_mode mode2;
757c219d 2879
c2f47e15 2880 if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
2881 return NULL_RTX;
757c219d 2882
c2f47e15 2883 arg0 = CALL_EXPR_ARG (exp, 0);
2884 arg1 = CALL_EXPR_ARG (exp, 1);
757c219d 2885 mode = TYPE_MODE (TREE_TYPE (exp));
2886
757c219d 2887 /* Emit a libcall to libgcc. */
2888
c2f47e15 2889 /* Mode of the 2nd argument must match that of an int. */
d0405f40 2890 mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
2891
757c219d 2892 if (target == NULL_RTX)
2893 target = gen_reg_rtx (mode);
2894
f97eea22 2895 op0 = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
757c219d 2896 if (GET_MODE (op0) != mode)
2897 op0 = convert_to_mode (mode, op0, 0);
1db6d067 2898 op1 = expand_expr (arg1, NULL_RTX, mode2, EXPAND_NORMAL);
d0405f40 2899 if (GET_MODE (op1) != mode2)
2900 op1 = convert_to_mode (mode2, op1, 0);
757c219d 2901
f36b9f69 2902 target = emit_library_call_value (optab_libfunc (powi_optab, mode),
2dd6f9ed 2903 target, LCT_CONST, mode, 2,
d0405f40 2904 op0, mode, op1, mode2);
757c219d 2905
2906 return target;
2907}
2908
48e1416a 2909/* Expand expression EXP which is a call to the strlen builtin. Return
c2f47e15 2910 NULL_RTX if we failed the caller should emit a normal call, otherwise
aed0bd19 2911 try to get the result in TARGET, if convenient. */
f7c44134 2912
53800dbe 2913static rtx
c2f47e15 2914expand_builtin_strlen (tree exp, rtx target,
aecda0d6 2915 enum machine_mode target_mode)
53800dbe 2916{
c2f47e15 2917 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2918 return NULL_RTX;
53800dbe 2919 else
2920 {
8786db1e 2921 struct expand_operand ops[4];
911c0150 2922 rtx pat;
c2f47e15 2923 tree len;
2924 tree src = CALL_EXPR_ARG (exp, 0);
8786db1e 2925 rtx src_reg, before_strlen;
2926 enum machine_mode insn_mode = target_mode;
ef2c4a29 2927 enum insn_code icode = CODE_FOR_nothing;
153c3b50 2928 unsigned int align;
6248e345 2929
2930 /* If the length can be computed at compile-time, return it. */
681fab1e 2931 len = c_strlen (src, 0);
6248e345 2932 if (len)
80cd7a5e 2933 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
6248e345 2934
681fab1e 2935 /* If the length can be computed at compile-time and is constant
2936 integer, but there are side-effects in src, evaluate
2937 src for side-effects, then return len.
2938 E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
2939 can be optimized into: i++; x = 3; */
2940 len = c_strlen (src, 1);
2941 if (len && TREE_CODE (len) == INTEGER_CST)
2942 {
2943 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2944 return expand_expr (len, target, target_mode, EXPAND_NORMAL);
2945 }
2946
957d0361 2947 align = get_pointer_alignment (src) / BITS_PER_UNIT;
53800dbe 2948
53800dbe 2949 /* If SRC is not a pointer type, don't do this operation inline. */
2950 if (align == 0)
c2f47e15 2951 return NULL_RTX;
53800dbe 2952
911c0150 2953 /* Bail out if we can't compute strlen in the right mode. */
53800dbe 2954 while (insn_mode != VOIDmode)
2955 {
d6bf3b14 2956 icode = optab_handler (strlen_optab, insn_mode);
53800dbe 2957 if (icode != CODE_FOR_nothing)
c28ae87f 2958 break;
53800dbe 2959
2960 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
2961 }
2962 if (insn_mode == VOIDmode)
c2f47e15 2963 return NULL_RTX;
53800dbe 2964
911c0150 2965 /* Make a place to hold the source address. We will not expand
2966 the actual source until we are sure that the expansion will
2967 not fail -- there are trees that cannot be expanded twice. */
2968 src_reg = gen_reg_rtx (Pmode);
53800dbe 2969
911c0150 2970 /* Mark the beginning of the strlen sequence so we can emit the
2971 source operand later. */
f0ce3b1f 2972 before_strlen = get_last_insn ();
53800dbe 2973
8786db1e 2974 create_output_operand (&ops[0], target, insn_mode);
2975 create_fixed_operand (&ops[1], gen_rtx_MEM (BLKmode, src_reg));
2976 create_integer_operand (&ops[2], 0);
2977 create_integer_operand (&ops[3], align);
2978 if (!maybe_expand_insn (icode, 4, ops))
c2f47e15 2979 return NULL_RTX;
911c0150 2980
2981 /* Now that we are assured of success, expand the source. */
2982 start_sequence ();
499eee58 2983 pat = expand_expr (src, src_reg, Pmode, EXPAND_NORMAL);
911c0150 2984 if (pat != src_reg)
499eee58 2985 {
2986#ifdef POINTERS_EXTEND_UNSIGNED
2987 if (GET_MODE (pat) != Pmode)
2988 pat = convert_to_mode (Pmode, pat,
2989 POINTERS_EXTEND_UNSIGNED);
2990#endif
2991 emit_move_insn (src_reg, pat);
2992 }
31d3e01c 2993 pat = get_insns ();
911c0150 2994 end_sequence ();
bceb0d1f 2995
2996 if (before_strlen)
2997 emit_insn_after (pat, before_strlen);
2998 else
2999 emit_insn_before (pat, get_insns ());
53800dbe 3000
3001 /* Return the value in the proper mode for this function. */
8786db1e 3002 if (GET_MODE (ops[0].value) == target_mode)
3003 target = ops[0].value;
53800dbe 3004 else if (target != 0)
8786db1e 3005 convert_move (target, ops[0].value, 0);
53800dbe 3006 else
8786db1e 3007 target = convert_to_mode (target_mode, ops[0].value, 0);
911c0150 3008
3009 return target;
53800dbe 3010 }
3011}
3012
6840589f 3013/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3014 bytes from constant string DATA + OFFSET and return it as target
3015 constant. */
3016
3017static rtx
aecda0d6 3018builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
3019 enum machine_mode mode)
6840589f 3020{
3021 const char *str = (const char *) data;
3022
64db345d 3023 gcc_assert (offset >= 0
3024 && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
3025 <= strlen (str) + 1));
6840589f 3026
3027 return c_readstr (str + offset, mode);
3028}
3029
c2f47e15 3030/* Expand a call EXP to the memcpy builtin.
3031 Return NULL_RTX if we failed, the caller should emit a normal call,
3b824fa6 3032 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3033 mode MODE if that's convenient). */
c2f47e15 3034
53800dbe 3035static rtx
a65c4d64 3036expand_builtin_memcpy (tree exp, rtx target)
53800dbe 3037{
c2f47e15 3038 if (!validate_arglist (exp,
3039 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3040 return NULL_RTX;
53800dbe 3041 else
3042 {
c2f47e15 3043 tree dest = CALL_EXPR_ARG (exp, 0);
3044 tree src = CALL_EXPR_ARG (exp, 1);
3045 tree len = CALL_EXPR_ARG (exp, 2);
6840589f 3046 const char *src_str;
957d0361 3047 unsigned int src_align = get_pointer_alignment (src);
3048 unsigned int dest_align = get_pointer_alignment (dest);
53800dbe 3049 rtx dest_mem, src_mem, dest_addr, len_rtx;
162719b3 3050 HOST_WIDE_INT expected_size = -1;
3051 unsigned int expected_align = 0;
5a0de151 3052
6f428e8b 3053 /* If DEST is not a pointer type, call the normal function. */
3054 if (dest_align == 0)
c2f47e15 3055 return NULL_RTX;
6f428e8b 3056
6f428e8b 3057 /* If either SRC is not a pointer type, don't do this
a0c938f0 3058 operation in-line. */
6f428e8b 3059 if (src_align == 0)
c2f47e15 3060 return NULL_RTX;
48e1416a 3061
8cee8dc0 3062 if (currently_expanding_gimple_stmt)
3063 stringop_block_profile (currently_expanding_gimple_stmt,
3064 &expected_align, &expected_size);
75a70cf9 3065
162719b3 3066 if (expected_align < dest_align)
3067 expected_align = dest_align;
d8ae1baa 3068 dest_mem = get_memory_rtx (dest, len);
2a631e19 3069 set_mem_align (dest_mem, dest_align);
8ec3c5c2 3070 len_rtx = expand_normal (len);
6840589f 3071 src_str = c_getstr (src);
3072
3073 /* If SRC is a string constant and block move would be done
3074 by pieces, we can avoid loading the string from memory
3075 and only stored the computed constants. */
3076 if (src_str
971ba038 3077 && CONST_INT_P (len_rtx)
6840589f 3078 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3079 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3080 CONST_CAST (char *, src_str),
3081 dest_align, false))
6840589f 3082 {
9fe0e1b8 3083 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3084 builtin_memcpy_read_str,
364c0c59 3085 CONST_CAST (char *, src_str),
3086 dest_align, false, 0);
a65c4d64 3087 dest_mem = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3088 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3089 return dest_mem;
6840589f 3090 }
3091
d8ae1baa 3092 src_mem = get_memory_rtx (src, len);
2a631e19 3093 set_mem_align (src_mem, src_align);
53800dbe 3094
53800dbe 3095 /* Copy word part most expediently. */
162719b3 3096 dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
3097 CALL_EXPR_TAILCALL (exp)
3098 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3099 expected_align, expected_size);
53800dbe 3100
3101 if (dest_addr == 0)
e5716f7e 3102 {
a65c4d64 3103 dest_addr = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3104 dest_addr = convert_memory_address (ptr_mode, dest_addr);
e5716f7e 3105 }
9fe0e1b8 3106 return dest_addr;
53800dbe 3107 }
3108}
3109
c2f47e15 3110/* Expand a call EXP to the mempcpy builtin.
3111 Return NULL_RTX if we failed; the caller should emit a normal call,
647661c6 3112 otherwise try to get the result in TARGET, if convenient (and in
9fe0e1b8 3113 mode MODE if that's convenient). If ENDP is 0 return the
3114 destination pointer, if ENDP is 1 return the end pointer ala
3115 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3116 stpcpy. */
647661c6 3117
3118static rtx
c8b17b2e 3119expand_builtin_mempcpy (tree exp, rtx target, enum machine_mode mode)
647661c6 3120{
c2f47e15 3121 if (!validate_arglist (exp,
3122 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3123 return NULL_RTX;
3124 else
3125 {
3126 tree dest = CALL_EXPR_ARG (exp, 0);
3127 tree src = CALL_EXPR_ARG (exp, 1);
3128 tree len = CALL_EXPR_ARG (exp, 2);
3129 return expand_builtin_mempcpy_args (dest, src, len,
c2f47e15 3130 target, mode, /*endp=*/ 1);
3131 }
3132}
3133
3134/* Helper function to do the actual work for expand_builtin_mempcpy. The
3135 arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out
3136 so that this can also be called without constructing an actual CALL_EXPR.
a65c4d64 3137 The other arguments and return value are the same as for
3138 expand_builtin_mempcpy. */
c2f47e15 3139
3140static rtx
a65c4d64 3141expand_builtin_mempcpy_args (tree dest, tree src, tree len,
c2f47e15 3142 rtx target, enum machine_mode mode, int endp)
3143{
3144 /* If return value is ignored, transform mempcpy into memcpy. */
b9a16870 3145 if (target == const0_rtx && builtin_decl_implicit_p (BUILT_IN_MEMCPY))
9fe0e1b8 3146 {
b9a16870 3147 tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
0568e9c1 3148 tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3,
3149 dest, src, len);
c8b17b2e 3150 return expand_expr (result, target, mode, EXPAND_NORMAL);
9fe0e1b8 3151 }
647661c6 3152 else
3153 {
9fe0e1b8 3154 const char *src_str;
957d0361 3155 unsigned int src_align = get_pointer_alignment (src);
3156 unsigned int dest_align = get_pointer_alignment (dest);
9fe0e1b8 3157 rtx dest_mem, src_mem, len_rtx;
a0c938f0 3158
7da1412b 3159 /* If either SRC or DEST is not a pointer type, don't do this
a0c938f0 3160 operation in-line. */
7da1412b 3161 if (dest_align == 0 || src_align == 0)
c2f47e15 3162 return NULL_RTX;
9fe0e1b8 3163
6217c238 3164 /* If LEN is not constant, call the normal function. */
3165 if (! host_integerp (len, 1))
c2f47e15 3166 return NULL_RTX;
0862b7e9 3167
8ec3c5c2 3168 len_rtx = expand_normal (len);
9fe0e1b8 3169 src_str = c_getstr (src);
647661c6 3170
9fe0e1b8 3171 /* If SRC is a string constant and block move would be done
3172 by pieces, we can avoid loading the string from memory
3173 and only stored the computed constants. */
3174 if (src_str
971ba038 3175 && CONST_INT_P (len_rtx)
9fe0e1b8 3176 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3177 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
364c0c59 3178 CONST_CAST (char *, src_str),
3179 dest_align, false))
9fe0e1b8 3180 {
d8ae1baa 3181 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3182 set_mem_align (dest_mem, dest_align);
3183 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3184 builtin_memcpy_read_str,
364c0c59 3185 CONST_CAST (char *, src_str),
3186 dest_align, false, endp);
9fe0e1b8 3187 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3188 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3189 return dest_mem;
647661c6 3190 }
3191
971ba038 3192 if (CONST_INT_P (len_rtx)
9fe0e1b8 3193 && can_move_by_pieces (INTVAL (len_rtx),
3194 MIN (dest_align, src_align)))
3195 {
d8ae1baa 3196 dest_mem = get_memory_rtx (dest, len);
9fe0e1b8 3197 set_mem_align (dest_mem, dest_align);
d8ae1baa 3198 src_mem = get_memory_rtx (src, len);
9fe0e1b8 3199 set_mem_align (src_mem, src_align);
3200 dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
3201 MIN (dest_align, src_align), endp);
3202 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
85d654dd 3203 dest_mem = convert_memory_address (ptr_mode, dest_mem);
9fe0e1b8 3204 return dest_mem;
3205 }
3206
c2f47e15 3207 return NULL_RTX;
647661c6 3208 }
3209}
3210
727c62dd 3211#ifndef HAVE_movstr
3212# define HAVE_movstr 0
3213# define CODE_FOR_movstr CODE_FOR_nothing
3214#endif
3215
c2f47e15 3216/* Expand into a movstr instruction, if one is available. Return NULL_RTX if
727c62dd 3217 we failed, the caller should emit a normal call, otherwise try to
3218 get the result in TARGET, if convenient. If ENDP is 0 return the
3219 destination pointer, if ENDP is 1 return the end pointer ala
3220 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3221 stpcpy. */
3222
3223static rtx
3224expand_movstr (tree dest, tree src, rtx target, int endp)
3225{
8786db1e 3226 struct expand_operand ops[3];
727c62dd 3227 rtx dest_mem;
3228 rtx src_mem;
727c62dd 3229
3230 if (!HAVE_movstr)
c2f47e15 3231 return NULL_RTX;
727c62dd 3232
d8ae1baa 3233 dest_mem = get_memory_rtx (dest, NULL);
3234 src_mem = get_memory_rtx (src, NULL);
727c62dd 3235 if (!endp)
3236 {
3237 target = force_reg (Pmode, XEXP (dest_mem, 0));
3238 dest_mem = replace_equiv_address (dest_mem, target);
727c62dd 3239 }
3240
8786db1e 3241 create_output_operand (&ops[0], endp ? target : NULL_RTX, Pmode);
3242 create_fixed_operand (&ops[1], dest_mem);
3243 create_fixed_operand (&ops[2], src_mem);
3244 expand_insn (CODE_FOR_movstr, 3, ops);
727c62dd 3245
8786db1e 3246 if (endp && target != const0_rtx)
c5aba89c 3247 {
8786db1e 3248 target = ops[0].value;
3249 /* movstr is supposed to set end to the address of the NUL
3250 terminator. If the caller requested a mempcpy-like return value,
3251 adjust it. */
3252 if (endp == 1)
3253 {
29c05e22 3254 rtx tem = plus_constant (GET_MODE (target),
3255 gen_lowpart (GET_MODE (target), target), 1);
8786db1e 3256 emit_move_insn (target, force_operand (tem, NULL_RTX));
3257 }
c5aba89c 3258 }
727c62dd 3259 return target;
3260}
3261
48e1416a 3262/* Expand expression EXP, which is a call to the strcpy builtin. Return
3263 NULL_RTX if we failed the caller should emit a normal call, otherwise
c2f47e15 3264 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3265 convenient). */
902de8ed 3266
53800dbe 3267static rtx
a65c4d64 3268expand_builtin_strcpy (tree exp, rtx target)
53800dbe 3269{
c2f47e15 3270 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3271 {
3272 tree dest = CALL_EXPR_ARG (exp, 0);
3273 tree src = CALL_EXPR_ARG (exp, 1);
a65c4d64 3274 return expand_builtin_strcpy_args (dest, src, target);
c2f47e15 3275 }
3276 return NULL_RTX;
3277}
3278
3279/* Helper function to do the actual work for expand_builtin_strcpy. The
3280 arguments to the builtin_strcpy call DEST and SRC are broken out
3281 so that this can also be called without constructing an actual CALL_EXPR.
3282 The other arguments and return value are the same as for
3283 expand_builtin_strcpy. */
3284
3285static rtx
a65c4d64 3286expand_builtin_strcpy_args (tree dest, tree src, rtx target)
c2f47e15 3287{
c2f47e15 3288 return expand_movstr (dest, src, target, /*endp=*/0);
53800dbe 3289}
3290
c2f47e15 3291/* Expand a call EXP to the stpcpy builtin.
3292 Return NULL_RTX if we failed the caller should emit a normal call,
3b824fa6 3293 otherwise try to get the result in TARGET, if convenient (and in
3294 mode MODE if that's convenient). */
3295
3296static rtx
dc369150 3297expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
3b824fa6 3298{
c2f47e15 3299 tree dst, src;
389dd41b 3300 location_t loc = EXPR_LOCATION (exp);
c2f47e15 3301
3302 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3303 return NULL_RTX;
3304
3305 dst = CALL_EXPR_ARG (exp, 0);
3306 src = CALL_EXPR_ARG (exp, 1);
3307
727c62dd 3308 /* If return value is ignored, transform stpcpy into strcpy. */
b9a16870 3309 if (target == const0_rtx && builtin_decl_implicit (BUILT_IN_STRCPY))
978836e5 3310 {
b9a16870 3311 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
0568e9c1 3312 tree result = build_call_nofold_loc (loc, fn, 2, dst, src);
c8b17b2e 3313 return expand_expr (result, target, mode, EXPAND_NORMAL);
978836e5 3314 }
3b824fa6 3315 else
3316 {
c2f47e15 3317 tree len, lenp1;
727c62dd 3318 rtx ret;
647661c6 3319
9fe0e1b8 3320 /* Ensure we get an actual string whose length can be evaluated at
a0c938f0 3321 compile-time, not an expression containing a string. This is
3322 because the latter will potentially produce pessimized code
3323 when used to produce the return value. */
681fab1e 3324 if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
c2f47e15 3325 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3326
389dd41b 3327 lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
a65c4d64 3328 ret = expand_builtin_mempcpy_args (dst, src, lenp1,
c2f47e15 3329 target, mode, /*endp=*/2);
727c62dd 3330
3331 if (ret)
3332 return ret;
3333
3334 if (TREE_CODE (len) == INTEGER_CST)
3335 {
8ec3c5c2 3336 rtx len_rtx = expand_normal (len);
727c62dd 3337
971ba038 3338 if (CONST_INT_P (len_rtx))
727c62dd 3339 {
a65c4d64 3340 ret = expand_builtin_strcpy_args (dst, src, target);
727c62dd 3341
3342 if (ret)
3343 {
3344 if (! target)
7ac87324 3345 {
3346 if (mode != VOIDmode)
3347 target = gen_reg_rtx (mode);
3348 else
3349 target = gen_reg_rtx (GET_MODE (ret));
3350 }
727c62dd 3351 if (GET_MODE (target) != GET_MODE (ret))
3352 ret = gen_lowpart (GET_MODE (target), ret);
3353
29c05e22 3354 ret = plus_constant (GET_MODE (ret), ret, INTVAL (len_rtx));
c5aba89c 3355 ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
64db345d 3356 gcc_assert (ret);
727c62dd 3357
3358 return target;
3359 }
3360 }
3361 }
3362
c2f47e15 3363 return expand_movstr (dst, src, target, /*endp=*/2);
3b824fa6 3364 }
3365}
3366
6840589f 3367/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3368 bytes from constant string DATA + OFFSET and return it as target
3369 constant. */
3370
09879952 3371rtx
aecda0d6 3372builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
3373 enum machine_mode mode)
6840589f 3374{
3375 const char *str = (const char *) data;
3376
3377 if ((unsigned HOST_WIDE_INT) offset > strlen (str))
3378 return const0_rtx;
3379
3380 return c_readstr (str + offset, mode);
3381}
3382
48e1416a 3383/* Expand expression EXP, which is a call to the strncpy builtin. Return
c2f47e15 3384 NULL_RTX if we failed the caller should emit a normal call. */
ed09096d 3385
3386static rtx
a65c4d64 3387expand_builtin_strncpy (tree exp, rtx target)
ed09096d 3388{
389dd41b 3389 location_t loc = EXPR_LOCATION (exp);
c2f47e15 3390
3391 if (validate_arglist (exp,
3392 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
ed09096d 3393 {
c2f47e15 3394 tree dest = CALL_EXPR_ARG (exp, 0);
3395 tree src = CALL_EXPR_ARG (exp, 1);
3396 tree len = CALL_EXPR_ARG (exp, 2);
3397 tree slen = c_strlen (src, 1);
6840589f 3398
8ff6a5cd 3399 /* We must be passed a constant len and src parameter. */
3400 if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
c2f47e15 3401 return NULL_RTX;
ed09096d 3402
389dd41b 3403 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
ed09096d 3404
3405 /* We're required to pad with trailing zeros if the requested
a0c938f0 3406 len is greater than strlen(s2)+1. In that case try to
6840589f 3407 use store_by_pieces, if it fails, punt. */
ed09096d 3408 if (tree_int_cst_lt (slen, len))
6840589f 3409 {
957d0361 3410 unsigned int dest_align = get_pointer_alignment (dest);
c2f47e15 3411 const char *p = c_getstr (src);
6840589f 3412 rtx dest_mem;
3413
27d0c333 3414 if (!p || dest_align == 0 || !host_integerp (len, 1)
3415 || !can_store_by_pieces (tree_low_cst (len, 1),
6840589f 3416 builtin_strncpy_read_str,
364c0c59 3417 CONST_CAST (char *, p),
3418 dest_align, false))
c2f47e15 3419 return NULL_RTX;
6840589f 3420
d8ae1baa 3421 dest_mem = get_memory_rtx (dest, len);
27d0c333 3422 store_by_pieces (dest_mem, tree_low_cst (len, 1),
6840589f 3423 builtin_strncpy_read_str,
364c0c59 3424 CONST_CAST (char *, p), dest_align, false, 0);
a65c4d64 3425 dest_mem = force_operand (XEXP (dest_mem, 0), target);
85d654dd 3426 dest_mem = convert_memory_address (ptr_mode, dest_mem);
e5716f7e 3427 return dest_mem;
6840589f 3428 }
ed09096d 3429 }
c2f47e15 3430 return NULL_RTX;
ed09096d 3431}
3432
ecc318ff 3433/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3434 bytes from constant string DATA + OFFSET and return it as target
3435 constant. */
3436
f656b751 3437rtx
aecda0d6 3438builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3439 enum machine_mode mode)
ecc318ff 3440{
3441 const char *c = (const char *) data;
364c0c59 3442 char *p = XALLOCAVEC (char, GET_MODE_SIZE (mode));
ecc318ff 3443
3444 memset (p, *c, GET_MODE_SIZE (mode));
3445
3446 return c_readstr (p, mode);
3447}
3448
a7ec6974 3449/* Callback routine for store_by_pieces. Return the RTL of a register
3450 containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
3451 char value given in the RTL register data. For example, if mode is
3452 4 bytes wide, return the RTL for 0x01010101*data. */
3453
3454static rtx
aecda0d6 3455builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3456 enum machine_mode mode)
a7ec6974 3457{
3458 rtx target, coeff;
3459 size_t size;
3460 char *p;
3461
3462 size = GET_MODE_SIZE (mode);
f0ce3b1f 3463 if (size == 1)
3464 return (rtx) data;
a7ec6974 3465
364c0c59 3466 p = XALLOCAVEC (char, size);
a7ec6974 3467 memset (p, 1, size);
3468 coeff = c_readstr (p, mode);
3469
f0ce3b1f 3470 target = convert_to_mode (mode, (rtx) data, 1);
a7ec6974 3471 target = expand_mult (mode, target, coeff, NULL_RTX, 1);
3472 return force_reg (mode, target);
3473}
3474
48e1416a 3475/* Expand expression EXP, which is a call to the memset builtin. Return
3476 NULL_RTX if we failed the caller should emit a normal call, otherwise
c2f47e15 3477 try to get the result in TARGET, if convenient (and in mode MODE if that's
6f428e8b 3478 convenient). */
902de8ed 3479
53800dbe 3480static rtx
c2f47e15 3481expand_builtin_memset (tree exp, rtx target, enum machine_mode mode)
53800dbe 3482{
c2f47e15 3483 if (!validate_arglist (exp,
3484 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
3485 return NULL_RTX;
53800dbe 3486 else
3487 {
c2f47e15 3488 tree dest = CALL_EXPR_ARG (exp, 0);
3489 tree val = CALL_EXPR_ARG (exp, 1);
3490 tree len = CALL_EXPR_ARG (exp, 2);
3491 return expand_builtin_memset_args (dest, val, len, target, mode, exp);
3492 }
3493}
53800dbe 3494
c2f47e15 3495/* Helper function to do the actual work for expand_builtin_memset. The
3496 arguments to the builtin_memset call DEST, VAL, and LEN are broken out
3497 so that this can also be called without constructing an actual CALL_EXPR.
3498 The other arguments and return value are the same as for
3499 expand_builtin_memset. */
6b961939 3500
c2f47e15 3501static rtx
3502expand_builtin_memset_args (tree dest, tree val, tree len,
3503 rtx target, enum machine_mode mode, tree orig_exp)
3504{
3505 tree fndecl, fn;
3506 enum built_in_function fcode;
03a5dda9 3507 enum machine_mode val_mode;
c2f47e15 3508 char c;
3509 unsigned int dest_align;
3510 rtx dest_mem, dest_addr, len_rtx;
3511 HOST_WIDE_INT expected_size = -1;
3512 unsigned int expected_align = 0;
53800dbe 3513
957d0361 3514 dest_align = get_pointer_alignment (dest);
162719b3 3515
c2f47e15 3516 /* If DEST is not a pointer type, don't do this operation in-line. */
3517 if (dest_align == 0)
3518 return NULL_RTX;
6f428e8b 3519
8cee8dc0 3520 if (currently_expanding_gimple_stmt)
3521 stringop_block_profile (currently_expanding_gimple_stmt,
3522 &expected_align, &expected_size);
75a70cf9 3523
c2f47e15 3524 if (expected_align < dest_align)
3525 expected_align = dest_align;
6b961939 3526
c2f47e15 3527 /* If the LEN parameter is zero, return DEST. */
3528 if (integer_zerop (len))
3529 {
3530 /* Evaluate and ignore VAL in case it has side-effects. */
3531 expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
3532 return expand_expr (dest, target, mode, EXPAND_NORMAL);
3533 }
7a3e5564 3534
c2f47e15 3535 /* Stabilize the arguments in case we fail. */
3536 dest = builtin_save_expr (dest);
3537 val = builtin_save_expr (val);
3538 len = builtin_save_expr (len);
a7ec6974 3539
c2f47e15 3540 len_rtx = expand_normal (len);
3541 dest_mem = get_memory_rtx (dest, len);
03a5dda9 3542 val_mode = TYPE_MODE (unsigned_char_type_node);
a7ec6974 3543
c2f47e15 3544 if (TREE_CODE (val) != INTEGER_CST)
3545 {
3546 rtx val_rtx;
a7ec6974 3547
c2f47e15 3548 val_rtx = expand_normal (val);
03a5dda9 3549 val_rtx = convert_to_mode (val_mode, val_rtx, 0);
53800dbe 3550
c2f47e15 3551 /* Assume that we can memset by pieces if we can store
3552 * the coefficients by pieces (in the required modes).
3553 * We can't pass builtin_memset_gen_str as that emits RTL. */
3554 c = 1;
3555 if (host_integerp (len, 1)
c2f47e15 3556 && can_store_by_pieces (tree_low_cst (len, 1),
4b297e2e 3557 builtin_memset_read_str, &c, dest_align,
3558 true))
c2f47e15 3559 {
03a5dda9 3560 val_rtx = force_reg (val_mode, val_rtx);
c2f47e15 3561 store_by_pieces (dest_mem, tree_low_cst (len, 1),
4b297e2e 3562 builtin_memset_gen_str, val_rtx, dest_align,
3563 true, 0);
c2f47e15 3564 }
3565 else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
3566 dest_align, expected_align,
3567 expected_size))
6b961939 3568 goto do_libcall;
48e1416a 3569
c2f47e15 3570 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3571 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3572 return dest_mem;
3573 }
53800dbe 3574
c2f47e15 3575 if (target_char_cast (val, &c))
3576 goto do_libcall;
ecc318ff 3577
c2f47e15 3578 if (c)
3579 {
3580 if (host_integerp (len, 1)
c2f47e15 3581 && can_store_by_pieces (tree_low_cst (len, 1),
4b297e2e 3582 builtin_memset_read_str, &c, dest_align,
3583 true))
c2f47e15 3584 store_by_pieces (dest_mem, tree_low_cst (len, 1),
4b297e2e 3585 builtin_memset_read_str, &c, dest_align, true, 0);
03a5dda9 3586 else if (!set_storage_via_setmem (dest_mem, len_rtx,
3587 gen_int_mode (c, val_mode),
c2f47e15 3588 dest_align, expected_align,
3589 expected_size))
3590 goto do_libcall;
48e1416a 3591
c2f47e15 3592 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3593 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3594 return dest_mem;
3595 }
ecc318ff 3596
c2f47e15 3597 set_mem_align (dest_mem, dest_align);
3598 dest_addr = clear_storage_hints (dest_mem, len_rtx,
3599 CALL_EXPR_TAILCALL (orig_exp)
3600 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
3601 expected_align, expected_size);
53800dbe 3602
c2f47e15 3603 if (dest_addr == 0)
3604 {
3605 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3606 dest_addr = convert_memory_address (ptr_mode, dest_addr);
3607 }
53800dbe 3608
c2f47e15 3609 return dest_addr;
6b961939 3610
c2f47e15 3611 do_libcall:
3612 fndecl = get_callee_fndecl (orig_exp);
3613 fcode = DECL_FUNCTION_CODE (fndecl);
3614 if (fcode == BUILT_IN_MEMSET)
0568e9c1 3615 fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 3,
3616 dest, val, len);
c2f47e15 3617 else if (fcode == BUILT_IN_BZERO)
0568e9c1 3618 fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 2,
3619 dest, len);
c2f47e15 3620 else
3621 gcc_unreachable ();
a65c4d64 3622 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
3623 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
c2f47e15 3624 return expand_call (fn, target, target == const0_rtx);
53800dbe 3625}
3626
48e1416a 3627/* Expand expression EXP, which is a call to the bzero builtin. Return
c2f47e15 3628 NULL_RTX if we failed the caller should emit a normal call. */
27d0c333 3629
ffc83088 3630static rtx
0b25db21 3631expand_builtin_bzero (tree exp)
ffc83088 3632{
c2f47e15 3633 tree dest, size;
389dd41b 3634 location_t loc = EXPR_LOCATION (exp);
ffc83088 3635
c2f47e15 3636 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
7369e7ba 3637 return NULL_RTX;
ffc83088 3638
c2f47e15 3639 dest = CALL_EXPR_ARG (exp, 0);
3640 size = CALL_EXPR_ARG (exp, 1);
bf8e3599 3641
7369e7ba 3642 /* New argument list transforming bzero(ptr x, int y) to
6f428e8b 3643 memset(ptr x, int 0, size_t y). This is done this way
3644 so that if it isn't expanded inline, we fallback to
3645 calling bzero instead of memset. */
bf8e3599 3646
c2f47e15 3647 return expand_builtin_memset_args (dest, integer_zero_node,
a0553bff 3648 fold_convert_loc (loc,
3649 size_type_node, size),
c2f47e15 3650 const0_rtx, VOIDmode, exp);
ffc83088 3651}
3652
7a3f89b5 3653/* Expand expression EXP, which is a call to the memcmp built-in function.
bd021c1c 3654 Return NULL_RTX if we failed and the caller should emit a normal call,
3655 otherwise try to get the result in TARGET, if convenient (and in mode
3656 MODE, if that's convenient). */
27d0c333 3657
53800dbe 3658static rtx
a65c4d64 3659expand_builtin_memcmp (tree exp, ATTRIBUTE_UNUSED rtx target,
3660 ATTRIBUTE_UNUSED enum machine_mode mode)
53800dbe 3661{
a65c4d64 3662 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
389dd41b 3663
c2f47e15 3664 if (!validate_arglist (exp,
3665 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3666 return NULL_RTX;
6f428e8b 3667
bd021c1c 3668 /* Note: The cmpstrnsi pattern, if it exists, is not suitable for
3669 implementing memcmp because it will stop if it encounters two
3670 zero bytes. */
3671#if defined HAVE_cmpmemsi
53800dbe 3672 {
0cd832f0 3673 rtx arg1_rtx, arg2_rtx, arg3_rtx;
53800dbe 3674 rtx result;
0cd832f0 3675 rtx insn;
c2f47e15 3676 tree arg1 = CALL_EXPR_ARG (exp, 0);
3677 tree arg2 = CALL_EXPR_ARG (exp, 1);
3678 tree len = CALL_EXPR_ARG (exp, 2);
53800dbe 3679
957d0361 3680 unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
3681 unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
b428c0a5 3682 enum machine_mode insn_mode;
3683
b428c0a5 3684 if (HAVE_cmpmemsi)
3685 insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
3686 else
c2f47e15 3687 return NULL_RTX;
53800dbe 3688
3689 /* If we don't have POINTER_TYPE, call the function. */
3690 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 3691 return NULL_RTX;
53800dbe 3692
3693 /* Make a place to write the result of the instruction. */
3694 result = target;
3695 if (! (result != 0
8ad4c111 3696 && REG_P (result) && GET_MODE (result) == insn_mode
53800dbe 3697 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3698 result = gen_reg_rtx (insn_mode);
3699
d8ae1baa 3700 arg1_rtx = get_memory_rtx (arg1, len);
3701 arg2_rtx = get_memory_rtx (arg2, len);
389dd41b 3702 arg3_rtx = expand_normal (fold_convert_loc (loc, sizetype, len));
83f88f8e 3703
3704 /* Set MEM_SIZE as appropriate. */
971ba038 3705 if (CONST_INT_P (arg3_rtx))
83f88f8e 3706 {
5b2a69fa 3707 set_mem_size (arg1_rtx, INTVAL (arg3_rtx));
3708 set_mem_size (arg2_rtx, INTVAL (arg3_rtx));
83f88f8e 3709 }
3710
b428c0a5 3711 if (HAVE_cmpmemsi)
3712 insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3713 GEN_INT (MIN (arg1_align, arg2_align)));
0cd832f0 3714 else
64db345d 3715 gcc_unreachable ();
0cd832f0 3716
3717 if (insn)
3718 emit_insn (insn);
3719 else
2dd6f9ed 3720 emit_library_call_value (memcmp_libfunc, result, LCT_PURE,
0cd832f0 3721 TYPE_MODE (integer_type_node), 3,
3722 XEXP (arg1_rtx, 0), Pmode,
3723 XEXP (arg2_rtx, 0), Pmode,
3724 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
78a8ed03 3725 TYPE_UNSIGNED (sizetype)),
0cd832f0 3726 TYPE_MODE (sizetype));
53800dbe 3727
3728 /* Return the value in the proper mode for this function. */
3729 mode = TYPE_MODE (TREE_TYPE (exp));
3730 if (GET_MODE (result) == mode)
3731 return result;
3732 else if (target != 0)
3733 {
3734 convert_move (target, result, 0);
3735 return target;
3736 }
3737 else
3738 return convert_to_mode (mode, result, 0);
3739 }
bd021c1c 3740#endif /* HAVE_cmpmemsi. */
53800dbe 3741
c2f47e15 3742 return NULL_RTX;
6f428e8b 3743}
3744
c2f47e15 3745/* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX
53800dbe 3746 if we failed the caller should emit a normal call, otherwise try to get
3747 the result in TARGET, if convenient. */
902de8ed 3748
53800dbe 3749static rtx
a65c4d64 3750expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
53800dbe 3751{
c2f47e15 3752 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3753 return NULL_RTX;
bf8e3599 3754
6ac5504b 3755#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
6b531606 3756 if (direct_optab_handler (cmpstr_optab, SImode) != CODE_FOR_nothing
3757 || direct_optab_handler (cmpstrn_optab, SImode) != CODE_FOR_nothing)
6ac5504b 3758 {
3759 rtx arg1_rtx, arg2_rtx;
3760 rtx result, insn = NULL_RTX;
3761 tree fndecl, fn;
c2f47e15 3762 tree arg1 = CALL_EXPR_ARG (exp, 0);
3763 tree arg2 = CALL_EXPR_ARG (exp, 1);
a0c938f0 3764
957d0361 3765 unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
3766 unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
6ac5504b 3767
3768 /* If we don't have POINTER_TYPE, call the function. */
3769 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 3770 return NULL_RTX;
7a3f89b5 3771
6ac5504b 3772 /* Stabilize the arguments in case gen_cmpstr(n)si fail. */
3773 arg1 = builtin_save_expr (arg1);
3774 arg2 = builtin_save_expr (arg2);
7a3f89b5 3775
d8ae1baa 3776 arg1_rtx = get_memory_rtx (arg1, NULL);
3777 arg2_rtx = get_memory_rtx (arg2, NULL);
53800dbe 3778
6ac5504b 3779#ifdef HAVE_cmpstrsi
3780 /* Try to call cmpstrsi. */
3781 if (HAVE_cmpstrsi)
3782 {
a0c938f0 3783 enum machine_mode insn_mode
6ac5504b 3784 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3785
3786 /* Make a place to write the result of the instruction. */
3787 result = target;
3788 if (! (result != 0
3789 && REG_P (result) && GET_MODE (result) == insn_mode
3790 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3791 result = gen_reg_rtx (insn_mode);
3792
3793 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
3794 GEN_INT (MIN (arg1_align, arg2_align)));
3795 }
3796#endif
03fd9d2c 3797#ifdef HAVE_cmpstrnsi
6ac5504b 3798 /* Try to determine at least one length and call cmpstrnsi. */
a0c938f0 3799 if (!insn && HAVE_cmpstrnsi)
6ac5504b 3800 {
3801 tree len;
3802 rtx arg3_rtx;
3803
a0c938f0 3804 enum machine_mode insn_mode
6ac5504b 3805 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
3806 tree len1 = c_strlen (arg1, 1);
3807 tree len2 = c_strlen (arg2, 1);
3808
3809 if (len1)
3810 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3811 if (len2)
3812 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3813
3814 /* If we don't have a constant length for the first, use the length
3815 of the second, if we know it. We don't require a constant for
3816 this case; some cost analysis could be done if both are available
3817 but neither is constant. For now, assume they're equally cheap,
3818 unless one has side effects. If both strings have constant lengths,
3819 use the smaller. */
3820
3821 if (!len1)
3822 len = len2;
3823 else if (!len2)
3824 len = len1;
3825 else if (TREE_SIDE_EFFECTS (len1))
3826 len = len2;
3827 else if (TREE_SIDE_EFFECTS (len2))
3828 len = len1;
3829 else if (TREE_CODE (len1) != INTEGER_CST)
3830 len = len2;
3831 else if (TREE_CODE (len2) != INTEGER_CST)
3832 len = len1;
3833 else if (tree_int_cst_lt (len1, len2))
3834 len = len1;
3835 else
3836 len = len2;
3837
3838 /* If both arguments have side effects, we cannot optimize. */
3839 if (!len || TREE_SIDE_EFFECTS (len))
6b961939 3840 goto do_libcall;
53800dbe 3841
8ec3c5c2 3842 arg3_rtx = expand_normal (len);
902de8ed 3843
6ac5504b 3844 /* Make a place to write the result of the instruction. */
3845 result = target;
3846 if (! (result != 0
3847 && REG_P (result) && GET_MODE (result) == insn_mode
3848 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3849 result = gen_reg_rtx (insn_mode);
53800dbe 3850
6ac5504b 3851 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3852 GEN_INT (MIN (arg1_align, arg2_align)));
3853 }
3854#endif
3f8aefe2 3855
6ac5504b 3856 if (insn)
3857 {
a65c4d64 3858 enum machine_mode mode;
6ac5504b 3859 emit_insn (insn);
3f8aefe2 3860
6ac5504b 3861 /* Return the value in the proper mode for this function. */
3862 mode = TYPE_MODE (TREE_TYPE (exp));
3863 if (GET_MODE (result) == mode)
3864 return result;
3865 if (target == 0)
3866 return convert_to_mode (mode, result, 0);
3867 convert_move (target, result, 0);
3868 return target;
3869 }
902de8ed 3870
6ac5504b 3871 /* Expand the library call ourselves using a stabilized argument
3872 list to avoid re-evaluating the function's arguments twice. */
2694880e 3873#ifdef HAVE_cmpstrnsi
6b961939 3874 do_libcall:
2694880e 3875#endif
6ac5504b 3876 fndecl = get_callee_fndecl (exp);
0568e9c1 3877 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2);
a65c4d64 3878 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
3879 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
6ac5504b 3880 return expand_call (fn, target, target == const0_rtx);
3881 }
7a3f89b5 3882#endif
c2f47e15 3883 return NULL_RTX;
83d79705 3884}
53800dbe 3885
48e1416a 3886/* Expand expression EXP, which is a call to the strncmp builtin. Return
c2f47e15 3887 NULL_RTX if we failed the caller should emit a normal call, otherwise try to get
ed09096d 3888 the result in TARGET, if convenient. */
27d0c333 3889
ed09096d 3890static rtx
a65c4d64 3891expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
3892 ATTRIBUTE_UNUSED enum machine_mode mode)
ed09096d 3893{
a65c4d64 3894 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
389dd41b 3895
c2f47e15 3896 if (!validate_arglist (exp,
3897 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3898 return NULL_RTX;
ed09096d 3899
6e34e617 3900 /* If c_strlen can determine an expression for one of the string
6ac5504b 3901 lengths, and it doesn't have side effects, then emit cmpstrnsi
7a3f89b5 3902 using length MIN(strlen(string)+1, arg3). */
6ac5504b 3903#ifdef HAVE_cmpstrnsi
3904 if (HAVE_cmpstrnsi)
7a3f89b5 3905 {
3906 tree len, len1, len2;
3907 rtx arg1_rtx, arg2_rtx, arg3_rtx;
3908 rtx result, insn;
0b25db21 3909 tree fndecl, fn;
c2f47e15 3910 tree arg1 = CALL_EXPR_ARG (exp, 0);
3911 tree arg2 = CALL_EXPR_ARG (exp, 1);
3912 tree arg3 = CALL_EXPR_ARG (exp, 2);
6f428e8b 3913
957d0361 3914 unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
3915 unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
7a3f89b5 3916 enum machine_mode insn_mode
6ac5504b 3917 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
bf8e3599 3918
681fab1e 3919 len1 = c_strlen (arg1, 1);
3920 len2 = c_strlen (arg2, 1);
7a3f89b5 3921
3922 if (len1)
389dd41b 3923 len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1);
7a3f89b5 3924 if (len2)
389dd41b 3925 len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2);
7a3f89b5 3926
3927 /* If we don't have a constant length for the first, use the length
3928 of the second, if we know it. We don't require a constant for
3929 this case; some cost analysis could be done if both are available
3930 but neither is constant. For now, assume they're equally cheap,
3931 unless one has side effects. If both strings have constant lengths,
3932 use the smaller. */
3933
3934 if (!len1)
3935 len = len2;
3936 else if (!len2)
3937 len = len1;
3938 else if (TREE_SIDE_EFFECTS (len1))
3939 len = len2;
3940 else if (TREE_SIDE_EFFECTS (len2))
3941 len = len1;
3942 else if (TREE_CODE (len1) != INTEGER_CST)
3943 len = len2;
3944 else if (TREE_CODE (len2) != INTEGER_CST)
3945 len = len1;
3946 else if (tree_int_cst_lt (len1, len2))
3947 len = len1;
3948 else
3949 len = len2;
6e34e617 3950
7a3f89b5 3951 /* If both arguments have side effects, we cannot optimize. */
3952 if (!len || TREE_SIDE_EFFECTS (len))
c2f47e15 3953 return NULL_RTX;
bf8e3599 3954
7a3f89b5 3955 /* The actual new length parameter is MIN(len,arg3). */
389dd41b 3956 len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len,
3957 fold_convert_loc (loc, TREE_TYPE (len), arg3));
7a3f89b5 3958
3959 /* If we don't have POINTER_TYPE, call the function. */
3960 if (arg1_align == 0 || arg2_align == 0)
c2f47e15 3961 return NULL_RTX;
7a3f89b5 3962
3963 /* Make a place to write the result of the instruction. */
3964 result = target;
3965 if (! (result != 0
8ad4c111 3966 && REG_P (result) && GET_MODE (result) == insn_mode
7a3f89b5 3967 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3968 result = gen_reg_rtx (insn_mode);
3969
a65c4d64 3970 /* Stabilize the arguments in case gen_cmpstrnsi fails. */
3971 arg1 = builtin_save_expr (arg1);
3972 arg2 = builtin_save_expr (arg2);
3973 len = builtin_save_expr (len);
27d0c333 3974
a65c4d64 3975 arg1_rtx = get_memory_rtx (arg1, len);
3976 arg2_rtx = get_memory_rtx (arg2, len);
3977 arg3_rtx = expand_normal (len);
3978 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3979 GEN_INT (MIN (arg1_align, arg2_align)));
3980 if (insn)
3981 {
3982 emit_insn (insn);
49f0327b 3983
a65c4d64 3984 /* Return the value in the proper mode for this function. */
3985 mode = TYPE_MODE (TREE_TYPE (exp));
3986 if (GET_MODE (result) == mode)
3987 return result;
3988 if (target == 0)
3989 return convert_to_mode (mode, result, 0);
3990 convert_move (target, result, 0);
3991 return target;
3992 }
27d0c333 3993
a65c4d64 3994 /* Expand the library call ourselves using a stabilized argument
3995 list to avoid re-evaluating the function's arguments twice. */
3996 fndecl = get_callee_fndecl (exp);
0568e9c1 3997 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 3,
3998 arg1, arg2, len);
a65c4d64 3999 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
4000 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4001 return expand_call (fn, target, target == const0_rtx);
4002 }
4003#endif
c2f47e15 4004 return NULL_RTX;
49f0327b 4005}
4006
a66c9326 4007/* Expand a call to __builtin_saveregs, generating the result in TARGET,
4008 if that's convenient. */
902de8ed 4009
a66c9326 4010rtx
aecda0d6 4011expand_builtin_saveregs (void)
53800dbe 4012{
a66c9326 4013 rtx val, seq;
53800dbe 4014
4015 /* Don't do __builtin_saveregs more than once in a function.
4016 Save the result of the first call and reuse it. */
4017 if (saveregs_value != 0)
4018 return saveregs_value;
53800dbe 4019
a66c9326 4020 /* When this function is called, it means that registers must be
4021 saved on entry to this function. So we migrate the call to the
4022 first insn of this function. */
4023
4024 start_sequence ();
53800dbe 4025
a66c9326 4026 /* Do whatever the machine needs done in this case. */
45550790 4027 val = targetm.calls.expand_builtin_saveregs ();
53800dbe 4028
a66c9326 4029 seq = get_insns ();
4030 end_sequence ();
53800dbe 4031
a66c9326 4032 saveregs_value = val;
53800dbe 4033
31d3e01c 4034 /* Put the insns after the NOTE that starts the function. If this
4035 is inside a start_sequence, make the outer-level insn chain current, so
a66c9326 4036 the code is placed at the start of the function. */
4037 push_topmost_sequence ();
0ec80471 4038 emit_insn_after (seq, entry_of_function ());
a66c9326 4039 pop_topmost_sequence ();
4040
4041 return val;
53800dbe 4042}
4043
79012a9d 4044/* Expand a call to __builtin_next_arg. */
27d0c333 4045
53800dbe 4046static rtx
79012a9d 4047expand_builtin_next_arg (void)
53800dbe 4048{
79012a9d 4049 /* Checking arguments is already done in fold_builtin_next_arg
4050 that must be called before this function. */
940ddc5c 4051 return expand_binop (ptr_mode, add_optab,
abe32cce 4052 crtl->args.internal_arg_pointer,
4053 crtl->args.arg_offset_rtx,
53800dbe 4054 NULL_RTX, 0, OPTAB_LIB_WIDEN);
4055}
4056
a66c9326 4057/* Make it easier for the backends by protecting the valist argument
4058 from multiple evaluations. */
4059
4060static tree
389dd41b 4061stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue)
a66c9326 4062{
5f57a8b1 4063 tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist));
4064
182cf5a9 4065 /* The current way of determining the type of valist is completely
4066 bogus. We should have the information on the va builtin instead. */
4067 if (!vatype)
4068 vatype = targetm.fn_abi_va_list (cfun->decl);
5f57a8b1 4069
4070 if (TREE_CODE (vatype) == ARRAY_TYPE)
a66c9326 4071 {
2d47cc32 4072 if (TREE_SIDE_EFFECTS (valist))
4073 valist = save_expr (valist);
11a61dea 4074
2d47cc32 4075 /* For this case, the backends will be expecting a pointer to
5f57a8b1 4076 vatype, but it's possible we've actually been given an array
4077 (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)).
2d47cc32 4078 So fix it. */
4079 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
8a15c04a 4080 {
5f57a8b1 4081 tree p1 = build_pointer_type (TREE_TYPE (vatype));
389dd41b 4082 valist = build_fold_addr_expr_with_type_loc (loc, valist, p1);
8a15c04a 4083 }
a66c9326 4084 }
11a61dea 4085 else
a66c9326 4086 {
182cf5a9 4087 tree pt = build_pointer_type (vatype);
11a61dea 4088
2d47cc32 4089 if (! needs_lvalue)
4090 {
11a61dea 4091 if (! TREE_SIDE_EFFECTS (valist))
4092 return valist;
bf8e3599 4093
389dd41b 4094 valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist);
a66c9326 4095 TREE_SIDE_EFFECTS (valist) = 1;
a66c9326 4096 }
2d47cc32 4097
11a61dea 4098 if (TREE_SIDE_EFFECTS (valist))
2d47cc32 4099 valist = save_expr (valist);
182cf5a9 4100 valist = fold_build2_loc (loc, MEM_REF,
4101 vatype, valist, build_int_cst (pt, 0));
a66c9326 4102 }
4103
4104 return valist;
4105}
4106
2e15d750 4107/* The "standard" definition of va_list is void*. */
4108
4109tree
4110std_build_builtin_va_list (void)
4111{
4112 return ptr_type_node;
4113}
4114
5f57a8b1 4115/* The "standard" abi va_list is va_list_type_node. */
4116
4117tree
4118std_fn_abi_va_list (tree fndecl ATTRIBUTE_UNUSED)
4119{
4120 return va_list_type_node;
4121}
4122
4123/* The "standard" type of va_list is va_list_type_node. */
4124
4125tree
4126std_canonical_va_list_type (tree type)
4127{
4128 tree wtype, htype;
4129
4130 if (INDIRECT_REF_P (type))
4131 type = TREE_TYPE (type);
4132 else if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE(type)))
4133 type = TREE_TYPE (type);
5f57a8b1 4134 wtype = va_list_type_node;
4135 htype = type;
7b36f9ab 4136 /* Treat structure va_list types. */
4137 if (TREE_CODE (wtype) == RECORD_TYPE && POINTER_TYPE_P (htype))
4138 htype = TREE_TYPE (htype);
4139 else if (TREE_CODE (wtype) == ARRAY_TYPE)
5f57a8b1 4140 {
4141 /* If va_list is an array type, the argument may have decayed
4142 to a pointer type, e.g. by being passed to another function.
4143 In that case, unwrap both types so that we can compare the
4144 underlying records. */
4145 if (TREE_CODE (htype) == ARRAY_TYPE
4146 || POINTER_TYPE_P (htype))
4147 {
4148 wtype = TREE_TYPE (wtype);
4149 htype = TREE_TYPE (htype);
4150 }
4151 }
4152 if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype))
4153 return va_list_type_node;
4154
4155 return NULL_TREE;
4156}
4157
a66c9326 4158/* The "standard" implementation of va_start: just assign `nextarg' to
4159 the variable. */
27d0c333 4160
a66c9326 4161void
aecda0d6 4162std_expand_builtin_va_start (tree valist, rtx nextarg)
a66c9326 4163{
f03c17bc 4164 rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
4165 convert_move (va_r, nextarg, 0);
a66c9326 4166}
4167
c2f47e15 4168/* Expand EXP, a call to __builtin_va_start. */
27d0c333 4169
a66c9326 4170static rtx
c2f47e15 4171expand_builtin_va_start (tree exp)
a66c9326 4172{
4173 rtx nextarg;
c2f47e15 4174 tree valist;
389dd41b 4175 location_t loc = EXPR_LOCATION (exp);
a66c9326 4176
c2f47e15 4177 if (call_expr_nargs (exp) < 2)
cb166087 4178 {
389dd41b 4179 error_at (loc, "too few arguments to function %<va_start%>");
cb166087 4180 return const0_rtx;
4181 }
a66c9326 4182
c2f47e15 4183 if (fold_builtin_next_arg (exp, true))
79012a9d 4184 return const0_rtx;
7c2f0500 4185
79012a9d 4186 nextarg = expand_builtin_next_arg ();
389dd41b 4187 valist = stabilize_va_list_loc (loc, CALL_EXPR_ARG (exp, 0), 1);
a66c9326 4188
8a58ed0a 4189 if (targetm.expand_builtin_va_start)
4190 targetm.expand_builtin_va_start (valist, nextarg);
4191 else
4192 std_expand_builtin_va_start (valist, nextarg);
a66c9326 4193
4194 return const0_rtx;
4195}
4196
a66c9326 4197/* The "standard" implementation of va_arg: read the value from the
4198 current (padded) address and increment by the (padded) size. */
f7c44134 4199
e0eca1fa 4200tree
75a70cf9 4201std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
4202 gimple_seq *post_p)
fcdd3ab3 4203{
52cc2eeb 4204 tree addr, t, type_size, rounded_size, valist_tmp;
b8e8e485 4205 unsigned HOST_WIDE_INT align, boundary;
bef380a4 4206 bool indirect;
52cc2eeb 4207
4208#ifdef ARGS_GROW_DOWNWARD
4209 /* All of the alignment and movement below is for args-grow-up machines.
4210 As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
4211 implement their own specialized gimplify_va_arg_expr routines. */
64db345d 4212 gcc_unreachable ();
52cc2eeb 4213#endif
fcdd3ab3 4214
bef380a4 4215 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
4216 if (indirect)
4217 type = build_pointer_type (type);
4218
52cc2eeb 4219 align = PARM_BOUNDARY / BITS_PER_UNIT;
bd99ba64 4220 boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
c8b779eb 4221
4222 /* When we align parameter on stack for caller, if the parameter
befa808c 4223 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
4224 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
c8b779eb 4225 here with caller. */
befa808c 4226 if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
4227 boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
c8b779eb 4228
4229 boundary /= BITS_PER_UNIT;
fcdd3ab3 4230
52cc2eeb 4231 /* Hoist the valist value into a temporary for the moment. */
ecdeeb37 4232 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
4233
fcdd3ab3 4234 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
4235 requires greater alignment, we must perform dynamic alignment. */
85c1f587 4236 if (boundary > align
4237 && !integer_zerop (TYPE_SIZE (type)))
fcdd3ab3 4238 {
41076ef6 4239 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
2cc66f2a 4240 fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
52cc2eeb 4241 gimplify_and_add (t, pre_p);
4242
41076ef6 4243 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
a0553bff 4244 fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
4245 valist_tmp,
4246 build_int_cst (TREE_TYPE (valist), -boundary)));
ecdeeb37 4247 gimplify_and_add (t, pre_p);
fcdd3ab3 4248 }
c5dc0c32 4249 else
4250 boundary = align;
4251
4252 /* If the actual alignment is less than the alignment of the type,
4253 adjust the type accordingly so that we don't assume strict alignment
f0b5f617 4254 when dereferencing the pointer. */
c5dc0c32 4255 boundary *= BITS_PER_UNIT;
4256 if (boundary < TYPE_ALIGN (type))
4257 {
4258 type = build_variant_type_copy (type);
4259 TYPE_ALIGN (type) = boundary;
4260 }
fcdd3ab3 4261
bcff3604 4262 /* Compute the rounded size of the type. */
52cc2eeb 4263 type_size = size_in_bytes (type);
4264 rounded_size = round_up (type_size, align);
4265
fcdd3ab3 4266 /* Reduce rounded_size so it's sharable with the postqueue. */
4267 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
4268
4269 /* Get AP. */
ecdeeb37 4270 addr = valist_tmp;
52cc2eeb 4271 if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
fcdd3ab3 4272 {
4273 /* Small args are padded downward. */
389dd41b 4274 t = fold_build2_loc (input_location, GT_EXPR, sizetype,
4275 rounded_size, size_int (align));
49d00087 4276 t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
4277 size_binop (MINUS_EXPR, rounded_size, type_size));
2cc66f2a 4278 addr = fold_build_pointer_plus (addr, t);
fcdd3ab3 4279 }
4280
fcdd3ab3 4281 /* Compute new value for AP. */
2cc66f2a 4282 t = fold_build_pointer_plus (valist_tmp, rounded_size);
41076ef6 4283 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
ecdeeb37 4284 gimplify_and_add (t, pre_p);
e0eca1fa 4285
4286 addr = fold_convert (build_pointer_type (type), addr);
fcdd3ab3 4287
bef380a4 4288 if (indirect)
f2462d6c 4289 addr = build_va_arg_indirect_ref (addr);
4290
4291 return build_va_arg_indirect_ref (addr);
4292}
a0930a69 4293
f2462d6c 4294/* Build an indirect-ref expression over the given TREE, which represents a
4295 piece of a va_arg() expansion. */
4296tree
4297build_va_arg_indirect_ref (tree addr)
4298{
5c9d7b33 4299 addr = build_simple_mem_ref_loc (EXPR_LOCATION (addr), addr);
f2462d6c 4300
a0930a69 4301 if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */
4302 mf_mark (addr);
bef380a4 4303
a0930a69 4304 return addr;
433006a9 4305}
4306
fcdd3ab3 4307/* Return a dummy expression of type TYPE in order to keep going after an
4308 error. */
4309
4310static tree
4311dummy_object (tree type)
4312{
535664e3 4313 tree t = build_int_cst (build_pointer_type (type), 0);
377bc54c 4314 return build2 (MEM_REF, type, t, t);
fcdd3ab3 4315}
4316
2799a2b7 4317/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
4318 builtin function, but a very special sort of operator. */
fcdd3ab3 4319
4320enum gimplify_status
75a70cf9 4321gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
fcdd3ab3 4322{
5f57a8b1 4323 tree promoted_type, have_va_type;
fcdd3ab3 4324 tree valist = TREE_OPERAND (*expr_p, 0);
4325 tree type = TREE_TYPE (*expr_p);
4326 tree t;
389dd41b 4327 location_t loc = EXPR_LOCATION (*expr_p);
fcdd3ab3 4328
4329 /* Verify that valist is of the proper type. */
fcdd3ab3 4330 have_va_type = TREE_TYPE (valist);
f43dda35 4331 if (have_va_type == error_mark_node)
4332 return GS_ERROR;
5f57a8b1 4333 have_va_type = targetm.canonical_va_list_type (have_va_type);
f43dda35 4334
5f57a8b1 4335 if (have_va_type == NULL_TREE)
fcdd3ab3 4336 {
e60a6f7b 4337 error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>");
e0eca1fa 4338 return GS_ERROR;
fcdd3ab3 4339 }
4340
4341 /* Generate a diagnostic for requesting data of a type that cannot
4342 be passed through `...' due to type promotion at the call site. */
5f57a8b1 4343 if ((promoted_type = lang_hooks.types.type_promotes_to (type))
fcdd3ab3 4344 != type)
4345 {
4346 static bool gave_help;
a52d5726 4347 bool warned;
fcdd3ab3 4348
4349 /* Unfortunately, this is merely undefined, rather than a constraint
4350 violation, so we cannot make this an error. If this call is never
4351 executed, the program is still strictly conforming. */
e60a6f7b 4352 warned = warning_at (loc, 0,
4353 "%qT is promoted to %qT when passed through %<...%>",
4354 type, promoted_type);
a52d5726 4355 if (!gave_help && warned)
fcdd3ab3 4356 {
4357 gave_help = true;
e60a6f7b 4358 inform (loc, "(so you should pass %qT not %qT to %<va_arg%>)",
4359 promoted_type, type);
fcdd3ab3 4360 }
4361
4362 /* We can, however, treat "undefined" any way we please.
4363 Call abort to encourage the user to fix the program. */
a52d5726 4364 if (warned)
e60a6f7b 4365 inform (loc, "if this code is reached, the program will abort");
ad0e7a06 4366 /* Before the abort, allow the evaluation of the va_list
4367 expression to exit or longjmp. */
4368 gimplify_and_add (valist, pre_p);
389dd41b 4369 t = build_call_expr_loc (loc,
b9a16870 4370 builtin_decl_implicit (BUILT_IN_TRAP), 0);
75a70cf9 4371 gimplify_and_add (t, pre_p);
fcdd3ab3 4372
4373 /* This is dead code, but go ahead and finish so that the
4374 mode of the result comes out right. */
4375 *expr_p = dummy_object (type);
4376 return GS_ALL_DONE;
4377 }
4378 else
4379 {
4380 /* Make it easier for the backends by protecting the valist argument
a0c938f0 4381 from multiple evaluations. */
5f57a8b1 4382 if (TREE_CODE (have_va_type) == ARRAY_TYPE)
e0eca1fa 4383 {
4384 /* For this case, the backends will be expecting a pointer to
5f57a8b1 4385 TREE_TYPE (abi), but it's possible we've
4386 actually been given an array (an actual TARGET_FN_ABI_VA_LIST).
e0eca1fa 4387 So fix it. */
4388 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
4389 {
5f57a8b1 4390 tree p1 = build_pointer_type (TREE_TYPE (have_va_type));
389dd41b 4391 valist = fold_convert_loc (loc, p1,
4392 build_fold_addr_expr_loc (loc, valist));
e0eca1fa 4393 }
75a70cf9 4394
e0eca1fa 4395 gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
4396 }
4397 else
4398 gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
fcdd3ab3 4399
17a6380d 4400 if (!targetm.gimplify_va_arg_expr)
75a70cf9 4401 /* FIXME: Once most targets are converted we should merely
89f18f73 4402 assert this is non-null. */
fcdd3ab3 4403 return GS_ALL_DONE;
4404
17a6380d 4405 *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
fcdd3ab3 4406 return GS_OK;
4407 }
4408}
4409
c2f47e15 4410/* Expand EXP, a call to __builtin_va_end. */
f7c44134 4411
a66c9326 4412static rtx
c2f47e15 4413expand_builtin_va_end (tree exp)
a66c9326 4414{
c2f47e15 4415 tree valist = CALL_EXPR_ARG (exp, 0);
8a15c04a 4416
8a15c04a 4417 /* Evaluate for side effects, if needed. I hate macros that don't
4418 do that. */
4419 if (TREE_SIDE_EFFECTS (valist))
4420 expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
a66c9326 4421
4422 return const0_rtx;
4423}
4424
c2f47e15 4425/* Expand EXP, a call to __builtin_va_copy. We do this as a
a66c9326 4426 builtin rather than just as an assignment in stdarg.h because of the
4427 nastiness of array-type va_list types. */
f7c44134 4428
a66c9326 4429static rtx
c2f47e15 4430expand_builtin_va_copy (tree exp)
a66c9326 4431{
4432 tree dst, src, t;
389dd41b 4433 location_t loc = EXPR_LOCATION (exp);
a66c9326 4434
c2f47e15 4435 dst = CALL_EXPR_ARG (exp, 0);
4436 src = CALL_EXPR_ARG (exp, 1);
a66c9326 4437
389dd41b 4438 dst = stabilize_va_list_loc (loc, dst, 1);
4439 src = stabilize_va_list_loc (loc, src, 0);
a66c9326 4440
5f57a8b1 4441 gcc_assert (cfun != NULL && cfun->decl != NULL_TREE);
4442
4443 if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE)
a66c9326 4444 {
5f57a8b1 4445 t = build2 (MODIFY_EXPR, targetm.fn_abi_va_list (cfun->decl), dst, src);
a66c9326 4446 TREE_SIDE_EFFECTS (t) = 1;
4447 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4448 }
4449 else
4450 {
11a61dea 4451 rtx dstb, srcb, size;
4452
4453 /* Evaluate to pointers. */
4454 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
4455 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
5f57a8b1 4456 size = expand_expr (TYPE_SIZE_UNIT (targetm.fn_abi_va_list (cfun->decl)),
4457 NULL_RTX, VOIDmode, EXPAND_NORMAL);
11a61dea 4458
85d654dd 4459 dstb = convert_memory_address (Pmode, dstb);
4460 srcb = convert_memory_address (Pmode, srcb);
726ec87c 4461
11a61dea 4462 /* "Dereference" to BLKmode memories. */
4463 dstb = gen_rtx_MEM (BLKmode, dstb);
ab6ab77e 4464 set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
5f57a8b1 4465 set_mem_align (dstb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 4466 srcb = gen_rtx_MEM (BLKmode, srcb);
ab6ab77e 4467 set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
5f57a8b1 4468 set_mem_align (srcb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl)));
11a61dea 4469
4470 /* Copy. */
0378dbdc 4471 emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
a66c9326 4472 }
4473
4474 return const0_rtx;
4475}
4476
53800dbe 4477/* Expand a call to one of the builtin functions __builtin_frame_address or
4478 __builtin_return_address. */
27d0c333 4479
53800dbe 4480static rtx
c2f47e15 4481expand_builtin_frame_address (tree fndecl, tree exp)
53800dbe 4482{
53800dbe 4483 /* The argument must be a nonnegative integer constant.
4484 It counts the number of frames to scan up the stack.
4485 The value is the return address saved in that frame. */
c2f47e15 4486 if (call_expr_nargs (exp) == 0)
53800dbe 4487 /* Warning about missing arg was already issued. */
4488 return const0_rtx;
c2f47e15 4489 else if (! host_integerp (CALL_EXPR_ARG (exp, 0), 1))
53800dbe 4490 {
4491 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
07e3a3d2 4492 error ("invalid argument to %<__builtin_frame_address%>");
53800dbe 4493 else
07e3a3d2 4494 error ("invalid argument to %<__builtin_return_address%>");
53800dbe 4495 return const0_rtx;
4496 }
4497 else
4498 {
27d0c333 4499 rtx tem
4500 = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
c2f47e15 4501 tree_low_cst (CALL_EXPR_ARG (exp, 0), 1));
53800dbe 4502
4503 /* Some ports cannot access arbitrary stack frames. */
4504 if (tem == NULL)
4505 {
4506 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
c3ceba8e 4507 warning (0, "unsupported argument to %<__builtin_frame_address%>");
53800dbe 4508 else
c3ceba8e 4509 warning (0, "unsupported argument to %<__builtin_return_address%>");
53800dbe 4510 return const0_rtx;
4511 }
4512
4513 /* For __builtin_frame_address, return what we've got. */
4514 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4515 return tem;
4516
8ad4c111 4517 if (!REG_P (tem)
53800dbe 4518 && ! CONSTANT_P (tem))
99182918 4519 tem = copy_addr_to_reg (tem);
53800dbe 4520 return tem;
4521 }
4522}
4523
990495a7 4524/* Expand EXP, a call to the alloca builtin. Return NULL_RTX if we
5be42b39 4525 failed and the caller should emit a normal call. CANNOT_ACCUMULATE
4526 is the same as for allocate_dynamic_stack_space. */
15c6cf6b 4527
53800dbe 4528static rtx
5be42b39 4529expand_builtin_alloca (tree exp, bool cannot_accumulate)
53800dbe 4530{
4531 rtx op0;
15c6cf6b 4532 rtx result;
581bf1c2 4533 bool valid_arglist;
4534 unsigned int align;
4535 bool alloca_with_align = (DECL_FUNCTION_CODE (get_callee_fndecl (exp))
4536 == BUILT_IN_ALLOCA_WITH_ALIGN);
53800dbe 4537
f883da84 4538 /* Emit normal call if we use mudflap. */
4539 if (flag_mudflap)
c2f47e15 4540 return NULL_RTX;
4ee9c684 4541
581bf1c2 4542 valid_arglist
4543 = (alloca_with_align
4544 ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
4545 : validate_arglist (exp, INTEGER_TYPE, VOID_TYPE));
4546
4547 if (!valid_arglist)
c2f47e15 4548 return NULL_RTX;
53800dbe 4549
4550 /* Compute the argument. */
c2f47e15 4551 op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
53800dbe 4552
581bf1c2 4553 /* Compute the alignment. */
4554 align = (alloca_with_align
4555 ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1))
4556 : BIGGEST_ALIGNMENT);
4557
53800dbe 4558 /* Allocate the desired space. */
581bf1c2 4559 result = allocate_dynamic_stack_space (op0, 0, align, cannot_accumulate);
85d654dd 4560 result = convert_memory_address (ptr_mode, result);
15c6cf6b 4561
4562 return result;
53800dbe 4563}
4564
74bdbe96 4565/* Expand a call to bswap builtin in EXP.
4566 Return NULL_RTX if a normal call should be emitted rather than expanding the
4567 function in-line. If convenient, the result should be placed in TARGET.
4568 SUBTARGET may be used as the target for computing one of EXP's operands. */
42791117 4569
4570static rtx
74bdbe96 4571expand_builtin_bswap (enum machine_mode target_mode, tree exp, rtx target,
4572 rtx subtarget)
42791117 4573{
42791117 4574 tree arg;
4575 rtx op0;
4576
c2f47e15 4577 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4578 return NULL_RTX;
42791117 4579
c2f47e15 4580 arg = CALL_EXPR_ARG (exp, 0);
74bdbe96 4581 op0 = expand_expr (arg,
4582 subtarget && GET_MODE (subtarget) == target_mode
4583 ? subtarget : NULL_RTX,
4584 target_mode, EXPAND_NORMAL);
4585 if (GET_MODE (op0) != target_mode)
4586 op0 = convert_to_mode (target_mode, op0, 1);
42791117 4587
74bdbe96 4588 target = expand_unop (target_mode, bswap_optab, op0, target, 1);
42791117 4589
4590 gcc_assert (target);
4591
74bdbe96 4592 return convert_to_mode (target_mode, target, 1);
42791117 4593}
4594
c2f47e15 4595/* Expand a call to a unary builtin in EXP.
4596 Return NULL_RTX if a normal call should be emitted rather than expanding the
53800dbe 4597 function in-line. If convenient, the result should be placed in TARGET.
4598 SUBTARGET may be used as the target for computing one of EXP's operands. */
15c6cf6b 4599
53800dbe 4600static rtx
c2f47e15 4601expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target,
aecda0d6 4602 rtx subtarget, optab op_optab)
53800dbe 4603{
4604 rtx op0;
c2f47e15 4605
4606 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
4607 return NULL_RTX;
53800dbe 4608
4609 /* Compute the argument. */
f97eea22 4610 op0 = expand_expr (CALL_EXPR_ARG (exp, 0),
4611 (subtarget
4612 && (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0)))
4613 == GET_MODE (subtarget))) ? subtarget : NULL_RTX,
1db6d067 4614 VOIDmode, EXPAND_NORMAL);
6a08d0ab 4615 /* Compute op, into TARGET if possible.
53800dbe 4616 Set TARGET to wherever the result comes back. */
c2f47e15 4617 target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
6aaa1f9e 4618 op_optab, op0, target, op_optab != clrsb_optab);
64db345d 4619 gcc_assert (target);
7d3f6cc7 4620
efb070c8 4621 return convert_to_mode (target_mode, target, 0);
53800dbe 4622}
89cfe6e5 4623
48e1416a 4624/* Expand a call to __builtin_expect. We just return our argument
5a74f77e 4625 as the builtin_expect semantic should've been already executed by
4626 tree branch prediction pass. */
89cfe6e5 4627
4628static rtx
c2f47e15 4629expand_builtin_expect (tree exp, rtx target)
89cfe6e5 4630{
1e4adcfc 4631 tree arg;
89cfe6e5 4632
c2f47e15 4633 if (call_expr_nargs (exp) < 2)
89cfe6e5 4634 return const0_rtx;
c2f47e15 4635 arg = CALL_EXPR_ARG (exp, 0);
89cfe6e5 4636
c2f47e15 4637 target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5a74f77e 4638 /* When guessing was done, the hints should be already stripped away. */
07311427 4639 gcc_assert (!flag_guess_branch_prob
852f689e 4640 || optimize == 0 || seen_error ());
89cfe6e5 4641 return target;
4642}
689df48e 4643
fca0886c 4644/* Expand a call to __builtin_assume_aligned. We just return our first
4645 argument as the builtin_assume_aligned semantic should've been already
4646 executed by CCP. */
4647
4648static rtx
4649expand_builtin_assume_aligned (tree exp, rtx target)
4650{
4651 if (call_expr_nargs (exp) < 2)
4652 return const0_rtx;
4653 target = expand_expr (CALL_EXPR_ARG (exp, 0), target, VOIDmode,
4654 EXPAND_NORMAL);
4655 gcc_assert (!TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 1))
4656 && (call_expr_nargs (exp) < 3
4657 || !TREE_SIDE_EFFECTS (CALL_EXPR_ARG (exp, 2))));
4658 return target;
4659}
4660
c22de3f0 4661void
aecda0d6 4662expand_builtin_trap (void)
a0ef1725 4663{
4664#ifdef HAVE_trap
4665 if (HAVE_trap)
f73960eb 4666 {
4667 rtx insn = emit_insn (gen_trap ());
4668 /* For trap insns when not accumulating outgoing args force
4669 REG_ARGS_SIZE note to prevent crossjumping of calls with
4670 different args sizes. */
4671 if (!ACCUMULATE_OUTGOING_ARGS)
4672 add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (stack_pointer_delta));
4673 }
a0ef1725 4674 else
4675#endif
4676 emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
4677 emit_barrier ();
4678}
78a74442 4679
d2b48f0c 4680/* Expand a call to __builtin_unreachable. We do nothing except emit
4681 a barrier saying that control flow will not pass here.
4682
4683 It is the responsibility of the program being compiled to ensure
4684 that control flow does never reach __builtin_unreachable. */
4685static void
4686expand_builtin_unreachable (void)
4687{
4688 emit_barrier ();
4689}
4690
c2f47e15 4691/* Expand EXP, a call to fabs, fabsf or fabsl.
4692 Return NULL_RTX if a normal call should be emitted rather than expanding
78a74442 4693 the function inline. If convenient, the result should be placed
4694 in TARGET. SUBTARGET may be used as the target for computing
4695 the operand. */
4696
4697static rtx
c2f47e15 4698expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
78a74442 4699{
4700 enum machine_mode mode;
4701 tree arg;
4702 rtx op0;
4703
c2f47e15 4704 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
4705 return NULL_RTX;
78a74442 4706
c2f47e15 4707 arg = CALL_EXPR_ARG (exp, 0);
c7f617c2 4708 CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);
78a74442 4709 mode = TYPE_MODE (TREE_TYPE (arg));
1db6d067 4710 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
78a74442 4711 return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
4712}
4713
c2f47e15 4714/* Expand EXP, a call to copysign, copysignf, or copysignl.
270436f3 4715 Return NULL is a normal call should be emitted rather than expanding the
4716 function inline. If convenient, the result should be placed in TARGET.
4717 SUBTARGET may be used as the target for computing the operand. */
4718
4719static rtx
c2f47e15 4720expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
270436f3 4721{
4722 rtx op0, op1;
4723 tree arg;
4724
c2f47e15 4725 if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
4726 return NULL_RTX;
270436f3 4727
c2f47e15 4728 arg = CALL_EXPR_ARG (exp, 0);
8ec3c5c2 4729 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
270436f3 4730
c2f47e15 4731 arg = CALL_EXPR_ARG (exp, 1);
8ec3c5c2 4732 op1 = expand_normal (arg);
270436f3 4733
4734 return expand_copysign (op0, op1, target);
4735}
4736
19bf118a 4737/* Create a new constant string literal and return a char* pointer to it.
4738 The STRING_CST value is the LEN characters at STR. */
1e8e9920 4739tree
19bf118a 4740build_string_literal (int len, const char *str)
4741{
4742 tree t, elem, index, type;
4743
4744 t = build_string (len, str);
4745 elem = build_type_variant (char_type_node, 1, 0);
40238f64 4746 index = build_index_type (size_int (len - 1));
19bf118a 4747 type = build_array_type (elem, index);
4748 TREE_TYPE (t) = type;
4749 TREE_CONSTANT (t) = 1;
4750 TREE_READONLY (t) = 1;
4751 TREE_STATIC (t) = 1;
4752
19bf118a 4753 type = build_pointer_type (elem);
40238f64 4754 t = build1 (ADDR_EXPR, type,
4755 build4 (ARRAY_REF, elem,
4756 t, integer_zero_node, NULL_TREE, NULL_TREE));
19bf118a 4757 return t;
4758}
4759
ac8fb6db 4760/* Expand a call to __builtin___clear_cache. */
4761
4762static rtx
4763expand_builtin___clear_cache (tree exp ATTRIBUTE_UNUSED)
4764{
4765#ifndef HAVE_clear_cache
4766#ifdef CLEAR_INSN_CACHE
4767 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
4768 does something. Just do the default expansion to a call to
4769 __clear_cache(). */
4770 return NULL_RTX;
4771#else
4772 /* There is no "clear_cache" insn, and __clear_cache() in libgcc
4773 does nothing. There is no need to call it. Do nothing. */
4774 return const0_rtx;
4775#endif /* CLEAR_INSN_CACHE */
4776#else
4777 /* We have a "clear_cache" insn, and it will handle everything. */
4778 tree begin, end;
4779 rtx begin_rtx, end_rtx;
ac8fb6db 4780
4781 /* We must not expand to a library call. If we did, any
4782 fallback library function in libgcc that might contain a call to
4783 __builtin___clear_cache() would recurse infinitely. */
4784 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4785 {
4786 error ("both arguments to %<__builtin___clear_cache%> must be pointers");
4787 return const0_rtx;
4788 }
4789
4790 if (HAVE_clear_cache)
4791 {
8786db1e 4792 struct expand_operand ops[2];
ac8fb6db 4793
4794 begin = CALL_EXPR_ARG (exp, 0);
4795 begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
ac8fb6db 4796
4797 end = CALL_EXPR_ARG (exp, 1);
4798 end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
ac8fb6db 4799
8786db1e 4800 create_address_operand (&ops[0], begin_rtx);
4801 create_address_operand (&ops[1], end_rtx);
4802 if (maybe_expand_insn (CODE_FOR_clear_cache, 2, ops))
4803 return const0_rtx;
ac8fb6db 4804 }
4805 return const0_rtx;
4806#endif /* HAVE_clear_cache */
4807}
4808
4ee9c684 4809/* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
4810
4811static rtx
4812round_trampoline_addr (rtx tramp)
4813{
4814 rtx temp, addend, mask;
4815
4816 /* If we don't need too much alignment, we'll have been guaranteed
4817 proper alignment by get_trampoline_type. */
4818 if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
4819 return tramp;
4820
4821 /* Round address up to desired boundary. */
4822 temp = gen_reg_rtx (Pmode);
4823 addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
4824 mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
4825
4826 temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
4827 temp, 0, OPTAB_LIB_WIDEN);
4828 tramp = expand_simple_binop (Pmode, AND, temp, mask,
4829 temp, 0, OPTAB_LIB_WIDEN);
4830
4831 return tramp;
4832}
4833
4834static rtx
c307f106 4835expand_builtin_init_trampoline (tree exp, bool onstack)
4ee9c684 4836{
4837 tree t_tramp, t_func, t_chain;
82c7907c 4838 rtx m_tramp, r_tramp, r_chain, tmp;
4ee9c684 4839
c2f47e15 4840 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
4ee9c684 4841 POINTER_TYPE, VOID_TYPE))
4842 return NULL_RTX;
4843
c2f47e15 4844 t_tramp = CALL_EXPR_ARG (exp, 0);
4845 t_func = CALL_EXPR_ARG (exp, 1);
4846 t_chain = CALL_EXPR_ARG (exp, 2);
4ee9c684 4847
8ec3c5c2 4848 r_tramp = expand_normal (t_tramp);
82c7907c 4849 m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
4850 MEM_NOTRAP_P (m_tramp) = 1;
4851
c307f106 4852 /* If ONSTACK, the TRAMP argument should be the address of a field
4853 within the local function's FRAME decl. Either way, let's see if
4854 we can fill in the MEM_ATTRs for this memory. */
82c7907c 4855 if (TREE_CODE (t_tramp) == ADDR_EXPR)
4856 set_mem_attributes_minus_bitpos (m_tramp, TREE_OPERAND (t_tramp, 0),
4857 true, 0);
4858
c307f106 4859 /* Creator of a heap trampoline is responsible for making sure the
4860 address is aligned to at least STACK_BOUNDARY. Normally malloc
4861 will ensure this anyhow. */
82c7907c 4862 tmp = round_trampoline_addr (r_tramp);
4863 if (tmp != r_tramp)
4864 {
4865 m_tramp = change_address (m_tramp, BLKmode, tmp);
4866 set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
5b2a69fa 4867 set_mem_size (m_tramp, TRAMPOLINE_SIZE);
82c7907c 4868 }
4869
4870 /* The FUNC argument should be the address of the nested function.
4871 Extract the actual function decl to pass to the hook. */
4872 gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
4873 t_func = TREE_OPERAND (t_func, 0);
4874 gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
4875
8ec3c5c2 4876 r_chain = expand_normal (t_chain);
4ee9c684 4877
4878 /* Generate insns to initialize the trampoline. */
82c7907c 4879 targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
4ee9c684 4880
c307f106 4881 if (onstack)
4882 {
4883 trampolines_created = 1;
8bc8a8f4 4884
c307f106 4885 warning_at (DECL_SOURCE_LOCATION (t_func), OPT_Wtrampolines,
4886 "trampoline generated for nested function %qD", t_func);
4887 }
8bc8a8f4 4888
4ee9c684 4889 return const0_rtx;
4890}
4891
4892static rtx
c2f47e15 4893expand_builtin_adjust_trampoline (tree exp)
4ee9c684 4894{
4895 rtx tramp;
4896
c2f47e15 4897 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
4ee9c684 4898 return NULL_RTX;
4899
c2f47e15 4900 tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
4ee9c684 4901 tramp = round_trampoline_addr (tramp);
82c7907c 4902 if (targetm.calls.trampoline_adjust_address)
4903 tramp = targetm.calls.trampoline_adjust_address (tramp);
4ee9c684 4904
4905 return tramp;
4906}
4907
93f564d6 4908/* Expand the call EXP to the built-in signbit, signbitf or signbitl
4909 function. The function first checks whether the back end provides
4910 an insn to implement signbit for the respective mode. If not, it
4911 checks whether the floating point format of the value is such that
4912 the sign bit can be extracted. If that is not the case, the
4913 function returns NULL_RTX to indicate that a normal call should be
4914 emitted rather than expanding the function in-line. EXP is the
4915 expression that is a call to the builtin function; if convenient,
4916 the result should be placed in TARGET. */
27f261ef 4917static rtx
4918expand_builtin_signbit (tree exp, rtx target)
4919{
4920 const struct real_format *fmt;
4921 enum machine_mode fmode, imode, rmode;
c2f47e15 4922 tree arg;
ca4f1f5b 4923 int word, bitpos;
27eda240 4924 enum insn_code icode;
27f261ef 4925 rtx temp;
389dd41b 4926 location_t loc = EXPR_LOCATION (exp);
27f261ef 4927
c2f47e15 4928 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
4929 return NULL_RTX;
27f261ef 4930
c2f47e15 4931 arg = CALL_EXPR_ARG (exp, 0);
27f261ef 4932 fmode = TYPE_MODE (TREE_TYPE (arg));
4933 rmode = TYPE_MODE (TREE_TYPE (exp));
4934 fmt = REAL_MODE_FORMAT (fmode);
4935
93f564d6 4936 arg = builtin_save_expr (arg);
4937
4938 /* Expand the argument yielding a RTX expression. */
4939 temp = expand_normal (arg);
4940
4941 /* Check if the back end provides an insn that handles signbit for the
4942 argument's mode. */
d6bf3b14 4943 icode = optab_handler (signbit_optab, fmode);
27eda240 4944 if (icode != CODE_FOR_nothing)
93f564d6 4945 {
4e2a2fb4 4946 rtx last = get_last_insn ();
93f564d6 4947 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
4e2a2fb4 4948 if (maybe_emit_unop_insn (icode, target, temp, UNKNOWN))
4949 return target;
4950 delete_insns_since (last);
93f564d6 4951 }
4952
27f261ef 4953 /* For floating point formats without a sign bit, implement signbit
4954 as "ARG < 0.0". */
8d564692 4955 bitpos = fmt->signbit_ro;
ca4f1f5b 4956 if (bitpos < 0)
27f261ef 4957 {
4958 /* But we can't do this if the format supports signed zero. */
4959 if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
c2f47e15 4960 return NULL_RTX;
27f261ef 4961
389dd41b 4962 arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg,
49d00087 4963 build_real (TREE_TYPE (arg), dconst0));
27f261ef 4964 return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
4965 }
4966
ca4f1f5b 4967 if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
27f261ef 4968 {
ca4f1f5b 4969 imode = int_mode_for_mode (fmode);
4970 if (imode == BLKmode)
c2f47e15 4971 return NULL_RTX;
ca4f1f5b 4972 temp = gen_lowpart (imode, temp);
24fd4260 4973 }
4974 else
4975 {
ca4f1f5b 4976 imode = word_mode;
4977 /* Handle targets with different FP word orders. */
4978 if (FLOAT_WORDS_BIG_ENDIAN)
a0c938f0 4979 word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
ca4f1f5b 4980 else
a0c938f0 4981 word = bitpos / BITS_PER_WORD;
ca4f1f5b 4982 temp = operand_subword_force (temp, word, fmode);
4983 bitpos = bitpos % BITS_PER_WORD;
4984 }
4985
44b0f1d0 4986 /* Force the intermediate word_mode (or narrower) result into a
4987 register. This avoids attempting to create paradoxical SUBREGs
4988 of floating point modes below. */
4989 temp = force_reg (imode, temp);
4990
ca4f1f5b 4991 /* If the bitpos is within the "result mode" lowpart, the operation
4992 can be implement with a single bitwise AND. Otherwise, we need
4993 a right shift and an AND. */
4994
4995 if (bitpos < GET_MODE_BITSIZE (rmode))
4996 {
cf8f0e63 4997 double_int mask = double_int_zero.set_bit (bitpos);
27f261ef 4998
4a46f016 4999 if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
ca4f1f5b 5000 temp = gen_lowpart (rmode, temp);
24fd4260 5001 temp = expand_binop (rmode, and_optab, temp,
3e052aec 5002 immed_double_int_const (mask, rmode),
ca4f1f5b 5003 NULL_RTX, 1, OPTAB_LIB_WIDEN);
27f261ef 5004 }
ca4f1f5b 5005 else
5006 {
5007 /* Perform a logical right shift to place the signbit in the least
a0c938f0 5008 significant bit, then truncate the result to the desired mode
ca4f1f5b 5009 and mask just this bit. */
f5ff0b21 5010 temp = expand_shift (RSHIFT_EXPR, imode, temp, bitpos, NULL_RTX, 1);
ca4f1f5b 5011 temp = gen_lowpart (rmode, temp);
5012 temp = expand_binop (rmode, and_optab, temp, const1_rtx,
5013 NULL_RTX, 1, OPTAB_LIB_WIDEN);
5014 }
5015
27f261ef 5016 return temp;
5017}
73673831 5018
5019/* Expand fork or exec calls. TARGET is the desired target of the
c2f47e15 5020 call. EXP is the call. FN is the
73673831 5021 identificator of the actual function. IGNORE is nonzero if the
5022 value is to be ignored. */
5023
5024static rtx
c2f47e15 5025expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
73673831 5026{
5027 tree id, decl;
5028 tree call;
5029
5030 /* If we are not profiling, just call the function. */
5031 if (!profile_arc_flag)
5032 return NULL_RTX;
5033
5034 /* Otherwise call the wrapper. This should be equivalent for the rest of
5035 compiler, so the code does not diverge, and the wrapper may run the
9c9bad97 5036 code necessary for keeping the profiling sane. */
73673831 5037
5038 switch (DECL_FUNCTION_CODE (fn))
5039 {
5040 case BUILT_IN_FORK:
5041 id = get_identifier ("__gcov_fork");
5042 break;
5043
5044 case BUILT_IN_EXECL:
5045 id = get_identifier ("__gcov_execl");
5046 break;
5047
5048 case BUILT_IN_EXECV:
5049 id = get_identifier ("__gcov_execv");
5050 break;
5051
5052 case BUILT_IN_EXECLP:
5053 id = get_identifier ("__gcov_execlp");
5054 break;
5055
5056 case BUILT_IN_EXECLE:
5057 id = get_identifier ("__gcov_execle");
5058 break;
5059
5060 case BUILT_IN_EXECVP:
5061 id = get_identifier ("__gcov_execvp");
5062 break;
5063
5064 case BUILT_IN_EXECVE:
5065 id = get_identifier ("__gcov_execve");
5066 break;
5067
5068 default:
64db345d 5069 gcc_unreachable ();
73673831 5070 }
5071
e60a6f7b 5072 decl = build_decl (DECL_SOURCE_LOCATION (fn),
5073 FUNCTION_DECL, id, TREE_TYPE (fn));
73673831 5074 DECL_EXTERNAL (decl) = 1;
5075 TREE_PUBLIC (decl) = 1;
5076 DECL_ARTIFICIAL (decl) = 1;
5077 TREE_NOTHROW (decl) = 1;
e82d310b 5078 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
5079 DECL_VISIBILITY_SPECIFIED (decl) = 1;
389dd41b 5080 call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0);
73673831 5081 return expand_call (call, target, ignore);
c2f47e15 5082 }
48e1416a 5083
b6a5fc45 5084
5085\f
3e272de8 5086/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
5087 the pointer in these functions is void*, the tree optimizers may remove
5088 casts. The mode computed in expand_builtin isn't reliable either, due
5089 to __sync_bool_compare_and_swap.
5090
5091 FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
5092 group of builtins. This gives us log2 of the mode size. */
5093
5094static inline enum machine_mode
5095get_builtin_sync_mode (int fcode_diff)
5096{
ad3a13b5 5097 /* The size is not negotiable, so ask not to get BLKmode in return
5098 if the target indicates that a smaller size would be better. */
5099 return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
3e272de8 5100}
5101
041e0215 5102/* Expand the memory expression LOC and return the appropriate memory operand
5103 for the builtin_sync operations. */
5104
5105static rtx
5106get_builtin_sync_mem (tree loc, enum machine_mode mode)
5107{
5108 rtx addr, mem;
5109
7f4d56ad 5110 addr = expand_expr (loc, NULL_RTX, ptr_mode, EXPAND_SUM);
5111 addr = convert_memory_address (Pmode, addr);
041e0215 5112
5113 /* Note that we explicitly do not want any alias information for this
5114 memory, so that we kill all other live memories. Otherwise we don't
5115 satisfy the full barrier semantics of the intrinsic. */
5116 mem = validize_mem (gen_rtx_MEM (mode, addr));
5117
153c3b50 5118 /* The alignment needs to be at least according to that of the mode. */
5119 set_mem_align (mem, MAX (GET_MODE_ALIGNMENT (mode),
957d0361 5120 get_pointer_alignment (loc)));
c94cfd1c 5121 set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
041e0215 5122 MEM_VOLATILE_P (mem) = 1;
5123
5124 return mem;
5125}
5126
1cd6e20d 5127/* Make sure an argument is in the right mode.
5128 EXP is the tree argument.
5129 MODE is the mode it should be in. */
5130
5131static rtx
5132expand_expr_force_mode (tree exp, enum machine_mode mode)
5133{
5134 rtx val;
5135 enum machine_mode old_mode;
5136
5137 val = expand_expr (exp, NULL_RTX, mode, EXPAND_NORMAL);
5138 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5139 of CONST_INTs, where we know the old_mode only from the call argument. */
5140
5141 old_mode = GET_MODE (val);
5142 if (old_mode == VOIDmode)
5143 old_mode = TYPE_MODE (TREE_TYPE (exp));
5144 val = convert_modes (mode, old_mode, val, 1);
5145 return val;
5146}
5147
5148
b6a5fc45 5149/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
c2f47e15 5150 EXP is the CALL_EXPR. CODE is the rtx code
b6a5fc45 5151 that corresponds to the arithmetic or logical operation from the name;
5152 an exception here is that NOT actually means NAND. TARGET is an optional
5153 place for us to store the results; AFTER is true if this is the
1cd6e20d 5154 fetch_and_xxx form. */
b6a5fc45 5155
5156static rtx
c2f47e15 5157expand_builtin_sync_operation (enum machine_mode mode, tree exp,
3e272de8 5158 enum rtx_code code, bool after,
1cd6e20d 5159 rtx target)
b6a5fc45 5160{
041e0215 5161 rtx val, mem;
e60a6f7b 5162 location_t loc = EXPR_LOCATION (exp);
b6a5fc45 5163
cf73e559 5164 if (code == NOT && warn_sync_nand)
5165 {
5166 tree fndecl = get_callee_fndecl (exp);
5167 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
5168
5169 static bool warned_f_a_n, warned_n_a_f;
5170
5171 switch (fcode)
5172 {
2797f13a 5173 case BUILT_IN_SYNC_FETCH_AND_NAND_1:
5174 case BUILT_IN_SYNC_FETCH_AND_NAND_2:
5175 case BUILT_IN_SYNC_FETCH_AND_NAND_4:
5176 case BUILT_IN_SYNC_FETCH_AND_NAND_8:
5177 case BUILT_IN_SYNC_FETCH_AND_NAND_16:
cf73e559 5178 if (warned_f_a_n)
5179 break;
5180
b9a16870 5181 fndecl = builtin_decl_implicit (BUILT_IN_SYNC_FETCH_AND_NAND_N);
e60a6f7b 5182 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
cf73e559 5183 warned_f_a_n = true;
5184 break;
5185
2797f13a 5186 case BUILT_IN_SYNC_NAND_AND_FETCH_1:
5187 case BUILT_IN_SYNC_NAND_AND_FETCH_2:
5188 case BUILT_IN_SYNC_NAND_AND_FETCH_4:
5189 case BUILT_IN_SYNC_NAND_AND_FETCH_8:
5190 case BUILT_IN_SYNC_NAND_AND_FETCH_16:
cf73e559 5191 if (warned_n_a_f)
5192 break;
5193
b9a16870 5194 fndecl = builtin_decl_implicit (BUILT_IN_SYNC_NAND_AND_FETCH_N);
e60a6f7b 5195 inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
cf73e559 5196 warned_n_a_f = true;
5197 break;
5198
5199 default:
5200 gcc_unreachable ();
5201 }
5202 }
5203
b6a5fc45 5204 /* Expand the operands. */
c2f47e15 5205 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1cd6e20d 5206 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
b6a5fc45 5207
1cd6e20d 5208 return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SEQ_CST,
5209 after);
b6a5fc45 5210}
5211
5212/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
c2f47e15 5213 intrinsics. EXP is the CALL_EXPR. IS_BOOL is
b6a5fc45 5214 true if this is the boolean form. TARGET is a place for us to store the
5215 results; this is NOT optional if IS_BOOL is true. */
5216
5217static rtx
c2f47e15 5218expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
3e272de8 5219 bool is_bool, rtx target)
b6a5fc45 5220{
041e0215 5221 rtx old_val, new_val, mem;
ba885f6a 5222 rtx *pbool, *poval;
b6a5fc45 5223
5224 /* Expand the operands. */
c2f47e15 5225 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1cd6e20d 5226 old_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5227 new_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
b6a5fc45 5228
ba885f6a 5229 pbool = poval = NULL;
5230 if (target != const0_rtx)
5231 {
5232 if (is_bool)
5233 pbool = &target;
5234 else
5235 poval = &target;
5236 }
5237 if (!expand_atomic_compare_and_swap (pbool, poval, mem, old_val, new_val,
5238 false, MEMMODEL_SEQ_CST,
5239 MEMMODEL_SEQ_CST))
1cd6e20d 5240 return NULL_RTX;
c2f47e15 5241
1cd6e20d 5242 return target;
b6a5fc45 5243}
5244
5245/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
5246 general form is actually an atomic exchange, and some targets only
5247 support a reduced form with the second argument being a constant 1.
48e1416a 5248 EXP is the CALL_EXPR; TARGET is an optional place for us to store
c2f47e15 5249 the results. */
b6a5fc45 5250
5251static rtx
2797f13a 5252expand_builtin_sync_lock_test_and_set (enum machine_mode mode, tree exp,
1cd6e20d 5253 rtx target)
b6a5fc45 5254{
041e0215 5255 rtx val, mem;
b6a5fc45 5256
5257 /* Expand the operands. */
c2f47e15 5258 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
1cd6e20d 5259 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5260
7821cde1 5261 return expand_sync_lock_test_and_set (target, mem, val);
1cd6e20d 5262}
5263
5264/* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */
5265
5266static void
5267expand_builtin_sync_lock_release (enum machine_mode mode, tree exp)
5268{
5269 rtx mem;
5270
5271 /* Expand the operands. */
5272 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5273
8808bf16 5274 expand_atomic_store (mem, const0_rtx, MEMMODEL_RELEASE, true);
1cd6e20d 5275}
5276
5277/* Given an integer representing an ``enum memmodel'', verify its
5278 correctness and return the memory model enum. */
5279
5280static enum memmodel
5281get_memmodel (tree exp)
5282{
5283 rtx op;
7f738025 5284 unsigned HOST_WIDE_INT val;
1cd6e20d 5285
5286 /* If the parameter is not a constant, it's a run time value so we'll just
5287 convert it to MEMMODEL_SEQ_CST to avoid annoying runtime checking. */
5288 if (TREE_CODE (exp) != INTEGER_CST)
5289 return MEMMODEL_SEQ_CST;
5290
5291 op = expand_normal (exp);
7f738025 5292
5293 val = INTVAL (op);
5294 if (targetm.memmodel_check)
5295 val = targetm.memmodel_check (val);
5296 else if (val & ~MEMMODEL_MASK)
5297 {
5298 warning (OPT_Winvalid_memory_model,
5299 "Unknown architecture specifier in memory model to builtin.");
5300 return MEMMODEL_SEQ_CST;
5301 }
5302
5303 if ((INTVAL(op) & MEMMODEL_MASK) >= MEMMODEL_LAST)
1cd6e20d 5304 {
5305 warning (OPT_Winvalid_memory_model,
5306 "invalid memory model argument to builtin");
5307 return MEMMODEL_SEQ_CST;
5308 }
7f738025 5309
5310 return (enum memmodel) val;
1cd6e20d 5311}
5312
5313/* Expand the __atomic_exchange intrinsic:
5314 TYPE __atomic_exchange (TYPE *object, TYPE desired, enum memmodel)
5315 EXP is the CALL_EXPR.
5316 TARGET is an optional place for us to store the results. */
5317
5318static rtx
5319expand_builtin_atomic_exchange (enum machine_mode mode, tree exp, rtx target)
5320{
5321 rtx val, mem;
5322 enum memmodel model;
5323
5324 model = get_memmodel (CALL_EXPR_ARG (exp, 2));
7f738025 5325 if ((model & MEMMODEL_MASK) == MEMMODEL_CONSUME)
1cd6e20d 5326 {
5327 error ("invalid memory model for %<__atomic_exchange%>");
5328 return NULL_RTX;
5329 }
5330
5331 if (!flag_inline_atomics)
5332 return NULL_RTX;
5333
5334 /* Expand the operands. */
5335 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5336 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5337
7821cde1 5338 return expand_atomic_exchange (target, mem, val, model);
1cd6e20d 5339}
5340
5341/* Expand the __atomic_compare_exchange intrinsic:
5342 bool __atomic_compare_exchange (TYPE *object, TYPE *expect,
5343 TYPE desired, BOOL weak,
5344 enum memmodel success,
5345 enum memmodel failure)
5346 EXP is the CALL_EXPR.
5347 TARGET is an optional place for us to store the results. */
5348
5349static rtx
5350expand_builtin_atomic_compare_exchange (enum machine_mode mode, tree exp,
5351 rtx target)
5352{
5353 rtx expect, desired, mem, oldval;
5354 enum memmodel success, failure;
5355 tree weak;
5356 bool is_weak;
5357
5358 success = get_memmodel (CALL_EXPR_ARG (exp, 4));
5359 failure = get_memmodel (CALL_EXPR_ARG (exp, 5));
5360
7f738025 5361 if ((failure & MEMMODEL_MASK) == MEMMODEL_RELEASE
5362 || (failure & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
1cd6e20d 5363 {
5364 error ("invalid failure memory model for %<__atomic_compare_exchange%>");
5365 return NULL_RTX;
5366 }
5367
5368 if (failure > success)
5369 {
5370 error ("failure memory model cannot be stronger than success "
5371 "memory model for %<__atomic_compare_exchange%>");
5372 return NULL_RTX;
5373 }
5374
5375 if (!flag_inline_atomics)
5376 return NULL_RTX;
5377
5378 /* Expand the operands. */
5379 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5380
5381 expect = expand_normal (CALL_EXPR_ARG (exp, 1));
5382 expect = convert_memory_address (Pmode, expect);
c401b131 5383 expect = gen_rtx_MEM (mode, expect);
1cd6e20d 5384 desired = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
5385
5386 weak = CALL_EXPR_ARG (exp, 3);
5387 is_weak = false;
5388 if (host_integerp (weak, 0) && tree_low_cst (weak, 0) != 0)
5389 is_weak = true;
5390
c401b131 5391 oldval = expect;
ba885f6a 5392 if (!expand_atomic_compare_and_swap ((target == const0_rtx ? NULL : &target),
5393 &oldval, mem, oldval, desired,
5394 is_weak, success, failure))
1cd6e20d 5395 return NULL_RTX;
5396
c401b131 5397 if (oldval != expect)
5398 emit_move_insn (expect, oldval);
5399
1cd6e20d 5400 return target;
5401}
5402
5403/* Expand the __atomic_load intrinsic:
5404 TYPE __atomic_load (TYPE *object, enum memmodel)
5405 EXP is the CALL_EXPR.
5406 TARGET is an optional place for us to store the results. */
5407
5408static rtx
5409expand_builtin_atomic_load (enum machine_mode mode, tree exp, rtx target)
5410{
5411 rtx mem;
5412 enum memmodel model;
5413
5414 model = get_memmodel (CALL_EXPR_ARG (exp, 1));
7f738025 5415 if ((model & MEMMODEL_MASK) == MEMMODEL_RELEASE
5416 || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
1cd6e20d 5417 {
5418 error ("invalid memory model for %<__atomic_load%>");
5419 return NULL_RTX;
5420 }
5421
5422 if (!flag_inline_atomics)
5423 return NULL_RTX;
5424
5425 /* Expand the operand. */
5426 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5427
5428 return expand_atomic_load (target, mem, model);
5429}
5430
5431
5432/* Expand the __atomic_store intrinsic:
5433 void __atomic_store (TYPE *object, TYPE desired, enum memmodel)
5434 EXP is the CALL_EXPR.
5435 TARGET is an optional place for us to store the results. */
5436
5437static rtx
5438expand_builtin_atomic_store (enum machine_mode mode, tree exp)
5439{
5440 rtx mem, val;
5441 enum memmodel model;
5442
5443 model = get_memmodel (CALL_EXPR_ARG (exp, 2));
7f738025 5444 if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED
5445 && (model & MEMMODEL_MASK) != MEMMODEL_SEQ_CST
5446 && (model & MEMMODEL_MASK) != MEMMODEL_RELEASE)
1cd6e20d 5447 {
5448 error ("invalid memory model for %<__atomic_store%>");
5449 return NULL_RTX;
5450 }
5451
5452 if (!flag_inline_atomics)
5453 return NULL_RTX;
5454
5455 /* Expand the operands. */
5456 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5457 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5458
8808bf16 5459 return expand_atomic_store (mem, val, model, false);
1cd6e20d 5460}
5461
5462/* Expand the __atomic_fetch_XXX intrinsic:
5463 TYPE __atomic_fetch_XXX (TYPE *object, TYPE val, enum memmodel)
5464 EXP is the CALL_EXPR.
5465 TARGET is an optional place for us to store the results.
5466 CODE is the operation, PLUS, MINUS, ADD, XOR, or IOR.
5467 FETCH_AFTER is true if returning the result of the operation.
5468 FETCH_AFTER is false if returning the value before the operation.
5469 IGNORE is true if the result is not used.
5470 EXT_CALL is the correct builtin for an external call if this cannot be
5471 resolved to an instruction sequence. */
5472
5473static rtx
5474expand_builtin_atomic_fetch_op (enum machine_mode mode, tree exp, rtx target,
5475 enum rtx_code code, bool fetch_after,
5476 bool ignore, enum built_in_function ext_call)
5477{
5478 rtx val, mem, ret;
5479 enum memmodel model;
5480 tree fndecl;
5481 tree addr;
5482
5483 model = get_memmodel (CALL_EXPR_ARG (exp, 2));
5484
5485 /* Expand the operands. */
5486 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5487 val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
5488
5489 /* Only try generating instructions if inlining is turned on. */
5490 if (flag_inline_atomics)
5491 {
5492 ret = expand_atomic_fetch_op (target, mem, val, code, model, fetch_after);
5493 if (ret)
5494 return ret;
5495 }
5496
5497 /* Return if a different routine isn't needed for the library call. */
5498 if (ext_call == BUILT_IN_NONE)
5499 return NULL_RTX;
5500
5501 /* Change the call to the specified function. */
5502 fndecl = get_callee_fndecl (exp);
5503 addr = CALL_EXPR_FN (exp);
5504 STRIP_NOPS (addr);
5505
5506 gcc_assert (TREE_OPERAND (addr, 0) == fndecl);
5507 TREE_OPERAND (addr, 0) = builtin_decl_explicit(ext_call);
5508
5509 /* Expand the call here so we can emit trailing code. */
5510 ret = expand_call (exp, target, ignore);
5511
5512 /* Replace the original function just in case it matters. */
5513 TREE_OPERAND (addr, 0) = fndecl;
5514
5515 /* Then issue the arithmetic correction to return the right result. */
5516 if (!ignore)
c449f851 5517 {
5518 if (code == NOT)
5519 {
5520 ret = expand_simple_binop (mode, AND, ret, val, NULL_RTX, true,
5521 OPTAB_LIB_WIDEN);
5522 ret = expand_simple_unop (mode, NOT, ret, target, true);
5523 }
5524 else
5525 ret = expand_simple_binop (mode, code, ret, val, target, true,
5526 OPTAB_LIB_WIDEN);
5527 }
1cd6e20d 5528 return ret;
5529}
5530
10b744a3 5531
7821cde1 5532#ifndef HAVE_atomic_clear
5533# define HAVE_atomic_clear 0
5534# define gen_atomic_clear(x,y) (gcc_unreachable (), NULL_RTX)
5535#endif
5536
10b744a3 5537/* Expand an atomic clear operation.
5538 void _atomic_clear (BOOL *obj, enum memmodel)
5539 EXP is the call expression. */
5540
5541static rtx
5542expand_builtin_atomic_clear (tree exp)
5543{
5544 enum machine_mode mode;
5545 rtx mem, ret;
5546 enum memmodel model;
5547
5548 mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0);
5549 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5550 model = get_memmodel (CALL_EXPR_ARG (exp, 1));
5551
7f738025 5552 if ((model & MEMMODEL_MASK) == MEMMODEL_ACQUIRE
5553 || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
10b744a3 5554 {
5555 error ("invalid memory model for %<__atomic_store%>");
5556 return const0_rtx;
5557 }
5558
7821cde1 5559 if (HAVE_atomic_clear)
5560 {
5561 emit_insn (gen_atomic_clear (mem, model));
5562 return const0_rtx;
5563 }
5564
10b744a3 5565 /* Try issuing an __atomic_store, and allow fallback to __sync_lock_release.
5566 Failing that, a store is issued by __atomic_store. The only way this can
5567 fail is if the bool type is larger than a word size. Unlikely, but
5568 handle it anyway for completeness. Assume a single threaded model since
5569 there is no atomic support in this case, and no barriers are required. */
5570 ret = expand_atomic_store (mem, const0_rtx, model, true);
5571 if (!ret)
5572 emit_move_insn (mem, const0_rtx);
5573 return const0_rtx;
5574}
5575
5576/* Expand an atomic test_and_set operation.
5577 bool _atomic_test_and_set (BOOL *obj, enum memmodel)
5578 EXP is the call expression. */
5579
5580static rtx
7821cde1 5581expand_builtin_atomic_test_and_set (tree exp, rtx target)
10b744a3 5582{
7821cde1 5583 rtx mem;
10b744a3 5584 enum memmodel model;
5585 enum machine_mode mode;
5586
5587 mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0);
5588 mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
5589 model = get_memmodel (CALL_EXPR_ARG (exp, 1));
5590
7821cde1 5591 return expand_atomic_test_and_set (target, mem, model);
10b744a3 5592}
5593
5594
1cd6e20d 5595/* Return true if (optional) argument ARG1 of size ARG0 is always lock free on
5596 this architecture. If ARG1 is NULL, use typical alignment for size ARG0. */
5597
5598static tree
5599fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
5600{
5601 int size;
5602 enum machine_mode mode;
5603 unsigned int mode_align, type_align;
5604
5605 if (TREE_CODE (arg0) != INTEGER_CST)
5606 return NULL_TREE;
b6a5fc45 5607
1cd6e20d 5608 size = INTVAL (expand_normal (arg0)) * BITS_PER_UNIT;
5609 mode = mode_for_size (size, MODE_INT, 0);
5610 mode_align = GET_MODE_ALIGNMENT (mode);
5611
5612 if (TREE_CODE (arg1) == INTEGER_CST && INTVAL (expand_normal (arg1)) == 0)
5613 type_align = mode_align;
5614 else
5615 {
5616 tree ttype = TREE_TYPE (arg1);
5617
5618 /* This function is usually invoked and folded immediately by the front
5619 end before anything else has a chance to look at it. The pointer
5620 parameter at this point is usually cast to a void *, so check for that
5621 and look past the cast. */
5622 if (TREE_CODE (arg1) == NOP_EXPR && POINTER_TYPE_P (ttype)
5623 && VOID_TYPE_P (TREE_TYPE (ttype)))
5624 arg1 = TREE_OPERAND (arg1, 0);
5625
5626 ttype = TREE_TYPE (arg1);
5627 gcc_assert (POINTER_TYPE_P (ttype));
5628
5629 /* Get the underlying type of the object. */
5630 ttype = TREE_TYPE (ttype);
5631 type_align = TYPE_ALIGN (ttype);
5632 }
5633
5634 /* If the object has smaller alignment, the the lock free routines cannot
5635 be used. */
5636 if (type_align < mode_align)
06308d2a 5637 return boolean_false_node;
1cd6e20d 5638
5639 /* Check if a compare_and_swap pattern exists for the mode which represents
5640 the required size. The pattern is not allowed to fail, so the existence
5641 of the pattern indicates support is present. */
29139cdc 5642 if (can_compare_and_swap_p (mode, true))
06308d2a 5643 return boolean_true_node;
1cd6e20d 5644 else
06308d2a 5645 return boolean_false_node;
1cd6e20d 5646}
5647
5648/* Return true if the parameters to call EXP represent an object which will
5649 always generate lock free instructions. The first argument represents the
5650 size of the object, and the second parameter is a pointer to the object
5651 itself. If NULL is passed for the object, then the result is based on
5652 typical alignment for an object of the specified size. Otherwise return
5653 false. */
5654
5655static rtx
5656expand_builtin_atomic_always_lock_free (tree exp)
5657{
5658 tree size;
5659 tree arg0 = CALL_EXPR_ARG (exp, 0);
5660 tree arg1 = CALL_EXPR_ARG (exp, 1);
5661
5662 if (TREE_CODE (arg0) != INTEGER_CST)
5663 {
5664 error ("non-constant argument 1 to __atomic_always_lock_free");
5665 return const0_rtx;
5666 }
5667
5668 size = fold_builtin_atomic_always_lock_free (arg0, arg1);
06308d2a 5669 if (size == boolean_true_node)
1cd6e20d 5670 return const1_rtx;
5671 return const0_rtx;
5672}
5673
5674/* Return a one or zero if it can be determined that object ARG1 of size ARG
5675 is lock free on this architecture. */
5676
5677static tree
5678fold_builtin_atomic_is_lock_free (tree arg0, tree arg1)
5679{
5680 if (!flag_inline_atomics)
5681 return NULL_TREE;
5682
5683 /* If it isn't always lock free, don't generate a result. */
06308d2a 5684 if (fold_builtin_atomic_always_lock_free (arg0, arg1) == boolean_true_node)
5685 return boolean_true_node;
1cd6e20d 5686
5687 return NULL_TREE;
5688}
5689
5690/* Return true if the parameters to call EXP represent an object which will
5691 always generate lock free instructions. The first argument represents the
5692 size of the object, and the second parameter is a pointer to the object
5693 itself. If NULL is passed for the object, then the result is based on
5694 typical alignment for an object of the specified size. Otherwise return
5695 NULL*/
5696
5697static rtx
5698expand_builtin_atomic_is_lock_free (tree exp)
5699{
5700 tree size;
5701 tree arg0 = CALL_EXPR_ARG (exp, 0);
5702 tree arg1 = CALL_EXPR_ARG (exp, 1);
5703
5704 if (!INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
5705 {
5706 error ("non-integer argument 1 to __atomic_is_lock_free");
5707 return NULL_RTX;
5708 }
5709
5710 if (!flag_inline_atomics)
5711 return NULL_RTX;
5712
5713 /* If the value is known at compile time, return the RTX for it. */
5714 size = fold_builtin_atomic_is_lock_free (arg0, arg1);
06308d2a 5715 if (size == boolean_true_node)
1cd6e20d 5716 return const1_rtx;
5717
5718 return NULL_RTX;
5719}
5720
1cd6e20d 5721/* Expand the __atomic_thread_fence intrinsic:
5722 void __atomic_thread_fence (enum memmodel)
5723 EXP is the CALL_EXPR. */
5724
5725static void
5726expand_builtin_atomic_thread_fence (tree exp)
5727{
fe54c06b 5728 enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
5729 expand_mem_thread_fence (model);
1cd6e20d 5730}
5731
5732/* Expand the __atomic_signal_fence intrinsic:
5733 void __atomic_signal_fence (enum memmodel)
5734 EXP is the CALL_EXPR. */
5735
5736static void
5737expand_builtin_atomic_signal_fence (tree exp)
5738{
fe54c06b 5739 enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
5740 expand_mem_signal_fence (model);
b6a5fc45 5741}
5742
5743/* Expand the __sync_synchronize intrinsic. */
5744
5745static void
2797f13a 5746expand_builtin_sync_synchronize (void)
b6a5fc45 5747{
fe54c06b 5748 expand_mem_thread_fence (MEMMODEL_SEQ_CST);
b6a5fc45 5749}
5750
badaa04c 5751static rtx
5752expand_builtin_thread_pointer (tree exp, rtx target)
5753{
5754 enum insn_code icode;
5755 if (!validate_arglist (exp, VOID_TYPE))
5756 return const0_rtx;
5757 icode = direct_optab_handler (get_thread_pointer_optab, Pmode);
5758 if (icode != CODE_FOR_nothing)
5759 {
5760 struct expand_operand op;
5761 if (!REG_P (target) || GET_MODE (target) != Pmode)
5762 target = gen_reg_rtx (Pmode);
5763 create_output_operand (&op, target, Pmode);
5764 expand_insn (icode, 1, &op);
5765 return target;
5766 }
5767 error ("__builtin_thread_pointer is not supported on this target");
5768 return const0_rtx;
5769}
5770
5771static void
5772expand_builtin_set_thread_pointer (tree exp)
5773{
5774 enum insn_code icode;
5775 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
5776 return;
5777 icode = direct_optab_handler (set_thread_pointer_optab, Pmode);
5778 if (icode != CODE_FOR_nothing)
5779 {
5780 struct expand_operand op;
5781 rtx val = expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX,
5782 Pmode, EXPAND_NORMAL);
6f343c10 5783 create_input_operand (&op, val, Pmode);
badaa04c 5784 expand_insn (icode, 1, &op);
5785 return;
5786 }
5787 error ("__builtin_set_thread_pointer is not supported on this target");
5788}
5789
53800dbe 5790\f
5791/* Expand an expression EXP that calls a built-in function,
5792 with result going to TARGET if that's convenient
5793 (and in mode MODE if that's convenient).
5794 SUBTARGET may be used as the target for computing one of EXP's operands.
5795 IGNORE is nonzero if the value is to be ignored. */
5796
5797rtx
aecda0d6 5798expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
5799 int ignore)
53800dbe 5800{
c6e6ecb1 5801 tree fndecl = get_callee_fndecl (exp);
53800dbe 5802 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
efb070c8 5803 enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
67fa4078 5804 int flags;
53800dbe 5805
8305149e 5806 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
883b2e73 5807 return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
bf8e3599 5808
53800dbe 5809 /* When not optimizing, generate calls to library functions for a certain
5810 set of builtins. */
cd9ff771 5811 if (!optimize
b6a5fc45 5812 && !called_as_built_in (fndecl)
2c281b15 5813 && fcode != BUILT_IN_ALLOCA
581bf1c2 5814 && fcode != BUILT_IN_ALLOCA_WITH_ALIGN
2c281b15 5815 && fcode != BUILT_IN_FREE)
cd9ff771 5816 return expand_call (exp, target, ignore);
53800dbe 5817
8d6d7930 5818 /* The built-in function expanders test for target == const0_rtx
5819 to determine whether the function's result will be ignored. */
5820 if (ignore)
5821 target = const0_rtx;
5822
5823 /* If the result of a pure or const built-in function is ignored, and
5824 none of its arguments are volatile, we can avoid expanding the
5825 built-in call and just evaluate the arguments for side-effects. */
5826 if (target == const0_rtx
67fa4078 5827 && ((flags = flags_from_decl_or_type (fndecl)) & (ECF_CONST | ECF_PURE))
5828 && !(flags & ECF_LOOPING_CONST_OR_PURE))
8d6d7930 5829 {
5830 bool volatilep = false;
5831 tree arg;
c2f47e15 5832 call_expr_arg_iterator iter;
8d6d7930 5833
c2f47e15 5834 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5835 if (TREE_THIS_VOLATILE (arg))
8d6d7930 5836 {
5837 volatilep = true;
5838 break;
5839 }
5840
5841 if (! volatilep)
5842 {
c2f47e15 5843 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
5844 expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
8d6d7930 5845 return const0_rtx;
5846 }
5847 }
5848
53800dbe 5849 switch (fcode)
5850 {
4f35b1fc 5851 CASE_FLT_FN (BUILT_IN_FABS):
c2f47e15 5852 target = expand_builtin_fabs (exp, target, subtarget);
78a74442 5853 if (target)
a0c938f0 5854 return target;
78a74442 5855 break;
5856
4f35b1fc 5857 CASE_FLT_FN (BUILT_IN_COPYSIGN):
c2f47e15 5858 target = expand_builtin_copysign (exp, target, subtarget);
270436f3 5859 if (target)
5860 return target;
5861 break;
5862
7d3f6cc7 5863 /* Just do a normal library call if we were unable to fold
5864 the values. */
4f35b1fc 5865 CASE_FLT_FN (BUILT_IN_CABS):
78a74442 5866 break;
53800dbe 5867
4f35b1fc 5868 CASE_FLT_FN (BUILT_IN_EXP):
5869 CASE_FLT_FN (BUILT_IN_EXP10):
5870 CASE_FLT_FN (BUILT_IN_POW10):
5871 CASE_FLT_FN (BUILT_IN_EXP2):
5872 CASE_FLT_FN (BUILT_IN_EXPM1):
5873 CASE_FLT_FN (BUILT_IN_LOGB):
4f35b1fc 5874 CASE_FLT_FN (BUILT_IN_LOG):
5875 CASE_FLT_FN (BUILT_IN_LOG10):
5876 CASE_FLT_FN (BUILT_IN_LOG2):
5877 CASE_FLT_FN (BUILT_IN_LOG1P):
5878 CASE_FLT_FN (BUILT_IN_TAN):
5879 CASE_FLT_FN (BUILT_IN_ASIN):
5880 CASE_FLT_FN (BUILT_IN_ACOS):
5881 CASE_FLT_FN (BUILT_IN_ATAN):
b3154a1f 5882 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
7f3be425 5883 /* Treat these like sqrt only if unsafe math optimizations are allowed,
5884 because of possible accuracy problems. */
5885 if (! flag_unsafe_math_optimizations)
53800dbe 5886 break;
4f35b1fc 5887 CASE_FLT_FN (BUILT_IN_SQRT):
5888 CASE_FLT_FN (BUILT_IN_FLOOR):
5889 CASE_FLT_FN (BUILT_IN_CEIL):
5890 CASE_FLT_FN (BUILT_IN_TRUNC):
5891 CASE_FLT_FN (BUILT_IN_ROUND):
5892 CASE_FLT_FN (BUILT_IN_NEARBYINT):
5893 CASE_FLT_FN (BUILT_IN_RINT):
53800dbe 5894 target = expand_builtin_mathfn (exp, target, subtarget);
5895 if (target)
5896 return target;
5897 break;
5898
7e0713b1 5899 CASE_FLT_FN (BUILT_IN_FMA):
5900 target = expand_builtin_mathfn_ternary (exp, target, subtarget);
5901 if (target)
5902 return target;
5903 break;
5904
a67a90e5 5905 CASE_FLT_FN (BUILT_IN_ILOGB):
5906 if (! flag_unsafe_math_optimizations)
5907 break;
69b779ea 5908 CASE_FLT_FN (BUILT_IN_ISINF):
cde061c1 5909 CASE_FLT_FN (BUILT_IN_FINITE):
5910 case BUILT_IN_ISFINITE:
8a1a9cb7 5911 case BUILT_IN_ISNORMAL:
f97eea22 5912 target = expand_builtin_interclass_mathfn (exp, target);
a67a90e5 5913 if (target)
5914 return target;
5915 break;
5916
80ff6494 5917 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 5918 CASE_FLT_FN (BUILT_IN_LCEIL):
5919 CASE_FLT_FN (BUILT_IN_LLCEIL):
5920 CASE_FLT_FN (BUILT_IN_LFLOOR):
80ff6494 5921 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 5922 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ff1b14e4 5923 target = expand_builtin_int_roundingfn (exp, target);
ad52b9b7 5924 if (target)
5925 return target;
5926 break;
5927
80ff6494 5928 CASE_FLT_FN (BUILT_IN_IRINT):
7d3afc77 5929 CASE_FLT_FN (BUILT_IN_LRINT):
5930 CASE_FLT_FN (BUILT_IN_LLRINT):
80ff6494 5931 CASE_FLT_FN (BUILT_IN_IROUND):
ef2f1a10 5932 CASE_FLT_FN (BUILT_IN_LROUND):
5933 CASE_FLT_FN (BUILT_IN_LLROUND):
ff1b14e4 5934 target = expand_builtin_int_roundingfn_2 (exp, target);
7d3afc77 5935 if (target)
5936 return target;
5937 break;
5938
4f35b1fc 5939 CASE_FLT_FN (BUILT_IN_POWI):
f97eea22 5940 target = expand_builtin_powi (exp, target);
757c219d 5941 if (target)
5942 return target;
5943 break;
5944
4f35b1fc 5945 CASE_FLT_FN (BUILT_IN_ATAN2):
5946 CASE_FLT_FN (BUILT_IN_LDEXP):
73a954a1 5947 CASE_FLT_FN (BUILT_IN_SCALB):
5948 CASE_FLT_FN (BUILT_IN_SCALBN):
5949 CASE_FLT_FN (BUILT_IN_SCALBLN):
0fd605a5 5950 if (! flag_unsafe_math_optimizations)
5951 break;
ef722005 5952
5953 CASE_FLT_FN (BUILT_IN_FMOD):
5954 CASE_FLT_FN (BUILT_IN_REMAINDER):
5955 CASE_FLT_FN (BUILT_IN_DREM):
0810ff17 5956 CASE_FLT_FN (BUILT_IN_POW):
0fd605a5 5957 target = expand_builtin_mathfn_2 (exp, target, subtarget);
5958 if (target)
5959 return target;
5960 break;
5961
d735c391 5962 CASE_FLT_FN (BUILT_IN_CEXPI):
f97eea22 5963 target = expand_builtin_cexpi (exp, target);
d735c391 5964 gcc_assert (target);
5965 return target;
5966
4f35b1fc 5967 CASE_FLT_FN (BUILT_IN_SIN):
5968 CASE_FLT_FN (BUILT_IN_COS):
6b43bae4 5969 if (! flag_unsafe_math_optimizations)
5970 break;
5971 target = expand_builtin_mathfn_3 (exp, target, subtarget);
5972 if (target)
5973 return target;
5974 break;
5975
c3147c1a 5976 CASE_FLT_FN (BUILT_IN_SINCOS):
5977 if (! flag_unsafe_math_optimizations)
5978 break;
5979 target = expand_builtin_sincos (exp);
5980 if (target)
5981 return target;
5982 break;
5983
53800dbe 5984 case BUILT_IN_APPLY_ARGS:
5985 return expand_builtin_apply_args ();
5986
5987 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
5988 FUNCTION with a copy of the parameters described by
5989 ARGUMENTS, and ARGSIZE. It returns a block of memory
5990 allocated on the stack into which is stored all the registers
5991 that might possibly be used for returning the result of a
5992 function. ARGUMENTS is the value returned by
5993 __builtin_apply_args. ARGSIZE is the number of bytes of
5994 arguments that must be copied. ??? How should this value be
5995 computed? We'll also need a safe worst case value for varargs
5996 functions. */
5997 case BUILT_IN_APPLY:
c2f47e15 5998 if (!validate_arglist (exp, POINTER_TYPE,
0eb671f7 5999 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
c2f47e15 6000 && !validate_arglist (exp, REFERENCE_TYPE,
0eb671f7 6001 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 6002 return const0_rtx;
6003 else
6004 {
53800dbe 6005 rtx ops[3];
6006
c2f47e15 6007 ops[0] = expand_normal (CALL_EXPR_ARG (exp, 0));
6008 ops[1] = expand_normal (CALL_EXPR_ARG (exp, 1));
6009 ops[2] = expand_normal (CALL_EXPR_ARG (exp, 2));
53800dbe 6010
6011 return expand_builtin_apply (ops[0], ops[1], ops[2]);
6012 }
6013
6014 /* __builtin_return (RESULT) causes the function to return the
6015 value described by RESULT. RESULT is address of the block of
6016 memory returned by __builtin_apply. */
6017 case BUILT_IN_RETURN:
c2f47e15 6018 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
6019 expand_builtin_return (expand_normal (CALL_EXPR_ARG (exp, 0)));
53800dbe 6020 return const0_rtx;
6021
6022 case BUILT_IN_SAVEREGS:
a66c9326 6023 return expand_builtin_saveregs ();
53800dbe 6024
48dc2227 6025 case BUILT_IN_VA_ARG_PACK:
6026 /* All valid uses of __builtin_va_arg_pack () are removed during
6027 inlining. */
b8c23db3 6028 error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
48dc2227 6029 return const0_rtx;
6030
4e1d7ea4 6031 case BUILT_IN_VA_ARG_PACK_LEN:
6032 /* All valid uses of __builtin_va_arg_pack_len () are removed during
6033 inlining. */
b8c23db3 6034 error ("%Kinvalid use of %<__builtin_va_arg_pack_len ()%>", exp);
4e1d7ea4 6035 return const0_rtx;
6036
53800dbe 6037 /* Return the address of the first anonymous stack arg. */
6038 case BUILT_IN_NEXT_ARG:
c2f47e15 6039 if (fold_builtin_next_arg (exp, false))
a0c938f0 6040 return const0_rtx;
79012a9d 6041 return expand_builtin_next_arg ();
53800dbe 6042
ac8fb6db 6043 case BUILT_IN_CLEAR_CACHE:
6044 target = expand_builtin___clear_cache (exp);
6045 if (target)
6046 return target;
6047 break;
6048
53800dbe 6049 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 6050 return expand_builtin_classify_type (exp);
53800dbe 6051
6052 case BUILT_IN_CONSTANT_P:
4ee9c684 6053 return const0_rtx;
53800dbe 6054
6055 case BUILT_IN_FRAME_ADDRESS:
6056 case BUILT_IN_RETURN_ADDRESS:
c2f47e15 6057 return expand_builtin_frame_address (fndecl, exp);
53800dbe 6058
6059 /* Returns the address of the area where the structure is returned.
6060 0 otherwise. */
6061 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
c2f47e15 6062 if (call_expr_nargs (exp) != 0
9342ee68 6063 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
e16ceb8e 6064 || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
9342ee68 6065 return const0_rtx;
53800dbe 6066 else
9342ee68 6067 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
53800dbe 6068
6069 case BUILT_IN_ALLOCA:
581bf1c2 6070 case BUILT_IN_ALLOCA_WITH_ALIGN:
990495a7 6071 /* If the allocation stems from the declaration of a variable-sized
6072 object, it cannot accumulate. */
a882d754 6073 target = expand_builtin_alloca (exp, CALL_ALLOCA_FOR_VAR_P (exp));
53800dbe 6074 if (target)
6075 return target;
6076 break;
6077
4ee9c684 6078 case BUILT_IN_STACK_SAVE:
6079 return expand_stack_save ();
6080
6081 case BUILT_IN_STACK_RESTORE:
c2f47e15 6082 expand_stack_restore (CALL_EXPR_ARG (exp, 0));
4ee9c684 6083 return const0_rtx;
6084
74bdbe96 6085 case BUILT_IN_BSWAP16:
42791117 6086 case BUILT_IN_BSWAP32:
6087 case BUILT_IN_BSWAP64:
74bdbe96 6088 target = expand_builtin_bswap (target_mode, exp, target, subtarget);
42791117 6089 if (target)
6090 return target;
6091 break;
6092
4f35b1fc 6093 CASE_INT_FN (BUILT_IN_FFS):
5053259b 6094 case BUILT_IN_FFSIMAX:
c2f47e15 6095 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6096 subtarget, ffs_optab);
6a08d0ab 6097 if (target)
6098 return target;
6099 break;
6100
4f35b1fc 6101 CASE_INT_FN (BUILT_IN_CLZ):
5053259b 6102 case BUILT_IN_CLZIMAX:
c2f47e15 6103 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6104 subtarget, clz_optab);
6a08d0ab 6105 if (target)
6106 return target;
6107 break;
6108
4f35b1fc 6109 CASE_INT_FN (BUILT_IN_CTZ):
5053259b 6110 case BUILT_IN_CTZIMAX:
c2f47e15 6111 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6112 subtarget, ctz_optab);
6a08d0ab 6113 if (target)
6114 return target;
6115 break;
6116
d8492bd3 6117 CASE_INT_FN (BUILT_IN_CLRSB):
6118 case BUILT_IN_CLRSBIMAX:
6119 target = expand_builtin_unop (target_mode, exp, target,
6120 subtarget, clrsb_optab);
6121 if (target)
6122 return target;
6123 break;
6124
4f35b1fc 6125 CASE_INT_FN (BUILT_IN_POPCOUNT):
5053259b 6126 case BUILT_IN_POPCOUNTIMAX:
c2f47e15 6127 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6128 subtarget, popcount_optab);
6a08d0ab 6129 if (target)
6130 return target;
6131 break;
6132
4f35b1fc 6133 CASE_INT_FN (BUILT_IN_PARITY):
5053259b 6134 case BUILT_IN_PARITYIMAX:
c2f47e15 6135 target = expand_builtin_unop (target_mode, exp, target,
efb070c8 6136 subtarget, parity_optab);
53800dbe 6137 if (target)
6138 return target;
6139 break;
6140
6141 case BUILT_IN_STRLEN:
c2f47e15 6142 target = expand_builtin_strlen (exp, target, target_mode);
53800dbe 6143 if (target)
6144 return target;
6145 break;
6146
6147 case BUILT_IN_STRCPY:
a65c4d64 6148 target = expand_builtin_strcpy (exp, target);
53800dbe 6149 if (target)
6150 return target;
6151 break;
bf8e3599 6152
ed09096d 6153 case BUILT_IN_STRNCPY:
a65c4d64 6154 target = expand_builtin_strncpy (exp, target);
ed09096d 6155 if (target)
6156 return target;
6157 break;
bf8e3599 6158
3b824fa6 6159 case BUILT_IN_STPCPY:
dc369150 6160 target = expand_builtin_stpcpy (exp, target, mode);
3b824fa6 6161 if (target)
6162 return target;
6163 break;
6164
53800dbe 6165 case BUILT_IN_MEMCPY:
a65c4d64 6166 target = expand_builtin_memcpy (exp, target);
3b824fa6 6167 if (target)
6168 return target;
6169 break;
6170
6171 case BUILT_IN_MEMPCPY:
c2f47e15 6172 target = expand_builtin_mempcpy (exp, target, mode);
53800dbe 6173 if (target)
6174 return target;
6175 break;
6176
6177 case BUILT_IN_MEMSET:
c2f47e15 6178 target = expand_builtin_memset (exp, target, mode);
53800dbe 6179 if (target)
6180 return target;
6181 break;
6182
ffc83088 6183 case BUILT_IN_BZERO:
0b25db21 6184 target = expand_builtin_bzero (exp);
ffc83088 6185 if (target)
6186 return target;
6187 break;
6188
53800dbe 6189 case BUILT_IN_STRCMP:
a65c4d64 6190 target = expand_builtin_strcmp (exp, target);
53800dbe 6191 if (target)
6192 return target;
6193 break;
6194
ed09096d 6195 case BUILT_IN_STRNCMP:
6196 target = expand_builtin_strncmp (exp, target, mode);
6197 if (target)
6198 return target;
6199 break;
6200
071f1696 6201 case BUILT_IN_BCMP:
53800dbe 6202 case BUILT_IN_MEMCMP:
c2f47e15 6203 target = expand_builtin_memcmp (exp, target, mode);
53800dbe 6204 if (target)
6205 return target;
6206 break;
53800dbe 6207
6208 case BUILT_IN_SETJMP:
2c8a1497 6209 /* This should have been lowered to the builtins below. */
6210 gcc_unreachable ();
6211
6212 case BUILT_IN_SETJMP_SETUP:
6213 /* __builtin_setjmp_setup is passed a pointer to an array of five words
6214 and the receiver label. */
c2f47e15 6215 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2c8a1497 6216 {
c2f47e15 6217 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
2c8a1497 6218 VOIDmode, EXPAND_NORMAL);
c2f47e15 6219 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
2c8a1497 6220 rtx label_r = label_rtx (label);
6221
6222 /* This is copied from the handling of non-local gotos. */
6223 expand_builtin_setjmp_setup (buf_addr, label_r);
6224 nonlocal_goto_handler_labels
6225 = gen_rtx_EXPR_LIST (VOIDmode, label_r,
6226 nonlocal_goto_handler_labels);
6227 /* ??? Do not let expand_label treat us as such since we would
6228 not want to be both on the list of non-local labels and on
6229 the list of forced labels. */
6230 FORCED_LABEL (label) = 0;
6231 return const0_rtx;
6232 }
6233 break;
6234
6235 case BUILT_IN_SETJMP_DISPATCHER:
6236 /* __builtin_setjmp_dispatcher is passed the dispatcher label. */
c2f47e15 6237 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6238 {
c2f47e15 6239 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6240 rtx label_r = label_rtx (label);
6241
6242 /* Remove the dispatcher label from the list of non-local labels
6243 since the receiver labels have been added to it above. */
6244 remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels);
6245 return const0_rtx;
6246 }
6247 break;
6248
6249 case BUILT_IN_SETJMP_RECEIVER:
6250 /* __builtin_setjmp_receiver is passed the receiver label. */
c2f47e15 6251 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
2c8a1497 6252 {
c2f47e15 6253 tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
2c8a1497 6254 rtx label_r = label_rtx (label);
6255
6256 expand_builtin_setjmp_receiver (label_r);
6257 return const0_rtx;
6258 }
6b7f6858 6259 break;
53800dbe 6260
6261 /* __builtin_longjmp is passed a pointer to an array of five words.
6262 It's similar to the C library longjmp function but works with
6263 __builtin_setjmp above. */
6264 case BUILT_IN_LONGJMP:
c2f47e15 6265 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 6266 {
c2f47e15 6267 rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
8ec3c5c2 6268 VOIDmode, EXPAND_NORMAL);
c2f47e15 6269 rtx value = expand_normal (CALL_EXPR_ARG (exp, 1));
53800dbe 6270
6271 if (value != const1_rtx)
6272 {
1e5fcbe2 6273 error ("%<__builtin_longjmp%> second argument must be 1");
53800dbe 6274 return const0_rtx;
6275 }
6276
6277 expand_builtin_longjmp (buf_addr, value);
6278 return const0_rtx;
6279 }
2c8a1497 6280 break;
53800dbe 6281
4ee9c684 6282 case BUILT_IN_NONLOCAL_GOTO:
c2f47e15 6283 target = expand_builtin_nonlocal_goto (exp);
4ee9c684 6284 if (target)
6285 return target;
6286 break;
6287
843d08a9 6288 /* This updates the setjmp buffer that is its argument with the value
6289 of the current stack pointer. */
6290 case BUILT_IN_UPDATE_SETJMP_BUF:
c2f47e15 6291 if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
843d08a9 6292 {
6293 rtx buf_addr
c2f47e15 6294 = expand_normal (CALL_EXPR_ARG (exp, 0));
843d08a9 6295
6296 expand_builtin_update_setjmp_buf (buf_addr);
6297 return const0_rtx;
6298 }
6299 break;
6300
53800dbe 6301 case BUILT_IN_TRAP:
a0ef1725 6302 expand_builtin_trap ();
53800dbe 6303 return const0_rtx;
6304
d2b48f0c 6305 case BUILT_IN_UNREACHABLE:
6306 expand_builtin_unreachable ();
6307 return const0_rtx;
6308
4f35b1fc 6309 CASE_FLT_FN (BUILT_IN_SIGNBIT):
004e23c4 6310 case BUILT_IN_SIGNBITD32:
6311 case BUILT_IN_SIGNBITD64:
6312 case BUILT_IN_SIGNBITD128:
27f261ef 6313 target = expand_builtin_signbit (exp, target);
6314 if (target)
6315 return target;
6316 break;
6317
53800dbe 6318 /* Various hooks for the DWARF 2 __throw routine. */
6319 case BUILT_IN_UNWIND_INIT:
6320 expand_builtin_unwind_init ();
6321 return const0_rtx;
6322 case BUILT_IN_DWARF_CFA:
6323 return virtual_cfa_rtx;
6324#ifdef DWARF2_UNWIND_INFO
f8f023a5 6325 case BUILT_IN_DWARF_SP_COLUMN:
6326 return expand_builtin_dwarf_sp_column ();
695e919b 6327 case BUILT_IN_INIT_DWARF_REG_SIZES:
c2f47e15 6328 expand_builtin_init_dwarf_reg_sizes (CALL_EXPR_ARG (exp, 0));
695e919b 6329 return const0_rtx;
53800dbe 6330#endif
6331 case BUILT_IN_FROB_RETURN_ADDR:
c2f47e15 6332 return expand_builtin_frob_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6333 case BUILT_IN_EXTRACT_RETURN_ADDR:
c2f47e15 6334 return expand_builtin_extract_return_addr (CALL_EXPR_ARG (exp, 0));
53800dbe 6335 case BUILT_IN_EH_RETURN:
c2f47e15 6336 expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
6337 CALL_EXPR_ARG (exp, 1));
53800dbe 6338 return const0_rtx;
df4b504c 6339#ifdef EH_RETURN_DATA_REGNO
6340 case BUILT_IN_EH_RETURN_DATA_REGNO:
c2f47e15 6341 return expand_builtin_eh_return_data_regno (exp);
df4b504c 6342#endif
26093bf4 6343 case BUILT_IN_EXTEND_POINTER:
c2f47e15 6344 return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
e38def9c 6345 case BUILT_IN_EH_POINTER:
6346 return expand_builtin_eh_pointer (exp);
6347 case BUILT_IN_EH_FILTER:
6348 return expand_builtin_eh_filter (exp);
6349 case BUILT_IN_EH_COPY_VALUES:
6350 return expand_builtin_eh_copy_values (exp);
26093bf4 6351
7ccc713a 6352 case BUILT_IN_VA_START:
c2f47e15 6353 return expand_builtin_va_start (exp);
a66c9326 6354 case BUILT_IN_VA_END:
c2f47e15 6355 return expand_builtin_va_end (exp);
a66c9326 6356 case BUILT_IN_VA_COPY:
c2f47e15 6357 return expand_builtin_va_copy (exp);
89cfe6e5 6358 case BUILT_IN_EXPECT:
c2f47e15 6359 return expand_builtin_expect (exp, target);
fca0886c 6360 case BUILT_IN_ASSUME_ALIGNED:
6361 return expand_builtin_assume_aligned (exp, target);
5e3608d8 6362 case BUILT_IN_PREFETCH:
c2f47e15 6363 expand_builtin_prefetch (exp);
5e3608d8 6364 return const0_rtx;
6365
4ee9c684 6366 case BUILT_IN_INIT_TRAMPOLINE:
c307f106 6367 return expand_builtin_init_trampoline (exp, true);
6368 case BUILT_IN_INIT_HEAP_TRAMPOLINE:
6369 return expand_builtin_init_trampoline (exp, false);
4ee9c684 6370 case BUILT_IN_ADJUST_TRAMPOLINE:
c2f47e15 6371 return expand_builtin_adjust_trampoline (exp);
4ee9c684 6372
73673831 6373 case BUILT_IN_FORK:
6374 case BUILT_IN_EXECL:
6375 case BUILT_IN_EXECV:
6376 case BUILT_IN_EXECLP:
6377 case BUILT_IN_EXECLE:
6378 case BUILT_IN_EXECVP:
6379 case BUILT_IN_EXECVE:
c2f47e15 6380 target = expand_builtin_fork_or_exec (fndecl, exp, target, ignore);
73673831 6381 if (target)
6382 return target;
6383 break;
53800dbe 6384
2797f13a 6385 case BUILT_IN_SYNC_FETCH_AND_ADD_1:
6386 case BUILT_IN_SYNC_FETCH_AND_ADD_2:
6387 case BUILT_IN_SYNC_FETCH_AND_ADD_4:
6388 case BUILT_IN_SYNC_FETCH_AND_ADD_8:
6389 case BUILT_IN_SYNC_FETCH_AND_ADD_16:
6390 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_ADD_1);
1cd6e20d 6391 target = expand_builtin_sync_operation (mode, exp, PLUS, false, target);
b6a5fc45 6392 if (target)
6393 return target;
6394 break;
6395
2797f13a 6396 case BUILT_IN_SYNC_FETCH_AND_SUB_1:
6397 case BUILT_IN_SYNC_FETCH_AND_SUB_2:
6398 case BUILT_IN_SYNC_FETCH_AND_SUB_4:
6399 case BUILT_IN_SYNC_FETCH_AND_SUB_8:
6400 case BUILT_IN_SYNC_FETCH_AND_SUB_16:
6401 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_SUB_1);
1cd6e20d 6402 target = expand_builtin_sync_operation (mode, exp, MINUS, false, target);
b6a5fc45 6403 if (target)
6404 return target;
6405 break;
6406
2797f13a 6407 case BUILT_IN_SYNC_FETCH_AND_OR_1:
6408 case BUILT_IN_SYNC_FETCH_AND_OR_2:
6409 case BUILT_IN_SYNC_FETCH_AND_OR_4:
6410 case BUILT_IN_SYNC_FETCH_AND_OR_8:
6411 case BUILT_IN_SYNC_FETCH_AND_OR_16:
6412 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_OR_1);
1cd6e20d 6413 target = expand_builtin_sync_operation (mode, exp, IOR, false, target);
b6a5fc45 6414 if (target)
6415 return target;
6416 break;
6417
2797f13a 6418 case BUILT_IN_SYNC_FETCH_AND_AND_1:
6419 case BUILT_IN_SYNC_FETCH_AND_AND_2:
6420 case BUILT_IN_SYNC_FETCH_AND_AND_4:
6421 case BUILT_IN_SYNC_FETCH_AND_AND_8:
6422 case BUILT_IN_SYNC_FETCH_AND_AND_16:
6423 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_AND_1);
1cd6e20d 6424 target = expand_builtin_sync_operation (mode, exp, AND, false, target);
b6a5fc45 6425 if (target)
6426 return target;
6427 break;
6428
2797f13a 6429 case BUILT_IN_SYNC_FETCH_AND_XOR_1:
6430 case BUILT_IN_SYNC_FETCH_AND_XOR_2:
6431 case BUILT_IN_SYNC_FETCH_AND_XOR_4:
6432 case BUILT_IN_SYNC_FETCH_AND_XOR_8:
6433 case BUILT_IN_SYNC_FETCH_AND_XOR_16:
6434 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_XOR_1);
1cd6e20d 6435 target = expand_builtin_sync_operation (mode, exp, XOR, false, target);
b6a5fc45 6436 if (target)
6437 return target;
6438 break;
6439
2797f13a 6440 case BUILT_IN_SYNC_FETCH_AND_NAND_1:
6441 case BUILT_IN_SYNC_FETCH_AND_NAND_2:
6442 case BUILT_IN_SYNC_FETCH_AND_NAND_4:
6443 case BUILT_IN_SYNC_FETCH_AND_NAND_8:
6444 case BUILT_IN_SYNC_FETCH_AND_NAND_16:
6445 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_FETCH_AND_NAND_1);
1cd6e20d 6446 target = expand_builtin_sync_operation (mode, exp, NOT, false, target);
b6a5fc45 6447 if (target)
6448 return target;
6449 break;
6450
2797f13a 6451 case BUILT_IN_SYNC_ADD_AND_FETCH_1:
6452 case BUILT_IN_SYNC_ADD_AND_FETCH_2:
6453 case BUILT_IN_SYNC_ADD_AND_FETCH_4:
6454 case BUILT_IN_SYNC_ADD_AND_FETCH_8:
6455 case BUILT_IN_SYNC_ADD_AND_FETCH_16:
6456 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_ADD_AND_FETCH_1);
1cd6e20d 6457 target = expand_builtin_sync_operation (mode, exp, PLUS, true, target);
b6a5fc45 6458 if (target)
6459 return target;
6460 break;
6461
2797f13a 6462 case BUILT_IN_SYNC_SUB_AND_FETCH_1:
6463 case BUILT_IN_SYNC_SUB_AND_FETCH_2:
6464 case BUILT_IN_SYNC_SUB_AND_FETCH_4:
6465 case BUILT_IN_SYNC_SUB_AND_FETCH_8:
6466 case BUILT_IN_SYNC_SUB_AND_FETCH_16:
6467 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_SUB_AND_FETCH_1);
1cd6e20d 6468 target = expand_builtin_sync_operation (mode, exp, MINUS, true, target);
b6a5fc45 6469 if (target)
6470 return target;
6471 break;
6472
2797f13a 6473 case BUILT_IN_SYNC_OR_AND_FETCH_1:
6474 case BUILT_IN_SYNC_OR_AND_FETCH_2:
6475 case BUILT_IN_SYNC_OR_AND_FETCH_4:
6476 case BUILT_IN_SYNC_OR_AND_FETCH_8:
6477 case BUILT_IN_SYNC_OR_AND_FETCH_16:
6478 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_OR_AND_FETCH_1);
1cd6e20d 6479 target = expand_builtin_sync_operation (mode, exp, IOR, true, target);
b6a5fc45 6480 if (target)
6481 return target;
6482 break;
6483
2797f13a 6484 case BUILT_IN_SYNC_AND_AND_FETCH_1:
6485 case BUILT_IN_SYNC_AND_AND_FETCH_2:
6486 case BUILT_IN_SYNC_AND_AND_FETCH_4:
6487 case BUILT_IN_SYNC_AND_AND_FETCH_8:
6488 case BUILT_IN_SYNC_AND_AND_FETCH_16:
6489 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_AND_AND_FETCH_1);
1cd6e20d 6490 target = expand_builtin_sync_operation (mode, exp, AND, true, target);
b6a5fc45 6491 if (target)
6492 return target;
6493 break;
6494
2797f13a 6495 case BUILT_IN_SYNC_XOR_AND_FETCH_1:
6496 case BUILT_IN_SYNC_XOR_AND_FETCH_2:
6497 case BUILT_IN_SYNC_XOR_AND_FETCH_4:
6498 case BUILT_IN_SYNC_XOR_AND_FETCH_8:
6499 case BUILT_IN_SYNC_XOR_AND_FETCH_16:
6500 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_XOR_AND_FETCH_1);
1cd6e20d 6501 target = expand_builtin_sync_operation (mode, exp, XOR, true, target);
b6a5fc45 6502 if (target)
6503 return target;
6504 break;
6505
2797f13a 6506 case BUILT_IN_SYNC_NAND_AND_FETCH_1:
6507 case BUILT_IN_SYNC_NAND_AND_FETCH_2:
6508 case BUILT_IN_SYNC_NAND_AND_FETCH_4:
6509 case BUILT_IN_SYNC_NAND_AND_FETCH_8:
6510 case BUILT_IN_SYNC_NAND_AND_FETCH_16:
6511 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_NAND_AND_FETCH_1);
1cd6e20d 6512 target = expand_builtin_sync_operation (mode, exp, NOT, true, target);
b6a5fc45 6513 if (target)
6514 return target;
6515 break;
6516
2797f13a 6517 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
6518 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
6519 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
6520 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
6521 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16:
a601d32a 6522 if (mode == VOIDmode)
6523 mode = TYPE_MODE (boolean_type_node);
b6a5fc45 6524 if (!target || !register_operand (target, mode))
6525 target = gen_reg_rtx (mode);
3e272de8 6526
2797f13a 6527 mode = get_builtin_sync_mode
6528 (fcode - BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1);
c2f47e15 6529 target = expand_builtin_compare_and_swap (mode, exp, true, target);
b6a5fc45 6530 if (target)
6531 return target;
6532 break;
6533
2797f13a 6534 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
6535 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
6536 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
6537 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
6538 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
6539 mode = get_builtin_sync_mode
6540 (fcode - BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1);
c2f47e15 6541 target = expand_builtin_compare_and_swap (mode, exp, false, target);
b6a5fc45 6542 if (target)
6543 return target;
6544 break;
6545
2797f13a 6546 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
6547 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
6548 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
6549 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
6550 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16:
6551 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_TEST_AND_SET_1);
6552 target = expand_builtin_sync_lock_test_and_set (mode, exp, target);
b6a5fc45 6553 if (target)
6554 return target;
6555 break;
6556
2797f13a 6557 case BUILT_IN_SYNC_LOCK_RELEASE_1:
6558 case BUILT_IN_SYNC_LOCK_RELEASE_2:
6559 case BUILT_IN_SYNC_LOCK_RELEASE_4:
6560 case BUILT_IN_SYNC_LOCK_RELEASE_8:
6561 case BUILT_IN_SYNC_LOCK_RELEASE_16:
6562 mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_LOCK_RELEASE_1);
6563 expand_builtin_sync_lock_release (mode, exp);
b6a5fc45 6564 return const0_rtx;
6565
2797f13a 6566 case BUILT_IN_SYNC_SYNCHRONIZE:
6567 expand_builtin_sync_synchronize ();
b6a5fc45 6568 return const0_rtx;
6569
1cd6e20d 6570 case BUILT_IN_ATOMIC_EXCHANGE_1:
6571 case BUILT_IN_ATOMIC_EXCHANGE_2:
6572 case BUILT_IN_ATOMIC_EXCHANGE_4:
6573 case BUILT_IN_ATOMIC_EXCHANGE_8:
6574 case BUILT_IN_ATOMIC_EXCHANGE_16:
6575 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_EXCHANGE_1);
6576 target = expand_builtin_atomic_exchange (mode, exp, target);
6577 if (target)
6578 return target;
6579 break;
6580
6581 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1:
6582 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2:
6583 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4:
6584 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8:
6585 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
2c201ad1 6586 {
6587 unsigned int nargs, z;
f1f41a6c 6588 vec<tree, va_gc> *vec;
2c201ad1 6589
6590 mode =
6591 get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1);
6592 target = expand_builtin_atomic_compare_exchange (mode, exp, target);
6593 if (target)
6594 return target;
6595
6596 /* If this is turned into an external library call, the weak parameter
6597 must be dropped to match the expected parameter list. */
6598 nargs = call_expr_nargs (exp);
f1f41a6c 6599 vec_alloc (vec, nargs - 1);
2c201ad1 6600 for (z = 0; z < 3; z++)
f1f41a6c 6601 vec->quick_push (CALL_EXPR_ARG (exp, z));
2c201ad1 6602 /* Skip the boolean weak parameter. */
6603 for (z = 4; z < 6; z++)
f1f41a6c 6604 vec->quick_push (CALL_EXPR_ARG (exp, z));
2c201ad1 6605 exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), vec);
6606 break;
6607 }
1cd6e20d 6608
6609 case BUILT_IN_ATOMIC_LOAD_1:
6610 case BUILT_IN_ATOMIC_LOAD_2:
6611 case BUILT_IN_ATOMIC_LOAD_4:
6612 case BUILT_IN_ATOMIC_LOAD_8:
6613 case BUILT_IN_ATOMIC_LOAD_16:
6614 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_LOAD_1);
6615 target = expand_builtin_atomic_load (mode, exp, target);
6616 if (target)
6617 return target;
6618 break;
6619
6620 case BUILT_IN_ATOMIC_STORE_1:
6621 case BUILT_IN_ATOMIC_STORE_2:
6622 case BUILT_IN_ATOMIC_STORE_4:
6623 case BUILT_IN_ATOMIC_STORE_8:
6624 case BUILT_IN_ATOMIC_STORE_16:
6625 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_STORE_1);
6626 target = expand_builtin_atomic_store (mode, exp);
6627 if (target)
6628 return const0_rtx;
6629 break;
6630
6631 case BUILT_IN_ATOMIC_ADD_FETCH_1:
6632 case BUILT_IN_ATOMIC_ADD_FETCH_2:
6633 case BUILT_IN_ATOMIC_ADD_FETCH_4:
6634 case BUILT_IN_ATOMIC_ADD_FETCH_8:
6635 case BUILT_IN_ATOMIC_ADD_FETCH_16:
6636 {
6637 enum built_in_function lib;
6638 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1);
6639 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_ADD_1 +
6640 (fcode - BUILT_IN_ATOMIC_ADD_FETCH_1));
6641 target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, true,
6642 ignore, lib);
6643 if (target)
6644 return target;
6645 break;
6646 }
6647 case BUILT_IN_ATOMIC_SUB_FETCH_1:
6648 case BUILT_IN_ATOMIC_SUB_FETCH_2:
6649 case BUILT_IN_ATOMIC_SUB_FETCH_4:
6650 case BUILT_IN_ATOMIC_SUB_FETCH_8:
6651 case BUILT_IN_ATOMIC_SUB_FETCH_16:
6652 {
6653 enum built_in_function lib;
6654 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1);
6655 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_SUB_1 +
6656 (fcode - BUILT_IN_ATOMIC_SUB_FETCH_1));
6657 target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, true,
6658 ignore, lib);
6659 if (target)
6660 return target;
6661 break;
6662 }
6663 case BUILT_IN_ATOMIC_AND_FETCH_1:
6664 case BUILT_IN_ATOMIC_AND_FETCH_2:
6665 case BUILT_IN_ATOMIC_AND_FETCH_4:
6666 case BUILT_IN_ATOMIC_AND_FETCH_8:
6667 case BUILT_IN_ATOMIC_AND_FETCH_16:
6668 {
6669 enum built_in_function lib;
6670 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_AND_FETCH_1);
6671 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_AND_1 +
6672 (fcode - BUILT_IN_ATOMIC_AND_FETCH_1));
6673 target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, true,
6674 ignore, lib);
6675 if (target)
6676 return target;
6677 break;
6678 }
6679 case BUILT_IN_ATOMIC_NAND_FETCH_1:
6680 case BUILT_IN_ATOMIC_NAND_FETCH_2:
6681 case BUILT_IN_ATOMIC_NAND_FETCH_4:
6682 case BUILT_IN_ATOMIC_NAND_FETCH_8:
6683 case BUILT_IN_ATOMIC_NAND_FETCH_16:
6684 {
6685 enum built_in_function lib;
6686 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1);
6687 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_NAND_1 +
6688 (fcode - BUILT_IN_ATOMIC_NAND_FETCH_1));
6689 target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, true,
6690 ignore, lib);
6691 if (target)
6692 return target;
6693 break;
6694 }
6695 case BUILT_IN_ATOMIC_XOR_FETCH_1:
6696 case BUILT_IN_ATOMIC_XOR_FETCH_2:
6697 case BUILT_IN_ATOMIC_XOR_FETCH_4:
6698 case BUILT_IN_ATOMIC_XOR_FETCH_8:
6699 case BUILT_IN_ATOMIC_XOR_FETCH_16:
6700 {
6701 enum built_in_function lib;
6702 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1);
6703 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_XOR_1 +
6704 (fcode - BUILT_IN_ATOMIC_XOR_FETCH_1));
6705 target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, true,
6706 ignore, lib);
6707 if (target)
6708 return target;
6709 break;
6710 }
6711 case BUILT_IN_ATOMIC_OR_FETCH_1:
6712 case BUILT_IN_ATOMIC_OR_FETCH_2:
6713 case BUILT_IN_ATOMIC_OR_FETCH_4:
6714 case BUILT_IN_ATOMIC_OR_FETCH_8:
6715 case BUILT_IN_ATOMIC_OR_FETCH_16:
6716 {
6717 enum built_in_function lib;
6718 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_OR_FETCH_1);
6719 lib = (enum built_in_function)((int)BUILT_IN_ATOMIC_FETCH_OR_1 +
6720 (fcode - BUILT_IN_ATOMIC_OR_FETCH_1));
6721 target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, true,
6722 ignore, lib);
6723 if (target)
6724 return target;
6725 break;
6726 }
6727 case BUILT_IN_ATOMIC_FETCH_ADD_1:
6728 case BUILT_IN_ATOMIC_FETCH_ADD_2:
6729 case BUILT_IN_ATOMIC_FETCH_ADD_4:
6730 case BUILT_IN_ATOMIC_FETCH_ADD_8:
6731 case BUILT_IN_ATOMIC_FETCH_ADD_16:
6732 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_ADD_1);
6733 target = expand_builtin_atomic_fetch_op (mode, exp, target, PLUS, false,
6734 ignore, BUILT_IN_NONE);
6735 if (target)
6736 return target;
6737 break;
6738
6739 case BUILT_IN_ATOMIC_FETCH_SUB_1:
6740 case BUILT_IN_ATOMIC_FETCH_SUB_2:
6741 case BUILT_IN_ATOMIC_FETCH_SUB_4:
6742 case BUILT_IN_ATOMIC_FETCH_SUB_8:
6743 case BUILT_IN_ATOMIC_FETCH_SUB_16:
6744 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_SUB_1);
6745 target = expand_builtin_atomic_fetch_op (mode, exp, target, MINUS, false,
6746 ignore, BUILT_IN_NONE);
6747 if (target)
6748 return target;
6749 break;
6750
6751 case BUILT_IN_ATOMIC_FETCH_AND_1:
6752 case BUILT_IN_ATOMIC_FETCH_AND_2:
6753 case BUILT_IN_ATOMIC_FETCH_AND_4:
6754 case BUILT_IN_ATOMIC_FETCH_AND_8:
6755 case BUILT_IN_ATOMIC_FETCH_AND_16:
6756 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_AND_1);
6757 target = expand_builtin_atomic_fetch_op (mode, exp, target, AND, false,
6758 ignore, BUILT_IN_NONE);
6759 if (target)
6760 return target;
6761 break;
6762
6763 case BUILT_IN_ATOMIC_FETCH_NAND_1:
6764 case BUILT_IN_ATOMIC_FETCH_NAND_2:
6765 case BUILT_IN_ATOMIC_FETCH_NAND_4:
6766 case BUILT_IN_ATOMIC_FETCH_NAND_8:
6767 case BUILT_IN_ATOMIC_FETCH_NAND_16:
6768 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_NAND_1);
6769 target = expand_builtin_atomic_fetch_op (mode, exp, target, NOT, false,
6770 ignore, BUILT_IN_NONE);
6771 if (target)
6772 return target;
6773 break;
6774
6775 case BUILT_IN_ATOMIC_FETCH_XOR_1:
6776 case BUILT_IN_ATOMIC_FETCH_XOR_2:
6777 case BUILT_IN_ATOMIC_FETCH_XOR_4:
6778 case BUILT_IN_ATOMIC_FETCH_XOR_8:
6779 case BUILT_IN_ATOMIC_FETCH_XOR_16:
6780 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_XOR_1);
6781 target = expand_builtin_atomic_fetch_op (mode, exp, target, XOR, false,
6782 ignore, BUILT_IN_NONE);
6783 if (target)
6784 return target;
6785 break;
6786
6787 case BUILT_IN_ATOMIC_FETCH_OR_1:
6788 case BUILT_IN_ATOMIC_FETCH_OR_2:
6789 case BUILT_IN_ATOMIC_FETCH_OR_4:
6790 case BUILT_IN_ATOMIC_FETCH_OR_8:
6791 case BUILT_IN_ATOMIC_FETCH_OR_16:
6792 mode = get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_FETCH_OR_1);
6793 target = expand_builtin_atomic_fetch_op (mode, exp, target, IOR, false,
6794 ignore, BUILT_IN_NONE);
6795 if (target)
6796 return target;
6797 break;
10b744a3 6798
6799 case BUILT_IN_ATOMIC_TEST_AND_SET:
7821cde1 6800 return expand_builtin_atomic_test_and_set (exp, target);
10b744a3 6801
6802 case BUILT_IN_ATOMIC_CLEAR:
6803 return expand_builtin_atomic_clear (exp);
1cd6e20d 6804
6805 case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
6806 return expand_builtin_atomic_always_lock_free (exp);
6807
6808 case BUILT_IN_ATOMIC_IS_LOCK_FREE:
6809 target = expand_builtin_atomic_is_lock_free (exp);
6810 if (target)
6811 return target;
6812 break;
6813
6814 case BUILT_IN_ATOMIC_THREAD_FENCE:
6815 expand_builtin_atomic_thread_fence (exp);
6816 return const0_rtx;
6817
6818 case BUILT_IN_ATOMIC_SIGNAL_FENCE:
6819 expand_builtin_atomic_signal_fence (exp);
6820 return const0_rtx;
6821
0a39fd54 6822 case BUILT_IN_OBJECT_SIZE:
6823 return expand_builtin_object_size (exp);
6824
6825 case BUILT_IN_MEMCPY_CHK:
6826 case BUILT_IN_MEMPCPY_CHK:
6827 case BUILT_IN_MEMMOVE_CHK:
6828 case BUILT_IN_MEMSET_CHK:
6829 target = expand_builtin_memory_chk (exp, target, mode, fcode);
6830 if (target)
6831 return target;
6832 break;
6833
6834 case BUILT_IN_STRCPY_CHK:
6835 case BUILT_IN_STPCPY_CHK:
6836 case BUILT_IN_STRNCPY_CHK:
1063acde 6837 case BUILT_IN_STPNCPY_CHK:
0a39fd54 6838 case BUILT_IN_STRCAT_CHK:
b356dfef 6839 case BUILT_IN_STRNCAT_CHK:
0a39fd54 6840 case BUILT_IN_SNPRINTF_CHK:
6841 case BUILT_IN_VSNPRINTF_CHK:
6842 maybe_emit_chk_warning (exp, fcode);
6843 break;
6844
6845 case BUILT_IN_SPRINTF_CHK:
6846 case BUILT_IN_VSPRINTF_CHK:
6847 maybe_emit_sprintf_chk_warning (exp, fcode);
6848 break;
6849
2c281b15 6850 case BUILT_IN_FREE:
f74ea1c2 6851 if (warn_free_nonheap_object)
6852 maybe_emit_free_warning (exp);
2c281b15 6853 break;
6854
badaa04c 6855 case BUILT_IN_THREAD_POINTER:
6856 return expand_builtin_thread_pointer (exp, target);
6857
6858 case BUILT_IN_SET_THREAD_POINTER:
6859 expand_builtin_set_thread_pointer (exp);
6860 return const0_rtx;
6861
92482ee0 6862 default: /* just do library call, if unknown builtin */
146c1b4f 6863 break;
53800dbe 6864 }
6865
6866 /* The switch statement above can drop through to cause the function
6867 to be called normally. */
6868 return expand_call (exp, target, ignore);
6869}
650e4c94 6870
805e22b2 6871/* Determine whether a tree node represents a call to a built-in
52203a9d 6872 function. If the tree T is a call to a built-in function with
6873 the right number of arguments of the appropriate types, return
6874 the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
6875 Otherwise the return value is END_BUILTINS. */
aecda0d6 6876
805e22b2 6877enum built_in_function
b7bf20db 6878builtin_mathfn_code (const_tree t)
805e22b2 6879{
b7bf20db 6880 const_tree fndecl, arg, parmlist;
6881 const_tree argtype, parmtype;
6882 const_call_expr_arg_iterator iter;
805e22b2 6883
6884 if (TREE_CODE (t) != CALL_EXPR
c2f47e15 6885 || TREE_CODE (CALL_EXPR_FN (t)) != ADDR_EXPR)
805e22b2 6886 return END_BUILTINS;
6887
c6e6ecb1 6888 fndecl = get_callee_fndecl (t);
6889 if (fndecl == NULL_TREE
52203a9d 6890 || TREE_CODE (fndecl) != FUNCTION_DECL
805e22b2 6891 || ! DECL_BUILT_IN (fndecl)
6892 || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
6893 return END_BUILTINS;
6894
52203a9d 6895 parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
b7bf20db 6896 init_const_call_expr_arg_iterator (t, &iter);
52203a9d 6897 for (; parmlist; parmlist = TREE_CHAIN (parmlist))
e9f80ff5 6898 {
52203a9d 6899 /* If a function doesn't take a variable number of arguments,
6900 the last element in the list will have type `void'. */
6901 parmtype = TREE_VALUE (parmlist);
6902 if (VOID_TYPE_P (parmtype))
6903 {
b7bf20db 6904 if (more_const_call_expr_args_p (&iter))
52203a9d 6905 return END_BUILTINS;
6906 return DECL_FUNCTION_CODE (fndecl);
6907 }
6908
b7bf20db 6909 if (! more_const_call_expr_args_p (&iter))
e9f80ff5 6910 return END_BUILTINS;
48e1416a 6911
b7bf20db 6912 arg = next_const_call_expr_arg (&iter);
c2f47e15 6913 argtype = TREE_TYPE (arg);
52203a9d 6914
6915 if (SCALAR_FLOAT_TYPE_P (parmtype))
6916 {
6917 if (! SCALAR_FLOAT_TYPE_P (argtype))
6918 return END_BUILTINS;
6919 }
6920 else if (COMPLEX_FLOAT_TYPE_P (parmtype))
6921 {
6922 if (! COMPLEX_FLOAT_TYPE_P (argtype))
6923 return END_BUILTINS;
6924 }
6925 else if (POINTER_TYPE_P (parmtype))
6926 {
6927 if (! POINTER_TYPE_P (argtype))
6928 return END_BUILTINS;
6929 }
6930 else if (INTEGRAL_TYPE_P (parmtype))
6931 {
6932 if (! INTEGRAL_TYPE_P (argtype))
6933 return END_BUILTINS;
6934 }
6935 else
e9f80ff5 6936 return END_BUILTINS;
e9f80ff5 6937 }
6938
52203a9d 6939 /* Variable-length argument list. */
805e22b2 6940 return DECL_FUNCTION_CODE (fndecl);
6941}
6942
c2f47e15 6943/* Fold a call to __builtin_constant_p, if we know its argument ARG will
6944 evaluate to a constant. */
650e4c94 6945
6946static tree
c2f47e15 6947fold_builtin_constant_p (tree arg)
650e4c94 6948{
650e4c94 6949 /* We return 1 for a numeric type that's known to be a constant
6950 value at compile-time or for an aggregate type that's a
6951 literal constant. */
c2f47e15 6952 STRIP_NOPS (arg);
650e4c94 6953
6954 /* If we know this is a constant, emit the constant of one. */
c2f47e15 6955 if (CONSTANT_CLASS_P (arg)
6956 || (TREE_CODE (arg) == CONSTRUCTOR
6957 && TREE_CONSTANT (arg)))
650e4c94 6958 return integer_one_node;
c2f47e15 6959 if (TREE_CODE (arg) == ADDR_EXPR)
adcfa3a3 6960 {
c2f47e15 6961 tree op = TREE_OPERAND (arg, 0);
adcfa3a3 6962 if (TREE_CODE (op) == STRING_CST
6963 || (TREE_CODE (op) == ARRAY_REF
6964 && integer_zerop (TREE_OPERAND (op, 1))
6965 && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
6966 return integer_one_node;
6967 }
650e4c94 6968
1fb4300c 6969 /* If this expression has side effects, show we don't know it to be a
6970 constant. Likewise if it's a pointer or aggregate type since in
6971 those case we only want literals, since those are only optimized
f97c71a1 6972 when generating RTL, not later.
6973 And finally, if we are compiling an initializer, not code, we
6974 need to return a definite result now; there's not going to be any
6975 more optimization done. */
c2f47e15 6976 if (TREE_SIDE_EFFECTS (arg)
6977 || AGGREGATE_TYPE_P (TREE_TYPE (arg))
6978 || POINTER_TYPE_P (TREE_TYPE (arg))
47be647d 6979 || cfun == 0
6980 || folding_initializer)
650e4c94 6981 return integer_zero_node;
6982
c2f47e15 6983 return NULL_TREE;
650e4c94 6984}
6985
76f5a783 6986/* Create builtin_expect with PRED and EXPECTED as its arguments and
6987 return it as a truthvalue. */
4ee9c684 6988
6989static tree
389dd41b 6990build_builtin_expect_predicate (location_t loc, tree pred, tree expected)
4ee9c684 6991{
76f5a783 6992 tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
4ee9c684 6993
b9a16870 6994 fn = builtin_decl_explicit (BUILT_IN_EXPECT);
76f5a783 6995 arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
6996 ret_type = TREE_TYPE (TREE_TYPE (fn));
6997 pred_type = TREE_VALUE (arg_types);
6998 expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
6999
389dd41b 7000 pred = fold_convert_loc (loc, pred_type, pred);
7001 expected = fold_convert_loc (loc, expected_type, expected);
7002 call_expr = build_call_expr_loc (loc, fn, 2, pred, expected);
76f5a783 7003
7004 return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
7005 build_int_cst (ret_type, 0));
7006}
7007
7008/* Fold a call to builtin_expect with arguments ARG0 and ARG1. Return
7009 NULL_TREE if no simplification is possible. */
7010
7011static tree
389dd41b 7012fold_builtin_expect (location_t loc, tree arg0, tree arg1)
76f5a783 7013{
083bada9 7014 tree inner, fndecl, inner_arg0;
76f5a783 7015 enum tree_code code;
7016
083bada9 7017 /* Distribute the expected value over short-circuiting operators.
7018 See through the cast from truthvalue_type_node to long. */
7019 inner_arg0 = arg0;
7020 while (TREE_CODE (inner_arg0) == NOP_EXPR
7021 && INTEGRAL_TYPE_P (TREE_TYPE (inner_arg0))
7022 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner_arg0, 0))))
7023 inner_arg0 = TREE_OPERAND (inner_arg0, 0);
7024
76f5a783 7025 /* If this is a builtin_expect within a builtin_expect keep the
7026 inner one. See through a comparison against a constant. It
7027 might have been added to create a thruthvalue. */
083bada9 7028 inner = inner_arg0;
7029
76f5a783 7030 if (COMPARISON_CLASS_P (inner)
7031 && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST)
7032 inner = TREE_OPERAND (inner, 0);
7033
7034 if (TREE_CODE (inner) == CALL_EXPR
7035 && (fndecl = get_callee_fndecl (inner))
7036 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
7037 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT)
7038 return arg0;
7039
083bada9 7040 inner = inner_arg0;
76f5a783 7041 code = TREE_CODE (inner);
7042 if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
7043 {
7044 tree op0 = TREE_OPERAND (inner, 0);
7045 tree op1 = TREE_OPERAND (inner, 1);
7046
389dd41b 7047 op0 = build_builtin_expect_predicate (loc, op0, arg1);
7048 op1 = build_builtin_expect_predicate (loc, op1, arg1);
76f5a783 7049 inner = build2 (code, TREE_TYPE (inner), op0, op1);
7050
389dd41b 7051 return fold_convert_loc (loc, TREE_TYPE (arg0), inner);
76f5a783 7052 }
7053
7054 /* If the argument isn't invariant then there's nothing else we can do. */
083bada9 7055 if (!TREE_CONSTANT (inner_arg0))
c2f47e15 7056 return NULL_TREE;
4ee9c684 7057
76f5a783 7058 /* If we expect that a comparison against the argument will fold to
7059 a constant return the constant. In practice, this means a true
7060 constant or the address of a non-weak symbol. */
083bada9 7061 inner = inner_arg0;
4ee9c684 7062 STRIP_NOPS (inner);
7063 if (TREE_CODE (inner) == ADDR_EXPR)
7064 {
7065 do
7066 {
7067 inner = TREE_OPERAND (inner, 0);
7068 }
7069 while (TREE_CODE (inner) == COMPONENT_REF
7070 || TREE_CODE (inner) == ARRAY_REF);
062b4460 7071 if ((TREE_CODE (inner) == VAR_DECL
7072 || TREE_CODE (inner) == FUNCTION_DECL)
7073 && DECL_WEAK (inner))
c2f47e15 7074 return NULL_TREE;
4ee9c684 7075 }
7076
76f5a783 7077 /* Otherwise, ARG0 already has the proper type for the return value. */
7078 return arg0;
4ee9c684 7079}
7080
c2f47e15 7081/* Fold a call to __builtin_classify_type with argument ARG. */
27d0c333 7082
539a3a92 7083static tree
c2f47e15 7084fold_builtin_classify_type (tree arg)
539a3a92 7085{
c2f47e15 7086 if (arg == 0)
7002a1c8 7087 return build_int_cst (integer_type_node, no_type_class);
539a3a92 7088
7002a1c8 7089 return build_int_cst (integer_type_node, type_to_class (TREE_TYPE (arg)));
539a3a92 7090}
7091
c2f47e15 7092/* Fold a call to __builtin_strlen with argument ARG. */
e6e27594 7093
7094static tree
c7cbde74 7095fold_builtin_strlen (location_t loc, tree type, tree arg)
e6e27594 7096{
c2f47e15 7097 if (!validate_arg (arg, POINTER_TYPE))
e6e27594 7098 return NULL_TREE;
7099 else
7100 {
c2f47e15 7101 tree len = c_strlen (arg, 0);
e6e27594 7102
7103 if (len)
c7cbde74 7104 return fold_convert_loc (loc, type, len);
e6e27594 7105
7106 return NULL_TREE;
7107 }
7108}
7109
92c43e3c 7110/* Fold a call to __builtin_inf or __builtin_huge_val. */
7111
7112static tree
389dd41b 7113fold_builtin_inf (location_t loc, tree type, int warn)
92c43e3c 7114{
aa870c1b 7115 REAL_VALUE_TYPE real;
7116
40f4dbd5 7117 /* __builtin_inff is intended to be usable to define INFINITY on all
7118 targets. If an infinity is not available, INFINITY expands "to a
7119 positive constant of type float that overflows at translation
7120 time", footnote "In this case, using INFINITY will violate the
7121 constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
7122 Thus we pedwarn to ensure this constraint violation is
7123 diagnosed. */
92c43e3c 7124 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
389dd41b 7125 pedwarn (loc, 0, "target format does not support infinity");
92c43e3c 7126
aa870c1b 7127 real_inf (&real);
7128 return build_real (type, real);
92c43e3c 7129}
7130
c2f47e15 7131/* Fold a call to __builtin_nan or __builtin_nans with argument ARG. */
b0db7939 7132
7133static tree
c2f47e15 7134fold_builtin_nan (tree arg, tree type, int quiet)
b0db7939 7135{
7136 REAL_VALUE_TYPE real;
7137 const char *str;
7138
c2f47e15 7139 if (!validate_arg (arg, POINTER_TYPE))
7140 return NULL_TREE;
7141 str = c_getstr (arg);
b0db7939 7142 if (!str)
c2f47e15 7143 return NULL_TREE;
b0db7939 7144
7145 if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
c2f47e15 7146 return NULL_TREE;
b0db7939 7147
7148 return build_real (type, real);
7149}
7150
277f8dd2 7151/* Return true if the floating point expression T has an integer value.
7152 We also allow +Inf, -Inf and NaN to be considered integer values. */
7153
7154static bool
7155integer_valued_real_p (tree t)
7156{
7157 switch (TREE_CODE (t))
7158 {
7159 case FLOAT_EXPR:
7160 return true;
7161
7162 case ABS_EXPR:
7163 case SAVE_EXPR:
277f8dd2 7164 return integer_valued_real_p (TREE_OPERAND (t, 0));
7165
7166 case COMPOUND_EXPR:
41076ef6 7167 case MODIFY_EXPR:
277f8dd2 7168 case BIND_EXPR:
75a70cf9 7169 return integer_valued_real_p (TREE_OPERAND (t, 1));
277f8dd2 7170
7171 case PLUS_EXPR:
7172 case MINUS_EXPR:
7173 case MULT_EXPR:
7174 case MIN_EXPR:
7175 case MAX_EXPR:
7176 return integer_valued_real_p (TREE_OPERAND (t, 0))
7177 && integer_valued_real_p (TREE_OPERAND (t, 1));
7178
7179 case COND_EXPR:
7180 return integer_valued_real_p (TREE_OPERAND (t, 1))
7181 && integer_valued_real_p (TREE_OPERAND (t, 2));
7182
7183 case REAL_CST:
0570334c 7184 return real_isinteger (TREE_REAL_CST_PTR (t), TYPE_MODE (TREE_TYPE (t)));
277f8dd2 7185
7186 case NOP_EXPR:
7187 {
7188 tree type = TREE_TYPE (TREE_OPERAND (t, 0));
7189 if (TREE_CODE (type) == INTEGER_TYPE)
7190 return true;
7191 if (TREE_CODE (type) == REAL_TYPE)
7192 return integer_valued_real_p (TREE_OPERAND (t, 0));
7193 break;
7194 }
7195
7196 case CALL_EXPR:
7197 switch (builtin_mathfn_code (t))
7198 {
4f35b1fc 7199 CASE_FLT_FN (BUILT_IN_CEIL):
7200 CASE_FLT_FN (BUILT_IN_FLOOR):
7201 CASE_FLT_FN (BUILT_IN_NEARBYINT):
7202 CASE_FLT_FN (BUILT_IN_RINT):
7203 CASE_FLT_FN (BUILT_IN_ROUND):
7204 CASE_FLT_FN (BUILT_IN_TRUNC):
277f8dd2 7205 return true;
7206
d4a43a03 7207 CASE_FLT_FN (BUILT_IN_FMIN):
7208 CASE_FLT_FN (BUILT_IN_FMAX):
c2f47e15 7209 return integer_valued_real_p (CALL_EXPR_ARG (t, 0))
7210 && integer_valued_real_p (CALL_EXPR_ARG (t, 1));
d4a43a03 7211
277f8dd2 7212 default:
7213 break;
7214 }
7215 break;
7216
7217 default:
7218 break;
7219 }
7220 return false;
7221}
7222
c2f47e15 7223/* FNDECL is assumed to be a builtin where truncation can be propagated
6528f4f4 7224 across (for instance floor((double)f) == (double)floorf (f).
c2f47e15 7225 Do the transformation for a call with argument ARG. */
277f8dd2 7226
6528f4f4 7227static tree
389dd41b 7228fold_trunc_transparent_mathfn (location_t loc, tree fndecl, tree arg)
6528f4f4 7229{
6528f4f4 7230 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
277f8dd2 7231
c2f47e15 7232 if (!validate_arg (arg, REAL_TYPE))
7233 return NULL_TREE;
6528f4f4 7234
277f8dd2 7235 /* Integer rounding functions are idempotent. */
7236 if (fcode == builtin_mathfn_code (arg))
7237 return arg;
7238
7239 /* If argument is already integer valued, and we don't need to worry
7240 about setting errno, there's no need to perform rounding. */
7241 if (! flag_errno_math && integer_valued_real_p (arg))
7242 return arg;
7243
7244 if (optimize)
6528f4f4 7245 {
277f8dd2 7246 tree arg0 = strip_float_extensions (arg);
2426241c 7247 tree ftype = TREE_TYPE (TREE_TYPE (fndecl));
6528f4f4 7248 tree newtype = TREE_TYPE (arg0);
7249 tree decl;
7250
7251 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7252 && (decl = mathfn_built_in (newtype, fcode)))
389dd41b 7253 return fold_convert_loc (loc, ftype,
7254 build_call_expr_loc (loc, decl, 1,
7255 fold_convert_loc (loc,
7256 newtype,
7257 arg0)));
6528f4f4 7258 }
c2f47e15 7259 return NULL_TREE;
6528f4f4 7260}
7261
c2f47e15 7262/* FNDECL is assumed to be builtin which can narrow the FP type of
7263 the argument, for instance lround((double)f) -> lroundf (f).
7264 Do the transformation for a call with argument ARG. */
9ed65c7f 7265
7266static tree
389dd41b 7267fold_fixed_mathfn (location_t loc, tree fndecl, tree arg)
9ed65c7f 7268{
9ed65c7f 7269 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
9ed65c7f 7270
c2f47e15 7271 if (!validate_arg (arg, REAL_TYPE))
7272 return NULL_TREE;
9ed65c7f 7273
7274 /* If argument is already integer valued, and we don't need to worry
7275 about setting errno, there's no need to perform rounding. */
7276 if (! flag_errno_math && integer_valued_real_p (arg))
389dd41b 7277 return fold_build1_loc (loc, FIX_TRUNC_EXPR,
7278 TREE_TYPE (TREE_TYPE (fndecl)), arg);
9ed65c7f 7279
7280 if (optimize)
7281 {
7282 tree ftype = TREE_TYPE (arg);
7283 tree arg0 = strip_float_extensions (arg);
7284 tree newtype = TREE_TYPE (arg0);
7285 tree decl;
7286
7287 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
7288 && (decl = mathfn_built_in (newtype, fcode)))
389dd41b 7289 return build_call_expr_loc (loc, decl, 1,
7290 fold_convert_loc (loc, newtype, arg0));
9ed65c7f 7291 }
73a0da56 7292
80ff6494 7293 /* Canonicalize iround (x) to lround (x) on ILP32 targets where
7294 sizeof (int) == sizeof (long). */
7295 if (TYPE_PRECISION (integer_type_node)
7296 == TYPE_PRECISION (long_integer_type_node))
7297 {
7298 tree newfn = NULL_TREE;
7299 switch (fcode)
7300 {
7301 CASE_FLT_FN (BUILT_IN_ICEIL):
7302 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
7303 break;
7304
7305 CASE_FLT_FN (BUILT_IN_IFLOOR):
7306 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
7307 break;
7308
7309 CASE_FLT_FN (BUILT_IN_IROUND):
7310 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
7311 break;
7312
7313 CASE_FLT_FN (BUILT_IN_IRINT):
7314 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
7315 break;
7316
7317 default:
7318 break;
7319 }
7320
7321 if (newfn)
7322 {
7323 tree newcall = build_call_expr_loc (loc, newfn, 1, arg);
7324 return fold_convert_loc (loc,
7325 TREE_TYPE (TREE_TYPE (fndecl)), newcall);
7326 }
7327 }
7328
73a0da56 7329 /* Canonicalize llround (x) to lround (x) on LP64 targets where
7330 sizeof (long long) == sizeof (long). */
7331 if (TYPE_PRECISION (long_long_integer_type_node)
7332 == TYPE_PRECISION (long_integer_type_node))
7333 {
7334 tree newfn = NULL_TREE;
7335 switch (fcode)
7336 {
7337 CASE_FLT_FN (BUILT_IN_LLCEIL):
7338 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
7339 break;
7340
7341 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7342 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
7343 break;
7344
7345 CASE_FLT_FN (BUILT_IN_LLROUND):
7346 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
7347 break;
7348
7349 CASE_FLT_FN (BUILT_IN_LLRINT):
7350 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
7351 break;
7352
7353 default:
7354 break;
7355 }
7356
7357 if (newfn)
7358 {
389dd41b 7359 tree newcall = build_call_expr_loc (loc, newfn, 1, arg);
7360 return fold_convert_loc (loc,
7361 TREE_TYPE (TREE_TYPE (fndecl)), newcall);
73a0da56 7362 }
7363 }
7364
c2f47e15 7365 return NULL_TREE;
9ed65c7f 7366}
7367
c2f47e15 7368/* Fold call to builtin cabs, cabsf or cabsl with argument ARG. TYPE is the
7369 return type. Return NULL_TREE if no simplification can be made. */
c63f4ad3 7370
7371static tree
389dd41b 7372fold_builtin_cabs (location_t loc, tree arg, tree type, tree fndecl)
c63f4ad3 7373{
c2f47e15 7374 tree res;
c63f4ad3 7375
b0ce8887 7376 if (!validate_arg (arg, COMPLEX_TYPE)
c63f4ad3 7377 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
7378 return NULL_TREE;
7379
b4725390 7380 /* Calculate the result when the argument is a constant. */
7381 if (TREE_CODE (arg) == COMPLEX_CST
7382 && (res = do_mpfr_arg2 (TREE_REALPART (arg), TREE_IMAGPART (arg),
7383 type, mpfr_hypot)))
7384 return res;
48e1416a 7385
1af0d139 7386 if (TREE_CODE (arg) == COMPLEX_EXPR)
7387 {
7388 tree real = TREE_OPERAND (arg, 0);
7389 tree imag = TREE_OPERAND (arg, 1);
48e1416a 7390
1af0d139 7391 /* If either part is zero, cabs is fabs of the other. */
7392 if (real_zerop (real))
389dd41b 7393 return fold_build1_loc (loc, ABS_EXPR, type, imag);
1af0d139 7394 if (real_zerop (imag))
389dd41b 7395 return fold_build1_loc (loc, ABS_EXPR, type, real);
1af0d139 7396
7397 /* cabs(x+xi) -> fabs(x)*sqrt(2). */
7398 if (flag_unsafe_math_optimizations
7399 && operand_equal_p (real, imag, OEP_PURE_SAME))
7400 {
2e7ca27b 7401 const REAL_VALUE_TYPE sqrt2_trunc
7910b2fb 7402 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
1af0d139 7403 STRIP_NOPS (real);
389dd41b 7404 return fold_build2_loc (loc, MULT_EXPR, type,
7405 fold_build1_loc (loc, ABS_EXPR, type, real),
2e7ca27b 7406 build_real (type, sqrt2_trunc));
1af0d139 7407 }
7408 }
c63f4ad3 7409
749891b2 7410 /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */
7411 if (TREE_CODE (arg) == NEGATE_EXPR
7412 || TREE_CODE (arg) == CONJ_EXPR)
389dd41b 7413 return build_call_expr_loc (loc, fndecl, 1, TREE_OPERAND (arg, 0));
749891b2 7414
7d3f6cc7 7415 /* Don't do this when optimizing for size. */
7416 if (flag_unsafe_math_optimizations
0bfd8d5c 7417 && optimize && optimize_function_for_speed_p (cfun))
c63f4ad3 7418 {
0da0dbfa 7419 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
c63f4ad3 7420
7421 if (sqrtfn != NULL_TREE)
7422 {
c2f47e15 7423 tree rpart, ipart, result;
c63f4ad3 7424
4ee9c684 7425 arg = builtin_save_expr (arg);
29a6518e 7426
389dd41b 7427 rpart = fold_build1_loc (loc, REALPART_EXPR, type, arg);
7428 ipart = fold_build1_loc (loc, IMAGPART_EXPR, type, arg);
c63f4ad3 7429
4ee9c684 7430 rpart = builtin_save_expr (rpart);
7431 ipart = builtin_save_expr (ipart);
c63f4ad3 7432
389dd41b 7433 result = fold_build2_loc (loc, PLUS_EXPR, type,
7434 fold_build2_loc (loc, MULT_EXPR, type,
49d00087 7435 rpart, rpart),
389dd41b 7436 fold_build2_loc (loc, MULT_EXPR, type,
49d00087 7437 ipart, ipart));
c63f4ad3 7438
389dd41b 7439 return build_call_expr_loc (loc, sqrtfn, 1, result);
c63f4ad3 7440 }
7441 }
7442
7443 return NULL_TREE;
7444}
7445
c2373fdb 7446/* Build a complex (inf +- 0i) for the result of cproj. TYPE is the
7447 complex tree type of the result. If NEG is true, the imaginary
7448 zero is negative. */
7449
7450static tree
7451build_complex_cproj (tree type, bool neg)
7452{
7453 REAL_VALUE_TYPE rinf, rzero = dconst0;
7454
7455 real_inf (&rinf);
7456 rzero.sign = neg;
7457 return build_complex (type, build_real (TREE_TYPE (type), rinf),
7458 build_real (TREE_TYPE (type), rzero));
7459}
7460
7461/* Fold call to builtin cproj, cprojf or cprojl with argument ARG. TYPE is the
7462 return type. Return NULL_TREE if no simplification can be made. */
7463
7464static tree
7465fold_builtin_cproj (location_t loc, tree arg, tree type)
7466{
7467 if (!validate_arg (arg, COMPLEX_TYPE)
7468 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
7469 return NULL_TREE;
7470
7471 /* If there are no infinities, return arg. */
7472 if (! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (type))))
7473 return non_lvalue_loc (loc, arg);
7474
7475 /* Calculate the result when the argument is a constant. */
7476 if (TREE_CODE (arg) == COMPLEX_CST)
7477 {
7478 const REAL_VALUE_TYPE *real = TREE_REAL_CST_PTR (TREE_REALPART (arg));
7479 const REAL_VALUE_TYPE *imag = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
7480
7481 if (real_isinf (real) || real_isinf (imag))
7482 return build_complex_cproj (type, imag->sign);
7483 else
7484 return arg;
7485 }
b4c7e601 7486 else if (TREE_CODE (arg) == COMPLEX_EXPR)
7487 {
7488 tree real = TREE_OPERAND (arg, 0);
7489 tree imag = TREE_OPERAND (arg, 1);
7490
7491 STRIP_NOPS (real);
7492 STRIP_NOPS (imag);
7493
7494 /* If the real part is inf and the imag part is known to be
7495 nonnegative, return (inf + 0i). Remember side-effects are
7496 possible in the imag part. */
7497 if (TREE_CODE (real) == REAL_CST
7498 && real_isinf (TREE_REAL_CST_PTR (real))
7499 && tree_expr_nonnegative_p (imag))
7500 return omit_one_operand_loc (loc, type,
7501 build_complex_cproj (type, false),
7502 arg);
7503
7504 /* If the imag part is inf, return (inf+I*copysign(0,imag)).
7505 Remember side-effects are possible in the real part. */
7506 if (TREE_CODE (imag) == REAL_CST
7507 && real_isinf (TREE_REAL_CST_PTR (imag)))
7508 return
7509 omit_one_operand_loc (loc, type,
7510 build_complex_cproj (type, TREE_REAL_CST_PTR
7511 (imag)->sign), arg);
7512 }
c2373fdb 7513
7514 return NULL_TREE;
7515}
7516
c2f47e15 7517/* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG.
7518 Return NULL_TREE if no simplification can be made. */
e6e27594 7519
7520static tree
389dd41b 7521fold_builtin_sqrt (location_t loc, tree arg, tree type)
e6e27594 7522{
7523
7524 enum built_in_function fcode;
b4e8ab0c 7525 tree res;
c2f47e15 7526
7527 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7528 return NULL_TREE;
7529
b4e8ab0c 7530 /* Calculate the result when the argument is a constant. */
7531 if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
7532 return res;
48e1416a 7533
e6e27594 7534 /* Optimize sqrt(expN(x)) = expN(x*0.5). */
7535 fcode = builtin_mathfn_code (arg);
7536 if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
7537 {
c2f47e15 7538 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
389dd41b 7539 arg = fold_build2_loc (loc, MULT_EXPR, type,
c2f47e15 7540 CALL_EXPR_ARG (arg, 0),
49d00087 7541 build_real (type, dconsthalf));
389dd41b 7542 return build_call_expr_loc (loc, expfn, 1, arg);
e6e27594 7543 }
7544
7545 /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */
7546 if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
7547 {
7548 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7549
7550 if (powfn)
7551 {
c2f47e15 7552 tree arg0 = CALL_EXPR_ARG (arg, 0);
e6e27594 7553 tree tree_root;
7554 /* The inner root was either sqrt or cbrt. */
57510da6 7555 /* This was a conditional expression but it triggered a bug
18381619 7556 in Sun C 5.5. */
ce6cd837 7557 REAL_VALUE_TYPE dconstroot;
7558 if (BUILTIN_SQRT_P (fcode))
7559 dconstroot = dconsthalf;
7560 else
7561 dconstroot = dconst_third ();
e6e27594 7562
7563 /* Adjust for the outer root. */
7564 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7565 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7566 tree_root = build_real (type, dconstroot);
389dd41b 7567 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
e6e27594 7568 }
7569 }
7570
bc33117f 7571 /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
e6e27594 7572 if (flag_unsafe_math_optimizations
7573 && (fcode == BUILT_IN_POW
7574 || fcode == BUILT_IN_POWF
7575 || fcode == BUILT_IN_POWL))
7576 {
c2f47e15 7577 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
7578 tree arg0 = CALL_EXPR_ARG (arg, 0);
7579 tree arg1 = CALL_EXPR_ARG (arg, 1);
bc33117f 7580 tree narg1;
7581 if (!tree_expr_nonnegative_p (arg0))
7582 arg0 = build1 (ABS_EXPR, type, arg0);
389dd41b 7583 narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 7584 build_real (type, dconsthalf));
389dd41b 7585 return build_call_expr_loc (loc, powfn, 2, arg0, narg1);
e6e27594 7586 }
7587
7588 return NULL_TREE;
7589}
7590
c2f47e15 7591/* Fold a builtin function call to cbrt, cbrtf, or cbrtl with argument ARG.
7592 Return NULL_TREE if no simplification can be made. */
7593
e6e27594 7594static tree
389dd41b 7595fold_builtin_cbrt (location_t loc, tree arg, tree type)
e6e27594 7596{
e6e27594 7597 const enum built_in_function fcode = builtin_mathfn_code (arg);
29f4cd78 7598 tree res;
e6e27594 7599
c2f47e15 7600 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7601 return NULL_TREE;
7602
29f4cd78 7603 /* Calculate the result when the argument is a constant. */
7604 if ((res = do_mpfr_arg1 (arg, type, mpfr_cbrt, NULL, NULL, 0)))
7605 return res;
e6e27594 7606
cdfeb715 7607 if (flag_unsafe_math_optimizations)
e6e27594 7608 {
cdfeb715 7609 /* Optimize cbrt(expN(x)) -> expN(x/3). */
7610 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 7611 {
c2f47e15 7612 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7613 const REAL_VALUE_TYPE third_trunc =
7910b2fb 7614 real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 7615 arg = fold_build2_loc (loc, MULT_EXPR, type,
c2f47e15 7616 CALL_EXPR_ARG (arg, 0),
49d00087 7617 build_real (type, third_trunc));
389dd41b 7618 return build_call_expr_loc (loc, expfn, 1, arg);
cdfeb715 7619 }
e6e27594 7620
cdfeb715 7621 /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */
7622 if (BUILTIN_SQRT_P (fcode))
a0c938f0 7623 {
cdfeb715 7624 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
e6e27594 7625
cdfeb715 7626 if (powfn)
7627 {
c2f47e15 7628 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7629 tree tree_root;
7910b2fb 7630 REAL_VALUE_TYPE dconstroot = dconst_third ();
cdfeb715 7631
7632 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7633 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7634 tree_root = build_real (type, dconstroot);
389dd41b 7635 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
cdfeb715 7636 }
e6e27594 7637 }
7638
cdfeb715 7639 /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */
7640 if (BUILTIN_CBRT_P (fcode))
a0c938f0 7641 {
c2f47e15 7642 tree arg0 = CALL_EXPR_ARG (arg, 0);
cdfeb715 7643 if (tree_expr_nonnegative_p (arg0))
7644 {
7645 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7646
7647 if (powfn)
a0c938f0 7648 {
cdfeb715 7649 tree tree_root;
7650 REAL_VALUE_TYPE dconstroot;
a0c938f0 7651
3fa759a9 7652 real_arithmetic (&dconstroot, MULT_EXPR,
7910b2fb 7653 dconst_third_ptr (), dconst_third_ptr ());
cdfeb715 7654 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7655 tree_root = build_real (type, dconstroot);
389dd41b 7656 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
cdfeb715 7657 }
7658 }
7659 }
a0c938f0 7660
cdfeb715 7661 /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */
48e1416a 7662 if (fcode == BUILT_IN_POW
c2f47e15 7663 || fcode == BUILT_IN_POWF
cdfeb715 7664 || fcode == BUILT_IN_POWL)
a0c938f0 7665 {
c2f47e15 7666 tree arg00 = CALL_EXPR_ARG (arg, 0);
7667 tree arg01 = CALL_EXPR_ARG (arg, 1);
cdfeb715 7668 if (tree_expr_nonnegative_p (arg00))
7669 {
c2f47e15 7670 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
cdfeb715 7671 const REAL_VALUE_TYPE dconstroot
7910b2fb 7672 = real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 7673 tree narg01 = fold_build2_loc (loc, MULT_EXPR, type, arg01,
49d00087 7674 build_real (type, dconstroot));
389dd41b 7675 return build_call_expr_loc (loc, powfn, 2, arg00, narg01);
cdfeb715 7676 }
7677 }
e6e27594 7678 }
7679 return NULL_TREE;
7680}
7681
c2f47e15 7682/* Fold function call to builtin cos, cosf, or cosl with argument ARG.
7683 TYPE is the type of the return value. Return NULL_TREE if no
7684 simplification can be made. */
7685
e6e27594 7686static tree
389dd41b 7687fold_builtin_cos (location_t loc,
7688 tree arg, tree type, tree fndecl)
e6e27594 7689{
e6ab33d8 7690 tree res, narg;
e6e27594 7691
c2f47e15 7692 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7693 return NULL_TREE;
7694
bffb7645 7695 /* Calculate the result when the argument is a constant. */
728bac60 7696 if ((res = do_mpfr_arg1 (arg, type, mpfr_cos, NULL, NULL, 0)))
bffb7645 7697 return res;
48e1416a 7698
e6e27594 7699 /* Optimize cos(-x) into cos (x). */
e6ab33d8 7700 if ((narg = fold_strip_sign_ops (arg)))
389dd41b 7701 return build_call_expr_loc (loc, fndecl, 1, narg);
e6e27594 7702
7703 return NULL_TREE;
7704}
7705
c2f47e15 7706/* Fold function call to builtin cosh, coshf, or coshl with argument ARG.
7707 Return NULL_TREE if no simplification can be made. */
7708
cacdc1af 7709static tree
389dd41b 7710fold_builtin_cosh (location_t loc, tree arg, tree type, tree fndecl)
cacdc1af 7711{
c2f47e15 7712 if (validate_arg (arg, REAL_TYPE))
cacdc1af 7713 {
cacdc1af 7714 tree res, narg;
7715
7716 /* Calculate the result when the argument is a constant. */
7717 if ((res = do_mpfr_arg1 (arg, type, mpfr_cosh, NULL, NULL, 0)))
7718 return res;
48e1416a 7719
cacdc1af 7720 /* Optimize cosh(-x) into cosh (x). */
7721 if ((narg = fold_strip_sign_ops (arg)))
389dd41b 7722 return build_call_expr_loc (loc, fndecl, 1, narg);
cacdc1af 7723 }
48e1416a 7724
cacdc1af 7725 return NULL_TREE;
7726}
7727
239d491a 7728/* Fold function call to builtin ccos (or ccosh if HYPER is TRUE) with
7729 argument ARG. TYPE is the type of the return value. Return
7730 NULL_TREE if no simplification can be made. */
7731
7732static tree
965d0f29 7733fold_builtin_ccos (location_t loc, tree arg, tree type, tree fndecl,
7734 bool hyper)
239d491a 7735{
7736 if (validate_arg (arg, COMPLEX_TYPE)
7737 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
7738 {
7739 tree tmp;
7740
239d491a 7741 /* Calculate the result when the argument is a constant. */
7742 if ((tmp = do_mpc_arg1 (arg, type, (hyper ? mpc_cosh : mpc_cos))))
7743 return tmp;
48e1416a 7744
239d491a 7745 /* Optimize fn(-x) into fn(x). */
7746 if ((tmp = fold_strip_sign_ops (arg)))
389dd41b 7747 return build_call_expr_loc (loc, fndecl, 1, tmp);
239d491a 7748 }
7749
7750 return NULL_TREE;
7751}
7752
c2f47e15 7753/* Fold function call to builtin tan, tanf, or tanl with argument ARG.
7754 Return NULL_TREE if no simplification can be made. */
7755
e6e27594 7756static tree
c2f47e15 7757fold_builtin_tan (tree arg, tree type)
e6e27594 7758{
7759 enum built_in_function fcode;
29f4cd78 7760 tree res;
e6e27594 7761
c2f47e15 7762 if (!validate_arg (arg, REAL_TYPE))
e6e27594 7763 return NULL_TREE;
7764
bffb7645 7765 /* Calculate the result when the argument is a constant. */
728bac60 7766 if ((res = do_mpfr_arg1 (arg, type, mpfr_tan, NULL, NULL, 0)))
bffb7645 7767 return res;
48e1416a 7768
e6e27594 7769 /* Optimize tan(atan(x)) = x. */
7770 fcode = builtin_mathfn_code (arg);
7771 if (flag_unsafe_math_optimizations
7772 && (fcode == BUILT_IN_ATAN
7773 || fcode == BUILT_IN_ATANF
7774 || fcode == BUILT_IN_ATANL))
c2f47e15 7775 return CALL_EXPR_ARG (arg, 0);
e6e27594 7776
7777 return NULL_TREE;
7778}
7779
d735c391 7780/* Fold function call to builtin sincos, sincosf, or sincosl. Return
7781 NULL_TREE if no simplification can be made. */
7782
7783static tree
389dd41b 7784fold_builtin_sincos (location_t loc,
7785 tree arg0, tree arg1, tree arg2)
d735c391 7786{
c2f47e15 7787 tree type;
d735c391 7788 tree res, fn, call;
7789
c2f47e15 7790 if (!validate_arg (arg0, REAL_TYPE)
7791 || !validate_arg (arg1, POINTER_TYPE)
7792 || !validate_arg (arg2, POINTER_TYPE))
d735c391 7793 return NULL_TREE;
7794
d735c391 7795 type = TREE_TYPE (arg0);
d735c391 7796
7797 /* Calculate the result when the argument is a constant. */
7798 if ((res = do_mpfr_sincos (arg0, arg1, arg2)))
7799 return res;
7800
7801 /* Canonicalize sincos to cexpi. */
2a6b4c77 7802 if (!TARGET_C99_FUNCTIONS)
7803 return NULL_TREE;
d735c391 7804 fn = mathfn_built_in (type, BUILT_IN_CEXPI);
7805 if (!fn)
7806 return NULL_TREE;
7807
389dd41b 7808 call = build_call_expr_loc (loc, fn, 1, arg0);
d735c391 7809 call = builtin_save_expr (call);
7810
a75b1c71 7811 return build2 (COMPOUND_EXPR, void_type_node,
d735c391 7812 build2 (MODIFY_EXPR, void_type_node,
389dd41b 7813 build_fold_indirect_ref_loc (loc, arg1),
d735c391 7814 build1 (IMAGPART_EXPR, type, call)),
7815 build2 (MODIFY_EXPR, void_type_node,
389dd41b 7816 build_fold_indirect_ref_loc (loc, arg2),
d735c391 7817 build1 (REALPART_EXPR, type, call)));
7818}
7819
c5bb2c4b 7820/* Fold function call to builtin cexp, cexpf, or cexpl. Return
7821 NULL_TREE if no simplification can be made. */
7822
7823static tree
389dd41b 7824fold_builtin_cexp (location_t loc, tree arg0, tree type)
c5bb2c4b 7825{
c2f47e15 7826 tree rtype;
c5bb2c4b 7827 tree realp, imagp, ifn;
239d491a 7828 tree res;
c5bb2c4b 7829
239d491a 7830 if (!validate_arg (arg0, COMPLEX_TYPE)
b0ce8887 7831 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) != REAL_TYPE)
c5bb2c4b 7832 return NULL_TREE;
7833
239d491a 7834 /* Calculate the result when the argument is a constant. */
7835 if ((res = do_mpc_arg1 (arg0, type, mpc_exp)))
7836 return res;
48e1416a 7837
c5bb2c4b 7838 rtype = TREE_TYPE (TREE_TYPE (arg0));
7839
7840 /* In case we can figure out the real part of arg0 and it is constant zero
7841 fold to cexpi. */
2a6b4c77 7842 if (!TARGET_C99_FUNCTIONS)
7843 return NULL_TREE;
c5bb2c4b 7844 ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI);
7845 if (!ifn)
7846 return NULL_TREE;
7847
389dd41b 7848 if ((realp = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0))
c5bb2c4b 7849 && real_zerop (realp))
7850 {
389dd41b 7851 tree narg = fold_build1_loc (loc, IMAGPART_EXPR, rtype, arg0);
7852 return build_call_expr_loc (loc, ifn, 1, narg);
c5bb2c4b 7853 }
7854
7855 /* In case we can easily decompose real and imaginary parts split cexp
7856 to exp (r) * cexpi (i). */
7857 if (flag_unsafe_math_optimizations
7858 && realp)
7859 {
7860 tree rfn, rcall, icall;
7861
7862 rfn = mathfn_built_in (rtype, BUILT_IN_EXP);
7863 if (!rfn)
7864 return NULL_TREE;
7865
389dd41b 7866 imagp = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
c5bb2c4b 7867 if (!imagp)
7868 return NULL_TREE;
7869
389dd41b 7870 icall = build_call_expr_loc (loc, ifn, 1, imagp);
c5bb2c4b 7871 icall = builtin_save_expr (icall);
389dd41b 7872 rcall = build_call_expr_loc (loc, rfn, 1, realp);
c5bb2c4b 7873 rcall = builtin_save_expr (rcall);
389dd41b 7874 return fold_build2_loc (loc, COMPLEX_EXPR, type,
7875 fold_build2_loc (loc, MULT_EXPR, rtype,
71bf42bb 7876 rcall,
389dd41b 7877 fold_build1_loc (loc, REALPART_EXPR,
7878 rtype, icall)),
7879 fold_build2_loc (loc, MULT_EXPR, rtype,
71bf42bb 7880 rcall,
389dd41b 7881 fold_build1_loc (loc, IMAGPART_EXPR,
7882 rtype, icall)));
c5bb2c4b 7883 }
7884
7885 return NULL_TREE;
7886}
7887
c2f47e15 7888/* Fold function call to builtin trunc, truncf or truncl with argument ARG.
7889 Return NULL_TREE if no simplification can be made. */
277f8dd2 7890
7891static tree
389dd41b 7892fold_builtin_trunc (location_t loc, tree fndecl, tree arg)
277f8dd2 7893{
c2f47e15 7894 if (!validate_arg (arg, REAL_TYPE))
7895 return NULL_TREE;
277f8dd2 7896
7897 /* Optimize trunc of constant value. */
f96bd2bf 7898 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7899 {
7900 REAL_VALUE_TYPE r, x;
2426241c 7901 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7902
7903 x = TREE_REAL_CST (arg);
7904 real_trunc (&r, TYPE_MODE (type), &x);
7905 return build_real (type, r);
7906 }
7907
389dd41b 7908 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7909}
7910
c2f47e15 7911/* Fold function call to builtin floor, floorf or floorl with argument ARG.
7912 Return NULL_TREE if no simplification can be made. */
277f8dd2 7913
7914static tree
389dd41b 7915fold_builtin_floor (location_t loc, tree fndecl, tree arg)
277f8dd2 7916{
c2f47e15 7917 if (!validate_arg (arg, REAL_TYPE))
7918 return NULL_TREE;
277f8dd2 7919
7920 /* Optimize floor of constant value. */
f96bd2bf 7921 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7922 {
7923 REAL_VALUE_TYPE x;
7924
7925 x = TREE_REAL_CST (arg);
7926 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7927 {
2426241c 7928 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7929 REAL_VALUE_TYPE r;
7930
7931 real_floor (&r, TYPE_MODE (type), &x);
7932 return build_real (type, r);
7933 }
7934 }
7935
acc2b92e 7936 /* Fold floor (x) where x is nonnegative to trunc (x). */
7937 if (tree_expr_nonnegative_p (arg))
30fe8286 7938 {
7939 tree truncfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_TRUNC);
7940 if (truncfn)
389dd41b 7941 return build_call_expr_loc (loc, truncfn, 1, arg);
30fe8286 7942 }
acc2b92e 7943
389dd41b 7944 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7945}
7946
c2f47e15 7947/* Fold function call to builtin ceil, ceilf or ceill with argument ARG.
7948 Return NULL_TREE if no simplification can be made. */
277f8dd2 7949
7950static tree
389dd41b 7951fold_builtin_ceil (location_t loc, tree fndecl, tree arg)
277f8dd2 7952{
c2f47e15 7953 if (!validate_arg (arg, REAL_TYPE))
7954 return NULL_TREE;
277f8dd2 7955
7956 /* Optimize ceil of constant value. */
f96bd2bf 7957 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
277f8dd2 7958 {
7959 REAL_VALUE_TYPE x;
7960
7961 x = TREE_REAL_CST (arg);
7962 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7963 {
2426241c 7964 tree type = TREE_TYPE (TREE_TYPE (fndecl));
277f8dd2 7965 REAL_VALUE_TYPE r;
7966
7967 real_ceil (&r, TYPE_MODE (type), &x);
7968 return build_real (type, r);
7969 }
7970 }
7971
389dd41b 7972 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
277f8dd2 7973}
7974
c2f47e15 7975/* Fold function call to builtin round, roundf or roundl with argument ARG.
7976 Return NULL_TREE if no simplification can be made. */
89ab3887 7977
7978static tree
389dd41b 7979fold_builtin_round (location_t loc, tree fndecl, tree arg)
89ab3887 7980{
c2f47e15 7981 if (!validate_arg (arg, REAL_TYPE))
7982 return NULL_TREE;
89ab3887 7983
34f17811 7984 /* Optimize round of constant value. */
f96bd2bf 7985 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
89ab3887 7986 {
7987 REAL_VALUE_TYPE x;
7988
7989 x = TREE_REAL_CST (arg);
7990 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7991 {
2426241c 7992 tree type = TREE_TYPE (TREE_TYPE (fndecl));
89ab3887 7993 REAL_VALUE_TYPE r;
7994
7995 real_round (&r, TYPE_MODE (type), &x);
7996 return build_real (type, r);
7997 }
7998 }
7999
389dd41b 8000 return fold_trunc_transparent_mathfn (loc, fndecl, arg);
89ab3887 8001}
8002
34f17811 8003/* Fold function call to builtin lround, lroundf or lroundl (or the
c2f47e15 8004 corresponding long long versions) and other rounding functions. ARG
8005 is the argument to the call. Return NULL_TREE if no simplification
8006 can be made. */
34f17811 8007
8008static tree
389dd41b 8009fold_builtin_int_roundingfn (location_t loc, tree fndecl, tree arg)
34f17811 8010{
c2f47e15 8011 if (!validate_arg (arg, REAL_TYPE))
8012 return NULL_TREE;
34f17811 8013
8014 /* Optimize lround of constant value. */
f96bd2bf 8015 if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
34f17811 8016 {
8017 const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
8018
776a7bab 8019 if (real_isfinite (&x))
34f17811 8020 {
2426241c 8021 tree itype = TREE_TYPE (TREE_TYPE (fndecl));
ca9b061d 8022 tree ftype = TREE_TYPE (arg);
a6caa15f 8023 double_int val;
34f17811 8024 REAL_VALUE_TYPE r;
8025
ad52b9b7 8026 switch (DECL_FUNCTION_CODE (fndecl))
8027 {
80ff6494 8028 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 8029 CASE_FLT_FN (BUILT_IN_LFLOOR):
8030 CASE_FLT_FN (BUILT_IN_LLFLOOR):
ad52b9b7 8031 real_floor (&r, TYPE_MODE (ftype), &x);
8032 break;
8033
80ff6494 8034 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 8035 CASE_FLT_FN (BUILT_IN_LCEIL):
8036 CASE_FLT_FN (BUILT_IN_LLCEIL):
ac148751 8037 real_ceil (&r, TYPE_MODE (ftype), &x);
8038 break;
8039
80ff6494 8040 CASE_FLT_FN (BUILT_IN_IROUND):
4f35b1fc 8041 CASE_FLT_FN (BUILT_IN_LROUND):
8042 CASE_FLT_FN (BUILT_IN_LLROUND):
ad52b9b7 8043 real_round (&r, TYPE_MODE (ftype), &x);
8044 break;
8045
8046 default:
8047 gcc_unreachable ();
8048 }
8049
a6caa15f 8050 real_to_integer2 ((HOST_WIDE_INT *)&val.low, &val.high, &r);
8051 if (double_int_fits_to_tree_p (itype, val))
8052 return double_int_to_tree (itype, val);
34f17811 8053 }
8054 }
8055
acc2b92e 8056 switch (DECL_FUNCTION_CODE (fndecl))
8057 {
8058 CASE_FLT_FN (BUILT_IN_LFLOOR):
8059 CASE_FLT_FN (BUILT_IN_LLFLOOR):
8060 /* Fold lfloor (x) where x is nonnegative to FIX_TRUNC (x). */
8061 if (tree_expr_nonnegative_p (arg))
389dd41b 8062 return fold_build1_loc (loc, FIX_TRUNC_EXPR,
8063 TREE_TYPE (TREE_TYPE (fndecl)), arg);
acc2b92e 8064 break;
8065 default:;
8066 }
8067
389dd41b 8068 return fold_fixed_mathfn (loc, fndecl, arg);
34f17811 8069}
8070
70fb4c07 8071/* Fold function call to builtin ffs, clz, ctz, popcount and parity
c2f47e15 8072 and their long and long long variants (i.e. ffsl and ffsll). ARG is
8073 the argument to the call. Return NULL_TREE if no simplification can
8074 be made. */
70fb4c07 8075
8076static tree
c2f47e15 8077fold_builtin_bitop (tree fndecl, tree arg)
70fb4c07 8078{
c2f47e15 8079 if (!validate_arg (arg, INTEGER_TYPE))
70fb4c07 8080 return NULL_TREE;
8081
8082 /* Optimize for constant argument. */
f96bd2bf 8083 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
70fb4c07 8084 {
8085 HOST_WIDE_INT hi, width, result;
8086 unsigned HOST_WIDE_INT lo;
7c446c95 8087 tree type;
70fb4c07 8088
8089 type = TREE_TYPE (arg);
8090 width = TYPE_PRECISION (type);
8091 lo = TREE_INT_CST_LOW (arg);
8092
8093 /* Clear all the bits that are beyond the type's precision. */
8094 if (width > HOST_BITS_PER_WIDE_INT)
8095 {
8096 hi = TREE_INT_CST_HIGH (arg);
24cd46a7 8097 if (width < HOST_BITS_PER_DOUBLE_INT)
6aaa1f9e 8098 hi &= ~((unsigned HOST_WIDE_INT) (-1)
8099 << (width - HOST_BITS_PER_WIDE_INT));
70fb4c07 8100 }
8101 else
8102 {
8103 hi = 0;
8104 if (width < HOST_BITS_PER_WIDE_INT)
8105 lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
8106 }
8107
8108 switch (DECL_FUNCTION_CODE (fndecl))
8109 {
4f35b1fc 8110 CASE_INT_FN (BUILT_IN_FFS):
70fb4c07 8111 if (lo != 0)
7e8d812e 8112 result = ffs_hwi (lo);
70fb4c07 8113 else if (hi != 0)
7e8d812e 8114 result = HOST_BITS_PER_WIDE_INT + ffs_hwi (hi);
70fb4c07 8115 else
8116 result = 0;
8117 break;
8118
4f35b1fc 8119 CASE_INT_FN (BUILT_IN_CLZ):
70fb4c07 8120 if (hi != 0)
8121 result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
8122 else if (lo != 0)
8123 result = width - floor_log2 (lo) - 1;
8124 else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
8125 result = width;
8126 break;
8127
4f35b1fc 8128 CASE_INT_FN (BUILT_IN_CTZ):
70fb4c07 8129 if (lo != 0)
7e8d812e 8130 result = ctz_hwi (lo);
70fb4c07 8131 else if (hi != 0)
7e8d812e 8132 result = HOST_BITS_PER_WIDE_INT + ctz_hwi (hi);
70fb4c07 8133 else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
8134 result = width;
8135 break;
8136
6aaa1f9e 8137 CASE_INT_FN (BUILT_IN_CLRSB):
8138 if (width > HOST_BITS_PER_WIDE_INT
8139 && (hi & ((unsigned HOST_WIDE_INT) 1
8140 << (width - HOST_BITS_PER_WIDE_INT - 1))) != 0)
8141 {
8142 hi = ~hi & ~((unsigned HOST_WIDE_INT) (-1)
8143 << (width - HOST_BITS_PER_WIDE_INT - 1));
8144 lo = ~lo;
8145 }
8146 else if (width <= HOST_BITS_PER_WIDE_INT
8147 && (lo & ((unsigned HOST_WIDE_INT) 1 << (width - 1))) != 0)
8148 lo = ~lo & ~((unsigned HOST_WIDE_INT) (-1) << (width - 1));
8149 if (hi != 0)
8150 result = width - floor_log2 (hi) - 2 - HOST_BITS_PER_WIDE_INT;
8151 else if (lo != 0)
8152 result = width - floor_log2 (lo) - 2;
8153 else
8154 result = width - 1;
8155 break;
8156
4f35b1fc 8157 CASE_INT_FN (BUILT_IN_POPCOUNT):
70fb4c07 8158 result = 0;
8159 while (lo)
8160 result++, lo &= lo - 1;
8161 while (hi)
7e8d812e 8162 result++, hi &= (unsigned HOST_WIDE_INT) hi - 1;
70fb4c07 8163 break;
8164
4f35b1fc 8165 CASE_INT_FN (BUILT_IN_PARITY):
70fb4c07 8166 result = 0;
8167 while (lo)
8168 result++, lo &= lo - 1;
8169 while (hi)
7e8d812e 8170 result++, hi &= (unsigned HOST_WIDE_INT) hi - 1;
70fb4c07 8171 result &= 1;
8172 break;
8173
8174 default:
64db345d 8175 gcc_unreachable ();
70fb4c07 8176 }
8177
2426241c 8178 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
70fb4c07 8179 }
8180
8181 return NULL_TREE;
8182}
8183
74bdbe96 8184/* Fold function call to builtin_bswap and the short, long and long long
42791117 8185 variants. Return NULL_TREE if no simplification can be made. */
8186static tree
c2f47e15 8187fold_builtin_bswap (tree fndecl, tree arg)
42791117 8188{
c2f47e15 8189 if (! validate_arg (arg, INTEGER_TYPE))
8190 return NULL_TREE;
42791117 8191
8192 /* Optimize constant value. */
f96bd2bf 8193 if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
42791117 8194 {
8195 HOST_WIDE_INT hi, width, r_hi = 0;
8196 unsigned HOST_WIDE_INT lo, r_lo = 0;
74bdbe96 8197 tree type = TREE_TYPE (TREE_TYPE (fndecl));
42791117 8198
42791117 8199 width = TYPE_PRECISION (type);
8200 lo = TREE_INT_CST_LOW (arg);
8201 hi = TREE_INT_CST_HIGH (arg);
8202
8203 switch (DECL_FUNCTION_CODE (fndecl))
8204 {
74bdbe96 8205 case BUILT_IN_BSWAP16:
42791117 8206 case BUILT_IN_BSWAP32:
8207 case BUILT_IN_BSWAP64:
8208 {
8209 int s;
8210
8211 for (s = 0; s < width; s += 8)
8212 {
8213 int d = width - s - 8;
8214 unsigned HOST_WIDE_INT byte;
8215
8216 if (s < HOST_BITS_PER_WIDE_INT)
8217 byte = (lo >> s) & 0xff;
8218 else
8219 byte = (hi >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff;
8220
8221 if (d < HOST_BITS_PER_WIDE_INT)
8222 r_lo |= byte << d;
8223 else
8224 r_hi |= byte << (d - HOST_BITS_PER_WIDE_INT);
8225 }
8226 }
8227
8228 break;
8229
8230 default:
8231 gcc_unreachable ();
8232 }
8233
8234 if (width < HOST_BITS_PER_WIDE_INT)
74bdbe96 8235 return build_int_cst (type, r_lo);
42791117 8236 else
74bdbe96 8237 return build_int_cst_wide (type, r_lo, r_hi);
42791117 8238 }
8239
8240 return NULL_TREE;
8241}
c2f47e15 8242
8918c507 8243/* A subroutine of fold_builtin to fold the various logarithmic
29f4cd78 8244 functions. Return NULL_TREE if no simplification can me made.
8245 FUNC is the corresponding MPFR logarithm function. */
8918c507 8246
8247static tree
389dd41b 8248fold_builtin_logarithm (location_t loc, tree fndecl, tree arg,
29f4cd78 8249 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8250{
c2f47e15 8251 if (validate_arg (arg, REAL_TYPE))
8918c507 8252 {
8918c507 8253 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8254 tree res;
8918c507 8255 const enum built_in_function fcode = builtin_mathfn_code (arg);
0862b7e9 8256
29f4cd78 8257 /* Calculate the result when the argument is a constant. */
8258 if ((res = do_mpfr_arg1 (arg, type, func, &dconst0, NULL, false)))
8259 return res;
8260
8918c507 8261 /* Special case, optimize logN(expN(x)) = x. */
8262 if (flag_unsafe_math_optimizations
29f4cd78 8263 && ((func == mpfr_log
8918c507 8264 && (fcode == BUILT_IN_EXP
8265 || fcode == BUILT_IN_EXPF
8266 || fcode == BUILT_IN_EXPL))
29f4cd78 8267 || (func == mpfr_log2
8918c507 8268 && (fcode == BUILT_IN_EXP2
8269 || fcode == BUILT_IN_EXP2F
8270 || fcode == BUILT_IN_EXP2L))
29f4cd78 8271 || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode)))))
389dd41b 8272 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
8918c507 8273
ca273d4a 8274 /* Optimize logN(func()) for various exponential functions. We
a0c938f0 8275 want to determine the value "x" and the power "exponent" in
8276 order to transform logN(x**exponent) into exponent*logN(x). */
8918c507 8277 if (flag_unsafe_math_optimizations)
a0c938f0 8278 {
8918c507 8279 tree exponent = 0, x = 0;
0862b7e9 8280
8918c507 8281 switch (fcode)
8282 {
4f35b1fc 8283 CASE_FLT_FN (BUILT_IN_EXP):
8918c507 8284 /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
48e1416a 8285 x = build_real (type, real_value_truncate (TYPE_MODE (type),
7910b2fb 8286 dconst_e ()));
c2f47e15 8287 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8288 break;
4f35b1fc 8289 CASE_FLT_FN (BUILT_IN_EXP2):
8918c507 8290 /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */
8291 x = build_real (type, dconst2);
c2f47e15 8292 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8293 break;
4f35b1fc 8294 CASE_FLT_FN (BUILT_IN_EXP10):
8295 CASE_FLT_FN (BUILT_IN_POW10):
8918c507 8296 /* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */
3fa759a9 8297 {
8298 REAL_VALUE_TYPE dconst10;
8299 real_from_integer (&dconst10, VOIDmode, 10, 0, 0);
8300 x = build_real (type, dconst10);
8301 }
c2f47e15 8302 exponent = CALL_EXPR_ARG (arg, 0);
8918c507 8303 break;
4f35b1fc 8304 CASE_FLT_FN (BUILT_IN_SQRT):
8918c507 8305 /* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */
c2f47e15 8306 x = CALL_EXPR_ARG (arg, 0);
8918c507 8307 exponent = build_real (type, dconsthalf);
8308 break;
4f35b1fc 8309 CASE_FLT_FN (BUILT_IN_CBRT):
8918c507 8310 /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */
c2f47e15 8311 x = CALL_EXPR_ARG (arg, 0);
8918c507 8312 exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
7910b2fb 8313 dconst_third ()));
8918c507 8314 break;
4f35b1fc 8315 CASE_FLT_FN (BUILT_IN_POW):
8918c507 8316 /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x). */
c2f47e15 8317 x = CALL_EXPR_ARG (arg, 0);
8318 exponent = CALL_EXPR_ARG (arg, 1);
8918c507 8319 break;
8320 default:
8321 break;
8322 }
8323
8324 /* Now perform the optimization. */
8325 if (x && exponent)
8326 {
389dd41b 8327 tree logfn = build_call_expr_loc (loc, fndecl, 1, x);
8328 return fold_build2_loc (loc, MULT_EXPR, type, exponent, logfn);
8918c507 8329 }
8330 }
8331 }
8332
c2f47e15 8333 return NULL_TREE;
8918c507 8334}
0862b7e9 8335
f0c477f2 8336/* Fold a builtin function call to hypot, hypotf, or hypotl. Return
8337 NULL_TREE if no simplification can be made. */
8338
8339static tree
389dd41b 8340fold_builtin_hypot (location_t loc, tree fndecl,
8341 tree arg0, tree arg1, tree type)
f0c477f2 8342{
e6ab33d8 8343 tree res, narg0, narg1;
f0c477f2 8344
c2f47e15 8345 if (!validate_arg (arg0, REAL_TYPE)
8346 || !validate_arg (arg1, REAL_TYPE))
f0c477f2 8347 return NULL_TREE;
8348
8349 /* Calculate the result when the argument is a constant. */
8350 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot)))
8351 return res;
48e1416a 8352
6c95f21c 8353 /* If either argument to hypot has a negate or abs, strip that off.
8354 E.g. hypot(-x,fabs(y)) -> hypot(x,y). */
e6ab33d8 8355 narg0 = fold_strip_sign_ops (arg0);
8356 narg1 = fold_strip_sign_ops (arg1);
8357 if (narg0 || narg1)
8358 {
48e1416a 8359 return build_call_expr_loc (loc, fndecl, 2, narg0 ? narg0 : arg0,
c2f47e15 8360 narg1 ? narg1 : arg1);
6c95f21c 8361 }
48e1416a 8362
f0c477f2 8363 /* If either argument is zero, hypot is fabs of the other. */
8364 if (real_zerop (arg0))
389dd41b 8365 return fold_build1_loc (loc, ABS_EXPR, type, arg1);
f0c477f2 8366 else if (real_zerop (arg1))
389dd41b 8367 return fold_build1_loc (loc, ABS_EXPR, type, arg0);
48e1416a 8368
6c95f21c 8369 /* hypot(x,x) -> fabs(x)*sqrt(2). */
8370 if (flag_unsafe_math_optimizations
8371 && operand_equal_p (arg0, arg1, OEP_PURE_SAME))
f0c477f2 8372 {
2e7ca27b 8373 const REAL_VALUE_TYPE sqrt2_trunc
7910b2fb 8374 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
389dd41b 8375 return fold_build2_loc (loc, MULT_EXPR, type,
8376 fold_build1_loc (loc, ABS_EXPR, type, arg0),
2e7ca27b 8377 build_real (type, sqrt2_trunc));
f0c477f2 8378 }
8379
f0c477f2 8380 return NULL_TREE;
8381}
8382
8383
e6e27594 8384/* Fold a builtin function call to pow, powf, or powl. Return
8385 NULL_TREE if no simplification can be made. */
8386static tree
389dd41b 8387fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
e6e27594 8388{
f0c477f2 8389 tree res;
e6e27594 8390
c2f47e15 8391 if (!validate_arg (arg0, REAL_TYPE)
8392 || !validate_arg (arg1, REAL_TYPE))
e6e27594 8393 return NULL_TREE;
8394
f0c477f2 8395 /* Calculate the result when the argument is a constant. */
8396 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_pow)))
8397 return res;
8398
e6e27594 8399 /* Optimize pow(1.0,y) = 1.0. */
8400 if (real_onep (arg0))
389dd41b 8401 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
e6e27594 8402
8403 if (TREE_CODE (arg1) == REAL_CST
f96bd2bf 8404 && !TREE_OVERFLOW (arg1))
e6e27594 8405 {
198d9bbe 8406 REAL_VALUE_TYPE cint;
e6e27594 8407 REAL_VALUE_TYPE c;
198d9bbe 8408 HOST_WIDE_INT n;
8409
e6e27594 8410 c = TREE_REAL_CST (arg1);
8411
8412 /* Optimize pow(x,0.0) = 1.0. */
8413 if (REAL_VALUES_EQUAL (c, dconst0))
389dd41b 8414 return omit_one_operand_loc (loc, type, build_real (type, dconst1),
e6e27594 8415 arg0);
8416
8417 /* Optimize pow(x,1.0) = x. */
8418 if (REAL_VALUES_EQUAL (c, dconst1))
8419 return arg0;
8420
8421 /* Optimize pow(x,-1.0) = 1.0/x. */
8422 if (REAL_VALUES_EQUAL (c, dconstm1))
389dd41b 8423 return fold_build2_loc (loc, RDIV_EXPR, type,
49d00087 8424 build_real (type, dconst1), arg0);
e6e27594 8425
8426 /* Optimize pow(x,0.5) = sqrt(x). */
8427 if (flag_unsafe_math_optimizations
8428 && REAL_VALUES_EQUAL (c, dconsthalf))
8429 {
8430 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
8431
8432 if (sqrtfn != NULL_TREE)
389dd41b 8433 return build_call_expr_loc (loc, sqrtfn, 1, arg0);
e6e27594 8434 }
8435
feb5b3eb 8436 /* Optimize pow(x,1.0/3.0) = cbrt(x). */
8437 if (flag_unsafe_math_optimizations)
8438 {
8439 const REAL_VALUE_TYPE dconstroot
7910b2fb 8440 = real_value_truncate (TYPE_MODE (type), dconst_third ());
feb5b3eb 8441
8442 if (REAL_VALUES_EQUAL (c, dconstroot))
8443 {
8444 tree cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT);
8445 if (cbrtfn != NULL_TREE)
389dd41b 8446 return build_call_expr_loc (loc, cbrtfn, 1, arg0);
feb5b3eb 8447 }
8448 }
8449
198d9bbe 8450 /* Check for an integer exponent. */
8451 n = real_to_integer (&c);
8452 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
8453 if (real_identical (&c, &cint))
e6e27594 8454 {
a2b30b48 8455 /* Attempt to evaluate pow at compile-time, unless this should
8456 raise an exception. */
198d9bbe 8457 if (TREE_CODE (arg0) == REAL_CST
a2b30b48 8458 && !TREE_OVERFLOW (arg0)
8459 && (n > 0
8460 || (!flag_trapping_math && !flag_errno_math)
8461 || !REAL_VALUES_EQUAL (TREE_REAL_CST (arg0), dconst0)))
e6e27594 8462 {
8463 REAL_VALUE_TYPE x;
8464 bool inexact;
8465
8466 x = TREE_REAL_CST (arg0);
8467 inexact = real_powi (&x, TYPE_MODE (type), &x, n);
8468 if (flag_unsafe_math_optimizations || !inexact)
8469 return build_real (type, x);
8470 }
198d9bbe 8471
8472 /* Strip sign ops from even integer powers. */
8473 if ((n & 1) == 0 && flag_unsafe_math_optimizations)
8474 {
8475 tree narg0 = fold_strip_sign_ops (arg0);
8476 if (narg0)
389dd41b 8477 return build_call_expr_loc (loc, fndecl, 2, narg0, arg1);
198d9bbe 8478 }
e6e27594 8479 }
8480 }
8481
cdfeb715 8482 if (flag_unsafe_math_optimizations)
e6e27594 8483 {
cdfeb715 8484 const enum built_in_function fcode = builtin_mathfn_code (arg0);
e6e27594 8485
cdfeb715 8486 /* Optimize pow(expN(x),y) = expN(x*y). */
8487 if (BUILTIN_EXPONENT_P (fcode))
a0c938f0 8488 {
c2f47e15 8489 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
8490 tree arg = CALL_EXPR_ARG (arg0, 0);
389dd41b 8491 arg = fold_build2_loc (loc, MULT_EXPR, type, arg, arg1);
8492 return build_call_expr_loc (loc, expfn, 1, arg);
cdfeb715 8493 }
e6e27594 8494
cdfeb715 8495 /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
8496 if (BUILTIN_SQRT_P (fcode))
a0c938f0 8497 {
c2f47e15 8498 tree narg0 = CALL_EXPR_ARG (arg0, 0);
389dd41b 8499 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 8500 build_real (type, dconsthalf));
389dd41b 8501 return build_call_expr_loc (loc, fndecl, 2, narg0, narg1);
cdfeb715 8502 }
8503
8504 /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */
8505 if (BUILTIN_CBRT_P (fcode))
a0c938f0 8506 {
c2f47e15 8507 tree arg = CALL_EXPR_ARG (arg0, 0);
cdfeb715 8508 if (tree_expr_nonnegative_p (arg))
8509 {
8510 const REAL_VALUE_TYPE dconstroot
7910b2fb 8511 = real_value_truncate (TYPE_MODE (type), dconst_third ());
389dd41b 8512 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
49d00087 8513 build_real (type, dconstroot));
389dd41b 8514 return build_call_expr_loc (loc, fndecl, 2, arg, narg1);
cdfeb715 8515 }
8516 }
a0c938f0 8517
49e436b5 8518 /* Optimize pow(pow(x,y),z) = pow(x,y*z) iff x is nonnegative. */
c2f47e15 8519 if (fcode == BUILT_IN_POW
8520 || fcode == BUILT_IN_POWF
8521 || fcode == BUILT_IN_POWL)
a0c938f0 8522 {
c2f47e15 8523 tree arg00 = CALL_EXPR_ARG (arg0, 0);
49e436b5 8524 if (tree_expr_nonnegative_p (arg00))
8525 {
8526 tree arg01 = CALL_EXPR_ARG (arg0, 1);
8527 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg01, arg1);
8528 return build_call_expr_loc (loc, fndecl, 2, arg00, narg1);
8529 }
cdfeb715 8530 }
e6e27594 8531 }
cdfeb715 8532
e6e27594 8533 return NULL_TREE;
8534}
8535
c2f47e15 8536/* Fold a builtin function call to powi, powif, or powil with argument ARG.
8537 Return NULL_TREE if no simplification can be made. */
b4d0c20c 8538static tree
389dd41b 8539fold_builtin_powi (location_t loc, tree fndecl ATTRIBUTE_UNUSED,
c2f47e15 8540 tree arg0, tree arg1, tree type)
b4d0c20c 8541{
c2f47e15 8542 if (!validate_arg (arg0, REAL_TYPE)
8543 || !validate_arg (arg1, INTEGER_TYPE))
b4d0c20c 8544 return NULL_TREE;
8545
8546 /* Optimize pow(1.0,y) = 1.0. */
8547 if (real_onep (arg0))
389dd41b 8548 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1);
b4d0c20c 8549
8550 if (host_integerp (arg1, 0))
8551 {
8552 HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
8553
8554 /* Evaluate powi at compile-time. */
8555 if (TREE_CODE (arg0) == REAL_CST
f96bd2bf 8556 && !TREE_OVERFLOW (arg0))
b4d0c20c 8557 {
8558 REAL_VALUE_TYPE x;
8559 x = TREE_REAL_CST (arg0);
8560 real_powi (&x, TYPE_MODE (type), &x, c);
8561 return build_real (type, x);
8562 }
8563
8564 /* Optimize pow(x,0) = 1.0. */
8565 if (c == 0)
389dd41b 8566 return omit_one_operand_loc (loc, type, build_real (type, dconst1),
b4d0c20c 8567 arg0);
8568
8569 /* Optimize pow(x,1) = x. */
8570 if (c == 1)
8571 return arg0;
8572
8573 /* Optimize pow(x,-1) = 1.0/x. */
8574 if (c == -1)
389dd41b 8575 return fold_build2_loc (loc, RDIV_EXPR, type,
49d00087 8576 build_real (type, dconst1), arg0);
b4d0c20c 8577 }
8578
8579 return NULL_TREE;
8580}
8581
8918c507 8582/* A subroutine of fold_builtin to fold the various exponent
c2f47e15 8583 functions. Return NULL_TREE if no simplification can be made.
debf9994 8584 FUNC is the corresponding MPFR exponent function. */
8918c507 8585
8586static tree
389dd41b 8587fold_builtin_exponent (location_t loc, tree fndecl, tree arg,
debf9994 8588 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
8918c507 8589{
c2f47e15 8590 if (validate_arg (arg, REAL_TYPE))
8918c507 8591 {
8918c507 8592 tree type = TREE_TYPE (TREE_TYPE (fndecl));
29f4cd78 8593 tree res;
48e1416a 8594
debf9994 8595 /* Calculate the result when the argument is a constant. */
728bac60 8596 if ((res = do_mpfr_arg1 (arg, type, func, NULL, NULL, 0)))
debf9994 8597 return res;
8918c507 8598
8599 /* Optimize expN(logN(x)) = x. */
8600 if (flag_unsafe_math_optimizations)
a0c938f0 8601 {
8918c507 8602 const enum built_in_function fcode = builtin_mathfn_code (arg);
8603
debf9994 8604 if ((func == mpfr_exp
8918c507 8605 && (fcode == BUILT_IN_LOG
8606 || fcode == BUILT_IN_LOGF
8607 || fcode == BUILT_IN_LOGL))
debf9994 8608 || (func == mpfr_exp2
8918c507 8609 && (fcode == BUILT_IN_LOG2
8610 || fcode == BUILT_IN_LOG2F
8611 || fcode == BUILT_IN_LOG2L))
debf9994 8612 || (func == mpfr_exp10
8918c507 8613 && (fcode == BUILT_IN_LOG10
8614 || fcode == BUILT_IN_LOG10F
8615 || fcode == BUILT_IN_LOG10L)))
389dd41b 8616 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
8918c507 8617 }
8618 }
8619
c2f47e15 8620 return NULL_TREE;
8918c507 8621}
8622
e973ffcc 8623/* Return true if VAR is a VAR_DECL or a component thereof. */
8624
8625static bool
8626var_decl_component_p (tree var)
8627{
8628 tree inner = var;
8629 while (handled_component_p (inner))
8630 inner = TREE_OPERAND (inner, 0);
8631 return SSA_VAR_P (inner);
8632}
8633
4f46f2b9 8634/* Fold function call to builtin memset. Return
9c8a1629 8635 NULL_TREE if no simplification can be made. */
8636
8637static tree
389dd41b 8638fold_builtin_memset (location_t loc, tree dest, tree c, tree len,
8639 tree type, bool ignore)
9c8a1629 8640{
45bb3afb 8641 tree var, ret, etype;
4f46f2b9 8642 unsigned HOST_WIDE_INT length, cval;
9c8a1629 8643
c2f47e15 8644 if (! validate_arg (dest, POINTER_TYPE)
8645 || ! validate_arg (c, INTEGER_TYPE)
8646 || ! validate_arg (len, INTEGER_TYPE))
8647 return NULL_TREE;
9c8a1629 8648
4f46f2b9 8649 if (! host_integerp (len, 1))
c2f47e15 8650 return NULL_TREE;
4f46f2b9 8651
9c8a1629 8652 /* If the LEN parameter is zero, return DEST. */
8653 if (integer_zerop (len))
389dd41b 8654 return omit_one_operand_loc (loc, type, dest, c);
9c8a1629 8655
d5d2f74a 8656 if (TREE_CODE (c) != INTEGER_CST || TREE_SIDE_EFFECTS (dest))
c2f47e15 8657 return NULL_TREE;
9c8a1629 8658
4f46f2b9 8659 var = dest;
8660 STRIP_NOPS (var);
8661 if (TREE_CODE (var) != ADDR_EXPR)
c2f47e15 8662 return NULL_TREE;
4f46f2b9 8663
8664 var = TREE_OPERAND (var, 0);
8665 if (TREE_THIS_VOLATILE (var))
c2f47e15 8666 return NULL_TREE;
4f46f2b9 8667
45bb3afb 8668 etype = TREE_TYPE (var);
8669 if (TREE_CODE (etype) == ARRAY_TYPE)
8670 etype = TREE_TYPE (etype);
8671
8672 if (!INTEGRAL_TYPE_P (etype)
8673 && !POINTER_TYPE_P (etype))
c2f47e15 8674 return NULL_TREE;
4f46f2b9 8675
e973ffcc 8676 if (! var_decl_component_p (var))
c2f47e15 8677 return NULL_TREE;
e973ffcc 8678
4f46f2b9 8679 length = tree_low_cst (len, 1);
45bb3afb 8680 if (GET_MODE_SIZE (TYPE_MODE (etype)) != length
957d0361 8681 || get_pointer_alignment (dest) / BITS_PER_UNIT < length)
c2f47e15 8682 return NULL_TREE;
4f46f2b9 8683
8684 if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT)
c2f47e15 8685 return NULL_TREE;
4f46f2b9 8686
8687 if (integer_zerop (c))
8688 cval = 0;
8689 else
8690 {
8691 if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64)
c2f47e15 8692 return NULL_TREE;
4f46f2b9 8693
d5d2f74a 8694 cval = TREE_INT_CST_LOW (c);
4f46f2b9 8695 cval &= 0xff;
8696 cval |= cval << 8;
8697 cval |= cval << 16;
8698 cval |= (cval << 31) << 1;
8699 }
8700
45bb3afb 8701 ret = build_int_cst_type (etype, cval);
389dd41b 8702 var = build_fold_indirect_ref_loc (loc,
8703 fold_convert_loc (loc,
8704 build_pointer_type (etype),
8705 dest));
45bb3afb 8706 ret = build2 (MODIFY_EXPR, etype, var, ret);
4f46f2b9 8707 if (ignore)
8708 return ret;
8709
389dd41b 8710 return omit_one_operand_loc (loc, type, dest, ret);
9c8a1629 8711}
8712
4f46f2b9 8713/* Fold function call to builtin memset. Return
9c8a1629 8714 NULL_TREE if no simplification can be made. */
8715
8716static tree
389dd41b 8717fold_builtin_bzero (location_t loc, tree dest, tree size, bool ignore)
9c8a1629 8718{
c2f47e15 8719 if (! validate_arg (dest, POINTER_TYPE)
8720 || ! validate_arg (size, INTEGER_TYPE))
8721 return NULL_TREE;
9c8a1629 8722
4f46f2b9 8723 if (!ignore)
c2f47e15 8724 return NULL_TREE;
a0c938f0 8725
4f46f2b9 8726 /* New argument list transforming bzero(ptr x, int y) to
8727 memset(ptr x, int 0, size_t y). This is done this way
8728 so that if it isn't expanded inline, we fallback to
8729 calling bzero instead of memset. */
8730
389dd41b 8731 return fold_builtin_memset (loc, dest, integer_zero_node,
a0553bff 8732 fold_convert_loc (loc, size_type_node, size),
c2f47e15 8733 void_type_node, ignore);
9c8a1629 8734}
8735
4f46f2b9 8736/* Fold function call to builtin mem{{,p}cpy,move}. Return
8737 NULL_TREE if no simplification can be made.
8738 If ENDP is 0, return DEST (like memcpy).
8739 If ENDP is 1, return DEST+LEN (like mempcpy).
8740 If ENDP is 2, return DEST+LEN-1 (like stpcpy).
8741 If ENDP is 3, return DEST, additionally *SRC and *DEST may overlap
8742 (memmove). */
9c8a1629 8743
8744static tree
389dd41b 8745fold_builtin_memory_op (location_t loc, tree dest, tree src,
8746 tree len, tree type, bool ignore, int endp)
9c8a1629 8747{
c2f47e15 8748 tree destvar, srcvar, expr;
9c8a1629 8749
c2f47e15 8750 if (! validate_arg (dest, POINTER_TYPE)
8751 || ! validate_arg (src, POINTER_TYPE)
8752 || ! validate_arg (len, INTEGER_TYPE))
8753 return NULL_TREE;
9c8a1629 8754
8755 /* If the LEN parameter is zero, return DEST. */
8756 if (integer_zerop (len))
389dd41b 8757 return omit_one_operand_loc (loc, type, dest, src);
9c8a1629 8758
4f46f2b9 8759 /* If SRC and DEST are the same (and not volatile), return
8760 DEST{,+LEN,+LEN-1}. */
9c8a1629 8761 if (operand_equal_p (src, dest, 0))
4f46f2b9 8762 expr = len;
8763 else
8764 {
5a84fdd6 8765 tree srctype, desttype;
153c3b50 8766 unsigned int src_align, dest_align;
182cf5a9 8767 tree off0;
5383fb56 8768
3b1757a2 8769 if (endp == 3)
8770 {
957d0361 8771 src_align = get_pointer_alignment (src);
8772 dest_align = get_pointer_alignment (dest);
5a84fdd6 8773
48e1416a 8774 /* Both DEST and SRC must be pointer types.
3b1757a2 8775 ??? This is what old code did. Is the testing for pointer types
8776 really mandatory?
8777
8778 If either SRC is readonly or length is 1, we can use memcpy. */
3f95c690 8779 if (!dest_align || !src_align)
8780 return NULL_TREE;
8781 if (readonly_data_expr (src)
8782 || (host_integerp (len, 1)
8783 && (MIN (src_align, dest_align) / BITS_PER_UNIT
12c655b1 8784 >= (unsigned HOST_WIDE_INT) tree_low_cst (len, 1))))
3b1757a2 8785 {
b9a16870 8786 tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
3b1757a2 8787 if (!fn)
c2f47e15 8788 return NULL_TREE;
389dd41b 8789 return build_call_expr_loc (loc, fn, 3, dest, src, len);
3b1757a2 8790 }
3f95c690 8791
8792 /* If *src and *dest can't overlap, optimize into memcpy as well. */
182cf5a9 8793 if (TREE_CODE (src) == ADDR_EXPR
8794 && TREE_CODE (dest) == ADDR_EXPR)
3f95c690 8795 {
f85fb819 8796 tree src_base, dest_base, fn;
8797 HOST_WIDE_INT src_offset = 0, dest_offset = 0;
8798 HOST_WIDE_INT size = -1;
8799 HOST_WIDE_INT maxsize = -1;
8800
182cf5a9 8801 srcvar = TREE_OPERAND (src, 0);
8802 src_base = get_ref_base_and_extent (srcvar, &src_offset,
8803 &size, &maxsize);
8804 destvar = TREE_OPERAND (dest, 0);
8805 dest_base = get_ref_base_and_extent (destvar, &dest_offset,
8806 &size, &maxsize);
f85fb819 8807 if (host_integerp (len, 1))
182cf5a9 8808 maxsize = tree_low_cst (len, 1);
f85fb819 8809 else
8810 maxsize = -1;
182cf5a9 8811 src_offset /= BITS_PER_UNIT;
8812 dest_offset /= BITS_PER_UNIT;
f85fb819 8813 if (SSA_VAR_P (src_base)
8814 && SSA_VAR_P (dest_base))
8815 {
8816 if (operand_equal_p (src_base, dest_base, 0)
8817 && ranges_overlap_p (src_offset, maxsize,
8818 dest_offset, maxsize))
8819 return NULL_TREE;
8820 }
182cf5a9 8821 else if (TREE_CODE (src_base) == MEM_REF
8822 && TREE_CODE (dest_base) == MEM_REF)
f85fb819 8823 {
182cf5a9 8824 double_int off;
f85fb819 8825 if (! operand_equal_p (TREE_OPERAND (src_base, 0),
182cf5a9 8826 TREE_OPERAND (dest_base, 0), 0))
8827 return NULL_TREE;
cf8f0e63 8828 off = mem_ref_offset (src_base) +
8829 double_int::from_shwi (src_offset);
8830 if (!off.fits_shwi ())
182cf5a9 8831 return NULL_TREE;
8832 src_offset = off.low;
cf8f0e63 8833 off = mem_ref_offset (dest_base) +
8834 double_int::from_shwi (dest_offset);
8835 if (!off.fits_shwi ())
182cf5a9 8836 return NULL_TREE;
8837 dest_offset = off.low;
8838 if (ranges_overlap_p (src_offset, maxsize,
8839 dest_offset, maxsize))
f85fb819 8840 return NULL_TREE;
8841 }
8842 else
8843 return NULL_TREE;
8844
b9a16870 8845 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
3f95c690 8846 if (!fn)
8847 return NULL_TREE;
389dd41b 8848 return build_call_expr_loc (loc, fn, 3, dest, src, len);
3f95c690 8849 }
c4222b63 8850
8851 /* If the destination and source do not alias optimize into
8852 memcpy as well. */
8853 if ((is_gimple_min_invariant (dest)
8854 || TREE_CODE (dest) == SSA_NAME)
8855 && (is_gimple_min_invariant (src)
8856 || TREE_CODE (src) == SSA_NAME))
8857 {
8858 ao_ref destr, srcr;
8859 ao_ref_init_from_ptr_and_size (&destr, dest, len);
8860 ao_ref_init_from_ptr_and_size (&srcr, src, len);
8861 if (!refs_may_alias_p_1 (&destr, &srcr, false))
8862 {
8863 tree fn;
b9a16870 8864 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
c4222b63 8865 if (!fn)
8866 return NULL_TREE;
8867 return build_call_expr_loc (loc, fn, 3, dest, src, len);
8868 }
8869 }
8870
c2f47e15 8871 return NULL_TREE;
3b1757a2 8872 }
4f46f2b9 8873
5a84fdd6 8874 if (!host_integerp (len, 0))
c2f47e15 8875 return NULL_TREE;
5a84fdd6 8876 /* FIXME:
8877 This logic lose for arguments like (type *)malloc (sizeof (type)),
8878 since we strip the casts of up to VOID return value from malloc.
8879 Perhaps we ought to inherit type from non-VOID argument here? */
8880 STRIP_NOPS (src);
8881 STRIP_NOPS (dest);
e07c7898 8882 if (!POINTER_TYPE_P (TREE_TYPE (src))
8883 || !POINTER_TYPE_P (TREE_TYPE (dest)))
8884 return NULL_TREE;
45bb3afb 8885 /* As we fold (void *)(p + CST) to (void *)p + CST undo this here. */
8886 if (TREE_CODE (src) == POINTER_PLUS_EXPR)
8887 {
8888 tree tem = TREE_OPERAND (src, 0);
8889 STRIP_NOPS (tem);
8890 if (tem != TREE_OPERAND (src, 0))
8891 src = build1 (NOP_EXPR, TREE_TYPE (tem), src);
8892 }
8893 if (TREE_CODE (dest) == POINTER_PLUS_EXPR)
8894 {
8895 tree tem = TREE_OPERAND (dest, 0);
8896 STRIP_NOPS (tem);
8897 if (tem != TREE_OPERAND (dest, 0))
8898 dest = build1 (NOP_EXPR, TREE_TYPE (tem), dest);
8899 }
5a84fdd6 8900 srctype = TREE_TYPE (TREE_TYPE (src));
e07c7898 8901 if (TREE_CODE (srctype) == ARRAY_TYPE
97d4c6a6 8902 && !tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
45bb3afb 8903 {
8904 srctype = TREE_TYPE (srctype);
8905 STRIP_NOPS (src);
8906 src = build1 (NOP_EXPR, build_pointer_type (srctype), src);
8907 }
5a84fdd6 8908 desttype = TREE_TYPE (TREE_TYPE (dest));
e07c7898 8909 if (TREE_CODE (desttype) == ARRAY_TYPE
97d4c6a6 8910 && !tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
45bb3afb 8911 {
8912 desttype = TREE_TYPE (desttype);
8913 STRIP_NOPS (dest);
8914 dest = build1 (NOP_EXPR, build_pointer_type (desttype), dest);
8915 }
e07c7898 8916 if (TREE_ADDRESSABLE (srctype)
8917 || TREE_ADDRESSABLE (desttype))
c2f47e15 8918 return NULL_TREE;
4f46f2b9 8919
957d0361 8920 src_align = get_pointer_alignment (src);
8921 dest_align = get_pointer_alignment (dest);
153c3b50 8922 if (dest_align < TYPE_ALIGN (desttype)
8923 || src_align < TYPE_ALIGN (srctype))
c2f47e15 8924 return NULL_TREE;
e973ffcc 8925
5a84fdd6 8926 if (!ignore)
8927 dest = builtin_save_expr (dest);
4f46f2b9 8928
182cf5a9 8929 /* Build accesses at offset zero with a ref-all character type. */
8930 off0 = build_int_cst (build_pointer_type_for_mode (char_type_node,
8931 ptr_mode, true), 0);
4f46f2b9 8932
182cf5a9 8933 destvar = dest;
8934 STRIP_NOPS (destvar);
8935 if (TREE_CODE (destvar) == ADDR_EXPR
8936 && var_decl_component_p (TREE_OPERAND (destvar, 0))
8937 && tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
8938 destvar = fold_build2 (MEM_REF, desttype, destvar, off0);
8939 else
8940 destvar = NULL_TREE;
8941
8942 srcvar = src;
8943 STRIP_NOPS (srcvar);
8944 if (TREE_CODE (srcvar) == ADDR_EXPR
8945 && var_decl_component_p (TREE_OPERAND (srcvar, 0))
5b99ff01 8946 && tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
8947 {
8948 if (!destvar
8949 || src_align >= TYPE_ALIGN (desttype))
8950 srcvar = fold_build2 (MEM_REF, destvar ? desttype : srctype,
8951 srcvar, off0);
8952 else if (!STRICT_ALIGNMENT)
8953 {
8954 srctype = build_aligned_type (TYPE_MAIN_VARIANT (desttype),
8955 src_align);
8956 srcvar = fold_build2 (MEM_REF, srctype, srcvar, off0);
8957 }
8958 else
8959 srcvar = NULL_TREE;
8960 }
182cf5a9 8961 else
8962 srcvar = NULL_TREE;
5383fb56 8963
8964 if (srcvar == NULL_TREE && destvar == NULL_TREE)
c2f47e15 8965 return NULL_TREE;
4f46f2b9 8966
5383fb56 8967 if (srcvar == NULL_TREE)
8968 {
182cf5a9 8969 STRIP_NOPS (src);
5b99ff01 8970 if (src_align >= TYPE_ALIGN (desttype))
8971 srcvar = fold_build2 (MEM_REF, desttype, src, off0);
8972 else
8973 {
8974 if (STRICT_ALIGNMENT)
8975 return NULL_TREE;
8976 srctype = build_aligned_type (TYPE_MAIN_VARIANT (desttype),
8977 src_align);
8978 srcvar = fold_build2 (MEM_REF, srctype, src, off0);
8979 }
5383fb56 8980 }
8981 else if (destvar == NULL_TREE)
8982 {
182cf5a9 8983 STRIP_NOPS (dest);
5b99ff01 8984 if (dest_align >= TYPE_ALIGN (srctype))
8985 destvar = fold_build2 (MEM_REF, srctype, dest, off0);
8986 else
8987 {
8988 if (STRICT_ALIGNMENT)
8989 return NULL_TREE;
8990 desttype = build_aligned_type (TYPE_MAIN_VARIANT (srctype),
8991 dest_align);
8992 destvar = fold_build2 (MEM_REF, desttype, dest, off0);
8993 }
5383fb56 8994 }
8995
182cf5a9 8996 expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, srcvar);
4f46f2b9 8997 }
8998
8999 if (ignore)
9000 return expr;
9001
9002 if (endp == 0 || endp == 3)
389dd41b 9003 return omit_one_operand_loc (loc, type, dest, expr);
4f46f2b9 9004
9005 if (expr == len)
c2f47e15 9006 expr = NULL_TREE;
4f46f2b9 9007
9008 if (endp == 2)
389dd41b 9009 len = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (len), len,
4f46f2b9 9010 ssize_int (1));
9011
2cc66f2a 9012 dest = fold_build_pointer_plus_loc (loc, dest, len);
389dd41b 9013 dest = fold_convert_loc (loc, type, dest);
4f46f2b9 9014 if (expr)
389dd41b 9015 dest = omit_one_operand_loc (loc, type, dest, expr);
4f46f2b9 9016 return dest;
9017}
9018
c2f47e15 9019/* Fold function call to builtin strcpy with arguments DEST and SRC.
9020 If LEN is not NULL, it represents the length of the string to be
9021 copied. Return NULL_TREE if no simplification can be made. */
9c8a1629 9022
f0613857 9023tree
389dd41b 9024fold_builtin_strcpy (location_t loc, tree fndecl, tree dest, tree src, tree len)
9c8a1629 9025{
c2f47e15 9026 tree fn;
9c8a1629 9027
c2f47e15 9028 if (!validate_arg (dest, POINTER_TYPE)
9029 || !validate_arg (src, POINTER_TYPE))
9030 return NULL_TREE;
9c8a1629 9031
9032 /* If SRC and DEST are the same (and not volatile), return DEST. */
9033 if (operand_equal_p (src, dest, 0))
389dd41b 9034 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
9c8a1629 9035
0bfd8d5c 9036 if (optimize_function_for_size_p (cfun))
c2f47e15 9037 return NULL_TREE;
f0613857 9038
b9a16870 9039 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
f0613857 9040 if (!fn)
c2f47e15 9041 return NULL_TREE;
f0613857 9042
9043 if (!len)
9044 {
9045 len = c_strlen (src, 1);
9046 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 9047 return NULL_TREE;
f0613857 9048 }
9049
bd6dcc04 9050 len = fold_convert_loc (loc, size_type_node, len);
9051 len = size_binop_loc (loc, PLUS_EXPR, len, build_int_cst (size_type_node, 1));
389dd41b 9052 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
9053 build_call_expr_loc (loc, fn, 3, dest, src, len));
9c8a1629 9054}
9055
a65c4d64 9056/* Fold function call to builtin stpcpy with arguments DEST and SRC.
9057 Return NULL_TREE if no simplification can be made. */
9058
9059static tree
9060fold_builtin_stpcpy (location_t loc, tree fndecl, tree dest, tree src)
9061{
9062 tree fn, len, lenp1, call, type;
9063
9064 if (!validate_arg (dest, POINTER_TYPE)
9065 || !validate_arg (src, POINTER_TYPE))
9066 return NULL_TREE;
9067
9068 len = c_strlen (src, 1);
9069 if (!len
9070 || TREE_CODE (len) != INTEGER_CST)
9071 return NULL_TREE;
9072
9073 if (optimize_function_for_size_p (cfun)
9074 /* If length is zero it's small enough. */
9075 && !integer_zerop (len))
9076 return NULL_TREE;
9077
b9a16870 9078 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
a65c4d64 9079 if (!fn)
9080 return NULL_TREE;
9081
bd6dcc04 9082 lenp1 = size_binop_loc (loc, PLUS_EXPR,
9083 fold_convert_loc (loc, size_type_node, len),
9084 build_int_cst (size_type_node, 1));
a65c4d64 9085 /* We use dest twice in building our expression. Save it from
9086 multiple expansions. */
9087 dest = builtin_save_expr (dest);
9088 call = build_call_expr_loc (loc, fn, 3, dest, src, lenp1);
9089
9090 type = TREE_TYPE (TREE_TYPE (fndecl));
2cc66f2a 9091 dest = fold_build_pointer_plus_loc (loc, dest, len);
a65c4d64 9092 dest = fold_convert_loc (loc, type, dest);
9093 dest = omit_one_operand_loc (loc, type, dest, call);
9094 return dest;
9095}
9096
c2f47e15 9097/* Fold function call to builtin strncpy with arguments DEST, SRC, and LEN.
9098 If SLEN is not NULL, it represents the length of the source string.
9099 Return NULL_TREE if no simplification can be made. */
9c8a1629 9100
f0613857 9101tree
389dd41b 9102fold_builtin_strncpy (location_t loc, tree fndecl, tree dest,
9103 tree src, tree len, tree slen)
9c8a1629 9104{
c2f47e15 9105 tree fn;
9c8a1629 9106
c2f47e15 9107 if (!validate_arg (dest, POINTER_TYPE)
9108 || !validate_arg (src, POINTER_TYPE)
9109 || !validate_arg (len, INTEGER_TYPE))
9110 return NULL_TREE;
9c8a1629 9111
9112 /* If the LEN parameter is zero, return DEST. */
9113 if (integer_zerop (len))
389dd41b 9114 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
9c8a1629 9115
19226313 9116 /* We can't compare slen with len as constants below if len is not a
9117 constant. */
9118 if (len == 0 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 9119 return NULL_TREE;
19226313 9120
f0613857 9121 if (!slen)
9122 slen = c_strlen (src, 1);
9123
9124 /* Now, we must be passed a constant src ptr parameter. */
9125 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
c2f47e15 9126 return NULL_TREE;
f0613857 9127
389dd41b 9128 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1));
f0613857 9129
9130 /* We do not support simplification of this case, though we do
9131 support it when expanding trees into RTL. */
9132 /* FIXME: generate a call to __builtin_memset. */
9133 if (tree_int_cst_lt (slen, len))
c2f47e15 9134 return NULL_TREE;
f0613857 9135
9136 /* OK transform into builtin memcpy. */
b9a16870 9137 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
f0613857 9138 if (!fn)
c2f47e15 9139 return NULL_TREE;
bd6dcc04 9140
9141 len = fold_convert_loc (loc, size_type_node, len);
389dd41b 9142 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
9143 build_call_expr_loc (loc, fn, 3, dest, src, len));
9c8a1629 9144}
9145
7959b13b 9146/* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the
9147 arguments to the call, and TYPE is its return type.
9148 Return NULL_TREE if no simplification can be made. */
9149
9150static tree
389dd41b 9151fold_builtin_memchr (location_t loc, tree arg1, tree arg2, tree len, tree type)
7959b13b 9152{
9153 if (!validate_arg (arg1, POINTER_TYPE)
9154 || !validate_arg (arg2, INTEGER_TYPE)
9155 || !validate_arg (len, INTEGER_TYPE))
9156 return NULL_TREE;
9157 else
9158 {
9159 const char *p1;
9160
9161 if (TREE_CODE (arg2) != INTEGER_CST
9162 || !host_integerp (len, 1))
9163 return NULL_TREE;
9164
9165 p1 = c_getstr (arg1);
9166 if (p1 && compare_tree_int (len, strlen (p1) + 1) <= 0)
9167 {
9168 char c;
9169 const char *r;
9170 tree tem;
9171
9172 if (target_char_cast (arg2, &c))
9173 return NULL_TREE;
9174
609cab98 9175 r = (const char *) memchr (p1, c, tree_low_cst (len, 1));
7959b13b 9176
9177 if (r == NULL)
9178 return build_int_cst (TREE_TYPE (arg1), 0);
9179
2cc66f2a 9180 tem = fold_build_pointer_plus_hwi_loc (loc, arg1, r - p1);
389dd41b 9181 return fold_convert_loc (loc, type, tem);
7959b13b 9182 }
9183 return NULL_TREE;
9184 }
9185}
9186
c2f47e15 9187/* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
9188 Return NULL_TREE if no simplification can be made. */
9c8a1629 9189
9190static tree
389dd41b 9191fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
9c8a1629 9192{
c4fef134 9193 const char *p1, *p2;
9c8a1629 9194
c2f47e15 9195 if (!validate_arg (arg1, POINTER_TYPE)
9196 || !validate_arg (arg2, POINTER_TYPE)
9197 || !validate_arg (len, INTEGER_TYPE))
9198 return NULL_TREE;
9c8a1629 9199
9200 /* If the LEN parameter is zero, return zero. */
9201 if (integer_zerop (len))
389dd41b 9202 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
c4fef134 9203 arg1, arg2);
9c8a1629 9204
9205 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9206 if (operand_equal_p (arg1, arg2, 0))
389dd41b 9207 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
c4fef134 9208
9209 p1 = c_getstr (arg1);
9210 p2 = c_getstr (arg2);
9211
9212 /* If all arguments are constant, and the value of len is not greater
9213 than the lengths of arg1 and arg2, evaluate at compile-time. */
9214 if (host_integerp (len, 1) && p1 && p2
9215 && compare_tree_int (len, strlen (p1) + 1) <= 0
9216 && compare_tree_int (len, strlen (p2) + 1) <= 0)
9217 {
9218 const int r = memcmp (p1, p2, tree_low_cst (len, 1));
9219
9220 if (r > 0)
9221 return integer_one_node;
9222 else if (r < 0)
9223 return integer_minus_one_node;
9224 else
9225 return integer_zero_node;
9226 }
9227
9228 /* If len parameter is one, return an expression corresponding to
9229 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
9230 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
9231 {
9232 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9233 tree cst_uchar_ptr_node
9234 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9235
389dd41b 9236 tree ind1
9237 = fold_convert_loc (loc, integer_type_node,
9238 build1 (INDIRECT_REF, cst_uchar_node,
9239 fold_convert_loc (loc,
9240 cst_uchar_ptr_node,
c4fef134 9241 arg1)));
389dd41b 9242 tree ind2
9243 = fold_convert_loc (loc, integer_type_node,
9244 build1 (INDIRECT_REF, cst_uchar_node,
9245 fold_convert_loc (loc,
9246 cst_uchar_ptr_node,
c4fef134 9247 arg2)));
389dd41b 9248 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
c4fef134 9249 }
9c8a1629 9250
c2f47e15 9251 return NULL_TREE;
9c8a1629 9252}
9253
c2f47e15 9254/* Fold function call to builtin strcmp with arguments ARG1 and ARG2.
9255 Return NULL_TREE if no simplification can be made. */
9c8a1629 9256
9257static tree
389dd41b 9258fold_builtin_strcmp (location_t loc, tree arg1, tree arg2)
9c8a1629 9259{
9c8a1629 9260 const char *p1, *p2;
9261
c2f47e15 9262 if (!validate_arg (arg1, POINTER_TYPE)
9263 || !validate_arg (arg2, POINTER_TYPE))
9264 return NULL_TREE;
9c8a1629 9265
9266 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9267 if (operand_equal_p (arg1, arg2, 0))
c4fef134 9268 return integer_zero_node;
9c8a1629 9269
9270 p1 = c_getstr (arg1);
9271 p2 = c_getstr (arg2);
9272
9273 if (p1 && p2)
9274 {
9c8a1629 9275 const int i = strcmp (p1, p2);
9276 if (i < 0)
c4fef134 9277 return integer_minus_one_node;
9c8a1629 9278 else if (i > 0)
c4fef134 9279 return integer_one_node;
9c8a1629 9280 else
c4fef134 9281 return integer_zero_node;
9282 }
9283
9284 /* If the second arg is "", return *(const unsigned char*)arg1. */
9285 if (p2 && *p2 == '\0')
9286 {
9287 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9288 tree cst_uchar_ptr_node
9289 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9290
389dd41b 9291 return fold_convert_loc (loc, integer_type_node,
9292 build1 (INDIRECT_REF, cst_uchar_node,
9293 fold_convert_loc (loc,
9294 cst_uchar_ptr_node,
9295 arg1)));
c4fef134 9296 }
9297
9298 /* If the first arg is "", return -*(const unsigned char*)arg2. */
9299 if (p1 && *p1 == '\0')
9300 {
9301 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9302 tree cst_uchar_ptr_node
9303 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9304
389dd41b 9305 tree temp
9306 = fold_convert_loc (loc, integer_type_node,
9307 build1 (INDIRECT_REF, cst_uchar_node,
9308 fold_convert_loc (loc,
9309 cst_uchar_ptr_node,
c4fef134 9310 arg2)));
389dd41b 9311 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp);
9c8a1629 9312 }
9313
c2f47e15 9314 return NULL_TREE;
9c8a1629 9315}
9316
c2f47e15 9317/* Fold function call to builtin strncmp with arguments ARG1, ARG2, and LEN.
9318 Return NULL_TREE if no simplification can be made. */
9c8a1629 9319
9320static tree
389dd41b 9321fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len)
9c8a1629 9322{
9c8a1629 9323 const char *p1, *p2;
9324
c2f47e15 9325 if (!validate_arg (arg1, POINTER_TYPE)
9326 || !validate_arg (arg2, POINTER_TYPE)
9327 || !validate_arg (len, INTEGER_TYPE))
9328 return NULL_TREE;
9c8a1629 9329
9330 /* If the LEN parameter is zero, return zero. */
9331 if (integer_zerop (len))
389dd41b 9332 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node,
c4fef134 9333 arg1, arg2);
9c8a1629 9334
9335 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
9336 if (operand_equal_p (arg1, arg2, 0))
389dd41b 9337 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
9c8a1629 9338
9339 p1 = c_getstr (arg1);
9340 p2 = c_getstr (arg2);
9341
9342 if (host_integerp (len, 1) && p1 && p2)
9343 {
9c8a1629 9344 const int i = strncmp (p1, p2, tree_low_cst (len, 1));
c4fef134 9345 if (i > 0)
9346 return integer_one_node;
9347 else if (i < 0)
9348 return integer_minus_one_node;
9c8a1629 9349 else
c4fef134 9350 return integer_zero_node;
9351 }
9352
9353 /* If the second arg is "", and the length is greater than zero,
9354 return *(const unsigned char*)arg1. */
9355 if (p2 && *p2 == '\0'
9356 && TREE_CODE (len) == INTEGER_CST
9357 && tree_int_cst_sgn (len) == 1)
9358 {
9359 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9360 tree cst_uchar_ptr_node
9361 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9362
389dd41b 9363 return fold_convert_loc (loc, integer_type_node,
9364 build1 (INDIRECT_REF, cst_uchar_node,
9365 fold_convert_loc (loc,
9366 cst_uchar_ptr_node,
9367 arg1)));
c4fef134 9368 }
9369
9370 /* If the first arg is "", and the length is greater than zero,
9371 return -*(const unsigned char*)arg2. */
9372 if (p1 && *p1 == '\0'
9373 && TREE_CODE (len) == INTEGER_CST
9374 && tree_int_cst_sgn (len) == 1)
9375 {
9376 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9377 tree cst_uchar_ptr_node
9378 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9379
389dd41b 9380 tree temp = fold_convert_loc (loc, integer_type_node,
9381 build1 (INDIRECT_REF, cst_uchar_node,
9382 fold_convert_loc (loc,
9383 cst_uchar_ptr_node,
9384 arg2)));
9385 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp);
c4fef134 9386 }
9387
9388 /* If len parameter is one, return an expression corresponding to
9389 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
9390 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
9391 {
9392 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
4f1b71c0 9393 tree cst_uchar_ptr_node
9394 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
9395
389dd41b 9396 tree ind1 = fold_convert_loc (loc, integer_type_node,
9397 build1 (INDIRECT_REF, cst_uchar_node,
9398 fold_convert_loc (loc,
9399 cst_uchar_ptr_node,
9400 arg1)));
9401 tree ind2 = fold_convert_loc (loc, integer_type_node,
9402 build1 (INDIRECT_REF, cst_uchar_node,
9403 fold_convert_loc (loc,
9404 cst_uchar_ptr_node,
9405 arg2)));
9406 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2);
9c8a1629 9407 }
9408
c2f47e15 9409 return NULL_TREE;
9c8a1629 9410}
9411
c2f47e15 9412/* Fold function call to builtin signbit, signbitf or signbitl with argument
9413 ARG. Return NULL_TREE if no simplification can be made. */
27f261ef 9414
9415static tree
389dd41b 9416fold_builtin_signbit (location_t loc, tree arg, tree type)
27f261ef 9417{
c2f47e15 9418 if (!validate_arg (arg, REAL_TYPE))
27f261ef 9419 return NULL_TREE;
9420
27f261ef 9421 /* If ARG is a compile-time constant, determine the result. */
9422 if (TREE_CODE (arg) == REAL_CST
f96bd2bf 9423 && !TREE_OVERFLOW (arg))
27f261ef 9424 {
9425 REAL_VALUE_TYPE c;
9426
9427 c = TREE_REAL_CST (arg);
385f3f36 9428 return (REAL_VALUE_NEGATIVE (c)
9429 ? build_one_cst (type)
9430 : build_zero_cst (type));
27f261ef 9431 }
9432
9433 /* If ARG is non-negative, the result is always zero. */
9434 if (tree_expr_nonnegative_p (arg))
389dd41b 9435 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
27f261ef 9436
9437 /* If ARG's format doesn't have signed zeros, return "arg < 0.0". */
9438 if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
de67cbb8 9439 return fold_convert (type,
9440 fold_build2_loc (loc, LT_EXPR, boolean_type_node, arg,
9441 build_real (TREE_TYPE (arg), dconst0)));
27f261ef 9442
9443 return NULL_TREE;
9444}
9445
c2f47e15 9446/* Fold function call to builtin copysign, copysignf or copysignl with
9447 arguments ARG1 and ARG2. Return NULL_TREE if no simplification can
9448 be made. */
467214fd 9449
9450static tree
389dd41b 9451fold_builtin_copysign (location_t loc, tree fndecl,
9452 tree arg1, tree arg2, tree type)
467214fd 9453{
c2f47e15 9454 tree tem;
467214fd 9455
c2f47e15 9456 if (!validate_arg (arg1, REAL_TYPE)
9457 || !validate_arg (arg2, REAL_TYPE))
467214fd 9458 return NULL_TREE;
9459
467214fd 9460 /* copysign(X,X) is X. */
9461 if (operand_equal_p (arg1, arg2, 0))
389dd41b 9462 return fold_convert_loc (loc, type, arg1);
467214fd 9463
9464 /* If ARG1 and ARG2 are compile-time constants, determine the result. */
9465 if (TREE_CODE (arg1) == REAL_CST
9466 && TREE_CODE (arg2) == REAL_CST
f96bd2bf 9467 && !TREE_OVERFLOW (arg1)
9468 && !TREE_OVERFLOW (arg2))
467214fd 9469 {
9470 REAL_VALUE_TYPE c1, c2;
9471
9472 c1 = TREE_REAL_CST (arg1);
9473 c2 = TREE_REAL_CST (arg2);
749680e2 9474 /* c1.sign := c2.sign. */
467214fd 9475 real_copysign (&c1, &c2);
9476 return build_real (type, c1);
467214fd 9477 }
9478
9479 /* copysign(X, Y) is fabs(X) when Y is always non-negative.
9480 Remember to evaluate Y for side-effects. */
9481 if (tree_expr_nonnegative_p (arg2))
389dd41b 9482 return omit_one_operand_loc (loc, type,
9483 fold_build1_loc (loc, ABS_EXPR, type, arg1),
467214fd 9484 arg2);
9485
198d9bbe 9486 /* Strip sign changing operations for the first argument. */
9487 tem = fold_strip_sign_ops (arg1);
9488 if (tem)
389dd41b 9489 return build_call_expr_loc (loc, fndecl, 2, tem, arg2);
198d9bbe 9490
467214fd 9491 return NULL_TREE;
9492}
9493
c2f47e15 9494/* Fold a call to builtin isascii with argument ARG. */
d49367d4 9495
9496static tree
389dd41b 9497fold_builtin_isascii (location_t loc, tree arg)
d49367d4 9498{
c2f47e15 9499 if (!validate_arg (arg, INTEGER_TYPE))
9500 return NULL_TREE;
d49367d4 9501 else
9502 {
9503 /* Transform isascii(c) -> ((c & ~0x7f) == 0). */
c90b5d40 9504 arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
7002a1c8 9505 build_int_cst (integer_type_node,
c90b5d40 9506 ~ (unsigned HOST_WIDE_INT) 0x7f));
389dd41b 9507 return fold_build2_loc (loc, EQ_EXPR, integer_type_node,
7002a1c8 9508 arg, integer_zero_node);
d49367d4 9509 }
9510}
9511
c2f47e15 9512/* Fold a call to builtin toascii with argument ARG. */
d49367d4 9513
9514static tree
389dd41b 9515fold_builtin_toascii (location_t loc, tree arg)
d49367d4 9516{
c2f47e15 9517 if (!validate_arg (arg, INTEGER_TYPE))
9518 return NULL_TREE;
48e1416a 9519
c2f47e15 9520 /* Transform toascii(c) -> (c & 0x7f). */
389dd41b 9521 return fold_build2_loc (loc, BIT_AND_EXPR, integer_type_node, arg,
7002a1c8 9522 build_int_cst (integer_type_node, 0x7f));
d49367d4 9523}
9524
c2f47e15 9525/* Fold a call to builtin isdigit with argument ARG. */
df1cf42e 9526
9527static tree
389dd41b 9528fold_builtin_isdigit (location_t loc, tree arg)
df1cf42e 9529{
c2f47e15 9530 if (!validate_arg (arg, INTEGER_TYPE))
9531 return NULL_TREE;
df1cf42e 9532 else
9533 {
9534 /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */
624d37a6 9535 /* According to the C standard, isdigit is unaffected by locale.
9536 However, it definitely is affected by the target character set. */
624d37a6 9537 unsigned HOST_WIDE_INT target_digit0
9538 = lang_hooks.to_target_charset ('0');
9539
9540 if (target_digit0 == 0)
9541 return NULL_TREE;
9542
389dd41b 9543 arg = fold_convert_loc (loc, unsigned_type_node, arg);
c90b5d40 9544 arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg,
9545 build_int_cst (unsigned_type_node, target_digit0));
389dd41b 9546 return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg,
f2532264 9547 build_int_cst (unsigned_type_node, 9));
df1cf42e 9548 }
9549}
27f261ef 9550
c2f47e15 9551/* Fold a call to fabs, fabsf or fabsl with argument ARG. */
d1aade50 9552
9553static tree
389dd41b 9554fold_builtin_fabs (location_t loc, tree arg, tree type)
d1aade50 9555{
c2f47e15 9556 if (!validate_arg (arg, REAL_TYPE))
9557 return NULL_TREE;
d1aade50 9558
389dd41b 9559 arg = fold_convert_loc (loc, type, arg);
d1aade50 9560 if (TREE_CODE (arg) == REAL_CST)
9561 return fold_abs_const (arg, type);
389dd41b 9562 return fold_build1_loc (loc, ABS_EXPR, type, arg);
d1aade50 9563}
9564
c2f47e15 9565/* Fold a call to abs, labs, llabs or imaxabs with argument ARG. */
d1aade50 9566
9567static tree
389dd41b 9568fold_builtin_abs (location_t loc, tree arg, tree type)
d1aade50 9569{
c2f47e15 9570 if (!validate_arg (arg, INTEGER_TYPE))
9571 return NULL_TREE;
d1aade50 9572
389dd41b 9573 arg = fold_convert_loc (loc, type, arg);
d1aade50 9574 if (TREE_CODE (arg) == INTEGER_CST)
9575 return fold_abs_const (arg, type);
389dd41b 9576 return fold_build1_loc (loc, ABS_EXPR, type, arg);
d1aade50 9577}
9578
b9be572e 9579/* Fold a fma operation with arguments ARG[012]. */
9580
9581tree
9582fold_fma (location_t loc ATTRIBUTE_UNUSED,
9583 tree type, tree arg0, tree arg1, tree arg2)
9584{
9585 if (TREE_CODE (arg0) == REAL_CST
9586 && TREE_CODE (arg1) == REAL_CST
9587 && TREE_CODE (arg2) == REAL_CST)
9588 return do_mpfr_arg3 (arg0, arg1, arg2, type, mpfr_fma);
9589
9590 return NULL_TREE;
9591}
9592
9593/* Fold a call to fma, fmaf, or fmal with arguments ARG[012]. */
9594
9595static tree
9596fold_builtin_fma (location_t loc, tree arg0, tree arg1, tree arg2, tree type)
9597{
9598 if (validate_arg (arg0, REAL_TYPE)
9599 && validate_arg(arg1, REAL_TYPE)
9600 && validate_arg(arg2, REAL_TYPE))
9601 {
9602 tree tem = fold_fma (loc, type, arg0, arg1, arg2);
9603 if (tem)
9604 return tem;
9605
9606 /* ??? Only expand to FMA_EXPR if it's directly supported. */
9607 if (optab_handler (fma_optab, TYPE_MODE (type)) != CODE_FOR_nothing)
9608 return fold_build3_loc (loc, FMA_EXPR, type, arg0, arg1, arg2);
9609 }
9610 return NULL_TREE;
9611}
9612
d4a43a03 9613/* Fold a call to builtin fmin or fmax. */
9614
9615static tree
389dd41b 9616fold_builtin_fmin_fmax (location_t loc, tree arg0, tree arg1,
9617 tree type, bool max)
d4a43a03 9618{
c2f47e15 9619 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, REAL_TYPE))
d4a43a03 9620 {
d4a43a03 9621 /* Calculate the result when the argument is a constant. */
9622 tree res = do_mpfr_arg2 (arg0, arg1, type, (max ? mpfr_max : mpfr_min));
9623
9624 if (res)
9625 return res;
9626
61fe3555 9627 /* If either argument is NaN, return the other one. Avoid the
9628 transformation if we get (and honor) a signalling NaN. Using
9629 omit_one_operand() ensures we create a non-lvalue. */
9630 if (TREE_CODE (arg0) == REAL_CST
9631 && real_isnan (&TREE_REAL_CST (arg0))
9632 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
9633 || ! TREE_REAL_CST (arg0).signalling))
389dd41b 9634 return omit_one_operand_loc (loc, type, arg1, arg0);
61fe3555 9635 if (TREE_CODE (arg1) == REAL_CST
9636 && real_isnan (&TREE_REAL_CST (arg1))
9637 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
9638 || ! TREE_REAL_CST (arg1).signalling))
389dd41b 9639 return omit_one_operand_loc (loc, type, arg0, arg1);
61fe3555 9640
d4a43a03 9641 /* Transform fmin/fmax(x,x) -> x. */
9642 if (operand_equal_p (arg0, arg1, OEP_PURE_SAME))
389dd41b 9643 return omit_one_operand_loc (loc, type, arg0, arg1);
48e1416a 9644
d4a43a03 9645 /* Convert fmin/fmax to MIN_EXPR/MAX_EXPR. C99 requires these
9646 functions to return the numeric arg if the other one is NaN.
9647 These tree codes don't honor that, so only transform if
9648 -ffinite-math-only is set. C99 doesn't require -0.0 to be
9649 handled, so we don't have to worry about it either. */
9650 if (flag_finite_math_only)
389dd41b 9651 return fold_build2_loc (loc, (max ? MAX_EXPR : MIN_EXPR), type,
9652 fold_convert_loc (loc, type, arg0),
9653 fold_convert_loc (loc, type, arg1));
d4a43a03 9654 }
9655 return NULL_TREE;
9656}
9657
abe4dcf6 9658/* Fold a call to builtin carg(a+bi) -> atan2(b,a). */
9659
9660static tree
389dd41b 9661fold_builtin_carg (location_t loc, tree arg, tree type)
abe4dcf6 9662{
239d491a 9663 if (validate_arg (arg, COMPLEX_TYPE)
9664 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
abe4dcf6 9665 {
9666 tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
48e1416a 9667
abe4dcf6 9668 if (atan2_fn)
9669 {
c2f47e15 9670 tree new_arg = builtin_save_expr (arg);
389dd41b 9671 tree r_arg = fold_build1_loc (loc, REALPART_EXPR, type, new_arg);
9672 tree i_arg = fold_build1_loc (loc, IMAGPART_EXPR, type, new_arg);
9673 return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg);
abe4dcf6 9674 }
9675 }
48e1416a 9676
abe4dcf6 9677 return NULL_TREE;
9678}
9679
cb2b9385 9680/* Fold a call to builtin logb/ilogb. */
9681
9682static tree
389dd41b 9683fold_builtin_logb (location_t loc, tree arg, tree rettype)
cb2b9385 9684{
9685 if (! validate_arg (arg, REAL_TYPE))
9686 return NULL_TREE;
48e1416a 9687
cb2b9385 9688 STRIP_NOPS (arg);
48e1416a 9689
cb2b9385 9690 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9691 {
9692 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
48e1416a 9693
cb2b9385 9694 switch (value->cl)
9695 {
9696 case rvc_nan:
9697 case rvc_inf:
9698 /* If arg is Inf or NaN and we're logb, return it. */
9699 if (TREE_CODE (rettype) == REAL_TYPE)
389dd41b 9700 return fold_convert_loc (loc, rettype, arg);
cb2b9385 9701 /* Fall through... */
9702 case rvc_zero:
9703 /* Zero may set errno and/or raise an exception for logb, also
9704 for ilogb we don't know FP_ILOGB0. */
9705 return NULL_TREE;
9706 case rvc_normal:
9707 /* For normal numbers, proceed iff radix == 2. In GCC,
9708 normalized significands are in the range [0.5, 1.0). We
9709 want the exponent as if they were [1.0, 2.0) so get the
9710 exponent and subtract 1. */
9711 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
389dd41b 9712 return fold_convert_loc (loc, rettype,
7002a1c8 9713 build_int_cst (integer_type_node,
389dd41b 9714 REAL_EXP (value)-1));
cb2b9385 9715 break;
9716 }
9717 }
48e1416a 9718
cb2b9385 9719 return NULL_TREE;
9720}
9721
9722/* Fold a call to builtin significand, if radix == 2. */
9723
9724static tree
389dd41b 9725fold_builtin_significand (location_t loc, tree arg, tree rettype)
cb2b9385 9726{
9727 if (! validate_arg (arg, REAL_TYPE))
9728 return NULL_TREE;
48e1416a 9729
cb2b9385 9730 STRIP_NOPS (arg);
48e1416a 9731
cb2b9385 9732 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
9733 {
9734 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
48e1416a 9735
cb2b9385 9736 switch (value->cl)
9737 {
9738 case rvc_zero:
9739 case rvc_nan:
9740 case rvc_inf:
9741 /* If arg is +-0, +-Inf or +-NaN, then return it. */
389dd41b 9742 return fold_convert_loc (loc, rettype, arg);
cb2b9385 9743 case rvc_normal:
9744 /* For normal numbers, proceed iff radix == 2. */
9745 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2)
9746 {
9747 REAL_VALUE_TYPE result = *value;
9748 /* In GCC, normalized significands are in the range [0.5,
9749 1.0). We want them to be [1.0, 2.0) so set the
9750 exponent to 1. */
9751 SET_REAL_EXP (&result, 1);
9752 return build_real (rettype, result);
9753 }
9754 break;
9755 }
9756 }
48e1416a 9757
cb2b9385 9758 return NULL_TREE;
9759}
9760
3838b9ae 9761/* Fold a call to builtin frexp, we can assume the base is 2. */
9762
9763static tree
389dd41b 9764fold_builtin_frexp (location_t loc, tree arg0, tree arg1, tree rettype)
3838b9ae 9765{
9766 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9767 return NULL_TREE;
48e1416a 9768
3838b9ae 9769 STRIP_NOPS (arg0);
48e1416a 9770
3838b9ae 9771 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9772 return NULL_TREE;
48e1416a 9773
389dd41b 9774 arg1 = build_fold_indirect_ref_loc (loc, arg1);
3838b9ae 9775
9776 /* Proceed if a valid pointer type was passed in. */
9777 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
9778 {
9779 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9780 tree frac, exp;
48e1416a 9781
3838b9ae 9782 switch (value->cl)
9783 {
9784 case rvc_zero:
9785 /* For +-0, return (*exp = 0, +-0). */
9786 exp = integer_zero_node;
9787 frac = arg0;
9788 break;
9789 case rvc_nan:
9790 case rvc_inf:
9791 /* For +-NaN or +-Inf, *exp is unspecified, return arg0. */
389dd41b 9792 return omit_one_operand_loc (loc, rettype, arg0, arg1);
3838b9ae 9793 case rvc_normal:
9794 {
9795 /* Since the frexp function always expects base 2, and in
9796 GCC normalized significands are already in the range
9797 [0.5, 1.0), we have exactly what frexp wants. */
9798 REAL_VALUE_TYPE frac_rvt = *value;
9799 SET_REAL_EXP (&frac_rvt, 0);
9800 frac = build_real (rettype, frac_rvt);
7002a1c8 9801 exp = build_int_cst (integer_type_node, REAL_EXP (value));
3838b9ae 9802 }
9803 break;
9804 default:
9805 gcc_unreachable ();
9806 }
48e1416a 9807
3838b9ae 9808 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
389dd41b 9809 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, exp);
3838b9ae 9810 TREE_SIDE_EFFECTS (arg1) = 1;
389dd41b 9811 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1, frac);
3838b9ae 9812 }
9813
9814 return NULL_TREE;
9815}
9816
7587301b 9817/* Fold a call to builtin ldexp or scalbn/scalbln. If LDEXP is true
9818 then we can assume the base is two. If it's false, then we have to
9819 check the mode of the TYPE parameter in certain cases. */
9820
9821static tree
389dd41b 9822fold_builtin_load_exponent (location_t loc, tree arg0, tree arg1,
9823 tree type, bool ldexp)
7587301b 9824{
9825 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, INTEGER_TYPE))
9826 {
9827 STRIP_NOPS (arg0);
9828 STRIP_NOPS (arg1);
9829
9830 /* If arg0 is 0, Inf or NaN, or if arg1 is 0, then return arg0. */
9831 if (real_zerop (arg0) || integer_zerop (arg1)
9832 || (TREE_CODE (arg0) == REAL_CST
776a7bab 9833 && !real_isfinite (&TREE_REAL_CST (arg0))))
389dd41b 9834 return omit_one_operand_loc (loc, type, arg0, arg1);
48e1416a 9835
7587301b 9836 /* If both arguments are constant, then try to evaluate it. */
9837 if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2)
9838 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
9839 && host_integerp (arg1, 0))
9840 {
9841 /* Bound the maximum adjustment to twice the range of the
9842 mode's valid exponents. Use abs to ensure the range is
9843 positive as a sanity check. */
48e1416a 9844 const long max_exp_adj = 2 *
7587301b 9845 labs (REAL_MODE_FORMAT (TYPE_MODE (type))->emax
9846 - REAL_MODE_FORMAT (TYPE_MODE (type))->emin);
9847
9848 /* Get the user-requested adjustment. */
9849 const HOST_WIDE_INT req_exp_adj = tree_low_cst (arg1, 0);
48e1416a 9850
7587301b 9851 /* The requested adjustment must be inside this range. This
9852 is a preliminary cap to avoid things like overflow, we
9853 may still fail to compute the result for other reasons. */
9854 if (-max_exp_adj < req_exp_adj && req_exp_adj < max_exp_adj)
9855 {
9856 REAL_VALUE_TYPE initial_result;
48e1416a 9857
7587301b 9858 real_ldexp (&initial_result, &TREE_REAL_CST (arg0), req_exp_adj);
9859
9860 /* Ensure we didn't overflow. */
9861 if (! real_isinf (&initial_result))
9862 {
9863 const REAL_VALUE_TYPE trunc_result
9864 = real_value_truncate (TYPE_MODE (type), initial_result);
48e1416a 9865
7587301b 9866 /* Only proceed if the target mode can hold the
9867 resulting value. */
9868 if (REAL_VALUES_EQUAL (initial_result, trunc_result))
9869 return build_real (type, trunc_result);
9870 }
9871 }
9872 }
9873 }
9874
9875 return NULL_TREE;
9876}
9877
ebf8b4f5 9878/* Fold a call to builtin modf. */
9879
9880static tree
389dd41b 9881fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
ebf8b4f5 9882{
9883 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
9884 return NULL_TREE;
48e1416a 9885
ebf8b4f5 9886 STRIP_NOPS (arg0);
48e1416a 9887
ebf8b4f5 9888 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
9889 return NULL_TREE;
48e1416a 9890
389dd41b 9891 arg1 = build_fold_indirect_ref_loc (loc, arg1);
ebf8b4f5 9892
9893 /* Proceed if a valid pointer type was passed in. */
9894 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
9895 {
9896 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
9897 REAL_VALUE_TYPE trunc, frac;
9898
9899 switch (value->cl)
9900 {
9901 case rvc_nan:
9902 case rvc_zero:
9903 /* For +-NaN or +-0, return (*arg1 = arg0, arg0). */
9904 trunc = frac = *value;
9905 break;
9906 case rvc_inf:
9907 /* For +-Inf, return (*arg1 = arg0, +-0). */
9908 frac = dconst0;
9909 frac.sign = value->sign;
9910 trunc = *value;
9911 break;
9912 case rvc_normal:
9913 /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)). */
9914 real_trunc (&trunc, VOIDmode, value);
9915 real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
9916 /* If the original number was negative and already
9917 integral, then the fractional part is -0.0. */
9918 if (value->sign && frac.cl == rvc_zero)
9919 frac.sign = value->sign;
9920 break;
9921 }
48e1416a 9922
ebf8b4f5 9923 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
389dd41b 9924 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1,
ebf8b4f5 9925 build_real (rettype, trunc));
9926 TREE_SIDE_EFFECTS (arg1) = 1;
389dd41b 9927 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1,
ebf8b4f5 9928 build_real (rettype, frac));
9929 }
48e1416a 9930
ebf8b4f5 9931 return NULL_TREE;
9932}
9933
a65c4d64 9934/* Given a location LOC, an interclass builtin function decl FNDECL
9935 and its single argument ARG, return an folded expression computing
9936 the same, or NULL_TREE if we either couldn't or didn't want to fold
9937 (the latter happen if there's an RTL instruction available). */
9938
9939static tree
9940fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
9941{
9942 enum machine_mode mode;
9943
9944 if (!validate_arg (arg, REAL_TYPE))
9945 return NULL_TREE;
9946
9947 if (interclass_mathfn_icode (arg, fndecl) != CODE_FOR_nothing)
9948 return NULL_TREE;
9949
9950 mode = TYPE_MODE (TREE_TYPE (arg));
9951
9952 /* If there is no optab, try generic code. */
9953 switch (DECL_FUNCTION_CODE (fndecl))
9954 {
9955 tree result;
9956
9957 CASE_FLT_FN (BUILT_IN_ISINF):
9958 {
9959 /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
b9a16870 9960 tree const isgr_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
a65c4d64 9961 tree const type = TREE_TYPE (arg);
9962 REAL_VALUE_TYPE r;
9963 char buf[128];
9964
9965 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9966 real_from_string (&r, buf);
9967 result = build_call_expr (isgr_fn, 2,
9968 fold_build1_loc (loc, ABS_EXPR, type, arg),
9969 build_real (type, r));
9970 return result;
9971 }
9972 CASE_FLT_FN (BUILT_IN_FINITE):
9973 case BUILT_IN_ISFINITE:
9974 {
9975 /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
b9a16870 9976 tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
a65c4d64 9977 tree const type = TREE_TYPE (arg);
9978 REAL_VALUE_TYPE r;
9979 char buf[128];
9980
9981 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
9982 real_from_string (&r, buf);
9983 result = build_call_expr (isle_fn, 2,
9984 fold_build1_loc (loc, ABS_EXPR, type, arg),
9985 build_real (type, r));
9986 /*result = fold_build2_loc (loc, UNGT_EXPR,
9987 TREE_TYPE (TREE_TYPE (fndecl)),
9988 fold_build1_loc (loc, ABS_EXPR, type, arg),
9989 build_real (type, r));
9990 result = fold_build1_loc (loc, TRUTH_NOT_EXPR,
9991 TREE_TYPE (TREE_TYPE (fndecl)),
9992 result);*/
9993 return result;
9994 }
9995 case BUILT_IN_ISNORMAL:
9996 {
9997 /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
9998 islessequal(fabs(x),DBL_MAX). */
b9a16870 9999 tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
10000 tree const isge_fn = builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL);
a65c4d64 10001 tree const type = TREE_TYPE (arg);
10002 REAL_VALUE_TYPE rmax, rmin;
10003 char buf[128];
10004
10005 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
10006 real_from_string (&rmax, buf);
10007 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
10008 real_from_string (&rmin, buf);
10009 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
10010 result = build_call_expr (isle_fn, 2, arg,
10011 build_real (type, rmax));
10012 result = fold_build2 (BIT_AND_EXPR, integer_type_node, result,
10013 build_call_expr (isge_fn, 2, arg,
10014 build_real (type, rmin)));
10015 return result;
10016 }
10017 default:
10018 break;
10019 }
10020
10021 return NULL_TREE;
10022}
10023
726069ba 10024/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
c2f47e15 10025 ARG is the argument for the call. */
726069ba 10026
10027static tree
389dd41b 10028fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
726069ba 10029{
726069ba 10030 tree type = TREE_TYPE (TREE_TYPE (fndecl));
726069ba 10031 REAL_VALUE_TYPE r;
10032
c2f47e15 10033 if (!validate_arg (arg, REAL_TYPE))
d43cee80 10034 return NULL_TREE;
726069ba 10035
726069ba 10036 switch (builtin_index)
10037 {
10038 case BUILT_IN_ISINF:
b70bfd00 10039 if (!HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 10040 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
726069ba 10041
10042 if (TREE_CODE (arg) == REAL_CST)
10043 {
10044 r = TREE_REAL_CST (arg);
10045 if (real_isinf (&r))
10046 return real_compare (GT_EXPR, &r, &dconst0)
10047 ? integer_one_node : integer_minus_one_node;
10048 else
10049 return integer_zero_node;
10050 }
10051
10052 return NULL_TREE;
10053
c319d56a 10054 case BUILT_IN_ISINF_SIGN:
10055 {
10056 /* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */
10057 /* In a boolean context, GCC will fold the inner COND_EXPR to
10058 1. So e.g. "if (isinf_sign(x))" would be folded to just
10059 "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
10060 tree signbit_fn = mathfn_built_in_1 (TREE_TYPE (arg), BUILT_IN_SIGNBIT, 0);
b9a16870 10061 tree isinf_fn = builtin_decl_explicit (BUILT_IN_ISINF);
c319d56a 10062 tree tmp = NULL_TREE;
10063
10064 arg = builtin_save_expr (arg);
10065
10066 if (signbit_fn && isinf_fn)
10067 {
389dd41b 10068 tree signbit_call = build_call_expr_loc (loc, signbit_fn, 1, arg);
10069 tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg);
c319d56a 10070
389dd41b 10071 signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
c319d56a 10072 signbit_call, integer_zero_node);
389dd41b 10073 isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
c319d56a 10074 isinf_call, integer_zero_node);
48e1416a 10075
389dd41b 10076 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call,
c319d56a 10077 integer_minus_one_node, integer_one_node);
389dd41b 10078 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
10079 isinf_call, tmp,
c319d56a 10080 integer_zero_node);
10081 }
10082
10083 return tmp;
10084 }
10085
cde061c1 10086 case BUILT_IN_ISFINITE:
b70bfd00 10087 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
10088 && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 10089 return omit_one_operand_loc (loc, type, integer_one_node, arg);
726069ba 10090
10091 if (TREE_CODE (arg) == REAL_CST)
10092 {
10093 r = TREE_REAL_CST (arg);
776a7bab 10094 return real_isfinite (&r) ? integer_one_node : integer_zero_node;
726069ba 10095 }
10096
10097 return NULL_TREE;
10098
10099 case BUILT_IN_ISNAN:
b70bfd00 10100 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))))
389dd41b 10101 return omit_one_operand_loc (loc, type, integer_zero_node, arg);
726069ba 10102
10103 if (TREE_CODE (arg) == REAL_CST)
10104 {
10105 r = TREE_REAL_CST (arg);
10106 return real_isnan (&r) ? integer_one_node : integer_zero_node;
10107 }
10108
10109 arg = builtin_save_expr (arg);
389dd41b 10110 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
726069ba 10111
10112 default:
64db345d 10113 gcc_unreachable ();
726069ba 10114 }
10115}
10116
19fbe3a4 10117/* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...).
10118 This builtin will generate code to return the appropriate floating
10119 point classification depending on the value of the floating point
10120 number passed in. The possible return values must be supplied as
921b27c0 10121 int arguments to the call in the following order: FP_NAN, FP_INFINITE,
19fbe3a4 10122 FP_NORMAL, FP_SUBNORMAL and FP_ZERO. The ellipses is for exactly
10123 one floating point argument which is "type generic". */
10124
10125static tree
389dd41b 10126fold_builtin_fpclassify (location_t loc, tree exp)
19fbe3a4 10127{
921b27c0 10128 tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
10129 arg, type, res, tmp;
19fbe3a4 10130 enum machine_mode mode;
10131 REAL_VALUE_TYPE r;
10132 char buf[128];
48e1416a 10133
19fbe3a4 10134 /* Verify the required arguments in the original call. */
10135 if (!validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE,
10136 INTEGER_TYPE, INTEGER_TYPE,
10137 INTEGER_TYPE, REAL_TYPE, VOID_TYPE))
10138 return NULL_TREE;
48e1416a 10139
19fbe3a4 10140 fp_nan = CALL_EXPR_ARG (exp, 0);
921b27c0 10141 fp_infinite = CALL_EXPR_ARG (exp, 1);
19fbe3a4 10142 fp_normal = CALL_EXPR_ARG (exp, 2);
10143 fp_subnormal = CALL_EXPR_ARG (exp, 3);
10144 fp_zero = CALL_EXPR_ARG (exp, 4);
10145 arg = CALL_EXPR_ARG (exp, 5);
10146 type = TREE_TYPE (arg);
10147 mode = TYPE_MODE (type);
389dd41b 10148 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
19fbe3a4 10149
48e1416a 10150 /* fpclassify(x) ->
19fbe3a4 10151 isnan(x) ? FP_NAN :
921b27c0 10152 (fabs(x) == Inf ? FP_INFINITE :
19fbe3a4 10153 (fabs(x) >= DBL_MIN ? FP_NORMAL :
10154 (x == 0 ? FP_ZERO : FP_SUBNORMAL))). */
48e1416a 10155
389dd41b 10156 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
19fbe3a4 10157 build_real (type, dconst0));
389dd41b 10158 res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
10159 tmp, fp_zero, fp_subnormal);
19fbe3a4 10160
10161 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
10162 real_from_string (&r, buf);
389dd41b 10163 tmp = fold_build2_loc (loc, GE_EXPR, integer_type_node,
10164 arg, build_real (type, r));
10165 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, fp_normal, res);
48e1416a 10166
19fbe3a4 10167 if (HONOR_INFINITIES (mode))
10168 {
10169 real_inf (&r);
389dd41b 10170 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
19fbe3a4 10171 build_real (type, r));
389dd41b 10172 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp,
10173 fp_infinite, res);
19fbe3a4 10174 }
10175
10176 if (HONOR_NANS (mode))
10177 {
389dd41b 10178 tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
10179 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, res, fp_nan);
19fbe3a4 10180 }
48e1416a 10181
19fbe3a4 10182 return res;
10183}
10184
9bc9f15f 10185/* Fold a call to an unordered comparison function such as
d5019fe8 10186 __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function
c2f47e15 10187 being called and ARG0 and ARG1 are the arguments for the call.
726069ba 10188 UNORDERED_CODE and ORDERED_CODE are comparison codes that give
10189 the opposite of the desired result. UNORDERED_CODE is used
10190 for modes that can hold NaNs and ORDERED_CODE is used for
10191 the rest. */
9bc9f15f 10192
10193static tree
389dd41b 10194fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
9bc9f15f 10195 enum tree_code unordered_code,
10196 enum tree_code ordered_code)
10197{
859f903a 10198 tree type = TREE_TYPE (TREE_TYPE (fndecl));
9bc9f15f 10199 enum tree_code code;
6978db0d 10200 tree type0, type1;
10201 enum tree_code code0, code1;
10202 tree cmp_type = NULL_TREE;
9bc9f15f 10203
6978db0d 10204 type0 = TREE_TYPE (arg0);
10205 type1 = TREE_TYPE (arg1);
a0c938f0 10206
6978db0d 10207 code0 = TREE_CODE (type0);
10208 code1 = TREE_CODE (type1);
a0c938f0 10209
6978db0d 10210 if (code0 == REAL_TYPE && code1 == REAL_TYPE)
10211 /* Choose the wider of two real types. */
10212 cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
10213 ? type0 : type1;
10214 else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
10215 cmp_type = type0;
10216 else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
10217 cmp_type = type1;
a0c938f0 10218
389dd41b 10219 arg0 = fold_convert_loc (loc, cmp_type, arg0);
10220 arg1 = fold_convert_loc (loc, cmp_type, arg1);
859f903a 10221
10222 if (unordered_code == UNORDERED_EXPR)
10223 {
b70bfd00 10224 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
389dd41b 10225 return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
10226 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
859f903a 10227 }
9bc9f15f 10228
b70bfd00 10229 code = HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
10230 : ordered_code;
389dd41b 10231 return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
10232 fold_build2_loc (loc, code, type, arg0, arg1));
9bc9f15f 10233}
10234
c2f47e15 10235/* Fold a call to built-in function FNDECL with 0 arguments.
10236 IGNORE is true if the result of the function call is ignored. This
10237 function returns NULL_TREE if no simplification was possible. */
650e4c94 10238
4ee9c684 10239static tree
389dd41b 10240fold_builtin_0 (location_t loc, tree fndecl, bool ignore ATTRIBUTE_UNUSED)
650e4c94 10241{
e9f80ff5 10242 tree type = TREE_TYPE (TREE_TYPE (fndecl));
c2f47e15 10243 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
189b3398 10244 switch (fcode)
650e4c94 10245 {
c2f47e15 10246 CASE_FLT_FN (BUILT_IN_INF):
10247 case BUILT_IN_INFD32:
10248 case BUILT_IN_INFD64:
10249 case BUILT_IN_INFD128:
389dd41b 10250 return fold_builtin_inf (loc, type, true);
7c2f0500 10251
c2f47e15 10252 CASE_FLT_FN (BUILT_IN_HUGE_VAL):
389dd41b 10253 return fold_builtin_inf (loc, type, false);
7c2f0500 10254
c2f47e15 10255 case BUILT_IN_CLASSIFY_TYPE:
10256 return fold_builtin_classify_type (NULL_TREE);
7c2f0500 10257
c2f47e15 10258 default:
10259 break;
10260 }
10261 return NULL_TREE;
10262}
7c2f0500 10263
c2f47e15 10264/* Fold a call to built-in function FNDECL with 1 argument, ARG0.
10265 IGNORE is true if the result of the function call is ignored. This
10266 function returns NULL_TREE if no simplification was possible. */
7c2f0500 10267
c2f47e15 10268static tree
389dd41b 10269fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
c2f47e15 10270{
10271 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10272 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10273 switch (fcode)
10274 {
650e4c94 10275 case BUILT_IN_CONSTANT_P:
7c2f0500 10276 {
c2f47e15 10277 tree val = fold_builtin_constant_p (arg0);
7c2f0500 10278
7c2f0500 10279 /* Gimplification will pull the CALL_EXPR for the builtin out of
10280 an if condition. When not optimizing, we'll not CSE it back.
10281 To avoid link error types of regressions, return false now. */
10282 if (!val && !optimize)
10283 val = integer_zero_node;
10284
10285 return val;
10286 }
650e4c94 10287
539a3a92 10288 case BUILT_IN_CLASSIFY_TYPE:
c2f47e15 10289 return fold_builtin_classify_type (arg0);
539a3a92 10290
650e4c94 10291 case BUILT_IN_STRLEN:
c7cbde74 10292 return fold_builtin_strlen (loc, type, arg0);
650e4c94 10293
4f35b1fc 10294 CASE_FLT_FN (BUILT_IN_FABS):
389dd41b 10295 return fold_builtin_fabs (loc, arg0, type);
d1aade50 10296
10297 case BUILT_IN_ABS:
10298 case BUILT_IN_LABS:
10299 case BUILT_IN_LLABS:
10300 case BUILT_IN_IMAXABS:
389dd41b 10301 return fold_builtin_abs (loc, arg0, type);
c63f4ad3 10302
4f35b1fc 10303 CASE_FLT_FN (BUILT_IN_CONJ):
239d491a 10304 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10305 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10306 return fold_build1_loc (loc, CONJ_EXPR, type, arg0);
c2f47e15 10307 break;
36d3581d 10308
4f35b1fc 10309 CASE_FLT_FN (BUILT_IN_CREAL):
239d491a 10310 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10311 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10312 return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));;
c2f47e15 10313 break;
36d3581d 10314
4f35b1fc 10315 CASE_FLT_FN (BUILT_IN_CIMAG):
b0ce8887 10316 if (validate_arg (arg0, COMPLEX_TYPE)
10317 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
389dd41b 10318 return non_lvalue_loc (loc, fold_build1_loc (loc, IMAGPART_EXPR, type, arg0));
c2f47e15 10319 break;
36d3581d 10320
503733d5 10321 CASE_FLT_FN (BUILT_IN_CCOS):
389dd41b 10322 return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ false);
48e1416a 10323
503733d5 10324 CASE_FLT_FN (BUILT_IN_CCOSH):
389dd41b 10325 return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ true);
48e1416a 10326
c2373fdb 10327 CASE_FLT_FN (BUILT_IN_CPROJ):
10328 return fold_builtin_cproj(loc, arg0, type);
10329
239d491a 10330 CASE_FLT_FN (BUILT_IN_CSIN):
10331 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10332 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10333 return do_mpc_arg1 (arg0, type, mpc_sin);
c2f47e15 10334 break;
48e1416a 10335
239d491a 10336 CASE_FLT_FN (BUILT_IN_CSINH):
10337 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10338 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10339 return do_mpc_arg1 (arg0, type, mpc_sinh);
10340 break;
48e1416a 10341
239d491a 10342 CASE_FLT_FN (BUILT_IN_CTAN):
10343 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10344 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10345 return do_mpc_arg1 (arg0, type, mpc_tan);
10346 break;
48e1416a 10347
239d491a 10348 CASE_FLT_FN (BUILT_IN_CTANH):
10349 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10350 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10351 return do_mpc_arg1 (arg0, type, mpc_tanh);
10352 break;
48e1416a 10353
239d491a 10354 CASE_FLT_FN (BUILT_IN_CLOG):
10355 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10356 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10357 return do_mpc_arg1 (arg0, type, mpc_log);
10358 break;
48e1416a 10359
239d491a 10360 CASE_FLT_FN (BUILT_IN_CSQRT):
10361 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10362 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
239d491a 10363 return do_mpc_arg1 (arg0, type, mpc_sqrt);
10364 break;
48e1416a 10365
0e7e6e7f 10366 CASE_FLT_FN (BUILT_IN_CASIN):
10367 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10368 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10369 return do_mpc_arg1 (arg0, type, mpc_asin);
10370 break;
48e1416a 10371
0e7e6e7f 10372 CASE_FLT_FN (BUILT_IN_CACOS):
10373 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10374 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10375 return do_mpc_arg1 (arg0, type, mpc_acos);
10376 break;
48e1416a 10377
0e7e6e7f 10378 CASE_FLT_FN (BUILT_IN_CATAN):
10379 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10380 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10381 return do_mpc_arg1 (arg0, type, mpc_atan);
10382 break;
48e1416a 10383
0e7e6e7f 10384 CASE_FLT_FN (BUILT_IN_CASINH):
10385 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10386 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10387 return do_mpc_arg1 (arg0, type, mpc_asinh);
10388 break;
48e1416a 10389
0e7e6e7f 10390 CASE_FLT_FN (BUILT_IN_CACOSH):
10391 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10392 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10393 return do_mpc_arg1 (arg0, type, mpc_acosh);
10394 break;
48e1416a 10395
0e7e6e7f 10396 CASE_FLT_FN (BUILT_IN_CATANH):
10397 if (validate_arg (arg0, COMPLEX_TYPE)
48e1416a 10398 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
0e7e6e7f 10399 return do_mpc_arg1 (arg0, type, mpc_atanh);
10400 break;
48e1416a 10401
4f35b1fc 10402 CASE_FLT_FN (BUILT_IN_CABS):
389dd41b 10403 return fold_builtin_cabs (loc, arg0, type, fndecl);
c63f4ad3 10404
abe4dcf6 10405 CASE_FLT_FN (BUILT_IN_CARG):
389dd41b 10406 return fold_builtin_carg (loc, arg0, type);
abe4dcf6 10407
4f35b1fc 10408 CASE_FLT_FN (BUILT_IN_SQRT):
389dd41b 10409 return fold_builtin_sqrt (loc, arg0, type);
805e22b2 10410
4f35b1fc 10411 CASE_FLT_FN (BUILT_IN_CBRT):
389dd41b 10412 return fold_builtin_cbrt (loc, arg0, type);
3bc5c41b 10413
728bac60 10414 CASE_FLT_FN (BUILT_IN_ASIN):
c2f47e15 10415 if (validate_arg (arg0, REAL_TYPE))
10416 return do_mpfr_arg1 (arg0, type, mpfr_asin,
728bac60 10417 &dconstm1, &dconst1, true);
10418 break;
10419
10420 CASE_FLT_FN (BUILT_IN_ACOS):
c2f47e15 10421 if (validate_arg (arg0, REAL_TYPE))
10422 return do_mpfr_arg1 (arg0, type, mpfr_acos,
728bac60 10423 &dconstm1, &dconst1, true);
10424 break;
10425
10426 CASE_FLT_FN (BUILT_IN_ATAN):
c2f47e15 10427 if (validate_arg (arg0, REAL_TYPE))
10428 return do_mpfr_arg1 (arg0, type, mpfr_atan, NULL, NULL, 0);
728bac60 10429 break;
10430
10431 CASE_FLT_FN (BUILT_IN_ASINH):
c2f47e15 10432 if (validate_arg (arg0, REAL_TYPE))
10433 return do_mpfr_arg1 (arg0, type, mpfr_asinh, NULL, NULL, 0);
728bac60 10434 break;
10435
10436 CASE_FLT_FN (BUILT_IN_ACOSH):
c2f47e15 10437 if (validate_arg (arg0, REAL_TYPE))
10438 return do_mpfr_arg1 (arg0, type, mpfr_acosh,
728bac60 10439 &dconst1, NULL, true);
10440 break;
10441
10442 CASE_FLT_FN (BUILT_IN_ATANH):
c2f47e15 10443 if (validate_arg (arg0, REAL_TYPE))
10444 return do_mpfr_arg1 (arg0, type, mpfr_atanh,
728bac60 10445 &dconstm1, &dconst1, false);
10446 break;
10447
4f35b1fc 10448 CASE_FLT_FN (BUILT_IN_SIN):
c2f47e15 10449 if (validate_arg (arg0, REAL_TYPE))
10450 return do_mpfr_arg1 (arg0, type, mpfr_sin, NULL, NULL, 0);
728bac60 10451 break;
77e89269 10452
4f35b1fc 10453 CASE_FLT_FN (BUILT_IN_COS):
389dd41b 10454 return fold_builtin_cos (loc, arg0, type, fndecl);
77e89269 10455
728bac60 10456 CASE_FLT_FN (BUILT_IN_TAN):
c2f47e15 10457 return fold_builtin_tan (arg0, type);
d735c391 10458
c5bb2c4b 10459 CASE_FLT_FN (BUILT_IN_CEXP):
389dd41b 10460 return fold_builtin_cexp (loc, arg0, type);
c5bb2c4b 10461
d735c391 10462 CASE_FLT_FN (BUILT_IN_CEXPI):
c2f47e15 10463 if (validate_arg (arg0, REAL_TYPE))
10464 return do_mpfr_sincos (arg0, NULL_TREE, NULL_TREE);
10465 break;
d92f994c 10466
728bac60 10467 CASE_FLT_FN (BUILT_IN_SINH):
c2f47e15 10468 if (validate_arg (arg0, REAL_TYPE))
10469 return do_mpfr_arg1 (arg0, type, mpfr_sinh, NULL, NULL, 0);
728bac60 10470 break;
10471
10472 CASE_FLT_FN (BUILT_IN_COSH):
389dd41b 10473 return fold_builtin_cosh (loc, arg0, type, fndecl);
728bac60 10474
10475 CASE_FLT_FN (BUILT_IN_TANH):
c2f47e15 10476 if (validate_arg (arg0, REAL_TYPE))
10477 return do_mpfr_arg1 (arg0, type, mpfr_tanh, NULL, NULL, 0);
728bac60 10478 break;
10479
29f4cd78 10480 CASE_FLT_FN (BUILT_IN_ERF):
c2f47e15 10481 if (validate_arg (arg0, REAL_TYPE))
10482 return do_mpfr_arg1 (arg0, type, mpfr_erf, NULL, NULL, 0);
29f4cd78 10483 break;
10484
10485 CASE_FLT_FN (BUILT_IN_ERFC):
c2f47e15 10486 if (validate_arg (arg0, REAL_TYPE))
10487 return do_mpfr_arg1 (arg0, type, mpfr_erfc, NULL, NULL, 0);
29f4cd78 10488 break;
10489
32dba52b 10490 CASE_FLT_FN (BUILT_IN_TGAMMA):
c2f47e15 10491 if (validate_arg (arg0, REAL_TYPE))
10492 return do_mpfr_arg1 (arg0, type, mpfr_gamma, NULL, NULL, 0);
32dba52b 10493 break;
48e1416a 10494
4f35b1fc 10495 CASE_FLT_FN (BUILT_IN_EXP):
389dd41b 10496 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp);
467214fd 10497
4f35b1fc 10498 CASE_FLT_FN (BUILT_IN_EXP2):
389dd41b 10499 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp2);
467214fd 10500
4f35b1fc 10501 CASE_FLT_FN (BUILT_IN_EXP10):
10502 CASE_FLT_FN (BUILT_IN_POW10):
389dd41b 10503 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp10);
467214fd 10504
29f4cd78 10505 CASE_FLT_FN (BUILT_IN_EXPM1):
c2f47e15 10506 if (validate_arg (arg0, REAL_TYPE))
10507 return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0);
29f4cd78 10508 break;
48e1416a 10509
4f35b1fc 10510 CASE_FLT_FN (BUILT_IN_LOG):
389dd41b 10511 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log);
467214fd 10512
4f35b1fc 10513 CASE_FLT_FN (BUILT_IN_LOG2):
389dd41b 10514 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log2);
467214fd 10515
4f35b1fc 10516 CASE_FLT_FN (BUILT_IN_LOG10):
389dd41b 10517 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log10);
29f4cd78 10518
10519 CASE_FLT_FN (BUILT_IN_LOG1P):
c2f47e15 10520 if (validate_arg (arg0, REAL_TYPE))
10521 return do_mpfr_arg1 (arg0, type, mpfr_log1p,
29f4cd78 10522 &dconstm1, NULL, false);
10523 break;
805e22b2 10524
65dd1378 10525 CASE_FLT_FN (BUILT_IN_J0):
10526 if (validate_arg (arg0, REAL_TYPE))
10527 return do_mpfr_arg1 (arg0, type, mpfr_j0,
10528 NULL, NULL, 0);
10529 break;
10530
10531 CASE_FLT_FN (BUILT_IN_J1):
10532 if (validate_arg (arg0, REAL_TYPE))
10533 return do_mpfr_arg1 (arg0, type, mpfr_j1,
10534 NULL, NULL, 0);
10535 break;
6ff9eeff 10536
10537 CASE_FLT_FN (BUILT_IN_Y0):
10538 if (validate_arg (arg0, REAL_TYPE))
10539 return do_mpfr_arg1 (arg0, type, mpfr_y0,
10540 &dconst0, NULL, false);
10541 break;
10542
10543 CASE_FLT_FN (BUILT_IN_Y1):
10544 if (validate_arg (arg0, REAL_TYPE))
10545 return do_mpfr_arg1 (arg0, type, mpfr_y1,
10546 &dconst0, NULL, false);
10547 break;
65dd1378 10548
4f35b1fc 10549 CASE_FLT_FN (BUILT_IN_NAN):
c4503c0a 10550 case BUILT_IN_NAND32:
10551 case BUILT_IN_NAND64:
10552 case BUILT_IN_NAND128:
c2f47e15 10553 return fold_builtin_nan (arg0, type, true);
b0db7939 10554
4f35b1fc 10555 CASE_FLT_FN (BUILT_IN_NANS):
c2f47e15 10556 return fold_builtin_nan (arg0, type, false);
b0db7939 10557
4f35b1fc 10558 CASE_FLT_FN (BUILT_IN_FLOOR):
389dd41b 10559 return fold_builtin_floor (loc, fndecl, arg0);
277f8dd2 10560
4f35b1fc 10561 CASE_FLT_FN (BUILT_IN_CEIL):
389dd41b 10562 return fold_builtin_ceil (loc, fndecl, arg0);
277f8dd2 10563
4f35b1fc 10564 CASE_FLT_FN (BUILT_IN_TRUNC):
389dd41b 10565 return fold_builtin_trunc (loc, fndecl, arg0);
277f8dd2 10566
4f35b1fc 10567 CASE_FLT_FN (BUILT_IN_ROUND):
389dd41b 10568 return fold_builtin_round (loc, fndecl, arg0);
89ab3887 10569
4f35b1fc 10570 CASE_FLT_FN (BUILT_IN_NEARBYINT):
10571 CASE_FLT_FN (BUILT_IN_RINT):
389dd41b 10572 return fold_trunc_transparent_mathfn (loc, fndecl, arg0);
6528f4f4 10573
80ff6494 10574 CASE_FLT_FN (BUILT_IN_ICEIL):
4f35b1fc 10575 CASE_FLT_FN (BUILT_IN_LCEIL):
10576 CASE_FLT_FN (BUILT_IN_LLCEIL):
10577 CASE_FLT_FN (BUILT_IN_LFLOOR):
80ff6494 10578 CASE_FLT_FN (BUILT_IN_IFLOOR):
4f35b1fc 10579 CASE_FLT_FN (BUILT_IN_LLFLOOR):
80ff6494 10580 CASE_FLT_FN (BUILT_IN_IROUND):
a0c938f0 10581 CASE_FLT_FN (BUILT_IN_LROUND):
4f35b1fc 10582 CASE_FLT_FN (BUILT_IN_LLROUND):
389dd41b 10583 return fold_builtin_int_roundingfn (loc, fndecl, arg0);
34f17811 10584
80ff6494 10585 CASE_FLT_FN (BUILT_IN_IRINT):
4f35b1fc 10586 CASE_FLT_FN (BUILT_IN_LRINT):
10587 CASE_FLT_FN (BUILT_IN_LLRINT):
389dd41b 10588 return fold_fixed_mathfn (loc, fndecl, arg0);
9ed65c7f 10589
74bdbe96 10590 case BUILT_IN_BSWAP16:
42791117 10591 case BUILT_IN_BSWAP32:
10592 case BUILT_IN_BSWAP64:
c2f47e15 10593 return fold_builtin_bswap (fndecl, arg0);
42791117 10594
4f35b1fc 10595 CASE_INT_FN (BUILT_IN_FFS):
10596 CASE_INT_FN (BUILT_IN_CLZ):
10597 CASE_INT_FN (BUILT_IN_CTZ):
6aaa1f9e 10598 CASE_INT_FN (BUILT_IN_CLRSB):
4f35b1fc 10599 CASE_INT_FN (BUILT_IN_POPCOUNT):
10600 CASE_INT_FN (BUILT_IN_PARITY):
c2f47e15 10601 return fold_builtin_bitop (fndecl, arg0);
9c8a1629 10602
4f35b1fc 10603 CASE_FLT_FN (BUILT_IN_SIGNBIT):
389dd41b 10604 return fold_builtin_signbit (loc, arg0, type);
27f261ef 10605
cb2b9385 10606 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
389dd41b 10607 return fold_builtin_significand (loc, arg0, type);
cb2b9385 10608
10609 CASE_FLT_FN (BUILT_IN_ILOGB):
10610 CASE_FLT_FN (BUILT_IN_LOGB):
389dd41b 10611 return fold_builtin_logb (loc, arg0, type);
cb2b9385 10612
d49367d4 10613 case BUILT_IN_ISASCII:
389dd41b 10614 return fold_builtin_isascii (loc, arg0);
d49367d4 10615
10616 case BUILT_IN_TOASCII:
389dd41b 10617 return fold_builtin_toascii (loc, arg0);
d49367d4 10618
df1cf42e 10619 case BUILT_IN_ISDIGIT:
389dd41b 10620 return fold_builtin_isdigit (loc, arg0);
467214fd 10621
4f35b1fc 10622 CASE_FLT_FN (BUILT_IN_FINITE):
c4503c0a 10623 case BUILT_IN_FINITED32:
10624 case BUILT_IN_FINITED64:
10625 case BUILT_IN_FINITED128:
cde061c1 10626 case BUILT_IN_ISFINITE:
a65c4d64 10627 {
10628 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISFINITE);
10629 if (ret)
10630 return ret;
10631 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10632 }
726069ba 10633
4f35b1fc 10634 CASE_FLT_FN (BUILT_IN_ISINF):
c4503c0a 10635 case BUILT_IN_ISINFD32:
10636 case BUILT_IN_ISINFD64:
10637 case BUILT_IN_ISINFD128:
a65c4d64 10638 {
10639 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF);
10640 if (ret)
10641 return ret;
10642 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
10643 }
10644
10645 case BUILT_IN_ISNORMAL:
10646 return fold_builtin_interclass_mathfn (loc, fndecl, arg0);
726069ba 10647
c319d56a 10648 case BUILT_IN_ISINF_SIGN:
389dd41b 10649 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF_SIGN);
c319d56a 10650
4f35b1fc 10651 CASE_FLT_FN (BUILT_IN_ISNAN):
c4503c0a 10652 case BUILT_IN_ISNAND32:
10653 case BUILT_IN_ISNAND64:
10654 case BUILT_IN_ISNAND128:
389dd41b 10655 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
c2f47e15 10656
10657 case BUILT_IN_PRINTF:
10658 case BUILT_IN_PRINTF_UNLOCKED:
10659 case BUILT_IN_VPRINTF:
389dd41b 10660 return fold_builtin_printf (loc, fndecl, arg0, NULL_TREE, ignore, fcode);
c2f47e15 10661
663870fc 10662 case BUILT_IN_FREE:
10663 if (integer_zerop (arg0))
10664 return build_empty_stmt (loc);
10665 break;
10666
c2f47e15 10667 default:
10668 break;
10669 }
10670
10671 return NULL_TREE;
10672
10673}
10674
10675/* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1.
10676 IGNORE is true if the result of the function call is ignored. This
10677 function returns NULL_TREE if no simplification was possible. */
10678
10679static tree
389dd41b 10680fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore)
c2f47e15 10681{
10682 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10683 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10684
10685 switch (fcode)
10686 {
65dd1378 10687 CASE_FLT_FN (BUILT_IN_JN):
10688 if (validate_arg (arg0, INTEGER_TYPE)
10689 && validate_arg (arg1, REAL_TYPE))
10690 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_jn, NULL, 0);
10691 break;
6ff9eeff 10692
10693 CASE_FLT_FN (BUILT_IN_YN):
10694 if (validate_arg (arg0, INTEGER_TYPE)
10695 && validate_arg (arg1, REAL_TYPE))
10696 return do_mpfr_bessel_n (arg0, arg1, type, mpfr_yn,
10697 &dconst0, false);
10698 break;
e5407ca6 10699
10700 CASE_FLT_FN (BUILT_IN_DREM):
10701 CASE_FLT_FN (BUILT_IN_REMAINDER):
10702 if (validate_arg (arg0, REAL_TYPE)
10703 && validate_arg(arg1, REAL_TYPE))
10704 return do_mpfr_arg2 (arg0, arg1, type, mpfr_remainder);
10705 break;
e84da7c1 10706
10707 CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
10708 CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
10709 if (validate_arg (arg0, REAL_TYPE)
10710 && validate_arg(arg1, POINTER_TYPE))
10711 return do_mpfr_lgamma_r (arg0, arg1, type);
10712 break;
c2f47e15 10713
10714 CASE_FLT_FN (BUILT_IN_ATAN2):
10715 if (validate_arg (arg0, REAL_TYPE)
10716 && validate_arg(arg1, REAL_TYPE))
10717 return do_mpfr_arg2 (arg0, arg1, type, mpfr_atan2);
10718 break;
10719
10720 CASE_FLT_FN (BUILT_IN_FDIM):
10721 if (validate_arg (arg0, REAL_TYPE)
10722 && validate_arg(arg1, REAL_TYPE))
10723 return do_mpfr_arg2 (arg0, arg1, type, mpfr_dim);
10724 break;
10725
10726 CASE_FLT_FN (BUILT_IN_HYPOT):
389dd41b 10727 return fold_builtin_hypot (loc, fndecl, arg0, arg1, type);
c2f47e15 10728
c699fab8 10729 CASE_FLT_FN (BUILT_IN_CPOW):
10730 if (validate_arg (arg0, COMPLEX_TYPE)
10731 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
10732 && validate_arg (arg1, COMPLEX_TYPE)
48e1416a 10733 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE)
652d9409 10734 return do_mpc_arg2 (arg0, arg1, type, /*do_nonfinite=*/ 0, mpc_pow);
c699fab8 10735 break;
c699fab8 10736
7587301b 10737 CASE_FLT_FN (BUILT_IN_LDEXP):
389dd41b 10738 return fold_builtin_load_exponent (loc, arg0, arg1, type, /*ldexp=*/true);
7587301b 10739 CASE_FLT_FN (BUILT_IN_SCALBN):
10740 CASE_FLT_FN (BUILT_IN_SCALBLN):
389dd41b 10741 return fold_builtin_load_exponent (loc, arg0, arg1,
10742 type, /*ldexp=*/false);
7587301b 10743
3838b9ae 10744 CASE_FLT_FN (BUILT_IN_FREXP):
389dd41b 10745 return fold_builtin_frexp (loc, arg0, arg1, type);
3838b9ae 10746
ebf8b4f5 10747 CASE_FLT_FN (BUILT_IN_MODF):
389dd41b 10748 return fold_builtin_modf (loc, arg0, arg1, type);
ebf8b4f5 10749
c2f47e15 10750 case BUILT_IN_BZERO:
389dd41b 10751 return fold_builtin_bzero (loc, arg0, arg1, ignore);
c2f47e15 10752
10753 case BUILT_IN_FPUTS:
389dd41b 10754 return fold_builtin_fputs (loc, arg0, arg1, ignore, false, NULL_TREE);
c2f47e15 10755
10756 case BUILT_IN_FPUTS_UNLOCKED:
389dd41b 10757 return fold_builtin_fputs (loc, arg0, arg1, ignore, true, NULL_TREE);
c2f47e15 10758
10759 case BUILT_IN_STRSTR:
389dd41b 10760 return fold_builtin_strstr (loc, arg0, arg1, type);
c2f47e15 10761
10762 case BUILT_IN_STRCAT:
389dd41b 10763 return fold_builtin_strcat (loc, arg0, arg1);
c2f47e15 10764
10765 case BUILT_IN_STRSPN:
389dd41b 10766 return fold_builtin_strspn (loc, arg0, arg1);
c2f47e15 10767
10768 case BUILT_IN_STRCSPN:
389dd41b 10769 return fold_builtin_strcspn (loc, arg0, arg1);
c2f47e15 10770
10771 case BUILT_IN_STRCHR:
10772 case BUILT_IN_INDEX:
389dd41b 10773 return fold_builtin_strchr (loc, arg0, arg1, type);
c2f47e15 10774
10775 case BUILT_IN_STRRCHR:
10776 case BUILT_IN_RINDEX:
389dd41b 10777 return fold_builtin_strrchr (loc, arg0, arg1, type);
c2f47e15 10778
10779 case BUILT_IN_STRCPY:
389dd41b 10780 return fold_builtin_strcpy (loc, fndecl, arg0, arg1, NULL_TREE);
c2f47e15 10781
c8b17b2e 10782 case BUILT_IN_STPCPY:
10783 if (ignore)
10784 {
b9a16870 10785 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
c8b17b2e 10786 if (!fn)
10787 break;
10788
389dd41b 10789 return build_call_expr_loc (loc, fn, 2, arg0, arg1);
c8b17b2e 10790 }
a65c4d64 10791 else
10792 return fold_builtin_stpcpy (loc, fndecl, arg0, arg1);
c8b17b2e 10793 break;
10794
c2f47e15 10795 case BUILT_IN_STRCMP:
389dd41b 10796 return fold_builtin_strcmp (loc, arg0, arg1);
c2f47e15 10797
10798 case BUILT_IN_STRPBRK:
389dd41b 10799 return fold_builtin_strpbrk (loc, arg0, arg1, type);
c2f47e15 10800
10801 case BUILT_IN_EXPECT:
389dd41b 10802 return fold_builtin_expect (loc, arg0, arg1);
c2f47e15 10803
10804 CASE_FLT_FN (BUILT_IN_POW):
389dd41b 10805 return fold_builtin_pow (loc, fndecl, arg0, arg1, type);
c2f47e15 10806
10807 CASE_FLT_FN (BUILT_IN_POWI):
389dd41b 10808 return fold_builtin_powi (loc, fndecl, arg0, arg1, type);
c2f47e15 10809
10810 CASE_FLT_FN (BUILT_IN_COPYSIGN):
389dd41b 10811 return fold_builtin_copysign (loc, fndecl, arg0, arg1, type);
c2f47e15 10812
10813 CASE_FLT_FN (BUILT_IN_FMIN):
389dd41b 10814 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/false);
c2f47e15 10815
10816 CASE_FLT_FN (BUILT_IN_FMAX):
389dd41b 10817 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/true);
726069ba 10818
9bc9f15f 10819 case BUILT_IN_ISGREATER:
389dd41b 10820 return fold_builtin_unordered_cmp (loc, fndecl,
10821 arg0, arg1, UNLE_EXPR, LE_EXPR);
9bc9f15f 10822 case BUILT_IN_ISGREATEREQUAL:
389dd41b 10823 return fold_builtin_unordered_cmp (loc, fndecl,
10824 arg0, arg1, UNLT_EXPR, LT_EXPR);
9bc9f15f 10825 case BUILT_IN_ISLESS:
389dd41b 10826 return fold_builtin_unordered_cmp (loc, fndecl,
10827 arg0, arg1, UNGE_EXPR, GE_EXPR);
9bc9f15f 10828 case BUILT_IN_ISLESSEQUAL:
389dd41b 10829 return fold_builtin_unordered_cmp (loc, fndecl,
10830 arg0, arg1, UNGT_EXPR, GT_EXPR);
9bc9f15f 10831 case BUILT_IN_ISLESSGREATER:
389dd41b 10832 return fold_builtin_unordered_cmp (loc, fndecl,
10833 arg0, arg1, UNEQ_EXPR, EQ_EXPR);
9bc9f15f 10834 case BUILT_IN_ISUNORDERED:
389dd41b 10835 return fold_builtin_unordered_cmp (loc, fndecl,
10836 arg0, arg1, UNORDERED_EXPR,
d5019fe8 10837 NOP_EXPR);
9bc9f15f 10838
7c2f0500 10839 /* We do the folding for va_start in the expander. */
10840 case BUILT_IN_VA_START:
10841 break;
f0613857 10842
c2f47e15 10843 case BUILT_IN_SPRINTF:
389dd41b 10844 return fold_builtin_sprintf (loc, arg0, arg1, NULL_TREE, ignore);
c2f47e15 10845
0a39fd54 10846 case BUILT_IN_OBJECT_SIZE:
c2f47e15 10847 return fold_builtin_object_size (arg0, arg1);
0a39fd54 10848
10849 case BUILT_IN_PRINTF:
10850 case BUILT_IN_PRINTF_UNLOCKED:
10851 case BUILT_IN_VPRINTF:
389dd41b 10852 return fold_builtin_printf (loc, fndecl, arg0, arg1, ignore, fcode);
c2f47e15 10853
0a39fd54 10854 case BUILT_IN_PRINTF_CHK:
10855 case BUILT_IN_VPRINTF_CHK:
c2f47e15 10856 if (!validate_arg (arg0, INTEGER_TYPE)
10857 || TREE_SIDE_EFFECTS (arg0))
10858 return NULL_TREE;
10859 else
389dd41b 10860 return fold_builtin_printf (loc, fndecl,
10861 arg1, NULL_TREE, ignore, fcode);
c2f47e15 10862 break;
0a39fd54 10863
10864 case BUILT_IN_FPRINTF:
10865 case BUILT_IN_FPRINTF_UNLOCKED:
10866 case BUILT_IN_VFPRINTF:
389dd41b 10867 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, NULL_TREE,
c2f47e15 10868 ignore, fcode);
10869
1cd6e20d 10870 case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
10871 return fold_builtin_atomic_always_lock_free (arg0, arg1);
10872
10873 case BUILT_IN_ATOMIC_IS_LOCK_FREE:
10874 return fold_builtin_atomic_is_lock_free (arg0, arg1);
10875
c2f47e15 10876 default:
10877 break;
10878 }
10879 return NULL_TREE;
10880}
10881
10882/* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
10883 and ARG2. IGNORE is true if the result of the function call is ignored.
10884 This function returns NULL_TREE if no simplification was possible. */
10885
10886static tree
389dd41b 10887fold_builtin_3 (location_t loc, tree fndecl,
10888 tree arg0, tree arg1, tree arg2, bool ignore)
c2f47e15 10889{
10890 tree type = TREE_TYPE (TREE_TYPE (fndecl));
10891 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10892 switch (fcode)
10893 {
10894
10895 CASE_FLT_FN (BUILT_IN_SINCOS):
389dd41b 10896 return fold_builtin_sincos (loc, arg0, arg1, arg2);
c2f47e15 10897
10898 CASE_FLT_FN (BUILT_IN_FMA):
b9be572e 10899 return fold_builtin_fma (loc, arg0, arg1, arg2, type);
c2f47e15 10900 break;
10901
e5407ca6 10902 CASE_FLT_FN (BUILT_IN_REMQUO):
10903 if (validate_arg (arg0, REAL_TYPE)
10904 && validate_arg(arg1, REAL_TYPE)
10905 && validate_arg(arg2, POINTER_TYPE))
10906 return do_mpfr_remquo (arg0, arg1, arg2);
10907 break;
e5407ca6 10908
c2f47e15 10909 case BUILT_IN_MEMSET:
389dd41b 10910 return fold_builtin_memset (loc, arg0, arg1, arg2, type, ignore);
c2f47e15 10911
10912 case BUILT_IN_BCOPY:
389dd41b 10913 return fold_builtin_memory_op (loc, arg1, arg0, arg2,
10914 void_type_node, true, /*endp=*/3);
c2f47e15 10915
10916 case BUILT_IN_MEMCPY:
389dd41b 10917 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10918 type, ignore, /*endp=*/0);
c2f47e15 10919
10920 case BUILT_IN_MEMPCPY:
389dd41b 10921 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10922 type, ignore, /*endp=*/1);
c2f47e15 10923
10924 case BUILT_IN_MEMMOVE:
389dd41b 10925 return fold_builtin_memory_op (loc, arg0, arg1, arg2,
10926 type, ignore, /*endp=*/3);
c2f47e15 10927
10928 case BUILT_IN_STRNCAT:
389dd41b 10929 return fold_builtin_strncat (loc, arg0, arg1, arg2);
c2f47e15 10930
10931 case BUILT_IN_STRNCPY:
389dd41b 10932 return fold_builtin_strncpy (loc, fndecl, arg0, arg1, arg2, NULL_TREE);
c2f47e15 10933
10934 case BUILT_IN_STRNCMP:
389dd41b 10935 return fold_builtin_strncmp (loc, arg0, arg1, arg2);
c2f47e15 10936
7959b13b 10937 case BUILT_IN_MEMCHR:
389dd41b 10938 return fold_builtin_memchr (loc, arg0, arg1, arg2, type);
7959b13b 10939
c2f47e15 10940 case BUILT_IN_BCMP:
10941 case BUILT_IN_MEMCMP:
389dd41b 10942 return fold_builtin_memcmp (loc, arg0, arg1, arg2);;
c2f47e15 10943
10944 case BUILT_IN_SPRINTF:
389dd41b 10945 return fold_builtin_sprintf (loc, arg0, arg1, arg2, ignore);
c2f47e15 10946
750d7b16 10947 case BUILT_IN_SNPRINTF:
10948 return fold_builtin_snprintf (loc, arg0, arg1, arg2, NULL_TREE, ignore);
10949
c2f47e15 10950 case BUILT_IN_STRCPY_CHK:
10951 case BUILT_IN_STPCPY_CHK:
389dd41b 10952 return fold_builtin_stxcpy_chk (loc, fndecl, arg0, arg1, arg2, NULL_TREE,
c2f47e15 10953 ignore, fcode);
10954
10955 case BUILT_IN_STRCAT_CHK:
389dd41b 10956 return fold_builtin_strcat_chk (loc, fndecl, arg0, arg1, arg2);
c2f47e15 10957
10958 case BUILT_IN_PRINTF_CHK:
10959 case BUILT_IN_VPRINTF_CHK:
10960 if (!validate_arg (arg0, INTEGER_TYPE)
10961 || TREE_SIDE_EFFECTS (arg0))
10962 return NULL_TREE;
10963 else
389dd41b 10964 return fold_builtin_printf (loc, fndecl, arg1, arg2, ignore, fcode);
c2f47e15 10965 break;
10966
10967 case BUILT_IN_FPRINTF:
10968 case BUILT_IN_FPRINTF_UNLOCKED:
10969 case BUILT_IN_VFPRINTF:
389dd41b 10970 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, arg2,
10971 ignore, fcode);
c2f47e15 10972
0a39fd54 10973 case BUILT_IN_FPRINTF_CHK:
10974 case BUILT_IN_VFPRINTF_CHK:
c2f47e15 10975 if (!validate_arg (arg1, INTEGER_TYPE)
10976 || TREE_SIDE_EFFECTS (arg1))
10977 return NULL_TREE;
10978 else
389dd41b 10979 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, NULL_TREE,
c2f47e15 10980 ignore, fcode);
0a39fd54 10981
650e4c94 10982 default:
10983 break;
10984 }
c2f47e15 10985 return NULL_TREE;
10986}
650e4c94 10987
c2f47e15 10988/* Fold a call to built-in function FNDECL with 4 arguments, ARG0, ARG1,
10989 ARG2, and ARG3. IGNORE is true if the result of the function call is
10990 ignored. This function returns NULL_TREE if no simplification was
10991 possible. */
48e1416a 10992
c2f47e15 10993static tree
389dd41b 10994fold_builtin_4 (location_t loc, tree fndecl,
10995 tree arg0, tree arg1, tree arg2, tree arg3, bool ignore)
c2f47e15 10996{
10997 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
10998
10999 switch (fcode)
11000 {
11001 case BUILT_IN_MEMCPY_CHK:
11002 case BUILT_IN_MEMPCPY_CHK:
11003 case BUILT_IN_MEMMOVE_CHK:
11004 case BUILT_IN_MEMSET_CHK:
389dd41b 11005 return fold_builtin_memory_chk (loc, fndecl, arg0, arg1, arg2, arg3,
c2f47e15 11006 NULL_TREE, ignore,
11007 DECL_FUNCTION_CODE (fndecl));
11008
11009 case BUILT_IN_STRNCPY_CHK:
1063acde 11010 case BUILT_IN_STPNCPY_CHK:
11011 return fold_builtin_stxncpy_chk (loc, arg0, arg1, arg2, arg3, NULL_TREE,
11012 ignore, fcode);
c2f47e15 11013
11014 case BUILT_IN_STRNCAT_CHK:
389dd41b 11015 return fold_builtin_strncat_chk (loc, fndecl, arg0, arg1, arg2, arg3);
c2f47e15 11016
750d7b16 11017 case BUILT_IN_SNPRINTF:
11018 return fold_builtin_snprintf (loc, arg0, arg1, arg2, arg3, ignore);
11019
c2f47e15 11020 case BUILT_IN_FPRINTF_CHK:
11021 case BUILT_IN_VFPRINTF_CHK:
11022 if (!validate_arg (arg1, INTEGER_TYPE)
11023 || TREE_SIDE_EFFECTS (arg1))
11024 return NULL_TREE;
11025 else
389dd41b 11026 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, arg3,
c2f47e15 11027 ignore, fcode);
11028 break;
11029
11030 default:
11031 break;
11032 }
11033 return NULL_TREE;
11034}
11035
11036/* Fold a call to built-in function FNDECL. ARGS is an array of NARGS
11037 arguments, where NARGS <= 4. IGNORE is true if the result of the
11038 function call is ignored. This function returns NULL_TREE if no
11039 simplification was possible. Note that this only folds builtins with
11040 fixed argument patterns. Foldings that do varargs-to-varargs
11041 transformations, or that match calls with more than 4 arguments,
11042 need to be handled with fold_builtin_varargs instead. */
48e1416a 11043
c2f47e15 11044#define MAX_ARGS_TO_FOLD_BUILTIN 4
48e1416a 11045
c2f47e15 11046static tree
389dd41b 11047fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool ignore)
c2f47e15 11048{
11049 tree ret = NULL_TREE;
a7f5bb2d 11050
c2f47e15 11051 switch (nargs)
11052 {
11053 case 0:
389dd41b 11054 ret = fold_builtin_0 (loc, fndecl, ignore);
c2f47e15 11055 break;
11056 case 1:
389dd41b 11057 ret = fold_builtin_1 (loc, fndecl, args[0], ignore);
c2f47e15 11058 break;
11059 case 2:
389dd41b 11060 ret = fold_builtin_2 (loc, fndecl, args[0], args[1], ignore);
c2f47e15 11061 break;
11062 case 3:
389dd41b 11063 ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2], ignore);
c2f47e15 11064 break;
11065 case 4:
389dd41b 11066 ret = fold_builtin_4 (loc, fndecl, args[0], args[1], args[2], args[3],
c2f47e15 11067 ignore);
11068 break;
11069 default:
11070 break;
11071 }
11072 if (ret)
11073 {
75a70cf9 11074 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
389dd41b 11075 SET_EXPR_LOCATION (ret, loc);
c2f47e15 11076 TREE_NO_WARNING (ret) = 1;
11077 return ret;
11078 }
11079 return NULL_TREE;
11080}
11081
11082/* Builtins with folding operations that operate on "..." arguments
11083 need special handling; we need to store the arguments in a convenient
11084 data structure before attempting any folding. Fortunately there are
11085 only a few builtins that fall into this category. FNDECL is the
11086 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
11087 result of the function call is ignored. */
11088
11089static tree
389dd41b 11090fold_builtin_varargs (location_t loc, tree fndecl, tree exp,
11091 bool ignore ATTRIBUTE_UNUSED)
c2f47e15 11092{
11093 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
11094 tree ret = NULL_TREE;
11095
11096 switch (fcode)
11097 {
11098 case BUILT_IN_SPRINTF_CHK:
11099 case BUILT_IN_VSPRINTF_CHK:
389dd41b 11100 ret = fold_builtin_sprintf_chk (loc, exp, fcode);
c2f47e15 11101 break;
11102
11103 case BUILT_IN_SNPRINTF_CHK:
11104 case BUILT_IN_VSNPRINTF_CHK:
389dd41b 11105 ret = fold_builtin_snprintf_chk (loc, exp, NULL_TREE, fcode);
19fbe3a4 11106 break;
11107
11108 case BUILT_IN_FPCLASSIFY:
389dd41b 11109 ret = fold_builtin_fpclassify (loc, exp);
19fbe3a4 11110 break;
c2f47e15 11111
11112 default:
11113 break;
11114 }
11115 if (ret)
11116 {
11117 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
389dd41b 11118 SET_EXPR_LOCATION (ret, loc);
c2f47e15 11119 TREE_NO_WARNING (ret) = 1;
11120 return ret;
11121 }
11122 return NULL_TREE;
650e4c94 11123}
7e15618b 11124
198622c0 11125/* Return true if FNDECL shouldn't be folded right now.
11126 If a built-in function has an inline attribute always_inline
11127 wrapper, defer folding it after always_inline functions have
11128 been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
11129 might not be performed. */
11130
51d2c51e 11131bool
198622c0 11132avoid_folding_inline_builtin (tree fndecl)
11133{
11134 return (DECL_DECLARED_INLINE_P (fndecl)
11135 && DECL_DISREGARD_INLINE_LIMITS (fndecl)
11136 && cfun
11137 && !cfun->always_inline_functions_inlined
11138 && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)));
11139}
11140
4ee9c684 11141/* A wrapper function for builtin folding that prevents warnings for
491e04ef 11142 "statement without effect" and the like, caused by removing the
4ee9c684 11143 call node earlier than the warning is generated. */
11144
11145tree
389dd41b 11146fold_call_expr (location_t loc, tree exp, bool ignore)
4ee9c684 11147{
c2f47e15 11148 tree ret = NULL_TREE;
11149 tree fndecl = get_callee_fndecl (exp);
11150 if (fndecl
11151 && TREE_CODE (fndecl) == FUNCTION_DECL
48dc2227 11152 && DECL_BUILT_IN (fndecl)
11153 /* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
11154 yet. Defer folding until we see all the arguments
11155 (after inlining). */
11156 && !CALL_EXPR_VA_ARG_PACK (exp))
11157 {
11158 int nargs = call_expr_nargs (exp);
11159
11160 /* Before gimplification CALL_EXPR_VA_ARG_PACK is not set, but
11161 instead last argument is __builtin_va_arg_pack (). Defer folding
11162 even in that case, until arguments are finalized. */
11163 if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
11164 {
11165 tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1));
11166 if (fndecl2
11167 && TREE_CODE (fndecl2) == FUNCTION_DECL
11168 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
11169 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
11170 return NULL_TREE;
11171 }
11172
198622c0 11173 if (avoid_folding_inline_builtin (fndecl))
11174 return NULL_TREE;
11175
c2f47e15 11176 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
97d67146 11177 return targetm.fold_builtin (fndecl, call_expr_nargs (exp),
11178 CALL_EXPR_ARGP (exp), ignore);
c2f47e15 11179 else
11180 {
c2f47e15 11181 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
11182 {
11183 tree *args = CALL_EXPR_ARGP (exp);
389dd41b 11184 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
c2f47e15 11185 }
11186 if (!ret)
389dd41b 11187 ret = fold_builtin_varargs (loc, fndecl, exp, ignore);
c2f47e15 11188 if (ret)
389dd41b 11189 return ret;
c2f47e15 11190 }
4ee9c684 11191 }
c2f47e15 11192 return NULL_TREE;
11193}
48e1416a 11194
c2f47e15 11195/* Conveniently construct a function call expression. FNDECL names the
414c3a2c 11196 function to be called and N arguments are passed in the array
11197 ARGARRAY. */
48e1416a 11198
c2f47e15 11199tree
414c3a2c 11200build_call_expr_loc_array (location_t loc, tree fndecl, int n, tree *argarray)
c2f47e15 11201{
11202 tree fntype = TREE_TYPE (fndecl);
11203 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
414c3a2c 11204
389dd41b 11205 return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray);
c2f47e15 11206}
11207
414c3a2c 11208/* Conveniently construct a function call expression. FNDECL names the
11209 function to be called and the arguments are passed in the vector
11210 VEC. */
11211
11212tree
f1f41a6c 11213build_call_expr_loc_vec (location_t loc, tree fndecl, vec<tree, va_gc> *vec)
414c3a2c 11214{
f1f41a6c 11215 return build_call_expr_loc_array (loc, fndecl, vec_safe_length (vec),
11216 vec_safe_address (vec));
414c3a2c 11217}
11218
11219
c2f47e15 11220/* Conveniently construct a function call expression. FNDECL names the
11221 function to be called, N is the number of arguments, and the "..."
11222 parameters are the argument expressions. */
48e1416a 11223
c2f47e15 11224tree
389dd41b 11225build_call_expr_loc (location_t loc, tree fndecl, int n, ...)
c2f47e15 11226{
11227 va_list ap;
414c3a2c 11228 tree *argarray = XALLOCAVEC (tree, n);
d01f58f9 11229 int i;
c2f47e15 11230
11231 va_start (ap, n);
d01f58f9 11232 for (i = 0; i < n; i++)
11233 argarray[i] = va_arg (ap, tree);
c2f47e15 11234 va_end (ap);
414c3a2c 11235 return build_call_expr_loc_array (loc, fndecl, n, argarray);
4ee9c684 11236}
11237
0568e9c1 11238/* Like build_call_expr_loc (UNKNOWN_LOCATION, ...). Duplicated because
11239 varargs macros aren't supported by all bootstrap compilers. */
11240
11241tree
11242build_call_expr (tree fndecl, int n, ...)
11243{
11244 va_list ap;
414c3a2c 11245 tree *argarray = XALLOCAVEC (tree, n);
0568e9c1 11246 int i;
11247
11248 va_start (ap, n);
11249 for (i = 0; i < n; i++)
11250 argarray[i] = va_arg (ap, tree);
11251 va_end (ap);
414c3a2c 11252 return build_call_expr_loc_array (UNKNOWN_LOCATION, fndecl, n, argarray);
0568e9c1 11253}
11254
c2f47e15 11255/* Construct a CALL_EXPR with type TYPE with FN as the function expression.
d01f58f9 11256 N arguments are passed in the array ARGARRAY. */
805e22b2 11257
11258tree
389dd41b 11259fold_builtin_call_array (location_t loc, tree type,
d01f58f9 11260 tree fn,
11261 int n,
11262 tree *argarray)
7e15618b 11263{
c2f47e15 11264 tree ret = NULL_TREE;
c2f47e15 11265 tree exp;
11266
11267 if (TREE_CODE (fn) == ADDR_EXPR)
11268 {
11269 tree fndecl = TREE_OPERAND (fn, 0);
11270 if (TREE_CODE (fndecl) == FUNCTION_DECL
11271 && DECL_BUILT_IN (fndecl))
11272 {
48dc2227 11273 /* If last argument is __builtin_va_arg_pack (), arguments to this
11274 function are not finalized yet. Defer folding until they are. */
11275 if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
11276 {
11277 tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
11278 if (fndecl2
11279 && TREE_CODE (fndecl2) == FUNCTION_DECL
11280 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
11281 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
389dd41b 11282 return build_call_array_loc (loc, type, fn, n, argarray);
48dc2227 11283 }
198622c0 11284 if (avoid_folding_inline_builtin (fndecl))
389dd41b 11285 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 11286 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
11287 {
97d67146 11288 ret = targetm.fold_builtin (fndecl, n, argarray, false);
11289 if (ret)
11290 return ret;
11291
389dd41b 11292 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 11293 }
11294 else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
11295 {
11296 /* First try the transformations that don't require consing up
11297 an exp. */
389dd41b 11298 ret = fold_builtin_n (loc, fndecl, argarray, n, false);
c2f47e15 11299 if (ret)
11300 return ret;
11301 }
11302
11303 /* If we got this far, we need to build an exp. */
389dd41b 11304 exp = build_call_array_loc (loc, type, fn, n, argarray);
11305 ret = fold_builtin_varargs (loc, fndecl, exp, false);
c2f47e15 11306 return ret ? ret : exp;
11307 }
11308 }
11309
389dd41b 11310 return build_call_array_loc (loc, type, fn, n, argarray);
c2f47e15 11311}
11312
af1409ad 11313/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
11314 list ARGS along with N new arguments in NEWARGS. SKIP is the number
11315 of arguments in ARGS to be omitted. OLDNARGS is the number of
11316 elements in ARGS. */
c2f47e15 11317
11318static tree
af1409ad 11319rewrite_call_expr_valist (location_t loc, int oldnargs, tree *args,
11320 int skip, tree fndecl, int n, va_list newargs)
c2f47e15 11321{
c2f47e15 11322 int nargs = oldnargs - skip + n;
c2f47e15 11323 tree *buffer;
11324
11325 if (n > 0)
11326 {
11327 int i, j;
7e15618b 11328
364c0c59 11329 buffer = XALLOCAVEC (tree, nargs);
c2f47e15 11330 for (i = 0; i < n; i++)
af1409ad 11331 buffer[i] = va_arg (newargs, tree);
c2f47e15 11332 for (j = skip; j < oldnargs; j++, i++)
af1409ad 11333 buffer[i] = args[j];
c2f47e15 11334 }
48e1416a 11335 else
af1409ad 11336 buffer = args + skip;
11337
11338 return build_call_expr_loc_array (loc, fndecl, nargs, buffer);
11339}
11340
11341/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
11342 list ARGS along with N new arguments specified as the "..."
11343 parameters. SKIP is the number of arguments in ARGS to be omitted.
11344 OLDNARGS is the number of elements in ARGS. */
11345
11346static tree
11347rewrite_call_expr_array (location_t loc, int oldnargs, tree *args,
11348 int skip, tree fndecl, int n, ...)
11349{
11350 va_list ap;
11351 tree t;
11352
11353 va_start (ap, n);
11354 t = rewrite_call_expr_valist (loc, oldnargs, args, skip, fndecl, n, ap);
11355 va_end (ap);
11356
11357 return t;
11358}
11359
11360/* Construct a new CALL_EXPR using the tail of the argument list of EXP
11361 along with N new arguments specified as the "..." parameters. SKIP
11362 is the number of arguments in EXP to be omitted. This function is used
11363 to do varargs-to-varargs transformations. */
11364
11365static tree
11366rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...)
11367{
11368 va_list ap;
11369 tree t;
11370
11371 va_start (ap, n);
11372 t = rewrite_call_expr_valist (loc, call_expr_nargs (exp),
11373 CALL_EXPR_ARGP (exp), skip, fndecl, n, ap);
11374 va_end (ap);
c2f47e15 11375
af1409ad 11376 return t;
c2f47e15 11377}
11378
11379/* Validate a single argument ARG against a tree code CODE representing
11380 a type. */
48e1416a 11381
c2f47e15 11382static bool
b7bf20db 11383validate_arg (const_tree arg, enum tree_code code)
c2f47e15 11384{
11385 if (!arg)
11386 return false;
11387 else if (code == POINTER_TYPE)
11388 return POINTER_TYPE_P (TREE_TYPE (arg));
c7f617c2 11389 else if (code == INTEGER_TYPE)
11390 return INTEGRAL_TYPE_P (TREE_TYPE (arg));
c2f47e15 11391 return code == TREE_CODE (TREE_TYPE (arg));
7e15618b 11392}
0eb671f7 11393
75a70cf9 11394/* This function validates the types of a function call argument list
11395 against a specified list of tree_codes. If the last specifier is a 0,
11396 that represents an ellipses, otherwise the last specifier must be a
11397 VOID_TYPE.
11398
11399 This is the GIMPLE version of validate_arglist. Eventually we want to
11400 completely convert builtins.c to work from GIMPLEs and the tree based
11401 validate_arglist will then be removed. */
11402
11403bool
11404validate_gimple_arglist (const_gimple call, ...)
11405{
11406 enum tree_code code;
11407 bool res = 0;
11408 va_list ap;
11409 const_tree arg;
11410 size_t i;
11411
11412 va_start (ap, call);
11413 i = 0;
11414
11415 do
11416 {
d62e827b 11417 code = (enum tree_code) va_arg (ap, int);
75a70cf9 11418 switch (code)
11419 {
11420 case 0:
11421 /* This signifies an ellipses, any further arguments are all ok. */
11422 res = true;
11423 goto end;
11424 case VOID_TYPE:
11425 /* This signifies an endlink, if no arguments remain, return
11426 true, otherwise return false. */
11427 res = (i == gimple_call_num_args (call));
11428 goto end;
11429 default:
11430 /* If no parameters remain or the parameter's code does not
11431 match the specified code, return false. Otherwise continue
11432 checking any remaining arguments. */
11433 arg = gimple_call_arg (call, i++);
11434 if (!validate_arg (arg, code))
11435 goto end;
11436 break;
11437 }
11438 }
11439 while (1);
11440
11441 /* We need gotos here since we can only have one VA_CLOSE in a
11442 function. */
11443 end: ;
11444 va_end (ap);
11445
11446 return res;
11447}
11448
0eb671f7 11449/* This function validates the types of a function call argument list
c2f47e15 11450 against a specified list of tree_codes. If the last specifier is a 0,
11451 that represents an ellipses, otherwise the last specifier must be a
11452 VOID_TYPE. */
27d0c333 11453
c2f47e15 11454bool
b7bf20db 11455validate_arglist (const_tree callexpr, ...)
0eb671f7 11456{
0eb671f7 11457 enum tree_code code;
c2f47e15 11458 bool res = 0;
ee582a61 11459 va_list ap;
b7bf20db 11460 const_call_expr_arg_iterator iter;
11461 const_tree arg;
aecda0d6 11462
c2f47e15 11463 va_start (ap, callexpr);
b7bf20db 11464 init_const_call_expr_arg_iterator (callexpr, &iter);
0eb671f7 11465
f0ce3b1f 11466 do
0eb671f7 11467 {
d62e827b 11468 code = (enum tree_code) va_arg (ap, int);
f0ce3b1f 11469 switch (code)
11470 {
11471 case 0:
11472 /* This signifies an ellipses, any further arguments are all ok. */
c2f47e15 11473 res = true;
f0ce3b1f 11474 goto end;
11475 case VOID_TYPE:
11476 /* This signifies an endlink, if no arguments remain, return
11477 true, otherwise return false. */
b7bf20db 11478 res = !more_const_call_expr_args_p (&iter);
f0ce3b1f 11479 goto end;
11480 default:
11481 /* If no parameters remain or the parameter's code does not
11482 match the specified code, return false. Otherwise continue
11483 checking any remaining arguments. */
b7bf20db 11484 arg = next_const_call_expr_arg (&iter);
c2f47e15 11485 if (!validate_arg (arg, code))
f0ce3b1f 11486 goto end;
11487 break;
11488 }
0eb671f7 11489 }
f0ce3b1f 11490 while (1);
0903457a 11491
11492 /* We need gotos here since we can only have one VA_CLOSE in a
11493 function. */
11494 end: ;
ee582a61 11495 va_end (ap);
0903457a 11496
11497 return res;
0eb671f7 11498}
fc2a2dcb 11499
fc2a2dcb 11500/* Default target-specific builtin expander that does nothing. */
11501
11502rtx
aecda0d6 11503default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
11504 rtx target ATTRIBUTE_UNUSED,
11505 rtx subtarget ATTRIBUTE_UNUSED,
11506 enum machine_mode mode ATTRIBUTE_UNUSED,
11507 int ignore ATTRIBUTE_UNUSED)
fc2a2dcb 11508{
11509 return NULL_RTX;
11510}
c7926a82 11511
01537105 11512/* Returns true is EXP represents data that would potentially reside
11513 in a readonly section. */
11514
11515static bool
11516readonly_data_expr (tree exp)
11517{
11518 STRIP_NOPS (exp);
11519
9ff0637e 11520 if (TREE_CODE (exp) != ADDR_EXPR)
11521 return false;
11522
11523 exp = get_base_address (TREE_OPERAND (exp, 0));
11524 if (!exp)
11525 return false;
11526
11527 /* Make sure we call decl_readonly_section only for trees it
11528 can handle (since it returns true for everything it doesn't
11529 understand). */
491e04ef 11530 if (TREE_CODE (exp) == STRING_CST
9ff0637e 11531 || TREE_CODE (exp) == CONSTRUCTOR
11532 || (TREE_CODE (exp) == VAR_DECL && TREE_STATIC (exp)))
11533 return decl_readonly_section (exp, 0);
01537105 11534 else
11535 return false;
11536}
4ee9c684 11537
c2f47e15 11538/* Simplify a call to the strstr builtin. S1 and S2 are the arguments
11539 to the call, and TYPE is its return type.
4ee9c684 11540
c2f47e15 11541 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11542 simplified form of the call as a tree.
11543
11544 The simplified form may be a constant or other expression which
11545 computes the same value, but in a more efficient manner (including
11546 calls to other builtin functions).
11547
11548 The call may contain arguments which need to be evaluated, but
11549 which are not useful to determine the result of the call. In
11550 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11551 COMPOUND_EXPR will be an argument which must be evaluated.
11552 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11553 COMPOUND_EXPR in the chain will contain the tree for the simplified
11554 form of the builtin function call. */
11555
11556static tree
389dd41b 11557fold_builtin_strstr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11558{
c2f47e15 11559 if (!validate_arg (s1, POINTER_TYPE)
11560 || !validate_arg (s2, POINTER_TYPE))
11561 return NULL_TREE;
4ee9c684 11562 else
11563 {
4ee9c684 11564 tree fn;
11565 const char *p1, *p2;
11566
11567 p2 = c_getstr (s2);
11568 if (p2 == NULL)
c2f47e15 11569 return NULL_TREE;
4ee9c684 11570
11571 p1 = c_getstr (s1);
11572 if (p1 != NULL)
11573 {
11574 const char *r = strstr (p1, p2);
daa1d5f5 11575 tree tem;
4ee9c684 11576
4ee9c684 11577 if (r == NULL)
779b4c41 11578 return build_int_cst (TREE_TYPE (s1), 0);
c0c67e38 11579
11580 /* Return an offset into the constant string argument. */
2cc66f2a 11581 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11582 return fold_convert_loc (loc, type, tem);
4ee9c684 11583 }
11584
7efa231c 11585 /* The argument is const char *, and the result is char *, so we need
11586 a type conversion here to avoid a warning. */
4ee9c684 11587 if (p2[0] == '\0')
389dd41b 11588 return fold_convert_loc (loc, type, s1);
4ee9c684 11589
11590 if (p2[1] != '\0')
c2f47e15 11591 return NULL_TREE;
4ee9c684 11592
b9a16870 11593 fn = builtin_decl_implicit (BUILT_IN_STRCHR);
4ee9c684 11594 if (!fn)
c2f47e15 11595 return NULL_TREE;
4ee9c684 11596
11597 /* New argument list transforming strstr(s1, s2) to
11598 strchr(s1, s2[0]). */
7002a1c8 11599 return build_call_expr_loc (loc, fn, 2, s1,
11600 build_int_cst (integer_type_node, p2[0]));
4ee9c684 11601 }
11602}
11603
c2f47e15 11604/* Simplify a call to the strchr builtin. S1 and S2 are the arguments to
11605 the call, and TYPE is its return type.
4ee9c684 11606
c2f47e15 11607 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11608 simplified form of the call as a tree.
11609
11610 The simplified form may be a constant or other expression which
11611 computes the same value, but in a more efficient manner (including
11612 calls to other builtin functions).
11613
11614 The call may contain arguments which need to be evaluated, but
11615 which are not useful to determine the result of the call. In
11616 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11617 COMPOUND_EXPR will be an argument which must be evaluated.
11618 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11619 COMPOUND_EXPR in the chain will contain the tree for the simplified
11620 form of the builtin function call. */
11621
11622static tree
389dd41b 11623fold_builtin_strchr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11624{
c2f47e15 11625 if (!validate_arg (s1, POINTER_TYPE)
11626 || !validate_arg (s2, INTEGER_TYPE))
11627 return NULL_TREE;
4ee9c684 11628 else
11629 {
4ee9c684 11630 const char *p1;
11631
11632 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 11633 return NULL_TREE;
4ee9c684 11634
11635 p1 = c_getstr (s1);
11636 if (p1 != NULL)
11637 {
11638 char c;
11639 const char *r;
daa1d5f5 11640 tree tem;
4ee9c684 11641
11642 if (target_char_cast (s2, &c))
c2f47e15 11643 return NULL_TREE;
4ee9c684 11644
11645 r = strchr (p1, c);
11646
11647 if (r == NULL)
779b4c41 11648 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11649
11650 /* Return an offset into the constant string argument. */
2cc66f2a 11651 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11652 return fold_convert_loc (loc, type, tem);
4ee9c684 11653 }
c2f47e15 11654 return NULL_TREE;
4ee9c684 11655 }
11656}
11657
c2f47e15 11658/* Simplify a call to the strrchr builtin. S1 and S2 are the arguments to
11659 the call, and TYPE is its return type.
4ee9c684 11660
c2f47e15 11661 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11662 simplified form of the call as a tree.
11663
11664 The simplified form may be a constant or other expression which
11665 computes the same value, but in a more efficient manner (including
11666 calls to other builtin functions).
11667
11668 The call may contain arguments which need to be evaluated, but
11669 which are not useful to determine the result of the call. In
11670 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11671 COMPOUND_EXPR will be an argument which must be evaluated.
11672 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11673 COMPOUND_EXPR in the chain will contain the tree for the simplified
11674 form of the builtin function call. */
11675
11676static tree
389dd41b 11677fold_builtin_strrchr (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11678{
c2f47e15 11679 if (!validate_arg (s1, POINTER_TYPE)
11680 || !validate_arg (s2, INTEGER_TYPE))
11681 return NULL_TREE;
4ee9c684 11682 else
11683 {
4ee9c684 11684 tree fn;
11685 const char *p1;
11686
11687 if (TREE_CODE (s2) != INTEGER_CST)
c2f47e15 11688 return NULL_TREE;
4ee9c684 11689
11690 p1 = c_getstr (s1);
11691 if (p1 != NULL)
11692 {
11693 char c;
11694 const char *r;
daa1d5f5 11695 tree tem;
4ee9c684 11696
11697 if (target_char_cast (s2, &c))
c2f47e15 11698 return NULL_TREE;
4ee9c684 11699
11700 r = strrchr (p1, c);
11701
11702 if (r == NULL)
779b4c41 11703 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11704
11705 /* Return an offset into the constant string argument. */
2cc66f2a 11706 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11707 return fold_convert_loc (loc, type, tem);
4ee9c684 11708 }
11709
11710 if (! integer_zerop (s2))
c2f47e15 11711 return NULL_TREE;
4ee9c684 11712
b9a16870 11713 fn = builtin_decl_implicit (BUILT_IN_STRCHR);
4ee9c684 11714 if (!fn)
c2f47e15 11715 return NULL_TREE;
4ee9c684 11716
11717 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
389dd41b 11718 return build_call_expr_loc (loc, fn, 2, s1, s2);
4ee9c684 11719 }
11720}
11721
c2f47e15 11722/* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments
11723 to the call, and TYPE is its return type.
4ee9c684 11724
c2f47e15 11725 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11726 simplified form of the call as a tree.
11727
11728 The simplified form may be a constant or other expression which
11729 computes the same value, but in a more efficient manner (including
11730 calls to other builtin functions).
11731
11732 The call may contain arguments which need to be evaluated, but
11733 which are not useful to determine the result of the call. In
11734 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11735 COMPOUND_EXPR will be an argument which must be evaluated.
11736 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11737 COMPOUND_EXPR in the chain will contain the tree for the simplified
11738 form of the builtin function call. */
11739
11740static tree
389dd41b 11741fold_builtin_strpbrk (location_t loc, tree s1, tree s2, tree type)
4ee9c684 11742{
c2f47e15 11743 if (!validate_arg (s1, POINTER_TYPE)
11744 || !validate_arg (s2, POINTER_TYPE))
11745 return NULL_TREE;
4ee9c684 11746 else
11747 {
4ee9c684 11748 tree fn;
11749 const char *p1, *p2;
11750
11751 p2 = c_getstr (s2);
11752 if (p2 == NULL)
c2f47e15 11753 return NULL_TREE;
4ee9c684 11754
11755 p1 = c_getstr (s1);
11756 if (p1 != NULL)
11757 {
11758 const char *r = strpbrk (p1, p2);
daa1d5f5 11759 tree tem;
4ee9c684 11760
11761 if (r == NULL)
779b4c41 11762 return build_int_cst (TREE_TYPE (s1), 0);
4ee9c684 11763
11764 /* Return an offset into the constant string argument. */
2cc66f2a 11765 tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
389dd41b 11766 return fold_convert_loc (loc, type, tem);
4ee9c684 11767 }
11768
11769 if (p2[0] == '\0')
05abc81b 11770 /* strpbrk(x, "") == NULL.
11771 Evaluate and ignore s1 in case it had side-effects. */
389dd41b 11772 return omit_one_operand_loc (loc, TREE_TYPE (s1), integer_zero_node, s1);
4ee9c684 11773
11774 if (p2[1] != '\0')
c2f47e15 11775 return NULL_TREE; /* Really call strpbrk. */
4ee9c684 11776
b9a16870 11777 fn = builtin_decl_implicit (BUILT_IN_STRCHR);
4ee9c684 11778 if (!fn)
c2f47e15 11779 return NULL_TREE;
4ee9c684 11780
11781 /* New argument list transforming strpbrk(s1, s2) to
11782 strchr(s1, s2[0]). */
7002a1c8 11783 return build_call_expr_loc (loc, fn, 2, s1,
11784 build_int_cst (integer_type_node, p2[0]));
4ee9c684 11785 }
11786}
11787
c2f47e15 11788/* Simplify a call to the strcat builtin. DST and SRC are the arguments
11789 to the call.
4ee9c684 11790
c2f47e15 11791 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11792 simplified form of the call as a tree.
11793
11794 The simplified form may be a constant or other expression which
11795 computes the same value, but in a more efficient manner (including
11796 calls to other builtin functions).
11797
11798 The call may contain arguments which need to be evaluated, but
11799 which are not useful to determine the result of the call. In
11800 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11801 COMPOUND_EXPR will be an argument which must be evaluated.
11802 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11803 COMPOUND_EXPR in the chain will contain the tree for the simplified
11804 form of the builtin function call. */
11805
11806static tree
389dd41b 11807fold_builtin_strcat (location_t loc ATTRIBUTE_UNUSED, tree dst, tree src)
4ee9c684 11808{
c2f47e15 11809 if (!validate_arg (dst, POINTER_TYPE)
11810 || !validate_arg (src, POINTER_TYPE))
11811 return NULL_TREE;
4ee9c684 11812 else
11813 {
4ee9c684 11814 const char *p = c_getstr (src);
11815
11816 /* If the string length is zero, return the dst parameter. */
11817 if (p && *p == '\0')
11818 return dst;
11819
a65c4d64 11820 if (optimize_insn_for_speed_p ())
11821 {
11822 /* See if we can store by pieces into (dst + strlen(dst)). */
11823 tree newdst, call;
b9a16870 11824 tree strlen_fn = builtin_decl_implicit (BUILT_IN_STRLEN);
11825 tree strcpy_fn = builtin_decl_implicit (BUILT_IN_STRCPY);
a65c4d64 11826
11827 if (!strlen_fn || !strcpy_fn)
11828 return NULL_TREE;
11829
11830 /* If we don't have a movstr we don't want to emit an strcpy
11831 call. We have to do that if the length of the source string
11832 isn't computable (in that case we can use memcpy probably
48e1416a 11833 later expanding to a sequence of mov instructions). If we
a65c4d64 11834 have movstr instructions we can emit strcpy calls. */
11835 if (!HAVE_movstr)
11836 {
11837 tree len = c_strlen (src, 1);
11838 if (! len || TREE_SIDE_EFFECTS (len))
11839 return NULL_TREE;
11840 }
11841
11842 /* Stabilize the argument list. */
11843 dst = builtin_save_expr (dst);
11844
11845 /* Create strlen (dst). */
11846 newdst = build_call_expr_loc (loc, strlen_fn, 1, dst);
11847 /* Create (dst p+ strlen (dst)). */
11848
2cc66f2a 11849 newdst = fold_build_pointer_plus_loc (loc, dst, newdst);
a65c4d64 11850 newdst = builtin_save_expr (newdst);
11851
11852 call = build_call_expr_loc (loc, strcpy_fn, 2, newdst, src);
11853 return build2 (COMPOUND_EXPR, TREE_TYPE (dst), call, dst);
11854 }
c2f47e15 11855 return NULL_TREE;
4ee9c684 11856 }
11857}
11858
c2f47e15 11859/* Simplify a call to the strncat builtin. DST, SRC, and LEN are the
11860 arguments to the call.
4ee9c684 11861
c2f47e15 11862 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11863 simplified form of the call as a tree.
11864
11865 The simplified form may be a constant or other expression which
11866 computes the same value, but in a more efficient manner (including
11867 calls to other builtin functions).
11868
11869 The call may contain arguments which need to be evaluated, but
11870 which are not useful to determine the result of the call. In
11871 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11872 COMPOUND_EXPR will be an argument which must be evaluated.
11873 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11874 COMPOUND_EXPR in the chain will contain the tree for the simplified
11875 form of the builtin function call. */
11876
11877static tree
389dd41b 11878fold_builtin_strncat (location_t loc, tree dst, tree src, tree len)
4ee9c684 11879{
c2f47e15 11880 if (!validate_arg (dst, POINTER_TYPE)
11881 || !validate_arg (src, POINTER_TYPE)
11882 || !validate_arg (len, INTEGER_TYPE))
11883 return NULL_TREE;
4ee9c684 11884 else
11885 {
4ee9c684 11886 const char *p = c_getstr (src);
11887
11888 /* If the requested length is zero, or the src parameter string
0a39fd54 11889 length is zero, return the dst parameter. */
4ee9c684 11890 if (integer_zerop (len) || (p && *p == '\0'))
389dd41b 11891 return omit_two_operands_loc (loc, TREE_TYPE (dst), dst, src, len);
4ee9c684 11892
11893 /* If the requested len is greater than or equal to the string
a0c938f0 11894 length, call strcat. */
4ee9c684 11895 if (TREE_CODE (len) == INTEGER_CST && p
11896 && compare_tree_int (len, strlen (p)) >= 0)
11897 {
b9a16870 11898 tree fn = builtin_decl_implicit (BUILT_IN_STRCAT);
4ee9c684 11899
11900 /* If the replacement _DECL isn't initialized, don't do the
11901 transformation. */
11902 if (!fn)
c2f47e15 11903 return NULL_TREE;
4ee9c684 11904
389dd41b 11905 return build_call_expr_loc (loc, fn, 2, dst, src);
4ee9c684 11906 }
c2f47e15 11907 return NULL_TREE;
4ee9c684 11908 }
11909}
11910
c2f47e15 11911/* Simplify a call to the strspn builtin. S1 and S2 are the arguments
11912 to the call.
4ee9c684 11913
c2f47e15 11914 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11915 simplified form of the call as a tree.
11916
11917 The simplified form may be a constant or other expression which
11918 computes the same value, but in a more efficient manner (including
11919 calls to other builtin functions).
11920
11921 The call may contain arguments which need to be evaluated, but
11922 which are not useful to determine the result of the call. In
11923 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11924 COMPOUND_EXPR will be an argument which must be evaluated.
11925 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11926 COMPOUND_EXPR in the chain will contain the tree for the simplified
11927 form of the builtin function call. */
11928
11929static tree
389dd41b 11930fold_builtin_strspn (location_t loc, tree s1, tree s2)
4ee9c684 11931{
c2f47e15 11932 if (!validate_arg (s1, POINTER_TYPE)
11933 || !validate_arg (s2, POINTER_TYPE))
11934 return NULL_TREE;
4ee9c684 11935 else
11936 {
4ee9c684 11937 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11938
11939 /* If both arguments are constants, evaluate at compile-time. */
11940 if (p1 && p2)
11941 {
11942 const size_t r = strspn (p1, p2);
547b938d 11943 return build_int_cst (size_type_node, r);
4ee9c684 11944 }
11945
c2f47e15 11946 /* If either argument is "", return NULL_TREE. */
4ee9c684 11947 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9bc9f15f 11948 /* Evaluate and ignore both arguments in case either one has
11949 side-effects. */
389dd41b 11950 return omit_two_operands_loc (loc, size_type_node, size_zero_node,
9bc9f15f 11951 s1, s2);
c2f47e15 11952 return NULL_TREE;
4ee9c684 11953 }
11954}
11955
c2f47e15 11956/* Simplify a call to the strcspn builtin. S1 and S2 are the arguments
11957 to the call.
4ee9c684 11958
c2f47e15 11959 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 11960 simplified form of the call as a tree.
11961
11962 The simplified form may be a constant or other expression which
11963 computes the same value, but in a more efficient manner (including
11964 calls to other builtin functions).
11965
11966 The call may contain arguments which need to be evaluated, but
11967 which are not useful to determine the result of the call. In
11968 this case we return a chain of COMPOUND_EXPRs. The LHS of each
11969 COMPOUND_EXPR will be an argument which must be evaluated.
11970 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
11971 COMPOUND_EXPR in the chain will contain the tree for the simplified
11972 form of the builtin function call. */
11973
11974static tree
389dd41b 11975fold_builtin_strcspn (location_t loc, tree s1, tree s2)
4ee9c684 11976{
c2f47e15 11977 if (!validate_arg (s1, POINTER_TYPE)
11978 || !validate_arg (s2, POINTER_TYPE))
11979 return NULL_TREE;
4ee9c684 11980 else
11981 {
4ee9c684 11982 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
11983
11984 /* If both arguments are constants, evaluate at compile-time. */
11985 if (p1 && p2)
11986 {
11987 const size_t r = strcspn (p1, p2);
547b938d 11988 return build_int_cst (size_type_node, r);
4ee9c684 11989 }
11990
c2f47e15 11991 /* If the first argument is "", return NULL_TREE. */
4ee9c684 11992 if (p1 && *p1 == '\0')
11993 {
11994 /* Evaluate and ignore argument s2 in case it has
11995 side-effects. */
389dd41b 11996 return omit_one_operand_loc (loc, size_type_node,
39761420 11997 size_zero_node, s2);
4ee9c684 11998 }
11999
12000 /* If the second argument is "", return __builtin_strlen(s1). */
12001 if (p2 && *p2 == '\0')
12002 {
b9a16870 12003 tree fn = builtin_decl_implicit (BUILT_IN_STRLEN);
4ee9c684 12004
12005 /* If the replacement _DECL isn't initialized, don't do the
12006 transformation. */
12007 if (!fn)
c2f47e15 12008 return NULL_TREE;
4ee9c684 12009
389dd41b 12010 return build_call_expr_loc (loc, fn, 1, s1);
4ee9c684 12011 }
c2f47e15 12012 return NULL_TREE;
4ee9c684 12013 }
12014}
12015
c2f47e15 12016/* Fold a call to the fputs builtin. ARG0 and ARG1 are the arguments
12017 to the call. IGNORE is true if the value returned
f0613857 12018 by the builtin will be ignored. UNLOCKED is true is true if this
12019 actually a call to fputs_unlocked. If LEN in non-NULL, it represents
12020 the known length of the string. Return NULL_TREE if no simplification
12021 was possible. */
4ee9c684 12022
12023tree
389dd41b 12024fold_builtin_fputs (location_t loc, tree arg0, tree arg1,
12025 bool ignore, bool unlocked, tree len)
4ee9c684 12026{
6d77ed92 12027 /* If we're using an unlocked function, assume the other unlocked
12028 functions exist explicitly. */
b9a16870 12029 tree const fn_fputc = (unlocked
12030 ? builtin_decl_explicit (BUILT_IN_FPUTC_UNLOCKED)
12031 : builtin_decl_implicit (BUILT_IN_FPUTC));
12032 tree const fn_fwrite = (unlocked
12033 ? builtin_decl_explicit (BUILT_IN_FWRITE_UNLOCKED)
12034 : builtin_decl_implicit (BUILT_IN_FWRITE));
4ee9c684 12035
c403edd4 12036 /* If the return value is used, don't do the transformation. */
12037 if (!ignore)
c2f47e15 12038 return NULL_TREE;
4ee9c684 12039
12040 /* Verify the arguments in the original call. */
c2f47e15 12041 if (!validate_arg (arg0, POINTER_TYPE)
12042 || !validate_arg (arg1, POINTER_TYPE))
12043 return NULL_TREE;
4ee9c684 12044
f0613857 12045 if (! len)
c2f47e15 12046 len = c_strlen (arg0, 0);
4ee9c684 12047
12048 /* Get the length of the string passed to fputs. If the length
12049 can't be determined, punt. */
12050 if (!len
12051 || TREE_CODE (len) != INTEGER_CST)
c2f47e15 12052 return NULL_TREE;
4ee9c684 12053
12054 switch (compare_tree_int (len, 1))
12055 {
12056 case -1: /* length is 0, delete the call entirely . */
389dd41b 12057 return omit_one_operand_loc (loc, integer_type_node,
12058 integer_zero_node, arg1);;
05abc81b 12059
4ee9c684 12060 case 0: /* length is 1, call fputc. */
12061 {
c2f47e15 12062 const char *p = c_getstr (arg0);
4ee9c684 12063
12064 if (p != NULL)
12065 {
c2f47e15 12066 if (fn_fputc)
389dd41b 12067 return build_call_expr_loc (loc, fn_fputc, 2,
7002a1c8 12068 build_int_cst
12069 (integer_type_node, p[0]), arg1);
c2f47e15 12070 else
12071 return NULL_TREE;
4ee9c684 12072 }
12073 }
12074 /* FALLTHROUGH */
12075 case 1: /* length is greater than 1, call fwrite. */
12076 {
0bed3869 12077 /* If optimizing for size keep fputs. */
0bfd8d5c 12078 if (optimize_function_for_size_p (cfun))
c2f47e15 12079 return NULL_TREE;
4ee9c684 12080 /* New argument list transforming fputs(string, stream) to
12081 fwrite(string, 1, len, stream). */
c2f47e15 12082 if (fn_fwrite)
389dd41b 12083 return build_call_expr_loc (loc, fn_fwrite, 4, arg0,
12084 size_one_node, len, arg1);
c2f47e15 12085 else
12086 return NULL_TREE;
4ee9c684 12087 }
12088 default:
64db345d 12089 gcc_unreachable ();
4ee9c684 12090 }
c2f47e15 12091 return NULL_TREE;
4ee9c684 12092}
12093
c2f47e15 12094/* Fold the next_arg or va_start call EXP. Returns true if there was an error
743b0c6a 12095 produced. False otherwise. This is done so that we don't output the error
12096 or warning twice or three times. */
75a70cf9 12097
743b0c6a 12098bool
c2f47e15 12099fold_builtin_next_arg (tree exp, bool va_start_p)
4ee9c684 12100{
12101 tree fntype = TREE_TYPE (current_function_decl);
c2f47e15 12102 int nargs = call_expr_nargs (exp);
12103 tree arg;
d98fd4a4 12104 /* There is good chance the current input_location points inside the
12105 definition of the va_start macro (perhaps on the token for
12106 builtin) in a system header, so warnings will not be emitted.
12107 Use the location in real source code. */
12108 source_location current_location =
12109 linemap_unwind_to_first_non_reserved_loc (line_table, input_location,
12110 NULL);
4ee9c684 12111
257d99c3 12112 if (!stdarg_p (fntype))
743b0c6a 12113 {
12114 error ("%<va_start%> used in function with fixed args");
12115 return true;
12116 }
c2f47e15 12117
12118 if (va_start_p)
79012a9d 12119 {
c2f47e15 12120 if (va_start_p && (nargs != 2))
12121 {
12122 error ("wrong number of arguments to function %<va_start%>");
12123 return true;
12124 }
12125 arg = CALL_EXPR_ARG (exp, 1);
79012a9d 12126 }
12127 /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
12128 when we checked the arguments and if needed issued a warning. */
c2f47e15 12129 else
4ee9c684 12130 {
c2f47e15 12131 if (nargs == 0)
12132 {
12133 /* Evidently an out of date version of <stdarg.h>; can't validate
12134 va_start's second argument, but can still work as intended. */
d98fd4a4 12135 warning_at (current_location,
7edb1062 12136 OPT_Wvarargs,
12137 "%<__builtin_next_arg%> called without an argument");
c2f47e15 12138 return true;
12139 }
12140 else if (nargs > 1)
a0c938f0 12141 {
c2f47e15 12142 error ("wrong number of arguments to function %<__builtin_next_arg%>");
a0c938f0 12143 return true;
12144 }
c2f47e15 12145 arg = CALL_EXPR_ARG (exp, 0);
12146 }
12147
a8dd994c 12148 if (TREE_CODE (arg) == SSA_NAME)
12149 arg = SSA_NAME_VAR (arg);
12150
c2f47e15 12151 /* We destructively modify the call to be __builtin_va_start (ap, 0)
48e1416a 12152 or __builtin_next_arg (0) the first time we see it, after checking
c2f47e15 12153 the arguments and if needed issuing a warning. */
12154 if (!integer_zerop (arg))
12155 {
12156 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
79012a9d 12157
4ee9c684 12158 /* Strip off all nops for the sake of the comparison. This
12159 is not quite the same as STRIP_NOPS. It does more.
12160 We must also strip off INDIRECT_EXPR for C++ reference
12161 parameters. */
72dd6141 12162 while (CONVERT_EXPR_P (arg)
4ee9c684 12163 || TREE_CODE (arg) == INDIRECT_REF)
12164 arg = TREE_OPERAND (arg, 0);
12165 if (arg != last_parm)
a0c938f0 12166 {
b08cf617 12167 /* FIXME: Sometimes with the tree optimizers we can get the
12168 not the last argument even though the user used the last
12169 argument. We just warn and set the arg to be the last
12170 argument so that we will get wrong-code because of
12171 it. */
d98fd4a4 12172 warning_at (current_location,
7edb1062 12173 OPT_Wvarargs,
d98fd4a4 12174 "second parameter of %<va_start%> not last named argument");
743b0c6a 12175 }
24158ad7 12176
12177 /* Undefined by C99 7.15.1.4p4 (va_start):
12178 "If the parameter parmN is declared with the register storage
12179 class, with a function or array type, or with a type that is
12180 not compatible with the type that results after application of
12181 the default argument promotions, the behavior is undefined."
12182 */
12183 else if (DECL_REGISTER (arg))
d98fd4a4 12184 {
12185 warning_at (current_location,
7edb1062 12186 OPT_Wvarargs,
d98fd4a4 12187 "undefined behaviour when second parameter of "
12188 "%<va_start%> is declared with %<register%> storage");
12189 }
24158ad7 12190
79012a9d 12191 /* We want to verify the second parameter just once before the tree
a0c938f0 12192 optimizers are run and then avoid keeping it in the tree,
12193 as otherwise we could warn even for correct code like:
12194 void foo (int i, ...)
12195 { va_list ap; i++; va_start (ap, i); va_end (ap); } */
c2f47e15 12196 if (va_start_p)
12197 CALL_EXPR_ARG (exp, 1) = integer_zero_node;
12198 else
12199 CALL_EXPR_ARG (exp, 0) = integer_zero_node;
743b0c6a 12200 }
12201 return false;
4ee9c684 12202}
12203
12204
c2f47e15 12205/* Simplify a call to the sprintf builtin with arguments DEST, FMT, and ORIG.
12206 ORIG may be null if this is a 2-argument call. We don't attempt to
12207 simplify calls with more than 3 arguments.
4ee9c684 12208
c2f47e15 12209 Return NULL_TREE if no simplification was possible, otherwise return the
4ee9c684 12210 simplified form of the call as a tree. If IGNORED is true, it means that
12211 the caller does not use the returned value of the function. */
12212
12213static tree
389dd41b 12214fold_builtin_sprintf (location_t loc, tree dest, tree fmt,
12215 tree orig, int ignored)
4ee9c684 12216{
c2f47e15 12217 tree call, retval;
4ee9c684 12218 const char *fmt_str = NULL;
12219
12220 /* Verify the required arguments in the original call. We deal with two
12221 types of sprintf() calls: 'sprintf (str, fmt)' and
12222 'sprintf (dest, "%s", orig)'. */
c2f47e15 12223 if (!validate_arg (dest, POINTER_TYPE)
12224 || !validate_arg (fmt, POINTER_TYPE))
12225 return NULL_TREE;
12226 if (orig && !validate_arg (orig, POINTER_TYPE))
4ee9c684 12227 return NULL_TREE;
4ee9c684 12228
12229 /* Check whether the format is a literal string constant. */
12230 fmt_str = c_getstr (fmt);
12231 if (fmt_str == NULL)
12232 return NULL_TREE;
12233
12234 call = NULL_TREE;
12235 retval = NULL_TREE;
12236
d4473c84 12237 if (!init_target_chars ())
c2f47e15 12238 return NULL_TREE;
99eabcc1 12239
4ee9c684 12240 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 12241 if (strchr (fmt_str, target_percent) == NULL)
4ee9c684 12242 {
b9a16870 12243 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
4ee9c684 12244
12245 if (!fn)
12246 return NULL_TREE;
12247
72dfb3f2 12248 /* Don't optimize sprintf (buf, "abc", ptr++). */
c2f47e15 12249 if (orig)
72dfb3f2 12250 return NULL_TREE;
12251
4ee9c684 12252 /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
12253 'format' is known to contain no % formats. */
389dd41b 12254 call = build_call_expr_loc (loc, fn, 2, dest, fmt);
4ee9c684 12255 if (!ignored)
7002a1c8 12256 retval = build_int_cst (integer_type_node, strlen (fmt_str));
4ee9c684 12257 }
12258
12259 /* If the format is "%s", use strcpy if the result isn't used. */
99eabcc1 12260 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
4ee9c684 12261 {
c2f47e15 12262 tree fn;
b9a16870 12263 fn = builtin_decl_implicit (BUILT_IN_STRCPY);
4ee9c684 12264
12265 if (!fn)
12266 return NULL_TREE;
12267
72dfb3f2 12268 /* Don't crash on sprintf (str1, "%s"). */
c2f47e15 12269 if (!orig)
72dfb3f2 12270 return NULL_TREE;
12271
4ee9c684 12272 /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2). */
4ee9c684 12273 if (!ignored)
12274 {
12275 retval = c_strlen (orig, 1);
12276 if (!retval || TREE_CODE (retval) != INTEGER_CST)
12277 return NULL_TREE;
12278 }
389dd41b 12279 call = build_call_expr_loc (loc, fn, 2, dest, orig);
4ee9c684 12280 }
12281
12282 if (call && retval)
12283 {
389dd41b 12284 retval = fold_convert_loc
b9a16870 12285 (loc, TREE_TYPE (TREE_TYPE (builtin_decl_implicit (BUILT_IN_SPRINTF))),
4ee9c684 12286 retval);
05abc81b 12287 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
4ee9c684 12288 }
12289 else
12290 return call;
12291}
0a39fd54 12292
750d7b16 12293/* Simplify a call to the snprintf builtin with arguments DEST, DESTSIZE,
12294 FMT, and ORIG. ORIG may be null if this is a 3-argument call. We don't
12295 attempt to simplify calls with more than 4 arguments.
12296
12297 Return NULL_TREE if no simplification was possible, otherwise return the
12298 simplified form of the call as a tree. If IGNORED is true, it means that
12299 the caller does not use the returned value of the function. */
12300
12301static tree
12302fold_builtin_snprintf (location_t loc, tree dest, tree destsize, tree fmt,
12303 tree orig, int ignored)
12304{
12305 tree call, retval;
12306 const char *fmt_str = NULL;
12307 unsigned HOST_WIDE_INT destlen;
12308
12309 /* Verify the required arguments in the original call. We deal with two
12310 types of snprintf() calls: 'snprintf (str, cst, fmt)' and
12311 'snprintf (dest, cst, "%s", orig)'. */
12312 if (!validate_arg (dest, POINTER_TYPE)
12313 || !validate_arg (destsize, INTEGER_TYPE)
12314 || !validate_arg (fmt, POINTER_TYPE))
12315 return NULL_TREE;
12316 if (orig && !validate_arg (orig, POINTER_TYPE))
12317 return NULL_TREE;
12318
12319 if (!host_integerp (destsize, 1))
12320 return NULL_TREE;
12321
12322 /* Check whether the format is a literal string constant. */
12323 fmt_str = c_getstr (fmt);
12324 if (fmt_str == NULL)
12325 return NULL_TREE;
12326
12327 call = NULL_TREE;
12328 retval = NULL_TREE;
12329
12330 if (!init_target_chars ())
12331 return NULL_TREE;
12332
12333 destlen = tree_low_cst (destsize, 1);
12334
12335 /* If the format doesn't contain % args or %%, use strcpy. */
12336 if (strchr (fmt_str, target_percent) == NULL)
12337 {
b9a16870 12338 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
750d7b16 12339 size_t len = strlen (fmt_str);
12340
12341 /* Don't optimize snprintf (buf, 4, "abc", ptr++). */
12342 if (orig)
12343 return NULL_TREE;
12344
12345 /* We could expand this as
12346 memcpy (str, fmt, cst - 1); str[cst - 1] = '\0';
12347 or to
12348 memcpy (str, fmt_with_nul_at_cstm1, cst);
12349 but in the former case that might increase code size
12350 and in the latter case grow .rodata section too much.
12351 So punt for now. */
12352 if (len >= destlen)
12353 return NULL_TREE;
12354
12355 if (!fn)
12356 return NULL_TREE;
12357
12358 /* Convert snprintf (str, cst, fmt) into strcpy (str, fmt) when
12359 'format' is known to contain no % formats and
12360 strlen (fmt) < cst. */
12361 call = build_call_expr_loc (loc, fn, 2, dest, fmt);
12362
12363 if (!ignored)
7002a1c8 12364 retval = build_int_cst (integer_type_node, strlen (fmt_str));
750d7b16 12365 }
12366
12367 /* If the format is "%s", use strcpy if the result isn't used. */
12368 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
12369 {
b9a16870 12370 tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
750d7b16 12371 unsigned HOST_WIDE_INT origlen;
12372
12373 /* Don't crash on snprintf (str1, cst, "%s"). */
12374 if (!orig)
12375 return NULL_TREE;
12376
12377 retval = c_strlen (orig, 1);
12378 if (!retval || !host_integerp (retval, 1))
12379 return NULL_TREE;
12380
12381 origlen = tree_low_cst (retval, 1);
12382 /* We could expand this as
12383 memcpy (str1, str2, cst - 1); str1[cst - 1] = '\0';
12384 or to
12385 memcpy (str1, str2_with_nul_at_cstm1, cst);
12386 but in the former case that might increase code size
12387 and in the latter case grow .rodata section too much.
12388 So punt for now. */
12389 if (origlen >= destlen)
12390 return NULL_TREE;
12391
12392 /* Convert snprintf (str1, cst, "%s", str2) into
12393 strcpy (str1, str2) if strlen (str2) < cst. */
12394 if (!fn)
12395 return NULL_TREE;
12396
12397 call = build_call_expr_loc (loc, fn, 2, dest, orig);
12398
12399 if (ignored)
12400 retval = NULL_TREE;
12401 }
12402
12403 if (call && retval)
12404 {
b9a16870 12405 tree fn = builtin_decl_explicit (BUILT_IN_SNPRINTF);
1914d98e 12406 retval = fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fn)), retval);
750d7b16 12407 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
12408 }
12409 else
12410 return call;
12411}
12412
c2f47e15 12413/* Expand a call EXP to __builtin_object_size. */
0a39fd54 12414
12415rtx
12416expand_builtin_object_size (tree exp)
12417{
12418 tree ost;
12419 int object_size_type;
12420 tree fndecl = get_callee_fndecl (exp);
0a39fd54 12421
c2f47e15 12422 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
0a39fd54 12423 {
b8c23db3 12424 error ("%Kfirst argument of %D must be a pointer, second integer constant",
12425 exp, fndecl);
0a39fd54 12426 expand_builtin_trap ();
12427 return const0_rtx;
12428 }
12429
c2f47e15 12430 ost = CALL_EXPR_ARG (exp, 1);
0a39fd54 12431 STRIP_NOPS (ost);
12432
12433 if (TREE_CODE (ost) != INTEGER_CST
12434 || tree_int_cst_sgn (ost) < 0
12435 || compare_tree_int (ost, 3) > 0)
12436 {
b8c23db3 12437 error ("%Klast argument of %D is not integer constant between 0 and 3",
12438 exp, fndecl);
0a39fd54 12439 expand_builtin_trap ();
12440 return const0_rtx;
12441 }
12442
12443 object_size_type = tree_low_cst (ost, 0);
12444
12445 return object_size_type < 2 ? constm1_rtx : const0_rtx;
12446}
12447
12448/* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
12449 FCODE is the BUILT_IN_* to use.
c2f47e15 12450 Return NULL_RTX if we failed; the caller should emit a normal call,
0a39fd54 12451 otherwise try to get the result in TARGET, if convenient (and in
12452 mode MODE if that's convenient). */
12453
12454static rtx
12455expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
12456 enum built_in_function fcode)
12457{
0a39fd54 12458 tree dest, src, len, size;
12459
c2f47e15 12460 if (!validate_arglist (exp,
0a39fd54 12461 POINTER_TYPE,
12462 fcode == BUILT_IN_MEMSET_CHK
12463 ? INTEGER_TYPE : POINTER_TYPE,
12464 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
c2f47e15 12465 return NULL_RTX;
0a39fd54 12466
c2f47e15 12467 dest = CALL_EXPR_ARG (exp, 0);
12468 src = CALL_EXPR_ARG (exp, 1);
12469 len = CALL_EXPR_ARG (exp, 2);
12470 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 12471
12472 if (! host_integerp (size, 1))
c2f47e15 12473 return NULL_RTX;
0a39fd54 12474
12475 if (host_integerp (len, 1) || integer_all_onesp (size))
12476 {
12477 tree fn;
12478
12479 if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
12480 {
b430e8d9 12481 warning_at (tree_nonartificial_location (exp),
12482 0, "%Kcall to %D will always overflow destination buffer",
12483 exp, get_callee_fndecl (exp));
c2f47e15 12484 return NULL_RTX;
0a39fd54 12485 }
12486
0a39fd54 12487 fn = NULL_TREE;
12488 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
12489 mem{cpy,pcpy,move,set} is available. */
12490 switch (fcode)
12491 {
12492 case BUILT_IN_MEMCPY_CHK:
b9a16870 12493 fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
0a39fd54 12494 break;
12495 case BUILT_IN_MEMPCPY_CHK:
b9a16870 12496 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
0a39fd54 12497 break;
12498 case BUILT_IN_MEMMOVE_CHK:
b9a16870 12499 fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
0a39fd54 12500 break;
12501 case BUILT_IN_MEMSET_CHK:
b9a16870 12502 fn = builtin_decl_explicit (BUILT_IN_MEMSET);
0a39fd54 12503 break;
12504 default:
12505 break;
12506 }
12507
12508 if (! fn)
c2f47e15 12509 return NULL_RTX;
0a39fd54 12510
0568e9c1 12511 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 3, dest, src, len);
a65c4d64 12512 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
12513 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0a39fd54 12514 return expand_expr (fn, target, mode, EXPAND_NORMAL);
12515 }
12516 else if (fcode == BUILT_IN_MEMSET_CHK)
c2f47e15 12517 return NULL_RTX;
0a39fd54 12518 else
12519 {
957d0361 12520 unsigned int dest_align = get_pointer_alignment (dest);
0a39fd54 12521
12522 /* If DEST is not a pointer type, call the normal function. */
12523 if (dest_align == 0)
c2f47e15 12524 return NULL_RTX;
0a39fd54 12525
12526 /* If SRC and DEST are the same (and not volatile), do nothing. */
12527 if (operand_equal_p (src, dest, 0))
12528 {
12529 tree expr;
12530
12531 if (fcode != BUILT_IN_MEMPCPY_CHK)
12532 {
12533 /* Evaluate and ignore LEN in case it has side-effects. */
12534 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
12535 return expand_expr (dest, target, mode, EXPAND_NORMAL);
12536 }
12537
2cc66f2a 12538 expr = fold_build_pointer_plus (dest, len);
0a39fd54 12539 return expand_expr (expr, target, mode, EXPAND_NORMAL);
12540 }
12541
12542 /* __memmove_chk special case. */
12543 if (fcode == BUILT_IN_MEMMOVE_CHK)
12544 {
957d0361 12545 unsigned int src_align = get_pointer_alignment (src);
0a39fd54 12546
12547 if (src_align == 0)
c2f47e15 12548 return NULL_RTX;
0a39fd54 12549
12550 /* If src is categorized for a readonly section we can use
12551 normal __memcpy_chk. */
12552 if (readonly_data_expr (src))
12553 {
b9a16870 12554 tree fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
0a39fd54 12555 if (!fn)
c2f47e15 12556 return NULL_RTX;
0568e9c1 12557 fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 4,
12558 dest, src, len, size);
a65c4d64 12559 gcc_assert (TREE_CODE (fn) == CALL_EXPR);
12560 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
0a39fd54 12561 return expand_expr (fn, target, mode, EXPAND_NORMAL);
12562 }
12563 }
c2f47e15 12564 return NULL_RTX;
0a39fd54 12565 }
12566}
12567
12568/* Emit warning if a buffer overflow is detected at compile time. */
12569
12570static void
12571maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
12572{
c2f47e15 12573 int is_strlen = 0;
0a39fd54 12574 tree len, size;
b430e8d9 12575 location_t loc = tree_nonartificial_location (exp);
0a39fd54 12576
12577 switch (fcode)
12578 {
12579 case BUILT_IN_STRCPY_CHK:
12580 case BUILT_IN_STPCPY_CHK:
12581 /* For __strcat_chk the warning will be emitted only if overflowing
12582 by at least strlen (dest) + 1 bytes. */
12583 case BUILT_IN_STRCAT_CHK:
c2f47e15 12584 len = CALL_EXPR_ARG (exp, 1);
12585 size = CALL_EXPR_ARG (exp, 2);
0a39fd54 12586 is_strlen = 1;
12587 break;
b356dfef 12588 case BUILT_IN_STRNCAT_CHK:
0a39fd54 12589 case BUILT_IN_STRNCPY_CHK:
1063acde 12590 case BUILT_IN_STPNCPY_CHK:
c2f47e15 12591 len = CALL_EXPR_ARG (exp, 2);
12592 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 12593 break;
12594 case BUILT_IN_SNPRINTF_CHK:
12595 case BUILT_IN_VSNPRINTF_CHK:
c2f47e15 12596 len = CALL_EXPR_ARG (exp, 1);
12597 size = CALL_EXPR_ARG (exp, 3);
0a39fd54 12598 break;
12599 default:
12600 gcc_unreachable ();
12601 }
12602
0a39fd54 12603 if (!len || !size)
12604 return;
12605
0a39fd54 12606 if (! host_integerp (size, 1) || integer_all_onesp (size))
12607 return;
12608
12609 if (is_strlen)
12610 {
12611 len = c_strlen (len, 1);
12612 if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
12613 return;
12614 }
b356dfef 12615 else if (fcode == BUILT_IN_STRNCAT_CHK)
12616 {
c2f47e15 12617 tree src = CALL_EXPR_ARG (exp, 1);
b356dfef 12618 if (! src || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
12619 return;
12620 src = c_strlen (src, 1);
12621 if (! src || ! host_integerp (src, 1))
12622 {
b430e8d9 12623 warning_at (loc, 0, "%Kcall to %D might overflow destination buffer",
12624 exp, get_callee_fndecl (exp));
b356dfef 12625 return;
12626 }
12627 else if (tree_int_cst_lt (src, size))
12628 return;
12629 }
0a39fd54 12630 else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
12631 return;
12632
b430e8d9 12633 warning_at (loc, 0, "%Kcall to %D will always overflow destination buffer",
12634 exp, get_callee_fndecl (exp));
0a39fd54 12635}
12636
12637/* Emit warning if a buffer overflow is detected at compile time
12638 in __sprintf_chk/__vsprintf_chk calls. */
12639
12640static void
12641maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
12642{
1e4adcfc 12643 tree size, len, fmt;
0a39fd54 12644 const char *fmt_str;
c2f47e15 12645 int nargs = call_expr_nargs (exp);
0a39fd54 12646
12647 /* Verify the required arguments in the original call. */
48e1416a 12648
c2f47e15 12649 if (nargs < 4)
0a39fd54 12650 return;
c2f47e15 12651 size = CALL_EXPR_ARG (exp, 2);
12652 fmt = CALL_EXPR_ARG (exp, 3);
0a39fd54 12653
12654 if (! host_integerp (size, 1) || integer_all_onesp (size))
12655 return;
12656
12657 /* Check whether the format is a literal string constant. */
12658 fmt_str = c_getstr (fmt);
12659 if (fmt_str == NULL)
12660 return;
12661
d4473c84 12662 if (!init_target_chars ())
99eabcc1 12663 return;
12664
0a39fd54 12665 /* If the format doesn't contain % args or %%, we know its size. */
99eabcc1 12666 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 12667 len = build_int_cstu (size_type_node, strlen (fmt_str));
12668 /* If the format is "%s" and first ... argument is a string literal,
12669 we know it too. */
c2f47e15 12670 else if (fcode == BUILT_IN_SPRINTF_CHK
12671 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 12672 {
12673 tree arg;
12674
c2f47e15 12675 if (nargs < 5)
0a39fd54 12676 return;
c2f47e15 12677 arg = CALL_EXPR_ARG (exp, 4);
0a39fd54 12678 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
12679 return;
12680
12681 len = c_strlen (arg, 1);
12682 if (!len || ! host_integerp (len, 1))
12683 return;
12684 }
12685 else
12686 return;
12687
12688 if (! tree_int_cst_lt (len, size))
b430e8d9 12689 warning_at (tree_nonartificial_location (exp),
12690 0, "%Kcall to %D will always overflow destination buffer",
12691 exp, get_callee_fndecl (exp));
0a39fd54 12692}
12693
2c281b15 12694/* Emit warning if a free is called with address of a variable. */
12695
12696static void
12697maybe_emit_free_warning (tree exp)
12698{
12699 tree arg = CALL_EXPR_ARG (exp, 0);
12700
12701 STRIP_NOPS (arg);
12702 if (TREE_CODE (arg) != ADDR_EXPR)
12703 return;
12704
12705 arg = get_base_address (TREE_OPERAND (arg, 0));
182cf5a9 12706 if (arg == NULL || INDIRECT_REF_P (arg) || TREE_CODE (arg) == MEM_REF)
2c281b15 12707 return;
12708
12709 if (SSA_VAR_P (arg))
f74ea1c2 12710 warning_at (tree_nonartificial_location (exp), OPT_Wfree_nonheap_object,
12711 "%Kattempt to free a non-heap object %qD", exp, arg);
2c281b15 12712 else
f74ea1c2 12713 warning_at (tree_nonartificial_location (exp), OPT_Wfree_nonheap_object,
12714 "%Kattempt to free a non-heap object", exp);
2c281b15 12715}
12716
c2f47e15 12717/* Fold a call to __builtin_object_size with arguments PTR and OST,
12718 if possible. */
0a39fd54 12719
12720tree
c2f47e15 12721fold_builtin_object_size (tree ptr, tree ost)
0a39fd54 12722{
a6caa15f 12723 unsigned HOST_WIDE_INT bytes;
0a39fd54 12724 int object_size_type;
12725
c2f47e15 12726 if (!validate_arg (ptr, POINTER_TYPE)
12727 || !validate_arg (ost, INTEGER_TYPE))
12728 return NULL_TREE;
0a39fd54 12729
0a39fd54 12730 STRIP_NOPS (ost);
12731
12732 if (TREE_CODE (ost) != INTEGER_CST
12733 || tree_int_cst_sgn (ost) < 0
12734 || compare_tree_int (ost, 3) > 0)
c2f47e15 12735 return NULL_TREE;
0a39fd54 12736
12737 object_size_type = tree_low_cst (ost, 0);
12738
12739 /* __builtin_object_size doesn't evaluate side-effects in its arguments;
12740 if there are any side-effects, it returns (size_t) -1 for types 0 and 1
12741 and (size_t) 0 for types 2 and 3. */
12742 if (TREE_SIDE_EFFECTS (ptr))
697bbc3f 12743 return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
0a39fd54 12744
12745 if (TREE_CODE (ptr) == ADDR_EXPR)
a6caa15f 12746 {
12747 bytes = compute_builtin_object_size (ptr, object_size_type);
12748 if (double_int_fits_to_tree_p (size_type_node,
cf8f0e63 12749 double_int::from_uhwi (bytes)))
a6caa15f 12750 return build_int_cstu (size_type_node, bytes);
12751 }
0a39fd54 12752 else if (TREE_CODE (ptr) == SSA_NAME)
12753 {
0a39fd54 12754 /* If object size is not known yet, delay folding until
12755 later. Maybe subsequent passes will help determining
12756 it. */
12757 bytes = compute_builtin_object_size (ptr, object_size_type);
a6caa15f 12758 if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2 ? -1 : 0)
12759 && double_int_fits_to_tree_p (size_type_node,
cf8f0e63 12760 double_int::from_uhwi (bytes)))
a6caa15f 12761 return build_int_cstu (size_type_node, bytes);
0a39fd54 12762 }
12763
a6caa15f 12764 return NULL_TREE;
0a39fd54 12765}
12766
12767/* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
c2f47e15 12768 DEST, SRC, LEN, and SIZE are the arguments to the call.
0a39fd54 12769 IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_*
12770 code of the builtin. If MAXLEN is not NULL, it is maximum length
12771 passed as third argument. */
12772
12773tree
389dd41b 12774fold_builtin_memory_chk (location_t loc, tree fndecl,
c2f47e15 12775 tree dest, tree src, tree len, tree size,
12776 tree maxlen, bool ignore,
0a39fd54 12777 enum built_in_function fcode)
12778{
c2f47e15 12779 tree fn;
0a39fd54 12780
c2f47e15 12781 if (!validate_arg (dest, POINTER_TYPE)
12782 || !validate_arg (src,
12783 (fcode == BUILT_IN_MEMSET_CHK
12784 ? INTEGER_TYPE : POINTER_TYPE))
12785 || !validate_arg (len, INTEGER_TYPE)
12786 || !validate_arg (size, INTEGER_TYPE))
12787 return NULL_TREE;
0a39fd54 12788
12789 /* If SRC and DEST are the same (and not volatile), return DEST
12790 (resp. DEST+LEN for __mempcpy_chk). */
12791 if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
12792 {
12793 if (fcode != BUILT_IN_MEMPCPY_CHK)
389dd41b 12794 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
12795 dest, len);
0a39fd54 12796 else
12797 {
2cc66f2a 12798 tree temp = fold_build_pointer_plus_loc (loc, dest, len);
389dd41b 12799 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), temp);
0a39fd54 12800 }
12801 }
12802
12803 if (! host_integerp (size, 1))
c2f47e15 12804 return NULL_TREE;
0a39fd54 12805
12806 if (! integer_all_onesp (size))
12807 {
12808 if (! host_integerp (len, 1))
12809 {
12810 /* If LEN is not constant, try MAXLEN too.
12811 For MAXLEN only allow optimizing into non-_ocs function
12812 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12813 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
12814 {
12815 if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
12816 {
12817 /* (void) __mempcpy_chk () can be optimized into
12818 (void) __memcpy_chk (). */
b9a16870 12819 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
0a39fd54 12820 if (!fn)
c2f47e15 12821 return NULL_TREE;
0a39fd54 12822
389dd41b 12823 return build_call_expr_loc (loc, fn, 4, dest, src, len, size);
0a39fd54 12824 }
c2f47e15 12825 return NULL_TREE;
0a39fd54 12826 }
0a39fd54 12827 }
ad89623c 12828 else
12829 maxlen = len;
0a39fd54 12830
ad89623c 12831 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12832 return NULL_TREE;
0a39fd54 12833 }
12834
0a39fd54 12835 fn = NULL_TREE;
12836 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
12837 mem{cpy,pcpy,move,set} is available. */
12838 switch (fcode)
12839 {
12840 case BUILT_IN_MEMCPY_CHK:
b9a16870 12841 fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
0a39fd54 12842 break;
12843 case BUILT_IN_MEMPCPY_CHK:
b9a16870 12844 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
0a39fd54 12845 break;
12846 case BUILT_IN_MEMMOVE_CHK:
b9a16870 12847 fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
0a39fd54 12848 break;
12849 case BUILT_IN_MEMSET_CHK:
b9a16870 12850 fn = builtin_decl_explicit (BUILT_IN_MEMSET);
0a39fd54 12851 break;
12852 default:
12853 break;
12854 }
12855
12856 if (!fn)
c2f47e15 12857 return NULL_TREE;
0a39fd54 12858
389dd41b 12859 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12860}
12861
12862/* Fold a call to the __st[rp]cpy_chk builtin.
c2f47e15 12863 DEST, SRC, and SIZE are the arguments to the call.
12864 IGNORE is true if return value can be ignored. FCODE is the BUILT_IN_*
0a39fd54 12865 code of the builtin. If MAXLEN is not NULL, it is maximum length of
12866 strings passed as second argument. */
12867
12868tree
389dd41b 12869fold_builtin_stxcpy_chk (location_t loc, tree fndecl, tree dest,
12870 tree src, tree size,
c2f47e15 12871 tree maxlen, bool ignore,
0a39fd54 12872 enum built_in_function fcode)
12873{
c2f47e15 12874 tree len, fn;
0a39fd54 12875
c2f47e15 12876 if (!validate_arg (dest, POINTER_TYPE)
12877 || !validate_arg (src, POINTER_TYPE)
12878 || !validate_arg (size, INTEGER_TYPE))
12879 return NULL_TREE;
0a39fd54 12880
12881 /* If SRC and DEST are the same (and not volatile), return DEST. */
12882 if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
389dd41b 12883 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest);
a0c938f0 12884
0a39fd54 12885 if (! host_integerp (size, 1))
c2f47e15 12886 return NULL_TREE;
0a39fd54 12887
12888 if (! integer_all_onesp (size))
12889 {
12890 len = c_strlen (src, 1);
12891 if (! len || ! host_integerp (len, 1))
12892 {
12893 /* If LEN is not constant, try MAXLEN too.
12894 For MAXLEN only allow optimizing into non-_ocs function
12895 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12896 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
12897 {
12898 if (fcode == BUILT_IN_STPCPY_CHK)
12899 {
12900 if (! ignore)
c2f47e15 12901 return NULL_TREE;
0a39fd54 12902
12903 /* If return value of __stpcpy_chk is ignored,
12904 optimize into __strcpy_chk. */
b9a16870 12905 fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
0a39fd54 12906 if (!fn)
c2f47e15 12907 return NULL_TREE;
0a39fd54 12908
389dd41b 12909 return build_call_expr_loc (loc, fn, 3, dest, src, size);
0a39fd54 12910 }
12911
12912 if (! len || TREE_SIDE_EFFECTS (len))
c2f47e15 12913 return NULL_TREE;
0a39fd54 12914
12915 /* If c_strlen returned something, but not a constant,
12916 transform __strcpy_chk into __memcpy_chk. */
b9a16870 12917 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
0a39fd54 12918 if (!fn)
c2f47e15 12919 return NULL_TREE;
0a39fd54 12920
bd6dcc04 12921 len = fold_convert_loc (loc, size_type_node, len);
12922 len = size_binop_loc (loc, PLUS_EXPR, len,
12923 build_int_cst (size_type_node, 1));
389dd41b 12924 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
12925 build_call_expr_loc (loc, fn, 4,
12926 dest, src, len, size));
0a39fd54 12927 }
0a39fd54 12928 }
ad89623c 12929 else
12930 maxlen = len;
12931
12932 if (! tree_int_cst_lt (maxlen, size))
c2f47e15 12933 return NULL_TREE;
0a39fd54 12934 }
12935
0a39fd54 12936 /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available. */
b9a16870 12937 fn = builtin_decl_explicit (fcode == BUILT_IN_STPCPY_CHK
12938 ? BUILT_IN_STPCPY : BUILT_IN_STRCPY);
0a39fd54 12939 if (!fn)
c2f47e15 12940 return NULL_TREE;
0a39fd54 12941
389dd41b 12942 return build_call_expr_loc (loc, fn, 2, dest, src);
0a39fd54 12943}
12944
1063acde 12945/* Fold a call to the __st{r,p}ncpy_chk builtin. DEST, SRC, LEN, and SIZE
c2f47e15 12946 are the arguments to the call. If MAXLEN is not NULL, it is maximum
1063acde 12947 length passed as third argument. IGNORE is true if return value can be
12948 ignored. FCODE is the BUILT_IN_* code of the builtin. */
0a39fd54 12949
12950tree
1063acde 12951fold_builtin_stxncpy_chk (location_t loc, tree dest, tree src,
12952 tree len, tree size, tree maxlen, bool ignore,
12953 enum built_in_function fcode)
0a39fd54 12954{
c2f47e15 12955 tree fn;
0a39fd54 12956
c2f47e15 12957 if (!validate_arg (dest, POINTER_TYPE)
12958 || !validate_arg (src, POINTER_TYPE)
12959 || !validate_arg (len, INTEGER_TYPE)
12960 || !validate_arg (size, INTEGER_TYPE))
12961 return NULL_TREE;
0a39fd54 12962
1063acde 12963 if (fcode == BUILT_IN_STPNCPY_CHK && ignore)
12964 {
12965 /* If return value of __stpncpy_chk is ignored,
12966 optimize into __strncpy_chk. */
12967 fn = builtin_decl_explicit (BUILT_IN_STRNCPY_CHK);
12968 if (fn)
12969 return build_call_expr_loc (loc, fn, 4, dest, src, len, size);
12970 }
12971
0a39fd54 12972 if (! host_integerp (size, 1))
c2f47e15 12973 return NULL_TREE;
0a39fd54 12974
12975 if (! integer_all_onesp (size))
12976 {
12977 if (! host_integerp (len, 1))
12978 {
12979 /* If LEN is not constant, try MAXLEN too.
12980 For MAXLEN only allow optimizing into non-_ocs function
12981 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
12982 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 12983 return NULL_TREE;
0a39fd54 12984 }
ad89623c 12985 else
12986 maxlen = len;
0a39fd54 12987
ad89623c 12988 if (tree_int_cst_lt (size, maxlen))
c2f47e15 12989 return NULL_TREE;
0a39fd54 12990 }
12991
1063acde 12992 /* If __builtin_st{r,p}ncpy_chk is used, assume st{r,p}ncpy is available. */
12993 fn = builtin_decl_explicit (fcode == BUILT_IN_STPNCPY_CHK
12994 ? BUILT_IN_STPNCPY : BUILT_IN_STRNCPY);
0a39fd54 12995 if (!fn)
c2f47e15 12996 return NULL_TREE;
0a39fd54 12997
389dd41b 12998 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 12999}
13000
c2f47e15 13001/* Fold a call to the __strcat_chk builtin FNDECL. DEST, SRC, and SIZE
13002 are the arguments to the call. */
0a39fd54 13003
13004static tree
389dd41b 13005fold_builtin_strcat_chk (location_t loc, tree fndecl, tree dest,
13006 tree src, tree size)
0a39fd54 13007{
c2f47e15 13008 tree fn;
0a39fd54 13009 const char *p;
13010
c2f47e15 13011 if (!validate_arg (dest, POINTER_TYPE)
13012 || !validate_arg (src, POINTER_TYPE)
13013 || !validate_arg (size, INTEGER_TYPE))
13014 return NULL_TREE;
0a39fd54 13015
13016 p = c_getstr (src);
13017 /* If the SRC parameter is "", return DEST. */
13018 if (p && *p == '\0')
389dd41b 13019 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
0a39fd54 13020
13021 if (! host_integerp (size, 1) || ! integer_all_onesp (size))
c2f47e15 13022 return NULL_TREE;
0a39fd54 13023
13024 /* If __builtin_strcat_chk is used, assume strcat is available. */
b9a16870 13025 fn = builtin_decl_explicit (BUILT_IN_STRCAT);
0a39fd54 13026 if (!fn)
c2f47e15 13027 return NULL_TREE;
0a39fd54 13028
389dd41b 13029 return build_call_expr_loc (loc, fn, 2, dest, src);
0a39fd54 13030}
13031
c2f47e15 13032/* Fold a call to the __strncat_chk builtin with arguments DEST, SRC,
13033 LEN, and SIZE. */
0a39fd54 13034
13035static tree
389dd41b 13036fold_builtin_strncat_chk (location_t loc, tree fndecl,
c2f47e15 13037 tree dest, tree src, tree len, tree size)
0a39fd54 13038{
c2f47e15 13039 tree fn;
0a39fd54 13040 const char *p;
13041
c2f47e15 13042 if (!validate_arg (dest, POINTER_TYPE)
13043 || !validate_arg (src, POINTER_TYPE)
13044 || !validate_arg (size, INTEGER_TYPE)
13045 || !validate_arg (size, INTEGER_TYPE))
13046 return NULL_TREE;
0a39fd54 13047
13048 p = c_getstr (src);
13049 /* If the SRC parameter is "" or if LEN is 0, return DEST. */
13050 if (p && *p == '\0')
389dd41b 13051 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
0a39fd54 13052 else if (integer_zerop (len))
389dd41b 13053 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
0a39fd54 13054
13055 if (! host_integerp (size, 1))
c2f47e15 13056 return NULL_TREE;
0a39fd54 13057
13058 if (! integer_all_onesp (size))
13059 {
13060 tree src_len = c_strlen (src, 1);
13061 if (src_len
13062 && host_integerp (src_len, 1)
13063 && host_integerp (len, 1)
13064 && ! tree_int_cst_lt (len, src_len))
13065 {
13066 /* If LEN >= strlen (SRC), optimize into __strcat_chk. */
b9a16870 13067 fn = builtin_decl_explicit (BUILT_IN_STRCAT_CHK);
0a39fd54 13068 if (!fn)
c2f47e15 13069 return NULL_TREE;
0a39fd54 13070
389dd41b 13071 return build_call_expr_loc (loc, fn, 3, dest, src, size);
0a39fd54 13072 }
c2f47e15 13073 return NULL_TREE;
0a39fd54 13074 }
13075
0a39fd54 13076 /* If __builtin_strncat_chk is used, assume strncat is available. */
b9a16870 13077 fn = builtin_decl_explicit (BUILT_IN_STRNCAT);
0a39fd54 13078 if (!fn)
c2f47e15 13079 return NULL_TREE;
0a39fd54 13080
389dd41b 13081 return build_call_expr_loc (loc, fn, 3, dest, src, len);
0a39fd54 13082}
13083
af1409ad 13084/* Fold a call EXP to __{,v}sprintf_chk having NARGS passed as ARGS.
13085 Return NULL_TREE if a normal call should be emitted rather than
13086 expanding the function inline. FCODE is either BUILT_IN_SPRINTF_CHK
13087 or BUILT_IN_VSPRINTF_CHK. */
0a39fd54 13088
13089static tree
af1409ad 13090fold_builtin_sprintf_chk_1 (location_t loc, int nargs, tree *args,
13091 enum built_in_function fcode)
0a39fd54 13092{
13093 tree dest, size, len, fn, fmt, flag;
13094 const char *fmt_str;
13095
13096 /* Verify the required arguments in the original call. */
c2f47e15 13097 if (nargs < 4)
13098 return NULL_TREE;
af1409ad 13099 dest = args[0];
c2f47e15 13100 if (!validate_arg (dest, POINTER_TYPE))
13101 return NULL_TREE;
af1409ad 13102 flag = args[1];
c2f47e15 13103 if (!validate_arg (flag, INTEGER_TYPE))
13104 return NULL_TREE;
af1409ad 13105 size = args[2];
c2f47e15 13106 if (!validate_arg (size, INTEGER_TYPE))
13107 return NULL_TREE;
af1409ad 13108 fmt = args[3];
c2f47e15 13109 if (!validate_arg (fmt, POINTER_TYPE))
13110 return NULL_TREE;
0a39fd54 13111
13112 if (! host_integerp (size, 1))
c2f47e15 13113 return NULL_TREE;
0a39fd54 13114
13115 len = NULL_TREE;
13116
d4473c84 13117 if (!init_target_chars ())
c2f47e15 13118 return NULL_TREE;
99eabcc1 13119
0a39fd54 13120 /* Check whether the format is a literal string constant. */
13121 fmt_str = c_getstr (fmt);
13122 if (fmt_str != NULL)
13123 {
13124 /* If the format doesn't contain % args or %%, we know the size. */
99eabcc1 13125 if (strchr (fmt_str, target_percent) == 0)
0a39fd54 13126 {
c2f47e15 13127 if (fcode != BUILT_IN_SPRINTF_CHK || nargs == 4)
0a39fd54 13128 len = build_int_cstu (size_type_node, strlen (fmt_str));
13129 }
13130 /* If the format is "%s" and first ... argument is a string literal,
13131 we know the size too. */
c2f47e15 13132 else if (fcode == BUILT_IN_SPRINTF_CHK
13133 && strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 13134 {
13135 tree arg;
13136
c2f47e15 13137 if (nargs == 5)
0a39fd54 13138 {
af1409ad 13139 arg = args[4];
c2f47e15 13140 if (validate_arg (arg, POINTER_TYPE))
0a39fd54 13141 {
13142 len = c_strlen (arg, 1);
13143 if (! len || ! host_integerp (len, 1))
13144 len = NULL_TREE;
13145 }
13146 }
13147 }
13148 }
13149
13150 if (! integer_all_onesp (size))
13151 {
13152 if (! len || ! tree_int_cst_lt (len, size))
c2f47e15 13153 return NULL_TREE;
0a39fd54 13154 }
13155
13156 /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
13157 or if format doesn't contain % chars or is "%s". */
13158 if (! integer_zerop (flag))
13159 {
13160 if (fmt_str == NULL)
c2f47e15 13161 return NULL_TREE;
13162 if (strchr (fmt_str, target_percent) != NULL
13163 && strcmp (fmt_str, target_percent_s))
13164 return NULL_TREE;
0a39fd54 13165 }
13166
0a39fd54 13167 /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
b9a16870 13168 fn = builtin_decl_explicit (fcode == BUILT_IN_VSPRINTF_CHK
13169 ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF);
0a39fd54 13170 if (!fn)
c2f47e15 13171 return NULL_TREE;
0a39fd54 13172
af1409ad 13173 return rewrite_call_expr_array (loc, nargs, args, 4, fn, 2, dest, fmt);
0a39fd54 13174}
13175
af1409ad 13176/* Fold a call EXP to __{,v}sprintf_chk. Return NULL_TREE if
0a39fd54 13177 a normal call should be emitted rather than expanding the function
af1409ad 13178 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
13179
13180static tree
13181fold_builtin_sprintf_chk (location_t loc, tree exp,
13182 enum built_in_function fcode)
13183{
13184 return fold_builtin_sprintf_chk_1 (loc, call_expr_nargs (exp),
13185 CALL_EXPR_ARGP (exp), fcode);
13186}
13187
13188/* Fold a call EXP to {,v}snprintf having NARGS passed as ARGS. Return
13189 NULL_TREE if a normal call should be emitted rather than expanding
13190 the function inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
0a39fd54 13191 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
13192 passed as second argument. */
13193
af1409ad 13194static tree
13195fold_builtin_snprintf_chk_1 (location_t loc, int nargs, tree *args,
13196 tree maxlen, enum built_in_function fcode)
0a39fd54 13197{
13198 tree dest, size, len, fn, fmt, flag;
13199 const char *fmt_str;
13200
13201 /* Verify the required arguments in the original call. */
af1409ad 13202 if (nargs < 5)
c2f47e15 13203 return NULL_TREE;
af1409ad 13204 dest = args[0];
c2f47e15 13205 if (!validate_arg (dest, POINTER_TYPE))
13206 return NULL_TREE;
af1409ad 13207 len = args[1];
c2f47e15 13208 if (!validate_arg (len, INTEGER_TYPE))
13209 return NULL_TREE;
af1409ad 13210 flag = args[2];
c2f47e15 13211 if (!validate_arg (flag, INTEGER_TYPE))
13212 return NULL_TREE;
af1409ad 13213 size = args[3];
c2f47e15 13214 if (!validate_arg (size, INTEGER_TYPE))
13215 return NULL_TREE;
af1409ad 13216 fmt = args[4];
c2f47e15 13217 if (!validate_arg (fmt, POINTER_TYPE))
13218 return NULL_TREE;
0a39fd54 13219
13220 if (! host_integerp (size, 1))
c2f47e15 13221 return NULL_TREE;
0a39fd54 13222
13223 if (! integer_all_onesp (size))
13224 {
13225 if (! host_integerp (len, 1))
13226 {
13227 /* If LEN is not constant, try MAXLEN too.
13228 For MAXLEN only allow optimizing into non-_ocs function
13229 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
13230 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
c2f47e15 13231 return NULL_TREE;
0a39fd54 13232 }
ad89623c 13233 else
13234 maxlen = len;
0a39fd54 13235
ad89623c 13236 if (tree_int_cst_lt (size, maxlen))
c2f47e15 13237 return NULL_TREE;
0a39fd54 13238 }
13239
d4473c84 13240 if (!init_target_chars ())
c2f47e15 13241 return NULL_TREE;
99eabcc1 13242
0a39fd54 13243 /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
13244 or if format doesn't contain % chars or is "%s". */
13245 if (! integer_zerop (flag))
13246 {
13247 fmt_str = c_getstr (fmt);
13248 if (fmt_str == NULL)
c2f47e15 13249 return NULL_TREE;
13250 if (strchr (fmt_str, target_percent) != NULL
13251 && strcmp (fmt_str, target_percent_s))
13252 return NULL_TREE;
0a39fd54 13253 }
13254
0a39fd54 13255 /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
13256 available. */
b9a16870 13257 fn = builtin_decl_explicit (fcode == BUILT_IN_VSNPRINTF_CHK
13258 ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF);
0a39fd54 13259 if (!fn)
c2f47e15 13260 return NULL_TREE;
0a39fd54 13261
af1409ad 13262 return rewrite_call_expr_array (loc, nargs, args, 5, fn, 3, dest, len, fmt);
13263}
13264
13265/* Fold a call EXP to {,v}snprintf. Return NULL_TREE if
13266 a normal call should be emitted rather than expanding the function
13267 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
13268 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
13269 passed as second argument. */
13270
13271tree
13272fold_builtin_snprintf_chk (location_t loc, tree exp, tree maxlen,
13273 enum built_in_function fcode)
13274{
13275 return fold_builtin_snprintf_chk_1 (loc, call_expr_nargs (exp),
13276 CALL_EXPR_ARGP (exp), maxlen, fcode);
0a39fd54 13277}
13278
13279/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 13280 FMT and ARG are the arguments to the call; we don't fold cases with
13281 more than 2 arguments, and ARG may be null if this is a 1-argument case.
0a39fd54 13282
c2f47e15 13283 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 13284 simplified form of the call as a tree. FCODE is the BUILT_IN_*
13285 code of the function to be simplified. */
13286
13287static tree
389dd41b 13288fold_builtin_printf (location_t loc, tree fndecl, tree fmt,
13289 tree arg, bool ignore,
0a39fd54 13290 enum built_in_function fcode)
13291{
c2f47e15 13292 tree fn_putchar, fn_puts, newarg, call = NULL_TREE;
0a39fd54 13293 const char *fmt_str = NULL;
13294
13295 /* If the return value is used, don't do the transformation. */
13296 if (! ignore)
c2f47e15 13297 return NULL_TREE;
0a39fd54 13298
13299 /* Verify the required arguments in the original call. */
c2f47e15 13300 if (!validate_arg (fmt, POINTER_TYPE))
13301 return NULL_TREE;
0a39fd54 13302
13303 /* Check whether the format is a literal string constant. */
13304 fmt_str = c_getstr (fmt);
13305 if (fmt_str == NULL)
13306 return NULL_TREE;
13307
13308 if (fcode == BUILT_IN_PRINTF_UNLOCKED)
13309 {
6d77ed92 13310 /* If we're using an unlocked function, assume the other
13311 unlocked functions exist explicitly. */
b9a16870 13312 fn_putchar = builtin_decl_explicit (BUILT_IN_PUTCHAR_UNLOCKED);
13313 fn_puts = builtin_decl_explicit (BUILT_IN_PUTS_UNLOCKED);
0a39fd54 13314 }
13315 else
13316 {
b9a16870 13317 fn_putchar = builtin_decl_implicit (BUILT_IN_PUTCHAR);
13318 fn_puts = builtin_decl_implicit (BUILT_IN_PUTS);
0a39fd54 13319 }
13320
d4473c84 13321 if (!init_target_chars ())
c2f47e15 13322 return NULL_TREE;
a0c938f0 13323
c2f47e15 13324 if (strcmp (fmt_str, target_percent_s) == 0
13325 || strchr (fmt_str, target_percent) == NULL)
0a39fd54 13326 {
13327 const char *str;
13328
99eabcc1 13329 if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 13330 {
13331 if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 13332 return NULL_TREE;
0a39fd54 13333
c2f47e15 13334 if (!arg || !validate_arg (arg, POINTER_TYPE))
13335 return NULL_TREE;
0a39fd54 13336
c2f47e15 13337 str = c_getstr (arg);
0a39fd54 13338 if (str == NULL)
c2f47e15 13339 return NULL_TREE;
0a39fd54 13340 }
13341 else
13342 {
13343 /* The format specifier doesn't contain any '%' characters. */
13344 if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
c2f47e15 13345 && arg)
13346 return NULL_TREE;
0a39fd54 13347 str = fmt_str;
13348 }
13349
13350 /* If the string was "", printf does nothing. */
13351 if (str[0] == '\0')
13352 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
13353
13354 /* If the string has length of 1, call putchar. */
13355 if (str[1] == '\0')
13356 {
13357 /* Given printf("c"), (where c is any one character,)
13358 convert "c"[0] to an int and pass that to the replacement
13359 function. */
7002a1c8 13360 newarg = build_int_cst (integer_type_node, str[0]);
c2f47e15 13361 if (fn_putchar)
389dd41b 13362 call = build_call_expr_loc (loc, fn_putchar, 1, newarg);
0a39fd54 13363 }
13364 else
13365 {
13366 /* If the string was "string\n", call puts("string"). */
13367 size_t len = strlen (str);
663dbd5e 13368 if ((unsigned char)str[len - 1] == target_newline
13369 && (size_t) (int) len == len
13370 && (int) len > 0)
0a39fd54 13371 {
663dbd5e 13372 char *newstr;
13373 tree offset_node, string_cst;
13374
0a39fd54 13375 /* Create a NUL-terminated string that's one char shorter
13376 than the original, stripping off the trailing '\n'. */
663dbd5e 13377 newarg = build_string_literal (len, str);
13378 string_cst = string_constant (newarg, &offset_node);
13379 gcc_checking_assert (string_cst
13380 && (TREE_STRING_LENGTH (string_cst)
13381 == (int) len)
13382 && integer_zerop (offset_node)
13383 && (unsigned char)
13384 TREE_STRING_POINTER (string_cst)[len - 1]
13385 == target_newline);
13386 /* build_string_literal creates a new STRING_CST,
13387 modify it in place to avoid double copying. */
13388 newstr = CONST_CAST (char *, TREE_STRING_POINTER (string_cst));
13389 newstr[len - 1] = '\0';
c2f47e15 13390 if (fn_puts)
389dd41b 13391 call = build_call_expr_loc (loc, fn_puts, 1, newarg);
0a39fd54 13392 }
13393 else
13394 /* We'd like to arrange to call fputs(string,stdout) here,
13395 but we need stdout and don't have a way to get it yet. */
c2f47e15 13396 return NULL_TREE;
0a39fd54 13397 }
13398 }
13399
13400 /* The other optimizations can be done only on the non-va_list variants. */
13401 else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
c2f47e15 13402 return NULL_TREE;
0a39fd54 13403
13404 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
99eabcc1 13405 else if (strcmp (fmt_str, target_percent_s_newline) == 0)
0a39fd54 13406 {
c2f47e15 13407 if (!arg || !validate_arg (arg, POINTER_TYPE))
13408 return NULL_TREE;
13409 if (fn_puts)
389dd41b 13410 call = build_call_expr_loc (loc, fn_puts, 1, arg);
0a39fd54 13411 }
13412
13413 /* If the format specifier was "%c", call __builtin_putchar(arg). */
99eabcc1 13414 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 13415 {
c2f47e15 13416 if (!arg || !validate_arg (arg, INTEGER_TYPE))
13417 return NULL_TREE;
13418 if (fn_putchar)
389dd41b 13419 call = build_call_expr_loc (loc, fn_putchar, 1, arg);
0a39fd54 13420 }
13421
c2f47e15 13422 if (!call)
13423 return NULL_TREE;
0a39fd54 13424
389dd41b 13425 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
0a39fd54 13426}
13427
13428/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
c2f47e15 13429 FP, FMT, and ARG are the arguments to the call. We don't fold calls with
13430 more than 3 arguments, and ARG may be null in the 2-argument case.
0a39fd54 13431
c2f47e15 13432 Return NULL_TREE if no simplification was possible, otherwise return the
0a39fd54 13433 simplified form of the call as a tree. FCODE is the BUILT_IN_*
13434 code of the function to be simplified. */
13435
13436static tree
389dd41b 13437fold_builtin_fprintf (location_t loc, tree fndecl, tree fp,
13438 tree fmt, tree arg, bool ignore,
0a39fd54 13439 enum built_in_function fcode)
13440{
c2f47e15 13441 tree fn_fputc, fn_fputs, call = NULL_TREE;
0a39fd54 13442 const char *fmt_str = NULL;
13443
13444 /* If the return value is used, don't do the transformation. */
13445 if (! ignore)
c2f47e15 13446 return NULL_TREE;
0a39fd54 13447
13448 /* Verify the required arguments in the original call. */
c2f47e15 13449 if (!validate_arg (fp, POINTER_TYPE))
13450 return NULL_TREE;
13451 if (!validate_arg (fmt, POINTER_TYPE))
13452 return NULL_TREE;
0a39fd54 13453
13454 /* Check whether the format is a literal string constant. */
13455 fmt_str = c_getstr (fmt);
13456 if (fmt_str == NULL)
13457 return NULL_TREE;
13458
13459 if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
13460 {
6d77ed92 13461 /* If we're using an unlocked function, assume the other
13462 unlocked functions exist explicitly. */
b9a16870 13463 fn_fputc = builtin_decl_explicit (BUILT_IN_FPUTC_UNLOCKED);
13464 fn_fputs = builtin_decl_explicit (BUILT_IN_FPUTS_UNLOCKED);
0a39fd54 13465 }
13466 else
13467 {
b9a16870 13468 fn_fputc = builtin_decl_implicit (BUILT_IN_FPUTC);
13469 fn_fputs = builtin_decl_implicit (BUILT_IN_FPUTS);
0a39fd54 13470 }
13471
d4473c84 13472 if (!init_target_chars ())
c2f47e15 13473 return NULL_TREE;
a0c938f0 13474
0a39fd54 13475 /* If the format doesn't contain % args or %%, use strcpy. */
99eabcc1 13476 if (strchr (fmt_str, target_percent) == NULL)
0a39fd54 13477 {
13478 if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
c2f47e15 13479 && arg)
13480 return NULL_TREE;
0a39fd54 13481
13482 /* If the format specifier was "", fprintf does nothing. */
13483 if (fmt_str[0] == '\0')
13484 {
13485 /* If FP has side-effects, just wait until gimplification is
13486 done. */
13487 if (TREE_SIDE_EFFECTS (fp))
c2f47e15 13488 return NULL_TREE;
0a39fd54 13489
13490 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
13491 }
13492
13493 /* When "string" doesn't contain %, replace all cases of
13494 fprintf (fp, string) with fputs (string, fp). The fputs
13495 builtin will take care of special cases like length == 1. */
c2f47e15 13496 if (fn_fputs)
389dd41b 13497 call = build_call_expr_loc (loc, fn_fputs, 2, fmt, fp);
0a39fd54 13498 }
13499
13500 /* The other optimizations can be done only on the non-va_list variants. */
13501 else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
c2f47e15 13502 return NULL_TREE;
0a39fd54 13503
13504 /* If the format specifier was "%s", call __builtin_fputs (arg, fp). */
99eabcc1 13505 else if (strcmp (fmt_str, target_percent_s) == 0)
0a39fd54 13506 {
c2f47e15 13507 if (!arg || !validate_arg (arg, POINTER_TYPE))
13508 return NULL_TREE;
13509 if (fn_fputs)
389dd41b 13510 call = build_call_expr_loc (loc, fn_fputs, 2, arg, fp);
0a39fd54 13511 }
13512
13513 /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */
99eabcc1 13514 else if (strcmp (fmt_str, target_percent_c) == 0)
0a39fd54 13515 {
c2f47e15 13516 if (!arg || !validate_arg (arg, INTEGER_TYPE))
13517 return NULL_TREE;
13518 if (fn_fputc)
389dd41b 13519 call = build_call_expr_loc (loc, fn_fputc, 2, arg, fp);
0a39fd54 13520 }
13521
c2f47e15 13522 if (!call)
13523 return NULL_TREE;
389dd41b 13524 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
0a39fd54 13525}
99eabcc1 13526
13527/* Initialize format string characters in the target charset. */
13528
13529static bool
13530init_target_chars (void)
13531{
13532 static bool init;
13533 if (!init)
13534 {
13535 target_newline = lang_hooks.to_target_charset ('\n');
13536 target_percent = lang_hooks.to_target_charset ('%');
13537 target_c = lang_hooks.to_target_charset ('c');
13538 target_s = lang_hooks.to_target_charset ('s');
13539 if (target_newline == 0 || target_percent == 0 || target_c == 0
13540 || target_s == 0)
13541 return false;
13542
13543 target_percent_c[0] = target_percent;
13544 target_percent_c[1] = target_c;
13545 target_percent_c[2] = '\0';
13546
13547 target_percent_s[0] = target_percent;
13548 target_percent_s[1] = target_s;
13549 target_percent_s[2] = '\0';
13550
13551 target_percent_s_newline[0] = target_percent;
13552 target_percent_s_newline[1] = target_s;
13553 target_percent_s_newline[2] = target_newline;
13554 target_percent_s_newline[3] = '\0';
a0c938f0 13555
99eabcc1 13556 init = true;
13557 }
13558 return true;
13559}
bffb7645 13560
f0c477f2 13561/* Helper function for do_mpfr_arg*(). Ensure M is a normal number
13562 and no overflow/underflow occurred. INEXACT is true if M was not
fa7637bd 13563 exactly calculated. TYPE is the tree type for the result. This
f0c477f2 13564 function assumes that you cleared the MPFR flags and then
13565 calculated M to see if anything subsequently set a flag prior to
13566 entering this function. Return NULL_TREE if any checks fail. */
13567
13568static tree
d4473c84 13569do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
f0c477f2 13570{
13571 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
13572 overflow/underflow occurred. If -frounding-math, proceed iff the
13573 result of calling FUNC was exact. */
d4473c84 13574 if (mpfr_number_p (m) && !mpfr_overflow_p () && !mpfr_underflow_p ()
f0c477f2 13575 && (!flag_rounding_math || !inexact))
13576 {
13577 REAL_VALUE_TYPE rr;
13578
66fa16e6 13579 real_from_mpfr (&rr, m, type, GMP_RNDN);
f0c477f2 13580 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
13581 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
13582 but the mpft_t is not, then we underflowed in the
13583 conversion. */
776a7bab 13584 if (real_isfinite (&rr)
f0c477f2 13585 && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0))
13586 {
13587 REAL_VALUE_TYPE rmode;
13588
13589 real_convert (&rmode, TYPE_MODE (type), &rr);
13590 /* Proceed iff the specified mode can hold the value. */
13591 if (real_identical (&rmode, &rr))
13592 return build_real (type, rmode);
13593 }
13594 }
13595 return NULL_TREE;
13596}
13597
239d491a 13598/* Helper function for do_mpc_arg*(). Ensure M is a normal complex
13599 number and no overflow/underflow occurred. INEXACT is true if M
13600 was not exactly calculated. TYPE is the tree type for the result.
13601 This function assumes that you cleared the MPFR flags and then
13602 calculated M to see if anything subsequently set a flag prior to
652d9409 13603 entering this function. Return NULL_TREE if any checks fail, if
13604 FORCE_CONVERT is true, then bypass the checks. */
239d491a 13605
13606static tree
652d9409 13607do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert)
239d491a 13608{
13609 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
13610 overflow/underflow occurred. If -frounding-math, proceed iff the
13611 result of calling FUNC was exact. */
652d9409 13612 if (force_convert
13613 || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m))
13614 && !mpfr_overflow_p () && !mpfr_underflow_p ()
13615 && (!flag_rounding_math || !inexact)))
239d491a 13616 {
13617 REAL_VALUE_TYPE re, im;
13618
b0e7c4d4 13619 real_from_mpfr (&re, mpc_realref (m), TREE_TYPE (type), GMP_RNDN);
13620 real_from_mpfr (&im, mpc_imagref (m), TREE_TYPE (type), GMP_RNDN);
239d491a 13621 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
13622 check for overflow/underflow. If the REAL_VALUE_TYPE is zero
13623 but the mpft_t is not, then we underflowed in the
13624 conversion. */
652d9409 13625 if (force_convert
13626 || (real_isfinite (&re) && real_isfinite (&im)
13627 && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0)
13628 && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0)))
239d491a 13629 {
13630 REAL_VALUE_TYPE re_mode, im_mode;
13631
13632 real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re);
13633 real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im);
13634 /* Proceed iff the specified mode can hold the value. */
652d9409 13635 if (force_convert
13636 || (real_identical (&re_mode, &re)
13637 && real_identical (&im_mode, &im)))
239d491a 13638 return build_complex (type, build_real (TREE_TYPE (type), re_mode),
13639 build_real (TREE_TYPE (type), im_mode));
13640 }
13641 }
13642 return NULL_TREE;
13643}
239d491a 13644
bffb7645 13645/* If argument ARG is a REAL_CST, call the one-argument mpfr function
13646 FUNC on it and return the resulting value as a tree with type TYPE.
728bac60 13647 If MIN and/or MAX are not NULL, then the supplied ARG must be
13648 within those bounds. If INCLUSIVE is true, then MIN/MAX are
13649 acceptable values, otherwise they are not. The mpfr precision is
13650 set to the precision of TYPE. We assume that function FUNC returns
13651 zero if the result could be calculated exactly within the requested
13652 precision. */
bffb7645 13653
13654static tree
728bac60 13655do_mpfr_arg1 (tree arg, tree type, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
13656 const REAL_VALUE_TYPE *min, const REAL_VALUE_TYPE *max,
13657 bool inclusive)
bffb7645 13658{
13659 tree result = NULL_TREE;
48e1416a 13660
bffb7645 13661 STRIP_NOPS (arg);
13662
bd7d6fa4 13663 /* To proceed, MPFR must exactly represent the target floating point
13664 format, which only happens when the target base equals two. */
13665 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13666 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
bffb7645 13667 {
f0c477f2 13668 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
bffb7645 13669
776a7bab 13670 if (real_isfinite (ra)
f0c477f2 13671 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min))
13672 && (!max || real_compare (inclusive ? LE_EXPR: LT_EXPR , ra, max)))
bffb7645 13673 {
e2eb2b7f 13674 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13675 const int prec = fmt->p;
13676 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
debf9994 13677 int inexact;
bffb7645 13678 mpfr_t m;
13679
13680 mpfr_init2 (m, prec);
66fa16e6 13681 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 13682 mpfr_clear_flags ();
e2eb2b7f 13683 inexact = func (m, m, rnd);
f0c477f2 13684 result = do_mpfr_ckconv (m, type, inexact);
bffb7645 13685 mpfr_clear (m);
13686 }
13687 }
48e1416a 13688
bffb7645 13689 return result;
13690}
f0c477f2 13691
13692/* If argument ARG is a REAL_CST, call the two-argument mpfr function
13693 FUNC on it and return the resulting value as a tree with type TYPE.
13694 The mpfr precision is set to the precision of TYPE. We assume that
13695 function FUNC returns zero if the result could be calculated
13696 exactly within the requested precision. */
13697
13698static tree
13699do_mpfr_arg2 (tree arg1, tree arg2, tree type,
13700 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
13701{
13702 tree result = NULL_TREE;
48e1416a 13703
f0c477f2 13704 STRIP_NOPS (arg1);
13705 STRIP_NOPS (arg2);
13706
bd7d6fa4 13707 /* To proceed, MPFR must exactly represent the target floating point
13708 format, which only happens when the target base equals two. */
13709 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13710 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
13711 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
f0c477f2 13712 {
13713 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
13714 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
13715
776a7bab 13716 if (real_isfinite (ra1) && real_isfinite (ra2))
f0c477f2 13717 {
e2eb2b7f 13718 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13719 const int prec = fmt->p;
13720 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
f0c477f2 13721 int inexact;
13722 mpfr_t m1, m2;
13723
13724 mpfr_inits2 (prec, m1, m2, NULL);
66fa16e6 13725 mpfr_from_real (m1, ra1, GMP_RNDN);
13726 mpfr_from_real (m2, ra2, GMP_RNDN);
d4473c84 13727 mpfr_clear_flags ();
e2eb2b7f 13728 inexact = func (m1, m1, m2, rnd);
f0c477f2 13729 result = do_mpfr_ckconv (m1, type, inexact);
13730 mpfr_clears (m1, m2, NULL);
13731 }
13732 }
48e1416a 13733
f0c477f2 13734 return result;
13735}
d92f994c 13736
9917422b 13737/* If argument ARG is a REAL_CST, call the three-argument mpfr function
13738 FUNC on it and return the resulting value as a tree with type TYPE.
13739 The mpfr precision is set to the precision of TYPE. We assume that
13740 function FUNC returns zero if the result could be calculated
13741 exactly within the requested precision. */
13742
13743static tree
13744do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type,
13745 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
13746{
13747 tree result = NULL_TREE;
48e1416a 13748
9917422b 13749 STRIP_NOPS (arg1);
13750 STRIP_NOPS (arg2);
13751 STRIP_NOPS (arg3);
13752
bd7d6fa4 13753 /* To proceed, MPFR must exactly represent the target floating point
13754 format, which only happens when the target base equals two. */
13755 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13756 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)
13757 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2)
13758 && TREE_CODE (arg3) == REAL_CST && !TREE_OVERFLOW (arg3))
9917422b 13759 {
13760 const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1);
13761 const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2);
13762 const REAL_VALUE_TYPE *const ra3 = &TREE_REAL_CST (arg3);
13763
776a7bab 13764 if (real_isfinite (ra1) && real_isfinite (ra2) && real_isfinite (ra3))
9917422b 13765 {
e2eb2b7f 13766 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13767 const int prec = fmt->p;
13768 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
9917422b 13769 int inexact;
13770 mpfr_t m1, m2, m3;
13771
13772 mpfr_inits2 (prec, m1, m2, m3, NULL);
66fa16e6 13773 mpfr_from_real (m1, ra1, GMP_RNDN);
13774 mpfr_from_real (m2, ra2, GMP_RNDN);
13775 mpfr_from_real (m3, ra3, GMP_RNDN);
d4473c84 13776 mpfr_clear_flags ();
e2eb2b7f 13777 inexact = func (m1, m1, m2, m3, rnd);
9917422b 13778 result = do_mpfr_ckconv (m1, type, inexact);
13779 mpfr_clears (m1, m2, m3, NULL);
13780 }
13781 }
48e1416a 13782
9917422b 13783 return result;
13784}
13785
d92f994c 13786/* If argument ARG is a REAL_CST, call mpfr_sin_cos() on it and set
13787 the pointers *(ARG_SINP) and *(ARG_COSP) to the resulting values.
d735c391 13788 If ARG_SINP and ARG_COSP are NULL then the result is returned
13789 as a complex value.
d92f994c 13790 The type is taken from the type of ARG and is used for setting the
13791 precision of the calculation and results. */
13792
13793static tree
13794do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp)
13795{
bd7d6fa4 13796 tree const type = TREE_TYPE (arg);
d92f994c 13797 tree result = NULL_TREE;
48e1416a 13798
d92f994c 13799 STRIP_NOPS (arg);
48e1416a 13800
bd7d6fa4 13801 /* To proceed, MPFR must exactly represent the target floating point
13802 format, which only happens when the target base equals two. */
13803 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
f96bd2bf 13804 && TREE_CODE (arg) == REAL_CST
13805 && !TREE_OVERFLOW (arg))
d92f994c 13806 {
13807 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg);
13808
776a7bab 13809 if (real_isfinite (ra))
d92f994c 13810 {
e2eb2b7f 13811 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13812 const int prec = fmt->p;
13813 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
d92f994c 13814 tree result_s, result_c;
13815 int inexact;
13816 mpfr_t m, ms, mc;
13817
13818 mpfr_inits2 (prec, m, ms, mc, NULL);
66fa16e6 13819 mpfr_from_real (m, ra, GMP_RNDN);
d4473c84 13820 mpfr_clear_flags ();
e2eb2b7f 13821 inexact = mpfr_sin_cos (ms, mc, m, rnd);
d92f994c 13822 result_s = do_mpfr_ckconv (ms, type, inexact);
13823 result_c = do_mpfr_ckconv (mc, type, inexact);
13824 mpfr_clears (m, ms, mc, NULL);
13825 if (result_s && result_c)
13826 {
d735c391 13827 /* If we are to return in a complex value do so. */
13828 if (!arg_sinp && !arg_cosp)
13829 return build_complex (build_complex_type (type),
13830 result_c, result_s);
13831
d92f994c 13832 /* Dereference the sin/cos pointer arguments. */
13833 arg_sinp = build_fold_indirect_ref (arg_sinp);
13834 arg_cosp = build_fold_indirect_ref (arg_cosp);
13835 /* Proceed if valid pointer type were passed in. */
13836 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_sinp)) == TYPE_MAIN_VARIANT (type)
13837 && TYPE_MAIN_VARIANT (TREE_TYPE (arg_cosp)) == TYPE_MAIN_VARIANT (type))
13838 {
13839 /* Set the values. */
41076ef6 13840 result_s = fold_build2 (MODIFY_EXPR, type, arg_sinp,
35cc02b5 13841 result_s);
d92f994c 13842 TREE_SIDE_EFFECTS (result_s) = 1;
41076ef6 13843 result_c = fold_build2 (MODIFY_EXPR, type, arg_cosp,
35cc02b5 13844 result_c);
d92f994c 13845 TREE_SIDE_EFFECTS (result_c) = 1;
13846 /* Combine the assignments into a compound expr. */
13847 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13848 result_s, result_c));
13849 }
13850 }
13851 }
13852 }
13853 return result;
13854}
65dd1378 13855
65dd1378 13856/* If argument ARG1 is an INTEGER_CST and ARG2 is a REAL_CST, call the
13857 two-argument mpfr order N Bessel function FUNC on them and return
13858 the resulting value as a tree with type TYPE. The mpfr precision
13859 is set to the precision of TYPE. We assume that function FUNC
13860 returns zero if the result could be calculated exactly within the
13861 requested precision. */
13862static tree
13863do_mpfr_bessel_n (tree arg1, tree arg2, tree type,
13864 int (*func)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
13865 const REAL_VALUE_TYPE *min, bool inclusive)
13866{
13867 tree result = NULL_TREE;
13868
13869 STRIP_NOPS (arg1);
13870 STRIP_NOPS (arg2);
13871
13872 /* To proceed, MPFR must exactly represent the target floating point
13873 format, which only happens when the target base equals two. */
13874 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13875 && host_integerp (arg1, 0)
13876 && TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
13877 {
13878 const HOST_WIDE_INT n = tree_low_cst(arg1, 0);
13879 const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg2);
13880
13881 if (n == (long)n
776a7bab 13882 && real_isfinite (ra)
65dd1378 13883 && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min)))
13884 {
e2eb2b7f 13885 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13886 const int prec = fmt->p;
13887 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
65dd1378 13888 int inexact;
13889 mpfr_t m;
13890
13891 mpfr_init2 (m, prec);
13892 mpfr_from_real (m, ra, GMP_RNDN);
13893 mpfr_clear_flags ();
e2eb2b7f 13894 inexact = func (m, n, m, rnd);
65dd1378 13895 result = do_mpfr_ckconv (m, type, inexact);
13896 mpfr_clear (m);
13897 }
13898 }
48e1416a 13899
65dd1378 13900 return result;
13901}
e5407ca6 13902
13903/* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set
13904 the pointer *(ARG_QUO) and return the result. The type is taken
13905 from the type of ARG0 and is used for setting the precision of the
13906 calculation and results. */
13907
13908static tree
13909do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
13910{
13911 tree const type = TREE_TYPE (arg0);
13912 tree result = NULL_TREE;
48e1416a 13913
e5407ca6 13914 STRIP_NOPS (arg0);
13915 STRIP_NOPS (arg1);
48e1416a 13916
e5407ca6 13917 /* To proceed, MPFR must exactly represent the target floating point
13918 format, which only happens when the target base equals two. */
13919 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13920 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
13921 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1))
13922 {
13923 const REAL_VALUE_TYPE *const ra0 = TREE_REAL_CST_PTR (arg0);
13924 const REAL_VALUE_TYPE *const ra1 = TREE_REAL_CST_PTR (arg1);
13925
776a7bab 13926 if (real_isfinite (ra0) && real_isfinite (ra1))
e5407ca6 13927 {
e2eb2b7f 13928 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
13929 const int prec = fmt->p;
13930 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
e5407ca6 13931 tree result_rem;
13932 long integer_quo;
13933 mpfr_t m0, m1;
13934
13935 mpfr_inits2 (prec, m0, m1, NULL);
13936 mpfr_from_real (m0, ra0, GMP_RNDN);
13937 mpfr_from_real (m1, ra1, GMP_RNDN);
13938 mpfr_clear_flags ();
e2eb2b7f 13939 mpfr_remquo (m0, &integer_quo, m0, m1, rnd);
e5407ca6 13940 /* Remquo is independent of the rounding mode, so pass
13941 inexact=0 to do_mpfr_ckconv(). */
13942 result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
13943 mpfr_clears (m0, m1, NULL);
13944 if (result_rem)
13945 {
13946 /* MPFR calculates quo in the host's long so it may
13947 return more bits in quo than the target int can hold
13948 if sizeof(host long) > sizeof(target int). This can
13949 happen even for native compilers in LP64 mode. In
13950 these cases, modulo the quo value with the largest
13951 number that the target int can hold while leaving one
13952 bit for the sign. */
13953 if (sizeof (integer_quo) * CHAR_BIT > INT_TYPE_SIZE)
13954 integer_quo %= (long)(1UL << (INT_TYPE_SIZE - 1));
13955
13956 /* Dereference the quo pointer argument. */
13957 arg_quo = build_fold_indirect_ref (arg_quo);
13958 /* Proceed iff a valid pointer type was passed in. */
13959 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_quo)) == integer_type_node)
13960 {
13961 /* Set the value. */
7002a1c8 13962 tree result_quo
13963 = fold_build2 (MODIFY_EXPR, TREE_TYPE (arg_quo), arg_quo,
13964 build_int_cst (TREE_TYPE (arg_quo),
13965 integer_quo));
e5407ca6 13966 TREE_SIDE_EFFECTS (result_quo) = 1;
13967 /* Combine the quo assignment with the rem. */
13968 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
13969 result_quo, result_rem));
13970 }
13971 }
13972 }
13973 }
13974 return result;
13975}
e84da7c1 13976
13977/* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the
13978 resulting value as a tree with type TYPE. The mpfr precision is
13979 set to the precision of TYPE. We assume that this mpfr function
13980 returns zero if the result could be calculated exactly within the
13981 requested precision. In addition, the integer pointer represented
13982 by ARG_SG will be dereferenced and set to the appropriate signgam
13983 (-1,1) value. */
13984
13985static tree
13986do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
13987{
13988 tree result = NULL_TREE;
13989
13990 STRIP_NOPS (arg);
48e1416a 13991
e84da7c1 13992 /* To proceed, MPFR must exactly represent the target floating point
13993 format, which only happens when the target base equals two. Also
13994 verify ARG is a constant and that ARG_SG is an int pointer. */
13995 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
13996 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg)
13997 && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE
13998 && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node)
13999 {
14000 const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg);
14001
14002 /* In addition to NaN and Inf, the argument cannot be zero or a
14003 negative integer. */
776a7bab 14004 if (real_isfinite (ra)
e84da7c1 14005 && ra->cl != rvc_zero
14006 && !(real_isneg(ra) && real_isinteger(ra, TYPE_MODE (type))))
14007 {
e2eb2b7f 14008 const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
14009 const int prec = fmt->p;
14010 const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
e84da7c1 14011 int inexact, sg;
14012 mpfr_t m;
14013 tree result_lg;
14014
14015 mpfr_init2 (m, prec);
14016 mpfr_from_real (m, ra, GMP_RNDN);
14017 mpfr_clear_flags ();
e2eb2b7f 14018 inexact = mpfr_lgamma (m, &sg, m, rnd);
e84da7c1 14019 result_lg = do_mpfr_ckconv (m, type, inexact);
14020 mpfr_clear (m);
14021 if (result_lg)
14022 {
14023 tree result_sg;
14024
14025 /* Dereference the arg_sg pointer argument. */
14026 arg_sg = build_fold_indirect_ref (arg_sg);
14027 /* Assign the signgam value into *arg_sg. */
14028 result_sg = fold_build2 (MODIFY_EXPR,
14029 TREE_TYPE (arg_sg), arg_sg,
7002a1c8 14030 build_int_cst (TREE_TYPE (arg_sg), sg));
e84da7c1 14031 TREE_SIDE_EFFECTS (result_sg) = 1;
14032 /* Combine the signgam assignment with the lgamma result. */
14033 result = non_lvalue (fold_build2 (COMPOUND_EXPR, type,
14034 result_sg, result_lg));
14035 }
14036 }
14037 }
14038
14039 return result;
14040}
75a70cf9 14041
239d491a 14042/* If argument ARG is a COMPLEX_CST, call the one-argument mpc
14043 function FUNC on it and return the resulting value as a tree with
14044 type TYPE. The mpfr precision is set to the precision of TYPE. We
14045 assume that function FUNC returns zero if the result could be
14046 calculated exactly within the requested precision. */
14047
14048static tree
14049do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t))
14050{
14051 tree result = NULL_TREE;
48e1416a 14052
239d491a 14053 STRIP_NOPS (arg);
14054
14055 /* To proceed, MPFR must exactly represent the target floating point
14056 format, which only happens when the target base equals two. */
14057 if (TREE_CODE (arg) == COMPLEX_CST && !TREE_OVERFLOW (arg)
14058 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE
14059 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))))->b == 2)
14060 {
14061 const REAL_VALUE_TYPE *const re = TREE_REAL_CST_PTR (TREE_REALPART (arg));
14062 const REAL_VALUE_TYPE *const im = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
14063
14064 if (real_isfinite (re) && real_isfinite (im))
14065 {
14066 const struct real_format *const fmt =
14067 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
14068 const int prec = fmt->p;
14069 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
44d89feb 14070 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
239d491a 14071 int inexact;
14072 mpc_t m;
48e1416a 14073
239d491a 14074 mpc_init2 (m, prec);
c3cfad90 14075 mpfr_from_real (mpc_realref(m), re, rnd);
14076 mpfr_from_real (mpc_imagref(m), im, rnd);
239d491a 14077 mpfr_clear_flags ();
44d89feb 14078 inexact = func (m, m, crnd);
652d9409 14079 result = do_mpc_ckconv (m, type, inexact, /*force_convert=*/ 0);
239d491a 14080 mpc_clear (m);
14081 }
14082 }
14083
14084 return result;
14085}
c699fab8 14086
14087/* If arguments ARG0 and ARG1 are a COMPLEX_CST, call the two-argument
14088 mpc function FUNC on it and return the resulting value as a tree
14089 with type TYPE. The mpfr precision is set to the precision of
14090 TYPE. We assume that function FUNC returns zero if the result
652d9409 14091 could be calculated exactly within the requested precision. If
14092 DO_NONFINITE is true, then fold expressions containing Inf or NaN
14093 in the arguments and/or results. */
c699fab8 14094
63e89698 14095tree
652d9409 14096do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
c699fab8 14097 int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
14098{
14099 tree result = NULL_TREE;
48e1416a 14100
c699fab8 14101 STRIP_NOPS (arg0);
14102 STRIP_NOPS (arg1);
14103
14104 /* To proceed, MPFR must exactly represent the target floating point
14105 format, which only happens when the target base equals two. */
14106 if (TREE_CODE (arg0) == COMPLEX_CST && !TREE_OVERFLOW (arg0)
14107 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
14108 && TREE_CODE (arg1) == COMPLEX_CST && !TREE_OVERFLOW (arg1)
14109 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE
14110 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))))->b == 2)
14111 {
14112 const REAL_VALUE_TYPE *const re0 = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
14113 const REAL_VALUE_TYPE *const im0 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
14114 const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1));
14115 const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1));
14116
652d9409 14117 if (do_nonfinite
14118 || (real_isfinite (re0) && real_isfinite (im0)
14119 && real_isfinite (re1) && real_isfinite (im1)))
c699fab8 14120 {
14121 const struct real_format *const fmt =
14122 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
14123 const int prec = fmt->p;
14124 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
14125 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
14126 int inexact;
14127 mpc_t m0, m1;
48e1416a 14128
c699fab8 14129 mpc_init2 (m0, prec);
14130 mpc_init2 (m1, prec);
14131 mpfr_from_real (mpc_realref(m0), re0, rnd);
14132 mpfr_from_real (mpc_imagref(m0), im0, rnd);
14133 mpfr_from_real (mpc_realref(m1), re1, rnd);
14134 mpfr_from_real (mpc_imagref(m1), im1, rnd);
14135 mpfr_clear_flags ();
14136 inexact = func (m0, m0, m1, crnd);
652d9409 14137 result = do_mpc_ckconv (m0, type, inexact, do_nonfinite);
c699fab8 14138 mpc_clear (m0);
14139 mpc_clear (m1);
14140 }
14141 }
14142
14143 return result;
14144}
239d491a 14145
75a70cf9 14146/* Fold a call STMT to __{,v}sprintf_chk. Return NULL_TREE if
14147 a normal call should be emitted rather than expanding the function
14148 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
14149
14150static tree
14151gimple_fold_builtin_sprintf_chk (gimple stmt, enum built_in_function fcode)
14152{
75a70cf9 14153 int nargs = gimple_call_num_args (stmt);
14154
af1409ad 14155 return fold_builtin_sprintf_chk_1 (gimple_location (stmt), nargs,
14156 (nargs > 0
14157 ? gimple_call_arg_ptr (stmt, 0)
14158 : &error_mark_node), fcode);
75a70cf9 14159}
14160
14161/* Fold a call STMT to {,v}snprintf. Return NULL_TREE if
14162 a normal call should be emitted rather than expanding the function
14163 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
14164 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
14165 passed as second argument. */
14166
14167tree
14168gimple_fold_builtin_snprintf_chk (gimple stmt, tree maxlen,
14169 enum built_in_function fcode)
14170{
af1409ad 14171 int nargs = gimple_call_num_args (stmt);
75a70cf9 14172
af1409ad 14173 return fold_builtin_snprintf_chk_1 (gimple_location (stmt), nargs,
14174 (nargs > 0
14175 ? gimple_call_arg_ptr (stmt, 0)
14176 : &error_mark_node), maxlen, fcode);
75a70cf9 14177}
14178
14179/* Builtins with folding operations that operate on "..." arguments
14180 need special handling; we need to store the arguments in a convenient
14181 data structure before attempting any folding. Fortunately there are
14182 only a few builtins that fall into this category. FNDECL is the
14183 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
14184 result of the function call is ignored. */
14185
14186static tree
389dd41b 14187gimple_fold_builtin_varargs (tree fndecl, gimple stmt,
14188 bool ignore ATTRIBUTE_UNUSED)
75a70cf9 14189{
14190 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
14191 tree ret = NULL_TREE;
14192
14193 switch (fcode)
14194 {
14195 case BUILT_IN_SPRINTF_CHK:
14196 case BUILT_IN_VSPRINTF_CHK:
14197 ret = gimple_fold_builtin_sprintf_chk (stmt, fcode);
14198 break;
14199
14200 case BUILT_IN_SNPRINTF_CHK:
14201 case BUILT_IN_VSNPRINTF_CHK:
14202 ret = gimple_fold_builtin_snprintf_chk (stmt, NULL_TREE, fcode);
14203
14204 default:
14205 break;
14206 }
14207 if (ret)
14208 {
14209 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
14210 TREE_NO_WARNING (ret) = 1;
14211 return ret;
14212 }
14213 return NULL_TREE;
14214}
14215
14216/* A wrapper function for builtin folding that prevents warnings for
14217 "statement without effect" and the like, caused by removing the
14218 call node earlier than the warning is generated. */
14219
14220tree
14221fold_call_stmt (gimple stmt, bool ignore)
14222{
14223 tree ret = NULL_TREE;
14224 tree fndecl = gimple_call_fndecl (stmt);
389dd41b 14225 location_t loc = gimple_location (stmt);
75a70cf9 14226 if (fndecl
14227 && TREE_CODE (fndecl) == FUNCTION_DECL
14228 && DECL_BUILT_IN (fndecl)
14229 && !gimple_call_va_arg_pack_p (stmt))
14230 {
14231 int nargs = gimple_call_num_args (stmt);
9845fb99 14232 tree *args = (nargs > 0
14233 ? gimple_call_arg_ptr (stmt, 0)
14234 : &error_mark_node);
75a70cf9 14235
198622c0 14236 if (avoid_folding_inline_builtin (fndecl))
14237 return NULL_TREE;
75a70cf9 14238 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
14239 {
9845fb99 14240 return targetm.fold_builtin (fndecl, nargs, args, ignore);
75a70cf9 14241 }
14242 else
14243 {
14244 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
9845fb99 14245 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
75a70cf9 14246 if (!ret)
14247 ret = gimple_fold_builtin_varargs (fndecl, stmt, ignore);
14248 if (ret)
14249 {
14250 /* Propagate location information from original call to
14251 expansion of builtin. Otherwise things like
14252 maybe_emit_chk_warning, that operate on the expansion
14253 of a builtin, will use the wrong location information. */
14254 if (gimple_has_location (stmt))
14255 {
14256 tree realret = ret;
14257 if (TREE_CODE (ret) == NOP_EXPR)
14258 realret = TREE_OPERAND (ret, 0);
14259 if (CAN_HAVE_LOCATION_P (realret)
14260 && !EXPR_HAS_LOCATION (realret))
389dd41b 14261 SET_EXPR_LOCATION (realret, loc);
75a70cf9 14262 return realret;
14263 }
14264 return ret;
14265 }
14266 }
14267 }
14268 return NULL_TREE;
14269}
7bfefa9d 14270
b9a16870 14271/* Look up the function in builtin_decl that corresponds to DECL
7bfefa9d 14272 and set ASMSPEC as its user assembler name. DECL must be a
14273 function decl that declares a builtin. */
14274
14275void
14276set_builtin_user_assembler_name (tree decl, const char *asmspec)
14277{
14278 tree builtin;
14279 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
14280 && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
14281 && asmspec != 0);
14282
b9a16870 14283 builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
4d8e0d6d 14284 set_user_assembler_name (builtin, asmspec);
7bfefa9d 14285 switch (DECL_FUNCTION_CODE (decl))
14286 {
14287 case BUILT_IN_MEMCPY:
14288 init_block_move_fn (asmspec);
14289 memcpy_libfunc = set_user_assembler_libfunc ("memcpy", asmspec);
14290 break;
14291 case BUILT_IN_MEMSET:
14292 init_block_clear_fn (asmspec);
14293 memset_libfunc = set_user_assembler_libfunc ("memset", asmspec);
14294 break;
14295 case BUILT_IN_MEMMOVE:
14296 memmove_libfunc = set_user_assembler_libfunc ("memmove", asmspec);
14297 break;
14298 case BUILT_IN_MEMCMP:
14299 memcmp_libfunc = set_user_assembler_libfunc ("memcmp", asmspec);
14300 break;
14301 case BUILT_IN_ABORT:
14302 abort_libfunc = set_user_assembler_libfunc ("abort", asmspec);
14303 break;
5a80a58b 14304 case BUILT_IN_FFS:
14305 if (INT_TYPE_SIZE < BITS_PER_WORD)
14306 {
14307 set_user_assembler_libfunc ("ffs", asmspec);
14308 set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE,
14309 MODE_INT, 0), "ffs");
14310 }
14311 break;
7bfefa9d 14312 default:
14313 break;
14314 }
14315}
a6b74a67 14316
14317/* Return true if DECL is a builtin that expands to a constant or similarly
14318 simple code. */
14319bool
14320is_simple_builtin (tree decl)
14321{
14322 if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
14323 switch (DECL_FUNCTION_CODE (decl))
14324 {
14325 /* Builtins that expand to constants. */
14326 case BUILT_IN_CONSTANT_P:
14327 case BUILT_IN_EXPECT:
14328 case BUILT_IN_OBJECT_SIZE:
14329 case BUILT_IN_UNREACHABLE:
14330 /* Simple register moves or loads from stack. */
fca0886c 14331 case BUILT_IN_ASSUME_ALIGNED:
a6b74a67 14332 case BUILT_IN_RETURN_ADDRESS:
14333 case BUILT_IN_EXTRACT_RETURN_ADDR:
14334 case BUILT_IN_FROB_RETURN_ADDR:
14335 case BUILT_IN_RETURN:
14336 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
14337 case BUILT_IN_FRAME_ADDRESS:
14338 case BUILT_IN_VA_END:
14339 case BUILT_IN_STACK_SAVE:
14340 case BUILT_IN_STACK_RESTORE:
14341 /* Exception state returns or moves registers around. */
14342 case BUILT_IN_EH_FILTER:
14343 case BUILT_IN_EH_POINTER:
14344 case BUILT_IN_EH_COPY_VALUES:
14345 return true;
14346
14347 default:
14348 return false;
14349 }
14350
14351 return false;
14352}
14353
14354/* Return true if DECL is a builtin that is not expensive, i.e., they are
14355 most probably expanded inline into reasonably simple code. This is a
14356 superset of is_simple_builtin. */
14357bool
14358is_inexpensive_builtin (tree decl)
14359{
14360 if (!decl)
14361 return false;
14362 else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_MD)
14363 return true;
14364 else if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
14365 switch (DECL_FUNCTION_CODE (decl))
14366 {
14367 case BUILT_IN_ABS:
14368 case BUILT_IN_ALLOCA:
581bf1c2 14369 case BUILT_IN_ALLOCA_WITH_ALIGN:
74bdbe96 14370 case BUILT_IN_BSWAP16:
a6b74a67 14371 case BUILT_IN_BSWAP32:
14372 case BUILT_IN_BSWAP64:
14373 case BUILT_IN_CLZ:
14374 case BUILT_IN_CLZIMAX:
14375 case BUILT_IN_CLZL:
14376 case BUILT_IN_CLZLL:
14377 case BUILT_IN_CTZ:
14378 case BUILT_IN_CTZIMAX:
14379 case BUILT_IN_CTZL:
14380 case BUILT_IN_CTZLL:
14381 case BUILT_IN_FFS:
14382 case BUILT_IN_FFSIMAX:
14383 case BUILT_IN_FFSL:
14384 case BUILT_IN_FFSLL:
14385 case BUILT_IN_IMAXABS:
14386 case BUILT_IN_FINITE:
14387 case BUILT_IN_FINITEF:
14388 case BUILT_IN_FINITEL:
14389 case BUILT_IN_FINITED32:
14390 case BUILT_IN_FINITED64:
14391 case BUILT_IN_FINITED128:
14392 case BUILT_IN_FPCLASSIFY:
14393 case BUILT_IN_ISFINITE:
14394 case BUILT_IN_ISINF_SIGN:
14395 case BUILT_IN_ISINF:
14396 case BUILT_IN_ISINFF:
14397 case BUILT_IN_ISINFL:
14398 case BUILT_IN_ISINFD32:
14399 case BUILT_IN_ISINFD64:
14400 case BUILT_IN_ISINFD128:
14401 case BUILT_IN_ISNAN:
14402 case BUILT_IN_ISNANF:
14403 case BUILT_IN_ISNANL:
14404 case BUILT_IN_ISNAND32:
14405 case BUILT_IN_ISNAND64:
14406 case BUILT_IN_ISNAND128:
14407 case BUILT_IN_ISNORMAL:
14408 case BUILT_IN_ISGREATER:
14409 case BUILT_IN_ISGREATEREQUAL:
14410 case BUILT_IN_ISLESS:
14411 case BUILT_IN_ISLESSEQUAL:
14412 case BUILT_IN_ISLESSGREATER:
14413 case BUILT_IN_ISUNORDERED:
14414 case BUILT_IN_VA_ARG_PACK:
14415 case BUILT_IN_VA_ARG_PACK_LEN:
14416 case BUILT_IN_VA_COPY:
14417 case BUILT_IN_TRAP:
14418 case BUILT_IN_SAVEREGS:
14419 case BUILT_IN_POPCOUNTL:
14420 case BUILT_IN_POPCOUNTLL:
14421 case BUILT_IN_POPCOUNTIMAX:
14422 case BUILT_IN_POPCOUNT:
14423 case BUILT_IN_PARITYL:
14424 case BUILT_IN_PARITYLL:
14425 case BUILT_IN_PARITYIMAX:
14426 case BUILT_IN_PARITY:
14427 case BUILT_IN_LABS:
14428 case BUILT_IN_LLABS:
14429 case BUILT_IN_PREFETCH:
14430 return true;
14431
14432 default:
14433 return is_simple_builtin (decl);
14434 }
14435
14436 return false;
14437}